Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/nettle/int/rsa-keygen-fips186.c
Line
Count
Source (jump to first uncovered line)
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.  If not, see <https://www.gnu.org/licenses/>.
22
 */
23
24
#if HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
28
#include <assert.h>
29
#include <stdlib.h>
30
#include <stdio.h>
31
#include <string.h>
32
33
#include <nettle/rsa.h>
34
#include "dsa-fips.h"
35
#include "rsa-fips.h"
36
37
#include <nettle/bignum.h>
38
39
static int rsa_provable_prime(mpz_t p, unsigned *prime_seed_length,
40
            void *prime_seed, unsigned bits,
41
            unsigned seed_length, const void *seed, mpz_t e,
42
            void *progress_ctx,
43
            nettle_progress_func *progress)
44
0
{
45
0
  mpz_t x, t, s, r1, r2, p0, sq;
46
0
  int ret;
47
0
  unsigned pcounter = 0;
48
0
  unsigned iterations;
49
0
  unsigned storage_length = 0, i;
50
0
  uint8_t *storage = NULL;
51
0
  uint8_t pseed[MAX_PVP_SEED_SIZE + 1];
52
0
  unsigned pseed_length = sizeof(pseed), tseed_length;
53
0
  unsigned max = bits * 5;
54
55
0
  mpz_init(p0);
56
0
  mpz_init(sq);
57
0
  mpz_init(x);
58
0
  mpz_init(t);
59
0
  mpz_init(s);
60
0
  mpz_init(r1);
61
0
  mpz_init(r2);
62
63
  /* p1 = p2 = 1 */
64
65
0
  ret = st_provable_prime(p0, &pseed_length, pseed, NULL,
66
0
        1 + div_ceil(bits, 2), seed_length, seed,
67
0
        progress_ctx, progress);
68
0
  if (ret == 0) {
69
0
    goto cleanup;
70
0
  }
71
72
0
  iterations = div_ceil(bits, DIGEST_SIZE * 8);
73
0
  mpz_set_ui(x, 0);
74
75
0
  if (iterations > 0) {
76
0
    storage_length = iterations * DIGEST_SIZE;
77
0
    storage = malloc(storage_length);
78
0
    if (storage == NULL) {
79
0
      goto fail;
80
0
    }
81
82
0
    nettle_mpz_set_str_256_u(s, pseed_length, pseed);
83
0
    for (i = 0; i < iterations; i++) {
84
0
      tseed_length =
85
0
        mpz_seed_sizeinbase_256_u(s, pseed_length);
86
0
      if (tseed_length > sizeof(pseed))
87
0
        goto fail;
88
0
      nettle_mpz_get_str_256(tseed_length, pseed, s);
89
90
0
      hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
91
0
           tseed_length, pseed);
92
0
      mpz_add_ui(s, s, 1);
93
0
    }
94
95
0
    nettle_mpz_set_str_256_u(x, storage_length, storage);
96
0
  }
97
98
  /* x = sqrt(2)*2^(bits-1) + (x mod 2^(bits) - sqrt(2)*2(bits-1)) */
99
100
  /* sq = sqrt(2)*2^(bits-1) */
101
0
  mpz_set_ui(r1, 1);
102
0
  mpz_mul_2exp(r1, r1, 2 * bits - 1);
103
0
  mpz_sqrt(sq, r1);
104
105
  /* r2 = 2^bits - sq */
106
0
  mpz_set_ui(r2, 1);
107
0
  mpz_mul_2exp(r2, r2, bits);
108
0
  mpz_sub(r2, r2, sq);
109
110
  /* x =  sqrt(2)*2^(bits-1) + (x mod (2^L - sqrt(2)*2^(bits-1)) */
111
0
  mpz_mod(x, x, r2);
112
0
  mpz_add(x, x, sq);
113
114
  /* y = p2 = p1 = 1 */
115
116
  /* r1 = (2 y p0 p1) */
117
0
  mpz_mul_2exp(r1, p0, 1);
118
119
  /* r2 = 2 p0 p1 p2 (p2=y=1) */
120
0
  mpz_set(r2, r1);
121
122
  /* r1 = (2 y p0 p1) + x */
123
0
  mpz_add(r1, r1, x);
