Coverage Report

Created: 2024-11-21 07:03

/src/boringssl/crypto/fipsmodule/dh/dh.c.inc
Line
Count
Source (jump to first uncovered line)
1
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2
 * All rights reserved.
3
 *
4
 * This package is an SSL implementation written
5
 * by Eric Young (eay@cryptsoft.com).
6
 * The implementation was written so as to conform with Netscapes SSL.
7
 *
8
 * This library is free for commercial and non-commercial use as long as
9
 * the following conditions are aheared to.  The following conditions
10
 * apply to all code found in this distribution, be it the RC4, RSA,
11
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12
 * included with this distribution is covered by the same copyright terms
13
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14
 *
15
 * Copyright remains Eric Young's, and as such any Copyright notices in
16
 * the code are not to be removed.
17
 * If this package is used in a product, Eric Young should be given attribution
18
 * as the author of the parts of the library used.
19
 * This can be in the form of a textual message at program startup or
20
 * in documentation (online or textual) provided with the package.
21
 *
22
 * Redistribution and use in source and binary forms, with or without
23
 * modification, are permitted provided that the following conditions
24
 * are met:
25
 * 1. Redistributions of source code must retain the copyright
26
 *    notice, this list of conditions and the following disclaimer.
27
 * 2. Redistributions in binary form must reproduce the above copyright
28
 *    notice, this list of conditions and the following disclaimer in the
29
 *    documentation and/or other materials provided with the distribution.
30
 * 3. All advertising materials mentioning features or use of this software
31
 *    must display the following acknowledgement:
32
 *    "This product includes cryptographic software written by
33
 *     Eric Young (eay@cryptsoft.com)"
34
 *    The word 'cryptographic' can be left out if the rouines from the library
35
 *    being used are not cryptographic related :-).
36
 * 4. If you include any Windows specific code (or a derivative thereof) from
37
 *    the apps directory (application code) you must include an acknowledgement:
38
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39
 *
40
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50
 * SUCH DAMAGE.
51
 *
52
 * The licence and distribution terms for any publically available version or
53
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
54
 * copied and put under another distribution licence
55
 * [including the GNU Public Licence.] */
56
57
#include <openssl/dh.h>
58
59
#include <string.h>
60
61
#include <openssl/bn.h>
62
#include <openssl/err.h>
63
#include <openssl/digest.h>
64
#include <openssl/mem.h>
65
#include <openssl/thread.h>
66
67
#include "../../internal.h"
68
#include "../bn/internal.h"
69
#include "../service_indicator/internal.h"
70
#include "internal.h"
71
72
73
114
DH *DH_new(void) {
74
114
  DH *dh = OPENSSL_zalloc(sizeof(DH));
75
114
  if (dh == NULL) {
76
0
    return NULL;
77
0
  }
78
79
114
  CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
80
114
  dh->references = 1;
81
114
  return dh;
82
114
}
83
84
118
void DH_free(DH *dh) {
85
118
  if (dh == NULL) {
86
4
    return;
87
4
  }
88
89
114
  if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
90
0
    return;
91
0
  }
92
93
114
  BN_MONT_CTX_free(dh->method_mont_p);
94
114
  BN_clear_free(dh->p);
95
114
  BN_clear_free(dh->g);
96
114
  BN_clear_free(dh->q);
97
114
  BN_clear_free(dh->pub_key);
98
114
  BN_clear_free(dh->priv_key);
99
114
  CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
100
101
114
  OPENSSL_free(dh);
102
114
}
103
104
0
unsigned DH_bits(const DH *dh) { return BN_num_bits(dh->p); }
105
106
0
const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
107
108
0
const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
109
110
0
const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
111
112
0
const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
113
114
0
const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
115
116
void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
117
170
                 const BIGNUM **out_priv_key) {
118
170
  if (out_pub_key != NULL) {
119
170
    *out_pub_key = dh->pub_key;
120
170
  }
121
170
  if (out_priv_key != NULL) {
122
170
    *out_priv_key = dh->priv_key;
123
170
  }
124
170
}
125
126
185
int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
127
185
  if (pub_key != NULL) {
128
0
    BN_free(dh->pub_key);
129
0
    dh->pub_key = pub_key;
130
0
  }
131
132
185
  if (priv_key != NULL) {
133
185
    BN_free(dh->priv_key);
134
185
    dh->priv_key = priv_key;
135
185
  }
136
137
185
  return 1;
138
185
}
139
140
void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
141
0
                 const BIGNUM **out_g) {
142
0
  if (out_p != NULL) {
143
0
    *out_p = dh->p;
144
0
  }
145
0
  if (out_q != NULL) {
146
0
    *out_q = dh->q;
147
0
  }
148
0
  if (out_g != NULL) {
149
0
    *out_g = dh->g;
150
0
  }
151
0
}
152
153
114
int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
154
114
  if ((dh->p == NULL && p == NULL) ||
155
114
      (dh->g == NULL && g == NULL)) {
156
0
    return 0;
157
0
  }
