Coverage Report

Created: 2025-03-18 06:55

/src/gnutls/lib/nettle/int/dsa-keygen-fips186.c
Line
Count
Source (jump to first uncovered line)
1
/* dsa-keygen.c
2
 *
3
 * Generation of DSA keypairs
4
 */
5
6
/* nettle, low-level cryptographics library
7
 *
8
 * Copyright (C) 2013, 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 <stdlib.h>
29
#include <string.h>
30
31
#include <nettle/dsa.h>
32
#include "dsa-fips.h"
33
34
#include <nettle/bignum.h>
35
36
unsigned _dsa_check_qp_sizes(unsigned q_bits, unsigned p_bits,
37
           unsigned generate)
38
0
{
39
0
  switch (q_bits) {
40
0
  case 160:
41
0
    FIPS_RULE(generate != 0, 0, "DSA 160-bit generation\n");
42
43
0
    if (p_bits != 1024)
44
0
      return 0;
45
0
    break;
46
0
  case 224:
47
0
    if (p_bits != 2048)
48
0
      return 0;
49
0
    break;
50
0
  case 256:
51
0
    if (p_bits != 2048 && p_bits != 3072)
52
0
      return 0;
53
0
    break;
54
0
  default:
55
0
    return 0;
56
0
  }
57
0
  return 1;
58
0
}
59
60
/* This generates p,q params using the A.1.2.1 algorithm in FIPS 186-4.
61
 * 
62
 * The hash function used is SHA384.
63
 */
64
int _dsa_generate_dss_pq(struct dsa_params *params,
65
       struct dss_params_validation_seeds *cert,
66
       unsigned seed_length, void *seed, void *progress_ctx,
67
       nettle_progress_func *progress,
68
       unsigned p_bits /* = L */, unsigned q_bits /* = N */)
69
0
{
70
0
  mpz_t r, p0, t, z, s, tmp, dp0;
71
0
  int ret;
72
0
  unsigned iterations, old_counter, i;
73
0
  uint8_t *storage = NULL;
74
0
  unsigned storage_length = 0;
75
76
0
  ret = _dsa_check_qp_sizes(q_bits, p_bits, 1);
77
0
  if (ret == 0) {
78
0
    return 0;
79
0
  }
80
81
0
  if (seed_length < q_bits / 8) {
82
0
    _gnutls_debug_log(
83
0
      "Seed length must be larger than %d bytes (it is %d)\n",
84
0
      q_bits / 8, seed_length);
85
0
    return 0;
86
0
  }
87
88
0
  mpz_init(p0);
89
0
  mpz_init(dp0);
90
0
  mpz_init(r);
91
0
  mpz_init(t);
92
0
  mpz_init(z);
93
0
  mpz_init(s);
94
0
  mpz_init(tmp);
95
96
  /* firstseed < 2^(N-1) */
97
0
  mpz_set_ui(r, 1);
98
0
  mpz_mul_2exp(r, r, q_bits - 1);
99
100
0
  nettle_mpz_set_str_256_u(s, seed_length, seed);
101
0
  if (mpz_cmp(s, r) < 0) {
102
0
    goto fail;
103
0
  }
104
105
0
  cert->qseed_length = sizeof(cert->qseed);
106
0
  cert->pseed_length = sizeof(cert->pseed);
107
108
0
  ret = st_provable_prime(params->q, &cert->qseed_length, cert->qseed,
109
0
        &cert->qgen_counter, q_bits, seed_length, seed,
110
0
        progress_ctx, progress);
111
0
  if (ret == 0) {
112
0
    goto fail;
113
0
  }
114
115
0
  if (progress)
116
0
    progress(progress_ctx, 'q');
117
118
0
  ret = st_provable_prime(p0, &cert->pseed_length, cert->pseed,
119
0
        &cert->pgen_counter, 1 + div_ceil(p_bits, 2),
120
0
        cert->qseed_length, cert->qseed, progress_ctx,
121
0
        progress);
122
0
  if (ret == 0) {
123
0
    goto fail;
124
0
  }
125
126
0
  iterations = div_ceil(p_bits, DIGEST_SIZE * 8);
127
0
  old_counter = cert->pgen_counter;
128
129
0
  if (iterations > 0) {
130
0
    storage_length = iterations * DIGEST_SIZE;
131
0
    storage = malloc(storage_length);
132
0
    if (storage == NULL) {
133
0
      goto fail;
134
0
    }
135
136
0
    nettle_mpz_set_str_256_u(s, cert->pseed_length, cert->pseed);
137
0
    for (i = 0; i < iterations; i++) {
138
0
      cert->pseed_length = nettle_mpz_sizeinbase_256_u(s);
139
0
      nettle_mpz_get_str_256(cert->pseed_length, cert->pseed,
140
0
                 s);
141
142
0
      hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
143
0
           cert->pseed_length, cert->pseed);
144
0
      mpz_add_ui(s, s, 1);
145
0
    }
146
147
    /* x = 2^(p_bits-1) + (x mod 2^(p_bits-1)) */
148
0
    nettle_mpz_set_str_256_u(tmp, storage_length, storage);
149
0
  }