124
125
  /* t = ((2 y p0 p1) + x) / (2 p0 p1 p2) */
126
0
  mpz_cdiv_q(t, r1, r2);
127
128
0
retry:
129
  /* p = t p2 - y = t - 1 */
130
0
  mpz_sub_ui(p, t, 1);
131
132
  /* p = 2(tp2-y)p0p1 */
133
0
  mpz_mul(p, p, p0);
134
0
  mpz_mul_2exp(p, p, 1);
135
136
  /* p = 2(tp2-y)p0p1 + 1 */
137
0
  mpz_add_ui(p, p, 1);
138
139
0
  mpz_set_ui(r2, 1);
140
0
  mpz_mul_2exp(r2, r2, bits);
141
142
0
  if (mpz_cmp(p, r2) > 0) {
143
    /* t = (2 y p0 p1) + sqrt(2)*2^(bits-1) / (2p0p1p2) */
144
0
    mpz_set(r1, p0);
145
    /* r1 = (2 y p0 p1) */
146
0
    mpz_mul_2exp(r1, r1, 1);
147
148
    /* sq =  sqrt(2)*2^(bits-1) */
149
150
    /* r1 = (2 y p0 p1) + sq */
151
0
    mpz_add(r1, r1, sq);
152
153
    /* r2 = 2 p0 p1 p2 */
154
0
    mpz_mul_2exp(r2, p0, 1);
155
156
    /* t = ((2 y p0 p1) + sq) / (2 p0 p1 p2) */
157
0
    mpz_cdiv_q(t, r1, r2);
158
0
  }
159
160
0
  pcounter++;
161
162
  /* r2 = p - 1 */
163
0
  mpz_sub_ui(r2, p, 1);
164
165
  /* r1 = GCD(p1, e) */
166
0
  mpz_gcd(r1, e, r2);
167
168
0
  if (mpz_cmp_ui(r1, 1) == 0) {
169
0
    mpz_set_ui(x, 0); /* a = 0 */
170
0
    if (iterations > 0) {
171
0
      for (i = 0; i < iterations; i++) {
172
0
        tseed_length = mpz_seed_sizeinbase_256_u(
173
0
          s, pseed_length);
174
0
        if (tseed_length > sizeof(pseed))
175
0
          goto fail;
176
0
        nettle_mpz_get_str_256(tseed_length, pseed, s);
177
178
0
        hash(&storage[(iterations - i - 1) *
179
0
                DIGEST_SIZE],
180
0
             tseed_length, pseed);
181
0
        mpz_add_ui(s, s, 1);
182
0
      }
183
184
0
      nettle_mpz_set_str_256_u(x, storage_length, storage);
185
0
    }
186
187
    /* a = 2 + a mod p-3 */
188
0
    mpz_sub_ui(r1, p,
189
0
         3); /* p is too large to worry about negatives */
190
0
    mpz_mod(x, x, r1);
191
0
    mpz_add_ui(x, x, 2);
192
193
    /* z = a^(2(tp2-y)p1) mod p */
194
195
    /* r1 = (tp2-y) */
196
0
    mpz_sub_ui(r1, t, 1);
197
    /* r1 = 2(tp2-y)p1 */
198
0
    mpz_mul_2exp(r1, r1, 1);
199
200
    /* z = r2 = a^r1 mod p */
201
0
    mpz_powm(r2, x, r1, p);
202
203
0
    mpz_sub_ui(r1, r2, 1);
204
0
    mpz_gcd(x, r1, p);
205
206
0
    if (mpz_cmp_ui(x, 1) == 0) {
207
0
      mpz_powm(r1, r2, p0, p);
208
0
      if (mpz_cmp_ui(r1, 1) == 0) {
209
0
        if (prime_seed_length != NULL) {
210
0
          tseed_length =
211
0
            mpz_seed_sizeinbase_256_u(
212
0
              s, pseed_length);
213
0
          if (tseed_length > sizeof(pseed))
214
0
            goto fail;
215
216
0
          nettle_mpz_get_str_256(tseed_length,
217
0
                     pseed, s);
218
219
0
          if (*prime_seed_length < tseed_length) {
220
0
            *prime_seed_length =
221
0
              tseed_length;
222
0
            goto fail;
223
0
          }
224
0
          *prime_seed_length = tseed_length;
225
0
          if (prime_seed != NULL)
226
0
            memcpy(prime_seed, pseed,
227
0
                   tseed_length);
228
0
        }
229
0
        ret = 1;
230
0
        goto cleanup;
231
0
      }
232
0
    }
233
0
  }