158
159
114
  if (p != NULL) {
160
114
    BN_free(dh->p);
161
114
    dh->p = p;
162
114
  }
163
164
114
  if (q != NULL) {
165
0
    BN_free(dh->q);
166
0
    dh->q = q;
167
0
  }
168
169
114
  if (g != NULL) {
170
114
    BN_free(dh->g);
171
114
    dh->g = g;
172
114
  }
173
174
  // Invalidate the cached Montgomery parameters.
175
114
  BN_MONT_CTX_free(dh->method_mont_p);
176
114
  dh->method_mont_p = NULL;
177
114
  return 1;
178
114
}
179
180
0
int DH_set_length(DH *dh, unsigned priv_length) {
181
0
  dh->priv_length = priv_length;
182
0
  return 1;
183
0
}
184
185
55
int DH_generate_key(DH *dh) {
186
55
  boringssl_ensure_ffdh_self_test();
187
188
55
  if (!dh_check_params_fast(dh)) {
189
16
    return 0;
190
16
  }
191
192
39
  int ok = 0;
193
39
  int generate_new_key = 0;
194
39
  BN_CTX *ctx = NULL;
195
39
  BIGNUM *pub_key = NULL, *priv_key = NULL, *priv_key_limit = NULL;
196
197
39
  ctx = BN_CTX_new();
198
39
  if (ctx == NULL) {
199
0
    goto err;
200
0
  }
201
202
39
  if (dh->priv_key == NULL) {
203
39
    priv_key = BN_new();
204
39
    if (priv_key == NULL) {
205
0
      goto err;
206
0
    }
207
39
    generate_new_key = 1;
208
39
  } else {
209
0
    priv_key = dh->priv_key;
210
0
  }
211
212
39
  if (dh->pub_key == NULL) {
213
39
    pub_key = BN_new();
214
39
    if (pub_key == NULL) {
215
0
      goto err;
216
0
    }
217
39
  } else {
218
0
    pub_key = dh->pub_key;
219
0
  }
220
221
39
  if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
222
39
                              dh->p, ctx)) {
223
0
    goto err;
224
0
  }
225
226
39
  if (generate_new_key) {
227
39
    if (dh->q) {
228
      // Section 5.6.1.1.4 of SP 800-56A Rev3 generates a private key uniformly
229
      // from [1, min(2^N-1, q-1)].
230
      //
231
      // Although SP 800-56A Rev3 now permits a private key length N,
232
      // |dh->priv_length| historically was ignored when q is available. We
233
      // continue to ignore it and interpret such a configuration as N = len(q).
234
0
      if (!BN_rand_range_ex(priv_key, 1, dh->q)) {
235
0
        goto err;
236
0
      }
237
39
    } else {
238
      // If q is unspecified, we expect p to be a safe prime, with g generating
239
      // the (p-1)/2 subgroup. So, we use q = (p-1)/2. (If g generates a smaller
240
      // prime-order subgroup, q will still divide (p-1)/2.)
241
      //
242
      // We set N from |dh->priv_length|. Section 5.6.1.1.4 of SP 800-56A Rev3
243
      // says to reject N > len(q), or N > num_bits(p) - 1. However, this logic
244
      // originally aligned with PKCS#3, which allows num_bits(p). Instead, we
245
      // clamp |dh->priv_length| before invoking the algorithm.
246
247
      // Compute M = min(2^N, q).
248
39
      priv_key_limit = BN_new();
249
39
      if (priv_key_limit == NULL) {
250
0
        goto err;
251
0
      }
252
39
      if (dh->priv_length == 0 || dh->priv_length >= BN_num_bits(dh->p) - 1) {
253
        // M = q = (p - 1) / 2.
254
39
        if (!BN_rshift1(priv_key_limit, dh->p)) {
255
0
          goto err;
256
0
        }
257
39
      } else {
258
        // M = 2^N.
259
0
        if (!BN_set_bit(priv_key_limit, dh->priv_length)) {
260
0
          goto err;
261
0
        }
262
0
      }
263
264
      // Choose a private key uniformly from [1, M-1].
265
39
      if (!BN_rand_range_ex(priv_key, 1, priv_key_limit)) {
266
0
        goto err;
267
0
      }
268
39
    }
269
39
  }
270
271
39
  if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
272
39
                                 dh->method_mont_p)) {
273
0
    goto err;
274
0
  }
275
276
39
  dh->pub_key = pub_key;
277
39
  dh->priv_key = priv_key;