150
151
0
  mpz_set_ui(r, 1);
152
0
  mpz_mul_2exp(r, r, p_bits - 1);
153
154
0
  mpz_fdiv_r_2exp(tmp, tmp, p_bits - 1);
155
0
  mpz_add(tmp, tmp, r);
156
157
  /* Generate candidate prime p in [2^(bits-1), 2^bits] */
158
159
  /* t = u[x/2c0] */
160
0
  mpz_mul_2exp(dp0, p0, 1); /* dp0 = 2*p0 */
161
0
  mpz_mul(dp0, dp0, params->q); /* dp0 = 2*p0*q */
162
163
0
  mpz_cdiv_q(t, tmp, dp0);
164
165
0
retry:
166
  /* c = 2p0*q*t + 1 */
167
0
  mpz_mul(params->p, dp0, t);
168
0
  mpz_add_ui(params->p, params->p, 1);
169
170
0
  if (mpz_sizeinbase(params->p, 2) > p_bits) {
171
    /* t = 2^(bits-1)/2qp0 */
172
0
    mpz_set_ui(tmp, 1);
173
0
    mpz_mul_2exp(tmp, tmp, p_bits - 1);
174
0
    mpz_cdiv_q(t, tmp, dp0);
175
176
    /* p = t* 2tq p0 + 1 */
177
0
    mpz_mul(params->p, dp0, t);
178
0
    mpz_add_ui(params->p, params->p, 1);
179
0
  }
180
181
0
  cert->pgen_counter++;
182
183
0
  mpz_set_ui(r, 0);
184
185
0
  if (iterations > 0) {
186
0
    for (i = 0; i < iterations; i++) {
187
0
      cert->pseed_length = nettle_mpz_sizeinbase_256_u(s);
188
0
      nettle_mpz_get_str_256(cert->pseed_length, cert->pseed,
189
0
                 s);
190
191
0
      hash(&storage[(iterations - i - 1) * DIGEST_SIZE],
192
0
           cert->pseed_length, cert->pseed);
193
0
      mpz_add_ui(s, s, 1);
194
0
    }
195
196
    /* r = a */
197
0
    nettle_mpz_set_str_256_u(r, storage_length, storage);
198
0
  }
199
200
0
  cert->pseed_length = nettle_mpz_sizeinbase_256_u(s);
201
0
  nettle_mpz_get_str_256(cert->pseed_length, cert->pseed, s);
202
203
  /* a = 2 + (a mod (p-3)) */
204
0
  mpz_sub_ui(tmp, params->p,
205
0
       3); /* c is too large to worry about negatives */
206
0
  mpz_mod(r, r, tmp);
207
0
  mpz_add_ui(r, r, 2);
208
209
  /* z = a^(2tq) mod p */
210
0
  mpz_mul_2exp(tmp, t, 1); /* tmp = 2t */
211
0
  mpz_mul(tmp, tmp, params->q); /* tmp = 2tq */
212
0
  mpz_powm(z, r, tmp, params->p);
213
214
0
  mpz_sub_ui(tmp, z, 1);
215
216
0
  mpz_gcd(tmp, tmp, params->p);
217
0
  if (mpz_cmp_ui(tmp, 1) == 0) {
218
0
    mpz_powm(tmp, z, p0, params->p);
219
0
    if (mpz_cmp_ui(tmp, 1) == 0) {
220
0
      goto success;
221
0
    }
222
0
  }
223
224
0
  if (progress)
225
0
    progress(progress_ctx, 'x');
226
227
0
  if (cert->pgen_counter >= (4 * p_bits + old_counter))
228
0
    return 0;
229
230
0
  mpz_add_ui(t, t, 1);
231
0
  goto retry;
232
233
0
success:
234
0
  if (progress)