234
235
0
  if (pcounter >= max) {
236
0
    goto fail;
237
0
  }
238
239
0
  mpz_add_ui(t, t, 1);
240
0
  goto retry;
241
242
0
fail:
243
0
  ret = 0;
244
0
cleanup:
245
0
  free(storage);
246
0
  mpz_clear(p0);
247
0
  mpz_clear(sq);
248
0
  mpz_clear(r1);
249
0
  mpz_clear(r2);
250
0
  mpz_clear(x);
251
0
  mpz_clear(t);
252
0
  mpz_clear(s);
253
254
0
  return ret;
255
0
}
256
257
/* Return the pre-defined seed length for modulus size, or 0 when the
258
 * modulus size is unsupported.
259
 */
260
static inline unsigned seed_length_for_modulus_size(unsigned modulus_size)
261
0
{
262
0
  switch (modulus_size) {
263
0
  case 2048: /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
264
0
    return 14 * 2;
265
0
  case 3072: /* SP 800-56B rev 2 Appendix D and FIPS 140-2 IG 7.5 */
266
0
    return 16 * 2;
267
0
  case 4096: /* SP 800-56B rev 2 Appendix D */
268
0
    return 19 * 2;
269
0
  case 6144: /* SP 800-56B rev 2 Appendix D */
270
0
    return 22 * 2;
271
0
  case 7680: /* FIPS 140-2 IG 7.5 */
272
0
    return 24 * 2;
273
0
  case 8192: /* SP 800-56B rev 2 Appendix D */
274
0
    return 25 * 2;
275
0
  case 15360: /* FIPS 140-2 IG 7.5 */
276
0
    return 32 * 2;
277
0
  default:
278
0
    return 0;
279
0
  }
280
0
}
281
282
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
283
 * 
284
 * The hash function used is SHA384.
285
 * The exponent e used is the value in pub->e.
286
 */
287
int _rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
288
            struct rsa_private_key *key,
289
            unsigned seed_length, uint8_t *seed,
290
            void *progress_ctx,
291
            nettle_progress_func *progress,
292
            /* Desired size of modulo, in bits */
293
            unsigned n_size)
294
0
{
295
0
  mpz_t t, r, p1, q1, lcm;
296
0
  int ret;
297
0
  struct dss_params_validation_seeds cert;
298
0
  unsigned l = n_size / 2;
299
0
  unsigned s = seed_length_for_modulus_size(n_size);
300
301
0
  if (!s) {
302
0
    FIPS_RULE(false, 0, "unsupported modulus size\n");
303
0
  }
304
305
0
  FIPS_RULE(seed_length != s, 0, "seed length other than %u bytes\n", s);
306
307
0
  if (!mpz_tstbit(pub->e, 0)) {
308
0
    _gnutls_debug_log("Unacceptable e (it is even)\n");
309
0
    return 0;
310
0
  }
311
312
0
  if (mpz_cmp_ui(pub->e, 65536) <= 0) {
313
0
    _gnutls_debug_log("Unacceptable e\n");
314
0
    return 0;
315
0
  }
316
317
0
  mpz_init(p1);
318
0
  mpz_init(q1);
319
0
  mpz_init(lcm);
320
0
  mpz_init(t);
321
0
  mpz_init(r);
322
323
0
  mpz_set_ui(t, 1);
324
0
  mpz_mul_2exp(t, t, 256);
325
326
0
  if (mpz_cmp(pub->e, t) >= 0) {
327
0
    ret = 0;
328
0
    goto cleanup;
329
0
  }
330
331
0
  cert.pseed_length = sizeof(cert.pseed);
332
0
  ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed, l,
333
0
         seed_length, seed, pub->e, progress_ctx,
334
0
         progress);
335
0
  if (ret == 0) {
336
0
    goto cleanup;
337
0
  }
338
339
0
  mpz_set_ui(r, 1);
