Coverage Report

Created: 2023-03-26 08:33

/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
40
rsa_provable_prime(mpz_t p,
41
       unsigned *prime_seed_length, void *prime_seed,
42
       unsigned bits,
43
       unsigned seed_length, const void *seed,
44
       mpz_t e, void *progress_ctx, nettle_progress_func * progress)
45
0
{
46
0
  mpz_t x, t, s, r1, r2, p0, sq;
47
0
  int ret;
48
0
  unsigned pcounter = 0;
49
0
  unsigned iterations;
50
0
  unsigned storage_length = 0, i;
51
0
  uint8_t *storage = NULL;
52
0
  uint8_t pseed[MAX_PVP_SEED_SIZE + 1];
53
0
  unsigned pseed_length = sizeof(pseed), tseed_length;
54
0
  unsigned max = bits * 5;
55
56
0
  mpz_init(p0);
57
0
  mpz_init(sq);
58
0
  mpz_init(x);
59
0
  mpz_init(t);
60
0
  mpz_init(s);
61
0
  mpz_init(r1);
62
0
  mpz_init(r2);
63
64
  /* p1 = p2 = 1 */
65
66
0
  ret = st_provable_prime(p0, &pseed_length, pseed,
67
0
        NULL, 1 + div_ceil(bits, 2), seed_length,
68
0
        seed, progress_ctx, progress);
69
0
  if (ret == 0) {
70
0
    goto cleanup;
71
0
  }
72
73
0
  iterations = div_ceil(bits, DIGEST_SIZE * 8);
74
0
  mpz_set_ui(x, 0);
75
76
0
  if (iterations > 0) {
77
0
    storage_length = iterations * DIGEST_SIZE;
78
0
    storage = malloc(storage_length);
79
0
    if (storage == NULL) {
80
0
      goto fail;
81
0
    }
82
83
0
    nettle_mpz_set_str_256_u(s, pseed_length, pseed);
84
0
    for (i = 0; i < iterations; i++) {
85
0
      tseed_length =
86
0
          mpz_seed_sizeinbase_256_u(s, pseed_length);
87
0
      if (tseed_length > sizeof(pseed))
88
0
        goto fail;
89
0
      nettle_mpz_get_str_256(tseed_length, pseed, s);
90
91
0
      hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
92
0
           tseed_length, pseed);
93
0
      mpz_add_ui(s, s, 1);
94
0
    }
95
96
0
    nettle_mpz_set_str_256_u(x, storage_length, storage);
97
0
  }
98
99
  /* x = sqrt(2)*2^(bits-1) + (x mod 2^(bits) - sqrt(2)*2(bits-1)) */
100
101
  /* sq = sqrt(2)*2^(bits-1) */
102
0
  mpz_set_ui(r1, 1);
103
0
  mpz_mul_2exp(r1, r1, 2 * bits - 1);
104
0
  mpz_sqrt(sq, r1);
105
106
  /* r2 = 2^bits - sq */
107
0
  mpz_set_ui(r2, 1);
108
0
  mpz_mul_2exp(r2, r2, bits);
109
0
  mpz_sub(r2, r2, sq);
110
111
  /* x =  sqrt(2)*2^(bits-1) + (x mod (2^L - sqrt(2)*2^(bits-1)) */
112
0
  mpz_mod(x, x, r2);
113
0
  mpz_add(x, x, sq);
114
115
  /* y = p2 = p1 = 1 */
116
117
  /* r1 = (2 y p0 p1) */
118
0
  mpz_mul_2exp(r1, p0, 1);
119
120
  /* r2 = 2 p0 p1 p2 (p2=y=1) */
121
0
  mpz_set(r2, r1);
122
123
  /* r1 = (2 y p0 p1) + x */
124
0
  mpz_add(r1, r1, x);
125
126
  /* t = ((2 y p0 p1) + x) / (2 p0 p1 p2) */
127
0
  mpz_cdiv_q(t, r1, r2);
128
129
0
 retry:
130
  /* p = t p2 - y = t - 1 */
131
0
  mpz_sub_ui(p, t, 1);
132
133
  /* p = 2(tp2-y)p0p1 */
134
0
  mpz_mul(p, p, p0);
135
0
  mpz_mul_2exp(p, p, 1);
136
137
  /* p = 2(tp2-y)p0p1 + 1 */
138
0
  mpz_add_ui(p, p, 1);
139
140
0
  mpz_set_ui(r2, 1);