235
0
    progress(progress_ctx, 'p');
236
237
0
  ret = 1;
238
0
  goto finish;
239
240
0
fail:
241
0
  ret = 0;
242
243
0
finish:
244
0
  mpz_clear(dp0);
245
0
  mpz_clear(p0);
246
0
  mpz_clear(tmp);
247
0
  mpz_clear(t);
248
0
  mpz_clear(z);
249
0
  mpz_clear(s);
250
0
  mpz_clear(r);
251
0
  free(storage);
252
0
  return ret;
253
0
}
254
255
int _dsa_generate_dss_g(struct dsa_params *params, unsigned domain_seed_size,
256
      const uint8_t *domain_seed, void *progress_ctx,
257
      nettle_progress_func *progress, unsigned index)
258
0
{
259
0
  mpz_t e, w;
260
0
  uint16_t count;
261
0
  uint8_t *dseed = NULL;
262
0
  unsigned dseed_size;
263
0
  unsigned pos;
264
0
  uint8_t digest[DIGEST_SIZE];
265
0
  int ret;
266
267
0
  if (index > 255 || domain_seed_size == 0)
268
0
    return 0;
269
270
0
  dseed_size = domain_seed_size + 4 + 1 + 2;
271
0
  dseed = malloc(dseed_size);
272
0
  if (dseed == NULL)
273
0
    return 0;
274
275
0
  mpz_init(e);
276
0
  mpz_init(w);
277
278
0
  memcpy(dseed, domain_seed, domain_seed_size);
279
0
  pos = domain_seed_size;
280
281
0
  memcpy(dseed + pos, "\x67\x67\x65\x6e", 4);
282
0
  pos += 4;
283
284
0
  *(dseed + pos) = (uint8_t)index;
285
0
  pos += 1;
286
287
0
  mpz_sub_ui(e, params->p, 1);
288
0
  mpz_fdiv_q(e, e, params->q);
289
290
0
  for (count = 1; count < 65535; count++) {
291
0
    *(dseed + pos) = (count >> 8) & 0xff;
292
0
    *(dseed + pos + 1) = count & 0xff;
293
294
0
    hash(digest, dseed_size, dseed);
295
296
0
    nettle_mpz_set_str_256_u(w, DIGEST_SIZE, digest);
297
298
0
    mpz_powm(params->g, w, e, params->p);
299
300
0
    if (mpz_cmp_ui(params->g, 2) >= 0) {
301
      /* found */
302
0
      goto success;
303
0
    }
304
0
    if (progress)
305
0
      progress(progress_ctx, 'x');
306
0
  }
307
308
  /* if we're here we failed */
309
0
  if (progress)
310
0
    progress(progress_ctx, 'X');
311
0
  ret = 0;
312
0
  goto finish;
313
314
0
success:
315
0
  if (progress)
316
0
    progress(progress_ctx, 'g');
317
318
0
  ret = 1;
319
320
0
finish:
321
0
  free(dseed);
322
0
  mpz_clear(e);
323
0
  mpz_clear(w);
324
0
  return ret;
325
0
}
326
327
/* Generates the public and private DSA (or DH) keys
328
 */
329
void _dsa_generate_dss_xy(struct dsa_params *params, mpz_t y, mpz_t x,
330
        void *random_ctx, nettle_random_func *random)
331
0
{
332
0
  mpz_t r;
333
334
0
  mpz_init(r);
335
0
  mpz_set(r, params->q);
336
0
  mpz_sub_ui(r, r, 2);
337
0
  nettle_mpz_random(x, random_ctx, random, r);
338
0
  mpz_add_ui(x, x, 1);
339
340
0
  mpz_powm(y, params->g, x, params->p);
341
342
0
  mpz_clear(r);
343
0
}
344
345
/* This generates p, q, g params using the algorithms from FIPS 186-4.
346
 * For p, q, the Shawe-Taylor algorithm is used.
347
 * For g, the verifiable canonical generation of the generator is used.
348
 * 
349
 * The hash function used is SHA384.
350
 * 
351
 * pub: The output public key
352
 * key: The output private key
353
 * cert: A certificate that can be used to verify the generated parameters
354
 * index: 1 for digital signatures (DSA), 2 for key establishment (DH)
355
 * p_bits: The requested size of p
356
 * q_bits: The requested size of q
357
 * 
358
 */