340
0
  mpz_mul_2exp(r, r, (l)-100);
341
342
0
  do {
343
0
    cert.qseed_length = sizeof(cert.qseed);
344
0
    ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed,
345
0
           l, cert.pseed_length, cert.pseed,
346
0
           pub->e, progress_ctx, progress);
347
0
    if (ret == 0) {
348
0
      goto cleanup;
349
0
    }
350
351
0
    cert.pseed_length = cert.qseed_length;
352
0
    memcpy(cert.pseed, cert.qseed, cert.qseed_length);
353
354
0
    if (mpz_cmp(key->p, key->q) > 0)
355
0
      mpz_sub(t, key->p, key->q);
356
0
    else
357
0
      mpz_sub(t, key->q, key->p);
358
0
  } while (mpz_cmp(t, r) <= 0);
359
360
0
  memset(&cert, 0, sizeof(cert));
361
362
0
  mpz_mul(pub->n, key->p, key->q);
363
364
0
  if (mpz_sizeinbase(pub->n, 2) != n_size) {
365
0
    ret = 0;
366
0
    goto cleanup;
367
0
  }
368
369
  /* c = q^{-1} (mod p) */
370
0
  if (mpz_invert(key->c, key->q, key->p) == 0) {
371
0
    ret = 0;
372
0
    goto cleanup;
373
0
  }
374
375
0
  mpz_sub_ui(p1, key->p, 1);
376
0
  mpz_sub_ui(q1, key->q, 1);
377
378
0
  mpz_lcm(lcm, p1, q1);
379
380
0
  if (mpz_invert(key->d, pub->e, lcm) == 0) {
381
0
    ret = 0;
382
0
    goto cleanup;
383
0
  }
384
385
  /* check whether d > 2^(nlen/2) -- FIPS186-4 5.3.1 */
386
0
  if (mpz_sizeinbase(key->d, 2) < n_size / 2) {
387
0
    ret = 0;
388
0
    goto cleanup;
389
0
  }
390
391
  /* Done! Almost, we must compute the auxiliary private values. */
392
  /* a = d % (p-1) */
393
0
  mpz_fdiv_r(key->a, key->d, p1);
394
395
  /* b = d % (q-1) */
396
0
  mpz_fdiv_r(key->b, key->d, q1);
397
398
  /* c was computed earlier */
399
400
0
  pub->size = key->size = (n_size + 7) / 8;
401
0
  if (pub->size < RSA_MINIMUM_N_OCTETS) {
402
0
    ret = 0;
403
0
    goto cleanup;
404
0
  }
405
406
0
  ret = 1;
407
0
cleanup:
408
0
  mpz_clear(p1);
409
0
  mpz_clear(q1);
410
0
  mpz_clear(lcm);
411
0
  mpz_clear(t);
412
0
  mpz_clear(r);
413
0
  return ret;
414
0
}
415
416
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
417
 * 
418
 * The hash function used is SHA384.
419
 * The exponent e used is the value in pub->e.
420
 */
421
int rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
422
           struct rsa_private_key *key,
423
           void *random_ctx, nettle_random_func *random,
424
           void *progress_ctx,
425
           nettle_progress_func *progress,
426
           unsigned *rseed_size, void *rseed,
427
           /* Desired size of modulo, in bits */
428
           unsigned n_size)
429
0
{
430
0
  uint8_t seed[128];
431
0
  unsigned seed_length;
432
0
  int ret;
433
434
0
  seed_length = seed_length_for_modulus_size(n_size);
435
0
  FIPS_RULE(!seed_length, 0, "unsupported modulus size\n");
436
437
0
  assert(seed_length <= sizeof(seed));
438
439
0
  random(random_ctx, seed_length, seed);
440
441
0
  if (rseed && rseed_size) {
442
0
    if (*rseed_size < seed_length) {
443
0
      return 0;
444
0
    }
445
0
    memcpy(rseed, seed, seed_length);
446
0
    *rseed_size = seed_length;
447
0
  }
448
449
0
  ret = _rsa_generate_fips186_4_keypair(pub, key, seed_length, seed,
450
0
                progress_ctx, progress, n_size);
451
0
  gnutls_memset(seed, 0, seed_length);
452
0
  return ret;
453
0
}