LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - rsa_alt_helpers.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 28.3 % 173 49
Test Date: 2025-06-29 08:09:00 Functions: 40.0 % 5 2

            Line data    Source code
       1              : /*
       2              :  *  Helper functions for the RSA module
       3              :  *
       4              :  *  Copyright The Mbed TLS Contributors
       5              :  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       6              :  *
       7              :  */
       8              : 
       9              : #include "common.h"
      10              : 
      11              : #if defined(MBEDTLS_RSA_C)
      12              : 
      13              : #include "mbedtls/rsa.h"
      14              : #include "mbedtls/bignum.h"
      15              : #include "rsa_alt_helpers.h"
      16              : 
      17              : /*
      18              :  * Compute RSA prime factors from public and private exponents
      19              :  *
      20              :  * Summary of algorithm:
      21              :  * Setting F := lcm(P-1,Q-1), the idea is as follows:
      22              :  *
      23              :  * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2)
      24              :  *     is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the
      25              :  *     square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four
      26              :  *     possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1)
      27              :  *     or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime
      28              :  *     factors of N.
      29              :  *
      30              :  * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same
      31              :  *     construction still applies since (-)^K is the identity on the set of
      32              :  *     roots of 1 in Z/NZ.
      33              :  *
      34              :  * The public and private key primitives (-)^E and (-)^D are mutually inverse
      35              :  * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e.
      36              :  * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L.
      37              :  * Splitting L = 2^t * K with K odd, we have
      38              :  *
      39              :  *   DE - 1 = FL = (F/2) * (2^(t+1)) * K,
      40              :  *
      41              :  * so (F / 2) * K is among the numbers
      42              :  *
      43              :  *   (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord
      44              :  *
      45              :  * where ord is the order of 2 in (DE - 1).
      46              :  * We can therefore iterate through these numbers apply the construction
      47              :  * of (a) and (b) above to attempt to factor N.
      48              :  *
      49              :  */
      50            2 : int mbedtls_rsa_deduce_primes(mbedtls_mpi const *N,
      51              :                               mbedtls_mpi const *E, mbedtls_mpi const *D,
      52              :                               mbedtls_mpi *P, mbedtls_mpi *Q)
      53              : {
      54            2 :     int ret = 0;
      55              : 
      56              :     uint16_t attempt;  /* Number of current attempt  */
      57              :     uint16_t iter;     /* Number of squares computed in the current attempt */
      58              : 
      59              :     uint16_t order;    /* Order of 2 in DE - 1 */
      60              : 
      61              :     mbedtls_mpi T;  /* Holds largest odd divisor of DE - 1     */
      62              :     mbedtls_mpi K;  /* Temporary holding the current candidate */
      63              : 
      64            2 :     const unsigned char primes[] = { 2,
      65              :                                      3,    5,    7,   11,   13,   17,   19,   23,
      66              :                                      29,   31,   37,   41,   43,   47,   53,   59,
      67              :                                      61,   67,   71,   73,   79,   83,   89,   97,
      68              :                                      101,  103,  107,  109,  113,  127,  131,  137,
      69              :                                      139,  149,  151,  157,  163,  167,  173,  179,
      70              :                                      181,  191,  193,  197,  199,  211,  223,  227,
      71              :                                      229,  233,  239,  241,  251 };
      72              : 
      73            2 :     const size_t num_primes = sizeof(primes) / sizeof(*primes);
      74              : 
      75            2 :     if (P == NULL || Q == NULL || P->p != NULL || Q->p != NULL) {
      76            0 :         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
      77              :     }
      78              : 
      79            4 :     if (mbedtls_mpi_cmp_int(N, 0) <= 0 ||
      80            4 :         mbedtls_mpi_cmp_int(D, 1) <= 0 ||
      81            4 :         mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
      82            4 :         mbedtls_mpi_cmp_int(E, 1) <= 0 ||
      83            2 :         mbedtls_mpi_cmp_mpi(E, N) >= 0) {
      84            0 :         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
      85              :     }
      86              : 
      87              :     /*
      88              :      * Initializations and temporary changes
      89              :      */
      90              : 
      91            2 :     mbedtls_mpi_init(&K);
      92            2 :     mbedtls_mpi_init(&T);
      93              : 
      94              :     /* T := DE - 1 */
      95            2 :     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&T, D,  E));
      96            2 :     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&T, &T, 1));
      97              : 
      98            2 :     if ((order = (uint16_t) mbedtls_mpi_lsb(&T)) == 0) {
      99            0 :         ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     100            0 :         goto cleanup;
     101              :     }
     102              : 
     103              :     /* After this operation, T holds the largest odd divisor of DE - 1. */
     104            2 :     MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&T, order));
     105              : 
     106              :     /*
     107              :      * Actual work
     108              :      */
     109              : 
     110              :     /* Skip trying 2 if N == 1 mod 8 */
     111            2 :     attempt = 0;
     112            2 :     if (N->p[0] % 8 == 1) {
     113            0 :         attempt = 1;
     114              :     }
     115              : 
     116            2 :     for (; attempt < num_primes; ++attempt) {
     117            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&K, primes[attempt]));
     118              : 
     119              :         /* Check if gcd(K,N) = 1 */
     120            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
     121            2 :         if (mbedtls_mpi_cmp_int(P, 1) != 0) {
     122            0 :             continue;
     123              :         }
     124              : 
     125              :         /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ...
     126              :          * and check whether they have nontrivial GCD with N. */
     127            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&K, &K, &T, N,
     128              :                                             Q /* temporarily use Q for storing Montgomery
     129              :                                                * multiplication helper values */));
     130              : 
     131            2 :         for (iter = 1; iter <= order; ++iter) {
     132              :             /* If we reach 1 prematurely, there's no point
     133              :              * in continuing to square K */
     134            2 :             if (mbedtls_mpi_cmp_int(&K, 1) == 0) {
     135            0 :                 break;
     136              :             }
     137              : 
     138            2 :             MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&K, &K, 1));
     139            2 :             MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(P, &K, N));
     140              : 
     141            4 :             if (mbedtls_mpi_cmp_int(P, 1) ==  1 &&
     142            2 :                 mbedtls_mpi_cmp_mpi(P, N) == -1) {
     143              :                 /*
     144              :                  * Have found a nontrivial divisor P of N.
     145              :                  * Set Q := N / P.
     146              :                  */
     147              : 
     148            2 :                 MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(Q, NULL, N, P));
     149            2 :                 goto cleanup;
     150              :             }
     151              : 
     152            0 :             MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
     153            0 :             MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &K));
     154            0 :             MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, N));
     155              :         }
     156              : 
     157              :         /*
     158              :          * If we get here, then either we prematurely aborted the loop because
     159              :          * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must
     160              :          * be 1 if D,E,N were consistent.
     161              :          * Check if that's the case and abort if not, to avoid very long,
     162              :          * yet eventually failing, computations if N,D,E were not sane.
     163              :          */
     164            0 :         if (mbedtls_mpi_cmp_int(&K, 1) != 0) {
     165            0 :             break;
     166              :         }
     167              :     }
     168              : 
     169            0 :     ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     170              : 
     171            2 : cleanup:
     172              : 
     173            2 :     mbedtls_mpi_free(&K);
     174            2 :     mbedtls_mpi_free(&T);
     175            2 :     return ret;
     176              : }
     177              : 
     178              : /*
     179              :  * Given P, Q and the public exponent E, deduce D.
     180              :  * This is essentially a modular inversion.
     181              :  */
     182            0 : int mbedtls_rsa_deduce_private_exponent(mbedtls_mpi const *P,
     183              :                                         mbedtls_mpi const *Q,
     184              :                                         mbedtls_mpi const *E,
     185              :                                         mbedtls_mpi *D)
     186              : {
     187            0 :     int ret = 0;
     188              :     mbedtls_mpi K, L;
     189              : 
     190            0 :     if (D == NULL || mbedtls_mpi_cmp_int(D, 0) != 0) {
     191            0 :         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     192              :     }
     193              : 
     194            0 :     if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
     195            0 :         mbedtls_mpi_cmp_int(Q, 1) <= 0 ||
     196            0 :         mbedtls_mpi_cmp_int(E, 0) == 0) {
     197            0 :         return MBEDTLS_ERR_MPI_BAD_INPUT_DATA;
     198              :     }
     199              : 
     200            0 :     mbedtls_mpi_init(&K);
     201            0 :     mbedtls_mpi_init(&L);
     202              : 
     203              :     /* Temporarily put K := P-1 and L := Q-1 */
     204            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
     205            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
     206              : 
     207              :     /* Temporarily put D := gcd(P-1, Q-1) */
     208            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_gcd(D, &K, &L));
     209              : 
     210              :     /* K := LCM(P-1, Q-1) */
     211            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, &K, &L));
     212            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_div_mpi(&K, NULL, &K, D));
     213              : 
     214              :     /* Compute modular inverse of E in LCM(P-1, Q-1) */
     215            0 :     MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(D, E, &K));
     216              : 
     217            0 : cleanup:
     218              : 
     219            0 :     mbedtls_mpi_free(&K);
     220            0 :     mbedtls_mpi_free(&L);
     221              : 
     222            0 :     return ret;
     223              : }
     224              : 
     225            2 : int mbedtls_rsa_deduce_crt(const mbedtls_mpi *P, const mbedtls_mpi *Q,
     226              :                            const mbedtls_mpi *D, mbedtls_mpi *DP,
     227              :                            mbedtls_mpi *DQ, mbedtls_mpi *QP)
     228              : {
     229            2 :     int ret = 0;
     230              :     mbedtls_mpi K;
     231            2 :     mbedtls_mpi_init(&K);
     232              : 
     233              :     /* DP = D mod P-1 */
     234            2 :     if (DP != NULL) {
     235            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
     236            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DP, D, &K));
     237              :     }
     238              : 
     239              :     /* DQ = D mod Q-1 */
     240            2 :     if (DQ != NULL) {
     241            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
     242            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(DQ, D, &K));
     243              :     }
     244              : 
     245              :     /* QP = Q^{-1} mod P */
     246            2 :     if (QP != NULL) {
     247            2 :         MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(QP, Q, P));
     248              :     }
     249              : 
     250            2 : cleanup:
     251            2 :     mbedtls_mpi_free(&K);
     252              : 
     253            2 :     return ret;
     254              : }
     255              : 
     256              : /*
     257              :  * Check that core RSA parameters are sane.
     258              :  */
     259            0 : int mbedtls_rsa_validate_params(const mbedtls_mpi *N, const mbedtls_mpi *P,
     260              :                                 const mbedtls_mpi *Q, const mbedtls_mpi *D,
     261              :                                 const mbedtls_mpi *E,
     262              :                                 int (*f_rng)(void *, unsigned char *, size_t),
     263              :                                 void *p_rng)
     264              : {
     265            0 :     int ret = 0;
     266              :     mbedtls_mpi K, L;
     267              : 
     268            0 :     mbedtls_mpi_init(&K);
     269            0 :     mbedtls_mpi_init(&L);
     270              : 
     271              :     /*
     272              :      * Step 1: If PRNG provided, check that P and Q are prime
     273              :      */
     274              : 
     275              : #if defined(MBEDTLS_GENPRIME)
     276              :     /*
     277              :      * When generating keys, the strongest security we support aims for an error
     278              :      * rate of at most 2^-100 and we are aiming for the same certainty here as
     279              :      * well.
     280              :      */
     281            0 :     if (f_rng != NULL && P != NULL &&
     282            0 :         (ret = mbedtls_mpi_is_prime_ext(P, 50, f_rng, p_rng)) != 0) {
     283            0 :         ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     284            0 :         goto cleanup;
     285              :     }
     286              : 
     287            0 :     if (f_rng != NULL && Q != NULL &&
     288            0 :         (ret = mbedtls_mpi_is_prime_ext(Q, 50, f_rng, p_rng)) != 0) {
     289            0 :         ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     290            0 :         goto cleanup;
     291              :     }
     292              : #else
     293              :     ((void) f_rng);
     294              :     ((void) p_rng);
     295              : #endif /* MBEDTLS_GENPRIME */
     296              : 
     297              :     /*
     298              :      * Step 2: Check that 1 < N = P * Q
     299              :      */
     300              : 
     301            0 :     if (P != NULL && Q != NULL && N != NULL) {
     302            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, P, Q));
     303            0 :         if (mbedtls_mpi_cmp_int(N, 1)  <= 0 ||
     304            0 :             mbedtls_mpi_cmp_mpi(&K, N) != 0) {
     305            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     306            0 :             goto cleanup;
     307              :         }
     308              :     }
     309              : 
     310              :     /*
     311              :      * Step 3: Check and 1 < D, E < N if present.
     312              :      */
     313              : 
     314            0 :     if (N != NULL && D != NULL && E != NULL) {
     315            0 :         if (mbedtls_mpi_cmp_int(D, 1) <= 0 ||
     316            0 :             mbedtls_mpi_cmp_int(E, 1) <= 0 ||
     317            0 :             mbedtls_mpi_cmp_mpi(D, N) >= 0 ||
     318            0 :             mbedtls_mpi_cmp_mpi(E, N) >= 0) {
     319            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     320            0 :             goto cleanup;
     321              :         }
     322              :     }
     323              : 
     324              :     /*
     325              :      * Step 4: Check that D, E are inverse modulo P-1 and Q-1
     326              :      */
     327              : 
     328            0 :     if (P != NULL && Q != NULL && D != NULL && E != NULL) {
     329            0 :         if (mbedtls_mpi_cmp_int(P, 1) <= 0 ||
     330            0 :             mbedtls_mpi_cmp_int(Q, 1) <= 0) {
     331            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     332            0 :             goto cleanup;
     333              :         }
     334              : 
     335              :         /* Compute DE-1 mod P-1 */
     336            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
     337            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
     338            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, P, 1));
     339            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
     340            0 :         if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
     341            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     342            0 :             goto cleanup;
     343              :         }
     344              : 
     345              :         /* Compute DE-1 mod Q-1 */
     346            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, D, E));
     347            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
     348            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&L, Q, 1));
     349            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, &L));
     350            0 :         if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
     351            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     352            0 :             goto cleanup;
     353              :         }
     354              :     }
     355              : 
     356            0 : cleanup:
     357              : 
     358            0 :     mbedtls_mpi_free(&K);
     359            0 :     mbedtls_mpi_free(&L);
     360              : 
     361              :     /* Wrap MPI error codes by RSA check failure error code */
     362            0 :     if (ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) {
     363            0 :         ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     364              :     }
     365              : 
     366            0 :     return ret;
     367              : }
     368              : 
     369              : /*
     370              :  * Check that RSA CRT parameters are in accordance with core parameters.
     371              :  */
     372            0 : int mbedtls_rsa_validate_crt(const mbedtls_mpi *P,  const mbedtls_mpi *Q,
     373              :                              const mbedtls_mpi *D,  const mbedtls_mpi *DP,
     374              :                              const mbedtls_mpi *DQ, const mbedtls_mpi *QP)
     375              : {
     376            0 :     int ret = 0;
     377              : 
     378              :     mbedtls_mpi K, L;
     379            0 :     mbedtls_mpi_init(&K);
     380            0 :     mbedtls_mpi_init(&L);
     381              : 
     382              :     /* Check that DP - D == 0 mod P - 1 */
     383            0 :     if (DP != NULL) {
     384            0 :         if (P == NULL) {
     385            0 :             ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     386            0 :             goto cleanup;
     387              :         }
     388              : 
     389            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, P, 1));
     390            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DP, D));
     391            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
     392              : 
     393            0 :         if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
     394            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     395            0 :             goto cleanup;
     396              :         }
     397              :     }
     398              : 
     399              :     /* Check that DQ - D == 0 mod Q - 1 */
     400            0 :     if (DQ != NULL) {
     401            0 :         if (Q == NULL) {
     402            0 :             ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     403            0 :             goto cleanup;
     404              :         }
     405              : 
     406            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, Q, 1));
     407            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&L, DQ, D));
     408            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&L, &L, &K));
     409              : 
     410            0 :         if (mbedtls_mpi_cmp_int(&L, 0) != 0) {
     411            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     412            0 :             goto cleanup;
     413              :         }
     414              :     }
     415              : 
     416              :     /* Check that QP * Q - 1 == 0 mod P */
     417            0 :     if (QP != NULL) {
     418            0 :         if (P == NULL || Q == NULL) {
     419            0 :             ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
     420            0 :             goto cleanup;
     421              :         }
     422              : 
     423            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&K, QP, Q));
     424            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&K, &K, 1));
     425            0 :         MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&K, &K, P));
     426            0 :         if (mbedtls_mpi_cmp_int(&K, 0) != 0) {
     427            0 :             ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     428            0 :             goto cleanup;
     429              :         }
     430              :     }
     431              : 
     432            0 : cleanup:
     433              : 
     434              :     /* Wrap MPI error codes by RSA check failure error code */
     435            0 :     if (ret != 0 &&
     436            0 :         ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED &&
     437              :         ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA) {
     438            0 :         ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED;
     439              :     }
     440              : 
     441            0 :     mbedtls_mpi_free(&K);
     442            0 :     mbedtls_mpi_free(&L);
     443              : 
     444            0 :     return ret;
     445              : }
     446              : 
     447              : #endif /* MBEDTLS_RSA_C */
        

Generated by: LCOV version 2.0-1