LCOV - code coverage report
Current view: top level - builds/gnutls/coverage/gnutls-git/lib/nettle/int - rsa-keygen-fips186.c (source / functions) Hit Total Coverage
Test: GnuTLS-3.6.14 Code Coverage Lines: 154 200 77.0 %
Date: 2020-10-30 04:50:48 Functions: 2 3 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Generation of RSA keypairs.
       3             :  */
       4             : 
       5             : /* nettle, low-level cryptographics library
       6             :  *
       7             :  * Copyright (C) 2002 Niels Möller
       8             :  * Copyright (C) 2014 Red Hat
       9             :  *  
      10             :  * The nettle library is free software; you can redistribute it and/or modify
      11             :  * it under the terms of the GNU Lesser General Public License as published by
      12             :  * the Free Software Foundation; either version 2.1 of the License, or (at your
      13             :  * option) any later version.
      14             :  * 
      15             :  * The nettle library is distributed in the hope that it will be useful, but
      16             :  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      17             :  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
      18             :  * License for more details.
      19             :  * 
      20             :  * You should have received a copy of the GNU Lesser General Public License
      21             :  * along with the nettle library; see the file COPYING.LIB.  If not, write to
      22             :  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
      23             :  * MA 02111-1301, USA.
      24             :  */
      25             : 
      26             : #if HAVE_CONFIG_H
      27             : #include "config.h"
      28             : #endif
      29             : 
      30             : #include <stdlib.h>
      31             : #include <stdio.h>
      32             : #include <string.h>
      33             : 
      34             : #include <nettle/rsa.h>
      35             : #include <dsa-fips.h>
      36             : #include <rsa-fips.h>
      37             : 
      38             : #include <nettle/bignum.h>
      39             : 
      40             : static int
      41          14 : rsa_provable_prime (mpz_t p,
      42             :                           unsigned *prime_seed_length, void *prime_seed,
      43             :                           unsigned bits,
      44             :                           unsigned seed_length, const void *seed,
      45             :                           mpz_t e,
      46             :                           void *progress_ctx, nettle_progress_func * progress)
      47             : {
      48          14 : mpz_t x, t, s, r1, r2, p0, sq;
      49          14 : int ret;
      50          14 : unsigned pcounter = 0;
      51          14 : unsigned iterations;
      52          14 : unsigned storage_length = 0, i;
      53          14 : uint8_t *storage = NULL;
      54          14 : uint8_t pseed[MAX_PVP_SEED_SIZE+1];
      55          14 : unsigned pseed_length = sizeof(pseed), tseed_length;
      56          14 : unsigned max = bits*5;
      57             : 
      58          14 :         mpz_init(p0);
      59          14 :         mpz_init(sq);
      60          14 :         mpz_init(x);
      61          14 :         mpz_init(t);
      62          14 :         mpz_init(s);
      63          14 :         mpz_init(r1);
      64          14 :         mpz_init(r2);
      65             : 
      66             :         /* p1 = p2 = 1 */
      67             : 
      68          28 :         ret = st_provable_prime(p0, &pseed_length, pseed,
      69          14 :                                 NULL, 1+div_ceil(bits,2), seed_length,
      70             :                                 seed, progress_ctx, progress);
      71          14 :         if (ret == 0) {
      72           0 :                 goto cleanup;
      73             :         }
      74             : 
      75          14 :         iterations = div_ceil(bits, DIGEST_SIZE*8);
      76          14 :         mpz_set_ui(x, 0);
      77             : 
      78          14 :         if (iterations > 0) {
      79          14 :                 storage_length = iterations * DIGEST_SIZE;
      80          14 :                 storage = malloc(storage_length);
      81          14 :                 if (storage == NULL) {
      82           0 :                         goto fail;
      83             :                 }
      84             : 
      85          14 :                 nettle_mpz_set_str_256_u(s, pseed_length, pseed);
      86          74 :                 for (i = 0; i < iterations; i++) {
      87          46 :                         tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length);
      88          46 :                         if (tseed_length > sizeof(pseed))
      89           0 :                                 goto fail;
      90          46 :                         nettle_mpz_get_str_256(tseed_length, pseed, s);
      91             : 
      92          46 :                         hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
      93             :                              tseed_length, pseed);
      94          46 :                         mpz_add_ui(s, s, 1);
      95             :                 }
      96             : 
      97          14 :                 nettle_mpz_set_str_256_u(x, storage_length, storage);
      98             :         }
      99             : 
     100             :         /* x = sqrt(2)*2^(bits-1) + (x mod 2^(bits) - sqrt(2)*2(bits-1)) */
     101             : 
     102             :         /* sq = sqrt(2)*2^(bits-1) */
     103          14 :         mpz_set_ui(r1, 1);
     104          14 :         mpz_mul_2exp(r1, r1, 2*bits-1);
     105          14 :         mpz_sqrt(sq, r1);
     106             : 
     107             :         /* r2 = 2^bits - sq */
     108          14 :         mpz_set_ui(r2, 1);
     109          14 :         mpz_mul_2exp(r2, r2, bits);
     110          14 :         mpz_sub(r2, r2, sq);
     111             : 
     112             :         /* x =  sqrt(2)*2^(bits-1) + (x mod (2^L - sqrt(2)*2^(bits-1)) */
     113          14 :         mpz_mod(x, x, r2);
     114          14 :         mpz_add(x, x, sq);
     115             : 
     116             :         /* y = p2 = p1 = 1 */
     117             : 
     118             :         /* r1 = (2 y p0 p1) */
     119          14 :         mpz_mul_2exp(r1, p0, 1);
     120             : 
     121             :         /* r2 = 2 p0 p1 p2 (p2=y=1) */
     122          14 :         mpz_set(r2, r1);
     123             : 
     124             :         /* r1 = (2 y p0 p1) + x */
     125          14 :         mpz_add(r1, r1, x);
     126             : 
     127             :         /* t = ((2 y p0 p1) + x) / (2 p0 p1 p2) */
     128          14 :         mpz_cdiv_q(t, r1, r2);
     129             : 
     130        5265 :  retry:
     131             :         /* p = t p2 - y = t - 1 */
     132        5265 :         mpz_sub_ui(p, t, 1);
     133             : 
     134             :         /* p = 2(tp2-y)p0p1 */
     135        5265 :         mpz_mul(p, p, p0);
     136        5265 :         mpz_mul_2exp(p, p, 1);
     137             : 
     138             :         /* p = 2(tp2-y)p0p1 + 1*/
     139        5265 :         mpz_add_ui(p, p, 1);
     140             : 
     141        5265 :         mpz_set_ui(r2, 1);
     142        5265 :         mpz_mul_2exp(r2, r2, bits);
     143             : 
     144        5265 :         if (mpz_cmp(p, r2) > 0) {
     145             :                 /* t = (2 y p0 p1) + sqrt(2)*2^(bits-1) / (2p0p1p2) */
     146           0 :                 mpz_set(r1, p0);
     147             :                 /* r1 = (2 y p0 p1) */
     148           0 :                 mpz_mul_2exp(r1, r1, 1);
     149             : 
     150             :                 /* sq =  sqrt(2)*2^(bits-1) */
     151             : 
     152             :                 /* r1 = (2 y p0 p1) + sq */
     153           0 :                 mpz_add(r1, r1, sq);
     154             : 
     155             :                 /* r2 = 2 p0 p1 p2 */
     156           0 :                 mpz_mul_2exp(r2, p0, 1);
     157             : 
     158             :                 /* t = ((2 y p0 p1) + sq) / (2 p0 p1 p2) */
     159           0 :                 mpz_cdiv_q(t, r1, r2);
     160             :         }
     161             : 
     162        5265 :         pcounter++;
     163             : 
     164             :         /* r2 = p - 1 */
     165        5265 :         mpz_sub_ui(r2, p, 1);
     166             : 
     167             :         /* r1 = GCD(p1, e) */
     168        5265 :         mpz_gcd(r1, e, r2);
     169             : 
     170        5265 :         if (mpz_cmp_ui(r1, 1) == 0) {
     171        5265 :                 mpz_set_ui(x, 0); /* a = 0 */
     172        5265 :                 if (iterations > 0) {
     173       22564 :                         for (i = 0; i < iterations; i++) {
     174       17299 :                                 tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length);
     175       17299 :                                 if (tseed_length > sizeof(pseed))
     176           0 :                                         goto fail;
     177       17299 :                                 nettle_mpz_get_str_256(tseed_length, pseed, s);
     178             : 
     179       17299 :                                 hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
     180             :                                      tseed_length, pseed);
     181       17299 :                                 mpz_add_ui(s, s, 1);
     182             :                         }
     183             : 
     184        5265 :                         nettle_mpz_set_str_256_u(x, storage_length, storage);
     185             :                 }
     186             : 
     187             :                 /* a = 2 + a mod p-3 */
     188        5265 :                 mpz_sub_ui(r1, p, 3);   /* p is too large to worry about negatives */
     189        5265 :                 mpz_mod(x, x, r1);
     190        5265 :                 mpz_add_ui(x, x, 2);
     191             : 
     192             :                 /* z = a^(2(tp2-y)p1) mod p */
     193             : 
     194             :                 /* r1 = (tp2-y) */
     195        5265 :                 mpz_sub_ui(r1, t, 1);
     196             :                 /* r1 = 2(tp2-y)p1 */
     197        5265 :                 mpz_mul_2exp(r1, r1, 1);
     198             : 
     199             :                 /* z = r2 = a^r1 mod p */
     200        5265 :                 mpz_powm(r2, x, r1, p);
     201             : 
     202        5265 :                 mpz_sub_ui(r1, r2, 1);
     203        5265 :                 mpz_gcd(x, r1, p);
     204             : 
     205        5265 :                 if (mpz_cmp_ui(x, 1) == 0) {
     206        2832 :                         mpz_powm(r1, r2, p0, p);
     207        2832 :                         if (mpz_cmp_ui(r1, 1) == 0) {
     208          14 :                                 if (prime_seed_length != NULL) {
     209          14 :                                         tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length);
     210          14 :                                         if (tseed_length > sizeof(pseed))
     211           0 :                                                 goto fail;
     212             : 
     213          14 :                                         nettle_mpz_get_str_256(tseed_length, pseed, s);
     214             : 
     215          14 :                                         if (*prime_seed_length < tseed_length) {
     216           0 :                                                 *prime_seed_length = tseed_length;
     217           0 :                                                 goto fail;
     218             :                                         }
     219          14 :                                         *prime_seed_length = tseed_length;
     220          14 :                                         if (prime_seed != NULL)
     221          14 :                                                 memcpy(prime_seed, pseed, tseed_length);
     222             :                                 }
     223          14 :                                 ret = 1;
     224          14 :                                 goto cleanup;
     225             :                         }
     226             :                 }
     227             :         }
     228             : 
     229        5251 :         if (pcounter >= max) {
     230           0 :                 goto fail;
     231             :         }
     232             : 
     233        5251 :         mpz_add_ui(t, t, 1);
     234        5251 :         goto retry;
     235             : 
     236             : fail:
     237             :         ret = 0;
     238          14 : cleanup:
     239          14 :         free(storage);
     240          14 :         mpz_clear(p0);
     241          14 :         mpz_clear(sq);
     242          14 :         mpz_clear(r1);
     243          14 :         mpz_clear(r2);
     244          14 :         mpz_clear(x);
     245          14 :         mpz_clear(t);
     246          14 :         mpz_clear(s);
     247             : 
     248          14 :         return ret;
     249             : }
     250             : 
     251             : /* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
     252             :  * 
     253             :  * The hash function used is SHA384.
     254             :  * The exponent e used is the value in pub->e.
     255             :  */
     256             : int
     257           7 : _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
     258             :                                 struct rsa_private_key *key,
     259             :                                 unsigned seed_length, uint8_t * seed,
     260             :                                 void *progress_ctx,
     261             :                                 nettle_progress_func * progress,
     262             :                                 /* Desired size of modulo, in bits */
     263             :                                 unsigned n_size)
     264             : {
     265           7 :         mpz_t t, r, p1, q1, lcm;
     266           7 :         int ret;
     267           7 :         struct dss_params_validation_seeds cert;
     268           7 :         unsigned l = n_size / 2;
     269             : 
     270           7 :         FIPS_RULE(n_size == 2048 && seed_length != 14 * 2, 0, "seed length other than 28 bytes\n");
     271           7 :         FIPS_RULE(n_size == 3072 && seed_length != 16 * 2, 0, "seed length other than 32 bytes\n");
     272           7 :         FIPS_RULE(n_size != 2048 && n_size != 3072, 0, "unsupported size for modulus\n");
     273             : 
     274           7 :         if (!mpz_tstbit(pub->e, 0)) {
     275           0 :                 _gnutls_debug_log("Unacceptable e (it is even)\n");
     276           0 :                 return 0;
     277             :         }
     278             : 
     279           7 :         if (mpz_cmp_ui(pub->e, 65536) <= 0) {
     280           0 :                 _gnutls_debug_log("Unacceptable e\n");
     281           0 :                 return 0;
     282             :         }
     283             : 
     284           7 :         mpz_init(p1);
     285           7 :         mpz_init(q1);
     286           7 :         mpz_init(lcm);
     287           7 :         mpz_init(t);
     288           7 :         mpz_init(r);
     289             : 
     290           7 :         mpz_set_ui(t, 1);
     291           7 :         mpz_mul_2exp(t, t, 256);
     292             : 
     293           7 :         if (mpz_cmp(pub->e, t) >= 0) {
     294           0 :                 ret = 0;
     295           0 :                 goto cleanup;
     296             :         }
     297             : 
     298           7 :         cert.pseed_length = sizeof(cert.pseed);
     299           7 :         ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed,
     300             :                                 l, seed_length,
     301             :                                 seed, pub->e, progress_ctx, progress);
     302           7 :         if (ret == 0) {
     303           0 :                 goto cleanup;
     304             :         }
     305             : 
     306           7 :         mpz_set_ui(r, 1);
     307           7 :         mpz_mul_2exp(r, r, (l) - 100);
     308             : 
     309           7 :         do {
     310           7 :                 cert.qseed_length = sizeof(cert.qseed);
     311           7 :                 ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed,
     312             :                                         l, cert.pseed_length, cert.pseed,
     313             :                                         pub->e,
     314             :                                         progress_ctx, progress);
     315           7 :                 if (ret == 0) {
     316           0 :                         goto cleanup;
     317             :                 }
     318             : 
     319             : 
     320           7 :                 cert.pseed_length = cert.qseed_length;
     321           7 :                 memcpy(cert.pseed, cert.qseed, cert.qseed_length);
     322             : 
     323             : 
     324           7 :                 if (mpz_cmp(key->p, key->q) > 0)
     325           2 :                         mpz_sub(t, key->p, key->q);
     326             :                 else
     327           5 :                         mpz_sub(t, key->q, key->p);
     328           7 :         } while (mpz_cmp(t, r) <= 0);
     329             : 
     330           7 :         memset(&cert, 0, sizeof(cert));
     331             : 
     332           7 :         mpz_mul(pub->n, key->p, key->q);
     333             : 
     334           7 :         if (mpz_sizeinbase(pub->n, 2) != n_size) {
     335           0 :                 ret = 0;
     336           0 :                 goto cleanup;
     337             :         }
     338             : 
     339             :         /* c = q^{-1} (mod p) */
     340           7 :         if (mpz_invert(key->c, key->q, key->p) == 0) {
     341           0 :                 ret = 0;
     342           0 :                 goto cleanup;
     343             :         }
     344             : 
     345           7 :         mpz_sub_ui(p1, key->p, 1);
     346           7 :         mpz_sub_ui(q1, key->q, 1);
     347             : 
     348           7 :         mpz_lcm(lcm, p1, q1);
     349             : 
     350           7 :         if (mpz_invert(key->d, pub->e, lcm) == 0) {
     351           0 :                 ret = 0;
     352           0 :                 goto cleanup;
     353             :         }
     354             : 
     355             :         /* check whether d > 2^(nlen/2) -- FIPS186-4 5.3.1 */
     356           7 :         if (mpz_sizeinbase(key->d, 2) < n_size/2) {
     357           0 :                 ret = 0;
     358           0 :                 goto cleanup;
     359             :         }
     360             : 
     361             :         /* Done! Almost, we must compute the auxiliary private values. */
     362             :         /* a = d % (p-1) */
     363           7 :         mpz_fdiv_r(key->a, key->d, p1);
     364             : 
     365             :         /* b = d % (q-1) */
     366           7 :         mpz_fdiv_r(key->b, key->d, q1);
     367             : 
     368             :         /* c was computed earlier */
     369             : 
     370           7 :         pub->size = key->size = (n_size + 7) / 8;
     371           7 :         if (pub->size < RSA_MINIMUM_N_OCTETS) {
     372           0 :                 ret = 0;
     373           0 :                 goto cleanup;
     374             :         }
     375             : 
     376             :         ret = 1;
     377           7 :  cleanup:
     378           7 :         mpz_clear(p1);
     379           7 :         mpz_clear(q1);
     380           7 :         mpz_clear(lcm);
     381           7 :         mpz_clear(t);
     382           7 :         mpz_clear(r);
     383           7 :         return ret;
     384             : }
     385             : 
     386             : /* Not entirely accurate but a good precision
     387             :  */
     388             : #define SEED_LENGTH(bits) (_gnutls_pk_bits_to_subgroup_bits(bits)/8)
     389             : 
     390             : /* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
     391             :  * 
     392             :  * The hash function used is SHA384.
     393             :  * The exponent e used is the value in pub->e.
     394             :  */
     395             : int
     396           0 : rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
     397             :                                struct rsa_private_key *key,
     398             :                                void *random_ctx, nettle_random_func * random,
     399             :                                void *progress_ctx,
     400             :                                nettle_progress_func * progress,
     401             :                                unsigned *rseed_size,
     402             :                                void *rseed,
     403             :                                /* Desired size of modulo, in bits */
     404             :                                unsigned n_size)
     405             : {
     406           0 :         uint8_t seed[128];
     407           0 :         unsigned seed_length;
     408           0 :         int ret;
     409             : 
     410           0 :         FIPS_RULE(n_size != 2048 && n_size != 3072, 0, "size of prime of other than 2048 or 3072\n");
     411             : 
     412           0 :         seed_length = SEED_LENGTH(n_size);
     413           0 :         if (seed_length > sizeof(seed))
     414             :                 return 0;
     415             : 
     416           0 :         random(random_ctx, seed_length, seed);
     417             : 
     418           0 :         if (rseed && rseed_size) {
     419           0 :                 if (*rseed_size < seed_length) {
     420             :                         return 0;
     421             :                 }
     422           0 :                 memcpy(rseed, seed, seed_length);
     423           0 :                 *rseed_size = seed_length;
     424             :         }
     425             : 
     426           0 :         ret = _rsa_generate_fips186_4_keypair(pub, key, seed_length, seed,
     427             :                                                progress_ctx, progress, n_size);
     428           0 :         gnutls_memset(seed, 0, seed_length);
     429           0 :         return ret;
     430             : }

Generated by: LCOV version 1.14