278
39
  ok = 1;
279
280
39
err:
281
39
  if (ok != 1) {
282
0
    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
283
0
  }
284
285
39
  if (dh->pub_key == NULL) {
286
0
    BN_free(pub_key);
287
0
  }
288
39
  if (dh->priv_key == NULL) {
289
0
    BN_free(priv_key);
290
0
  }
291
39
  BN_free(priv_key_limit);
292
39
  BN_CTX_free(ctx);
293
39
  return ok;
294
39
}
295
296
static int dh_compute_key(DH *dh, BIGNUM *out_shared_key,
297
59
                          const BIGNUM *peers_key, BN_CTX *ctx) {
298
59
  if (!dh_check_params_fast(dh)) {
299
22
    return 0;
300
22
  }
301
302
37
  if (dh->priv_key == NULL) {
303
0
    OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
304
0
    return 0;
305
0
  }
306
307
37
  int check_result;
308
37
  if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
309
17
    OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
310
17
    return 0;
311
17
  }
312
313
20
  int ret = 0;
314
20
  BN_CTX_start(ctx);
315
20
  BIGNUM *p_minus_1 = BN_CTX_get(ctx);
316
317
20
  if (!p_minus_1 ||
318
20
      !BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
319
20
                              dh->p, ctx)) {
320
0
    goto err;
321
0
  }
322
323
20
  if (!BN_mod_exp_mont_consttime(out_shared_key, peers_key, dh->priv_key, dh->p,
324
20
                                 ctx, dh->method_mont_p) ||
325
20
      !BN_copy(p_minus_1, dh->p) ||
326
20
      !BN_sub_word(p_minus_1, 1)) {
327
0
    OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
328
0
    goto err;
329
0
  }
330
331
  // This performs the check required by SP 800-56Ar3 section 5.7.1.1 step two.
332
20
  if (BN_cmp_word(out_shared_key, 1) <= 0 ||
333
20
      BN_cmp(out_shared_key, p_minus_1) == 0) {
334
0
    OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
335
0
    goto err;
336
0
  }
337
338
20
  ret = 1;
339
340
20
 err:
341
20
  BN_CTX_end(ctx);
342
20
  return ret;
343
20
}
344
345
int dh_compute_key_padded_no_self_test(unsigned char *out,
346
0
                                       const BIGNUM *peers_key, DH *dh) {
347
0
  BN_CTX *ctx = BN_CTX_new();
348
0
  if (ctx == NULL) {
349
0
    return -1;
350
0
  }
351
0
  BN_CTX_start(ctx);
352
353
0
  int dh_size = DH_size(dh);
354
0
  int ret = -1;
355
0
  BIGNUM *shared_key = BN_CTX_get(ctx);
356
0
  if (shared_key &&
357
0
      dh_compute_key(dh, shared_key, peers_key, ctx) &&
358
0
      BN_bn2bin_padded(out, dh_size, shared_key)) {
359
0
    ret = dh_size;
360
0
  }
361
362
0
  BN_CTX_end(ctx);
363
0
  BN_CTX_free(ctx);
364
0
  return ret;
365
0
}
366
367
0
int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
368
0
  boringssl_ensure_ffdh_self_test();
369
370
0
  return dh_compute_key_padded_no_self_test(out, peers_key, dh);
371
0
}
372
373
59
int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
374
59
  boringssl_ensure_ffdh_self_test();
375
376
59
  BN_CTX *ctx = BN_CTX_new();
377
59
  if (ctx == NULL) {
378
0
    return -1;
379
0
  }
380
59
  BN_CTX_start(ctx);
381
382
59
  int ret = -1;
383
59
  BIGNUM *shared_key = BN_CTX_get(ctx);
384
59
  if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
385
    // A |BIGNUM|'s byte count fits in |int|.
386
20
    ret = (int)BN_bn2bin(shared_key, out);
387
20
  }
388
389
59
  BN_CTX_end(ctx);
390
59
  BN_CTX_free(ctx);
391
59
  return ret;