141
0
  mpz_mul_2exp(r2, r2, bits);
142
143
0
  if (mpz_cmp(p, r2) > 0) {
144
    /* t = (2 y p0 p1) + sqrt(2)*2^(bits-1) / (2p0p1p2) */
145
0
    mpz_set(r1, p0);
146
    /* r1 = (2 y p0 p1) */
147
0
    mpz_mul_2exp(r1, r1, 1);
148
149
    /* sq =  sqrt(2)*2^(bits-1) */
150
151
    /* r1 = (2 y p0 p1) + sq */
152
0
    mpz_add(r1, r1, sq);
153
154
    /* r2 = 2 p0 p1 p2 */
155
0
    mpz_mul_2exp(r2, p0, 1);
156
157
    /* t = ((2 y p0 p1) + sq) / (2 p0 p1 p2) */
158
0
    mpz_cdiv_q(t, r1, r2);
159
0
  }
160
161
0
  pcounter++;
162
163
  /* r2 = p - 1 */
164
0
  mpz_sub_ui(r2, p, 1);
165
166
  /* r1 = GCD(p1, e) */
167
0
  mpz_gcd(r1, e, r2);
168
169
0
  if (mpz_cmp_ui(r1, 1) == 0) {
170
0
    mpz_set_ui(x, 0); /* a = 0 */
171
0
    if (iterations > 0) {
172
0
      for (i = 0; i < iterations; i++) {
173
0
        tseed_length =
174
0
            mpz_seed_sizeinbase_256_u(s, pseed_length);
175
0
        if (tseed_length > sizeof(pseed))
176
0
          goto fail;
177
0
        nettle_mpz_get_str_256(tseed_length, pseed, s);
178
179
0
        hash(&storage
180
0
             [(iterations - i - 1) * DIGEST_SIZE],
181
0
             tseed_length, pseed);
182
0
        mpz_add_ui(s, s, 1);
183
0
      }
184
185
0
      nettle_mpz_set_str_256_u(x, storage_length, storage);
186
0
    }
187
188
    /* a = 2 + a mod p-3 */
189
0
    mpz_sub_ui(r1, p, 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(s,
212
0
                      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
281
0
}
282
283
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
284
 * 
285
 * The hash function used is SHA384.
286
 * The exponent e used is the value in pub->e.
287
 */
288
int
289
_rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
290
        struct rsa_private_key *key,
291
        unsigned seed_length, uint8_t * seed,
292
        void *progress_ctx,
293
        nettle_progress_func * progress,
294
        /* Desired size of modulo, in bits */
295
        unsigned n_size)
296
0
{
297
0
  mpz_t t, r, p1, q1, lcm;
298
0
  int ret;
299
0
  struct dss_params_validation_seeds cert;
300
0
  unsigned l = n_size / 2;
301
0
  unsigned s = seed_length_for_modulus_size(n_size);
302
303
0
  if (!s) {
304
0
    FIPS_RULE(false, 0, "unsupported modulus size\n");
305
0
  }
306
307
0
  FIPS_RULE(seed_length != s, 0, "seed length other than %u bytes\n", s);
308
309
0
  if (!mpz_tstbit(pub->e, 0)) {
310
0
    _gnutls_debug_log("Unacceptable e (it is even)\n");
311
0
    return 0;
312
0
  }
313
314
0
  if (mpz_cmp_ui(pub->e, 65536) <= 0) {
315
0
    _gnutls_debug_log("Unacceptable e\n");
316
0
    return 0;
317
0
  }
318
319
0
  mpz_init(p1);
320
0
  mpz_init(q1);
321
0
  mpz_init(lcm);
322
0
  mpz_init(t);
323
0
  mpz_init(r);
324
325
0
  mpz_set_ui(t, 1);
326
0
  mpz_mul_2exp(t, t, 256);
327
328
0
  if (mpz_cmp(pub->e, t) >= 0) {
329
0
    ret = 0;
330
0
    goto cleanup;
331
0
  }
332
333
0
  cert.pseed_length = sizeof(cert.pseed);
334
0
  ret = rsa_provable_prime(key->p, &cert.pseed_length, cert.pseed,
335
0
         l, seed_length,
336
0
         seed, pub->e, progress_ctx, progress);
337
0
  if (ret == 0) {
338
0
    goto cleanup;
339
0
  }
340
341
0
  mpz_set_ui(r, 1);
342
0
  mpz_mul_2exp(r, r, (l) - 100);
343
344
0
  do {
345
0
    cert.qseed_length = sizeof(cert.qseed);
346
0
    ret = rsa_provable_prime(key->q, &cert.qseed_length, cert.qseed,
347
0
           l, cert.pseed_length, cert.pseed,
348
0
           pub->e, progress_ctx, progress);
349
0
    if (ret == 0) {
350
0
      goto cleanup;
351
0
    }
352
353
0
    cert.pseed_length = cert.qseed_length;
354
0
    memcpy(cert.pseed, cert.qseed, cert.qseed_length);
355
356
0
    if (mpz_cmp(key->p, key->q) > 0)
357
0
      mpz_sub(t, key->p, key->q);
358
0
    else
359
0
      mpz_sub(t, key->q, key->p);
360
0
  } while (mpz_cmp(t, r) <= 0);
361
362
0
  memset(&cert, 0, sizeof(cert));
363
364
0
  mpz_mul(pub->n, key->p, key->q);
365
366
0
  if (mpz_sizeinbase(pub->n, 2) != n_size) {
367
0
    ret = 0;
368
0
    goto cleanup;
369
0
  }
370
371
  /* c = q^{-1} (mod p) */
372
0
  if (mpz_invert(key->c, key->q, key->p) == 0) {
373
0
    ret = 0;
374
0
    goto cleanup;
375
0
  }
376
377
0
  mpz_sub_ui(p1, key->p, 1);
378
0
  mpz_sub_ui(q1, key->q, 1);
379
380
0
  mpz_lcm(lcm, p1, q1);
381
382
0
  if (mpz_invert(key->d, pub->e, lcm) == 0) {
383
0
    ret = 0;
384
0
    goto cleanup;
385
0
  }
386
387
  /* check whether d > 2^(nlen/2) -- FIPS186-4 5.3.1 */
388
0
  if (mpz_sizeinbase(key->d, 2) < n_size / 2) {
389
0
    ret = 0;
390
0
    goto cleanup;
391
0
  }
392
393
  /* Done! Almost, we must compute the auxiliary private values. */
394
  /* a = d % (p-1) */
395
0
  mpz_fdiv_r(key->a, key->d, p1);
396
397
  /* b = d % (q-1) */
398
0
  mpz_fdiv_r(key->b, key->d, q1);
399
400
  /* c was computed earlier */
401
402
0
  pub->size = key->size = (n_size + 7) / 8;
403
0
  if (pub->size < RSA_MINIMUM_N_OCTETS) {
404
0
    ret = 0;
405
0
    goto cleanup;
406
0
  }
407
408
0
  ret = 1;
409
0
 cleanup:
410
0
  mpz_clear(p1);
411
0
  mpz_clear(q1);
412
0
  mpz_clear(lcm);
413
0
  mpz_clear(t);
414
0
  mpz_clear(r);
415
0
  return ret;
416
0
}
417
418
/* This generates p,q params using the B.3.2.2 algorithm in FIPS 186-4.
419
 * 
420
 * The hash function used is SHA384.
421
 * The exponent e used is the value in pub->e.
422
 */
423
int
424
rsa_generate_fips186_4_keypair(struct rsa_public_key *pub,
425
             struct rsa_private_key *key,
426
             void *random_ctx, nettle_random_func * random,
427
             void *progress_ctx,
428
             nettle_progress_func * progress,
429
             unsigned *rseed_size, void *rseed,
430
             /* Desired size of modulo, in bits */
431
             unsigned n_size)
432
0
{
433
0
  uint8_t seed[128];
434
0
  unsigned seed_length;
435
0
  int ret;
436
437
0
  seed_length = seed_length_for_modulus_size(n_size);
438
0
  FIPS_RULE(!seed_length, 0, "unsupported modulus size\n");
439
440
0
  assert(seed_length <= sizeof(seed));
441
442
0
  random(random_ctx, seed_length, seed);
443
444
0
  if (rseed && rseed_size) {
445
0
    if (*rseed_size < seed_length) {
446
0
      return 0;
447
0
    }
448
0
    memcpy(rseed, seed, seed_length);
449
0
    *rseed_size = seed_length;
450
0
  }
451
452
0
  ret = _rsa_generate_fips186_4_keypair(pub, key, seed_length, seed,
453
0
                progress_ctx, progress, n_size);
454
0
  gnutls_memset(seed, 0, seed_length);
455
0
  return ret;
456
0
}