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

Generated by: LCOV version 2.0-1