359
int dsa_generate_dss_pqg(struct dsa_params *params,
360
       struct dss_params_validation_seeds *cert,
361
       unsigned index, void *random_ctx,
362
       nettle_random_func *random, void *progress_ctx,
363
       nettle_progress_func *progress,
364
       unsigned p_bits /* = L */, unsigned q_bits /* = N */)
365
0
{
366
0
  int ret;
367
0
  uint8_t domain_seed[MAX_PVP_SEED_SIZE * 3];
368
0
  unsigned domain_seed_size = 0;
369
370
0
  ret = _dsa_check_qp_sizes(q_bits, p_bits, 1);
371
0
  if (ret == 0)
372
0
    return 0;
373
374
0
  cert->seed_length = 2 * (q_bits / 8) + 1;
375
376
0
  if (cert->seed_length > sizeof(cert->seed))
377
0
    return 0;
378
379
0
  random(random_ctx, cert->seed_length, cert->seed);
380
381
0
  ret = _dsa_generate_dss_pq(params, cert, cert->seed_length, cert->seed,
382
0
           progress_ctx, progress, p_bits, q_bits);
383
0
  if (ret == 0)
384
0
    return 0;
385
386
0
  domain_seed_size =
387
0
    cert->seed_length + cert->qseed_length + cert->pseed_length;
388
0
  memcpy(domain_seed, cert->seed, cert->seed_length);
389
0
  memcpy(&domain_seed[cert->seed_length], cert->pseed,
390
0
         cert->pseed_length);
391
0
  memcpy(&domain_seed[cert->seed_length + cert->pseed_length],
392
0
         cert->qseed, cert->qseed_length);
393
0
  ret = _dsa_generate_dss_g(params, domain_seed_size, domain_seed,
394
0
          progress_ctx, progress, index);
395
0
  if (ret == 0)
396
0
    return 0;
397
398
0
  return 1;
399
0
}
400
401
int _dsa_generate_dss_pqg(struct dsa_params *params,
402
        struct dss_params_validation_seeds *cert,
403
        unsigned index, unsigned seed_size, void *seed,
404
        void *progress_ctx, nettle_progress_func *progress,
405
        unsigned p_bits /* = L */, unsigned q_bits /* = N */)
406
0
{
407
0
  int ret;
408
0
  uint8_t domain_seed[MAX_PVP_SEED_SIZE * 3];
409
0
  unsigned domain_seed_size = 0;
410
411
0
  ret = _dsa_check_qp_sizes(q_bits, p_bits, 1);
412
0
  if (ret == 0)
413
0
    return 0;
414
415
0
  if (_gnutls_fips_mode_enabled() != 0) {
416
0
    cert->seed_length = 2 * (q_bits / 8) + 1;
417
418
0
    FIPS_RULE(cert->seed_length != seed_size, 0,
419
0
        "unsupported DSA seed length (is %d, should be %d)\n",
420
0
        seed_size, cert->seed_length);
421
0
  } else {
422
0
    cert->seed_length = seed_size;
423
0
  }
424
425
0
  if (cert->seed_length > sizeof(cert->seed))
426
0
    return 0;
427
428
0
  memcpy(cert->seed, seed, cert->seed_length);
429
430
0
  ret = _dsa_generate_dss_pq(params, cert, cert->seed_length, cert->seed,
431
0
           progress_ctx, progress, p_bits, q_bits);
432
0
  if (ret == 0)
433
0
    return 0;
434
435
0
  domain_seed_size =
436
0
    cert->seed_length + cert->qseed_length + cert->pseed_length;
437
0
  memcpy(domain_seed, cert->seed, cert->seed_length);
438
0
  memcpy(&domain_seed[cert->seed_length], cert->pseed,
439
0
         cert->pseed_length);
440
0
  memcpy(&domain_seed[cert->seed_length + cert->pseed_length],
441
0
         cert->qseed, cert->qseed_length);
442
0
  ret = _dsa_generate_dss_g(params, domain_seed_size, domain_seed,
443
0
          progress_ctx, progress, index);
444
0
  if (ret == 0)
445
0
    return 0;
446
447
0
  return 1;
448
0
}
449
450
int dsa_generate_dss_keypair(struct dsa_params *params, mpz_t y, mpz_t x,
451
           void *random_ctx, nettle_random_func *random,
452
           void *progress_ctx, nettle_progress_func *progress)
453
0
{
454
0
  _dsa_generate_dss_xy(params, y, x, random_ctx, random);
455
456
0
  if (progress)
457
0
    progress(progress_ctx, '\n');
458
459
0
  return 1;
460
0
}