392
59
}
393
394
int DH_compute_key_hashed(DH *dh, uint8_t *out, size_t *out_len,
395
                          size_t max_out_len, const BIGNUM *peers_key,
396
0
                          const EVP_MD *digest) {
397
0
  *out_len = SIZE_MAX;
398
399
0
  const size_t digest_len = EVP_MD_size(digest);
400
0
  if (digest_len > max_out_len) {
401
0
    return 0;
402
0
  }
403
404
0
  FIPS_service_indicator_lock_state();
405
406
0
  int ret = 0;
407
0
  const size_t dh_len = DH_size(dh);
408
0
  uint8_t *shared_bytes = OPENSSL_malloc(dh_len);
409
0
  unsigned out_len_unsigned;
410
0
  if (!shared_bytes ||
411
      // SP 800-56A is ambiguous about whether the output should be padded prior
412
      // to revision three. But revision three, section C.1, awkwardly specifies
413
      // padding to the length of p.
414
      //
415
      // Also, padded output avoids side-channels, so is always strongly
416
      // advisable.
417
0
      DH_compute_key_padded(shared_bytes, peers_key, dh) != (int)dh_len ||
418
0
      !EVP_Digest(shared_bytes, dh_len, out, &out_len_unsigned, digest, NULL) ||
419
0
      out_len_unsigned != digest_len) {
420
0
    goto err;
421
0
  }
422
423
0
  *out_len = digest_len;
424
0
  ret = 1;
425
426
0
 err:
427
0
  FIPS_service_indicator_unlock_state();
428
0
  OPENSSL_free(shared_bytes);
429
0
  return ret;
430
0
}
431
432
59
int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
433
434
0
unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
435
436
0
int DH_up_ref(DH *dh) {
437
0
  CRYPTO_refcount_inc(&dh->references);
438
0
  return 1;
439
0
}
440
441
0
DH *DH_get_rfc7919_2048(void) {
442
  // This is the prime from https://tools.ietf.org/html/rfc7919#appendix-A.1,
443
  // which is specifically approved for FIPS in appendix D of SP 800-56Ar3.
444
0
  static const BN_ULONG kFFDHE2048Data[] = {
445
0
      TOBN(0xffffffff, 0xffffffff), TOBN(0x886b4238, 0x61285c97),
446
0
      TOBN(0xc6f34a26, 0xc1b2effa), TOBN(0xc58ef183, 0x7d1683b2),
447
0
      TOBN(0x3bb5fcbc, 0x2ec22005), TOBN(0xc3fe3b1b, 0x4c6fad73),
448
0
      TOBN(0x8e4f1232, 0xeef28183), TOBN(0x9172fe9c, 0xe98583ff),
449
0
      TOBN(0xc03404cd, 0x28342f61), TOBN(0x9e02fce1, 0xcdf7e2ec),
450
0
      TOBN(0x0b07a7c8, 0xee0a6d70), TOBN(0xae56ede7, 0x6372bb19),
451
0
      TOBN(0x1d4f42a3, 0xde394df4), TOBN(0xb96adab7, 0x60d7f468),
452
0
      TOBN(0xd108a94b, 0xb2c8e3fb), TOBN(0xbc0ab182, 0xb324fb61),
453
0
      TOBN(0x30acca4f, 0x483a797a), TOBN(0x1df158a1, 0x36ade735),
454
0
      TOBN(0xe2a689da, 0xf3efe872), TOBN(0x984f0c70, 0xe0e68b77),
455
0
      TOBN(0xb557135e, 0x7f57c935), TOBN(0x85636555, 0x3ded1af3),
456
0
      TOBN(0x2433f51f, 0x5f066ed0), TOBN(0xd3df1ed5, 0xd5fd6561),
457
0
      TOBN(0xf681b202, 0xaec4617a), TOBN(0x7d2fe363, 0x630c75d8),
458
0
      TOBN(0xcc939dce, 0x249b3ef9), TOBN(0xa9e13641, 0x146433fb),
459
0
      TOBN(0xd8b9c583, 0xce2d3695), TOBN(0xafdc5620, 0x273d3cf1),
460
0
      TOBN(0xadf85458, 0xa2bb4a9a), TOBN(0xffffffff, 0xffffffff),
461
0
  };
462
463
0
  BIGNUM *const ffdhe2048_p = BN_new();
464
0
  BIGNUM *const ffdhe2048_q = BN_new();
465
0
  BIGNUM *const ffdhe2048_g = BN_new();
466
0
  DH *const dh = DH_new();
467
468
0
  if (!ffdhe2048_p || !ffdhe2048_q || !ffdhe2048_g || !dh) {
469
0
    goto err;
470
0
  }
471
472
0
  bn_set_static_words(ffdhe2048_p, kFFDHE2048Data,
473
0
                      OPENSSL_ARRAY_SIZE(kFFDHE2048Data));
474
475
0
  if (!BN_rshift1(ffdhe2048_q, ffdhe2048_p) ||
476
0
      !BN_set_word(ffdhe2048_g, 2) ||
477
0
      !DH_set0_pqg(dh, ffdhe2048_p, ffdhe2048_q, ffdhe2048_g)) {
478
0
    goto err;
479
0
  }
480
481
0
  return dh;
482
483
0
 err:
484
0
    BN_free(ffdhe2048_p);
485
0
    BN_free(ffdhe2048_q);
486
0
    BN_free(ffdhe2048_g);
487
0
    DH_free(dh);
488
0
    return NULL;
489
0
}