xref: /aosp_15_r20/external/boringssl/src/crypto/fipsmodule/dh/dh.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1 /* Copyright (C) 1995-1998 Eric Young ([email protected])
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 
DH_new(void)73 DH *DH_new(void) {
74   DH *dh = OPENSSL_zalloc(sizeof(DH));
75   if (dh == NULL) {
76     return NULL;
77   }
78 
79   CRYPTO_MUTEX_init(&dh->method_mont_p_lock);
80   dh->references = 1;
81   return dh;
82 }
83 
DH_free(DH * dh)84 void DH_free(DH *dh) {
85   if (dh == NULL) {
86     return;
87   }
88 
89   if (!CRYPTO_refcount_dec_and_test_zero(&dh->references)) {
90     return;
91   }
92 
93   BN_MONT_CTX_free(dh->method_mont_p);
94   BN_clear_free(dh->p);
95   BN_clear_free(dh->g);
96   BN_clear_free(dh->q);
97   BN_clear_free(dh->pub_key);
98   BN_clear_free(dh->priv_key);
99   CRYPTO_MUTEX_cleanup(&dh->method_mont_p_lock);
100 
101   OPENSSL_free(dh);
102 }
103 
DH_bits(const DH * dh)104 unsigned DH_bits(const DH *dh) { return BN_num_bits(dh->p); }
105 
DH_get0_pub_key(const DH * dh)106 const BIGNUM *DH_get0_pub_key(const DH *dh) { return dh->pub_key; }
107 
DH_get0_priv_key(const DH * dh)108 const BIGNUM *DH_get0_priv_key(const DH *dh) { return dh->priv_key; }
109 
DH_get0_p(const DH * dh)110 const BIGNUM *DH_get0_p(const DH *dh) { return dh->p; }
111 
DH_get0_q(const DH * dh)112 const BIGNUM *DH_get0_q(const DH *dh) { return dh->q; }
113 
DH_get0_g(const DH * dh)114 const BIGNUM *DH_get0_g(const DH *dh) { return dh->g; }
115 
DH_get0_key(const DH * dh,const BIGNUM ** out_pub_key,const BIGNUM ** out_priv_key)116 void DH_get0_key(const DH *dh, const BIGNUM **out_pub_key,
117                  const BIGNUM **out_priv_key) {
118   if (out_pub_key != NULL) {
119     *out_pub_key = dh->pub_key;
120   }
121   if (out_priv_key != NULL) {
122     *out_priv_key = dh->priv_key;
123   }
124 }
125 
DH_set0_key(DH * dh,BIGNUM * pub_key,BIGNUM * priv_key)126 int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) {
127   if (pub_key != NULL) {
128     BN_free(dh->pub_key);
129     dh->pub_key = pub_key;
130   }
131 
132   if (priv_key != NULL) {
133     BN_free(dh->priv_key);
134     dh->priv_key = priv_key;
135   }
136 
137   return 1;
138 }
139 
DH_get0_pqg(const DH * dh,const BIGNUM ** out_p,const BIGNUM ** out_q,const BIGNUM ** out_g)140 void DH_get0_pqg(const DH *dh, const BIGNUM **out_p, const BIGNUM **out_q,
141                  const BIGNUM **out_g) {
142   if (out_p != NULL) {
143     *out_p = dh->p;
144   }
145   if (out_q != NULL) {
146     *out_q = dh->q;
147   }
148   if (out_g != NULL) {
149     *out_g = dh->g;
150   }
151 }
152 
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)153 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
154   if ((dh->p == NULL && p == NULL) ||
155       (dh->g == NULL && g == NULL)) {
156     return 0;
157   }
158 
159   if (p != NULL) {
160     BN_free(dh->p);
161     dh->p = p;
162   }
163 
164   if (q != NULL) {
165     BN_free(dh->q);
166     dh->q = q;
167   }
168 
169   if (g != NULL) {
170     BN_free(dh->g);
171     dh->g = g;
172   }
173 
174   // Invalidate the cached Montgomery parameters.
175   BN_MONT_CTX_free(dh->method_mont_p);
176   dh->method_mont_p = NULL;
177   return 1;
178 }
179 
DH_set_length(DH * dh,unsigned priv_length)180 int DH_set_length(DH *dh, unsigned priv_length) {
181   dh->priv_length = priv_length;
182   return 1;
183 }
184 
DH_generate_key(DH * dh)185 int DH_generate_key(DH *dh) {
186   boringssl_ensure_ffdh_self_test();
187 
188   if (!dh_check_params_fast(dh)) {
189     return 0;
190   }
191 
192   int ok = 0;
193   int generate_new_key = 0;
194   BN_CTX *ctx = NULL;
195   BIGNUM *pub_key = NULL, *priv_key = NULL, *priv_key_limit = NULL;
196 
197   ctx = BN_CTX_new();
198   if (ctx == NULL) {
199     goto err;
200   }
201 
202   if (dh->priv_key == NULL) {
203     priv_key = BN_new();
204     if (priv_key == NULL) {
205       goto err;
206     }
207     generate_new_key = 1;
208   } else {
209     priv_key = dh->priv_key;
210   }
211 
212   if (dh->pub_key == NULL) {
213     pub_key = BN_new();
214     if (pub_key == NULL) {
215       goto err;
216     }
217   } else {
218     pub_key = dh->pub_key;
219   }
220 
221   if (!BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
222                               dh->p, ctx)) {
223     goto err;
224   }
225 
226   if (generate_new_key) {
227     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       if (!BN_rand_range_ex(priv_key, 1, dh->q)) {
235         goto err;
236       }
237     } 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       priv_key_limit = BN_new();
249       if (priv_key_limit == NULL) {
250         goto err;
251       }
252       if (dh->priv_length == 0 || dh->priv_length >= BN_num_bits(dh->p) - 1) {
253         // M = q = (p - 1) / 2.
254         if (!BN_rshift1(priv_key_limit, dh->p)) {
255           goto err;
256         }
257       } else {
258         // M = 2^N.
259         if (!BN_set_bit(priv_key_limit, dh->priv_length)) {
260           goto err;
261         }
262       }
263 
264       // Choose a private key uniformly from [1, M-1].
265       if (!BN_rand_range_ex(priv_key, 1, priv_key_limit)) {
266         goto err;
267       }
268     }
269   }
270 
271   if (!BN_mod_exp_mont_consttime(pub_key, dh->g, priv_key, dh->p, ctx,
272                                  dh->method_mont_p)) {
273     goto err;
274   }
275 
276   dh->pub_key = pub_key;
277   dh->priv_key = priv_key;
278   ok = 1;
279 
280 err:
281   if (ok != 1) {
282     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
283   }
284 
285   if (dh->pub_key == NULL) {
286     BN_free(pub_key);
287   }
288   if (dh->priv_key == NULL) {
289     BN_free(priv_key);
290   }
291   BN_free(priv_key_limit);
292   BN_CTX_free(ctx);
293   return ok;
294 }
295 
dh_compute_key(DH * dh,BIGNUM * out_shared_key,const BIGNUM * peers_key,BN_CTX * ctx)296 static int dh_compute_key(DH *dh, BIGNUM *out_shared_key,
297                           const BIGNUM *peers_key, BN_CTX *ctx) {
298   if (!dh_check_params_fast(dh)) {
299     return 0;
300   }
301 
302   if (dh->priv_key == NULL) {
303     OPENSSL_PUT_ERROR(DH, DH_R_NO_PRIVATE_VALUE);
304     return 0;
305   }
306 
307   int check_result;
308   if (!DH_check_pub_key(dh, peers_key, &check_result) || check_result) {
309     OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
310     return 0;
311   }
312 
313   int ret = 0;
314   BN_CTX_start(ctx);
315   BIGNUM *p_minus_1 = BN_CTX_get(ctx);
316 
317   if (!p_minus_1 ||
318       !BN_MONT_CTX_set_locked(&dh->method_mont_p, &dh->method_mont_p_lock,
319                               dh->p, ctx)) {
320     goto err;
321   }
322 
323   if (!BN_mod_exp_mont_consttime(out_shared_key, peers_key, dh->priv_key, dh->p,
324                                  ctx, dh->method_mont_p) ||
325       !BN_copy(p_minus_1, dh->p) ||
326       !BN_sub_word(p_minus_1, 1)) {
327     OPENSSL_PUT_ERROR(DH, ERR_R_BN_LIB);
328     goto err;
329   }
330 
331   // This performs the check required by SP 800-56Ar3 section 5.7.1.1 step two.
332   if (BN_cmp_word(out_shared_key, 1) <= 0 ||
333       BN_cmp(out_shared_key, p_minus_1) == 0) {
334     OPENSSL_PUT_ERROR(DH, DH_R_INVALID_PUBKEY);
335     goto err;
336   }
337 
338   ret = 1;
339 
340  err:
341   BN_CTX_end(ctx);
342   return ret;
343 }
344 
dh_compute_key_padded_no_self_test(unsigned char * out,const BIGNUM * peers_key,DH * dh)345 int dh_compute_key_padded_no_self_test(unsigned char *out,
346                                        const BIGNUM *peers_key, DH *dh) {
347   BN_CTX *ctx = BN_CTX_new();
348   if (ctx == NULL) {
349     return -1;
350   }
351   BN_CTX_start(ctx);
352 
353   int dh_size = DH_size(dh);
354   int ret = -1;
355   BIGNUM *shared_key = BN_CTX_get(ctx);
356   if (shared_key &&
357       dh_compute_key(dh, shared_key, peers_key, ctx) &&
358       BN_bn2bin_padded(out, dh_size, shared_key)) {
359     ret = dh_size;
360   }
361 
362   BN_CTX_end(ctx);
363   BN_CTX_free(ctx);
364   return ret;
365 }
366 
DH_compute_key_padded(unsigned char * out,const BIGNUM * peers_key,DH * dh)367 int DH_compute_key_padded(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
368   boringssl_ensure_ffdh_self_test();
369 
370   return dh_compute_key_padded_no_self_test(out, peers_key, dh);
371 }
372 
DH_compute_key(unsigned char * out,const BIGNUM * peers_key,DH * dh)373 int DH_compute_key(unsigned char *out, const BIGNUM *peers_key, DH *dh) {
374   boringssl_ensure_ffdh_self_test();
375 
376   BN_CTX *ctx = BN_CTX_new();
377   if (ctx == NULL) {
378     return -1;
379   }
380   BN_CTX_start(ctx);
381 
382   int ret = -1;
383   BIGNUM *shared_key = BN_CTX_get(ctx);
384   if (shared_key && dh_compute_key(dh, shared_key, peers_key, ctx)) {
385     // A |BIGNUM|'s byte count fits in |int|.
386     ret = (int)BN_bn2bin(shared_key, out);
387   }
388 
389   BN_CTX_end(ctx);
390   BN_CTX_free(ctx);
391   return ret;
392 }
393 
DH_compute_key_hashed(DH * dh,uint8_t * out,size_t * out_len,size_t max_out_len,const BIGNUM * peers_key,const EVP_MD * digest)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                           const EVP_MD *digest) {
397   *out_len = SIZE_MAX;
398 
399   const size_t digest_len = EVP_MD_size(digest);
400   if (digest_len > max_out_len) {
401     return 0;
402   }
403 
404   FIPS_service_indicator_lock_state();
405 
406   int ret = 0;
407   const size_t dh_len = DH_size(dh);
408   uint8_t *shared_bytes = OPENSSL_malloc(dh_len);
409   unsigned out_len_unsigned;
410   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       DH_compute_key_padded(shared_bytes, peers_key, dh) != (int)dh_len ||
418       !EVP_Digest(shared_bytes, dh_len, out, &out_len_unsigned, digest, NULL) ||
419       out_len_unsigned != digest_len) {
420     goto err;
421   }
422 
423   *out_len = digest_len;
424   ret = 1;
425 
426  err:
427   FIPS_service_indicator_unlock_state();
428   OPENSSL_free(shared_bytes);
429   return ret;
430 }
431 
DH_size(const DH * dh)432 int DH_size(const DH *dh) { return BN_num_bytes(dh->p); }
433 
DH_num_bits(const DH * dh)434 unsigned DH_num_bits(const DH *dh) { return BN_num_bits(dh->p); }
435 
DH_up_ref(DH * dh)436 int DH_up_ref(DH *dh) {
437   CRYPTO_refcount_inc(&dh->references);
438   return 1;
439 }
440 
DH_get_rfc7919_2048(void)441 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   static const BN_ULONG kFFDHE2048Data[] = {
445       TOBN(0xffffffff, 0xffffffff), TOBN(0x886b4238, 0x61285c97),
446       TOBN(0xc6f34a26, 0xc1b2effa), TOBN(0xc58ef183, 0x7d1683b2),
447       TOBN(0x3bb5fcbc, 0x2ec22005), TOBN(0xc3fe3b1b, 0x4c6fad73),
448       TOBN(0x8e4f1232, 0xeef28183), TOBN(0x9172fe9c, 0xe98583ff),
449       TOBN(0xc03404cd, 0x28342f61), TOBN(0x9e02fce1, 0xcdf7e2ec),
450       TOBN(0x0b07a7c8, 0xee0a6d70), TOBN(0xae56ede7, 0x6372bb19),
451       TOBN(0x1d4f42a3, 0xde394df4), TOBN(0xb96adab7, 0x60d7f468),
452       TOBN(0xd108a94b, 0xb2c8e3fb), TOBN(0xbc0ab182, 0xb324fb61),
453       TOBN(0x30acca4f, 0x483a797a), TOBN(0x1df158a1, 0x36ade735),
454       TOBN(0xe2a689da, 0xf3efe872), TOBN(0x984f0c70, 0xe0e68b77),
455       TOBN(0xb557135e, 0x7f57c935), TOBN(0x85636555, 0x3ded1af3),
456       TOBN(0x2433f51f, 0x5f066ed0), TOBN(0xd3df1ed5, 0xd5fd6561),
457       TOBN(0xf681b202, 0xaec4617a), TOBN(0x7d2fe363, 0x630c75d8),
458       TOBN(0xcc939dce, 0x249b3ef9), TOBN(0xa9e13641, 0x146433fb),
459       TOBN(0xd8b9c583, 0xce2d3695), TOBN(0xafdc5620, 0x273d3cf1),
460       TOBN(0xadf85458, 0xa2bb4a9a), TOBN(0xffffffff, 0xffffffff),
461   };
462 
463   BIGNUM *const ffdhe2048_p = BN_new();
464   BIGNUM *const ffdhe2048_q = BN_new();
465   BIGNUM *const ffdhe2048_g = BN_new();
466   DH *const dh = DH_new();
467 
468   if (!ffdhe2048_p || !ffdhe2048_q || !ffdhe2048_g || !dh) {
469     goto err;
470   }
471 
472   bn_set_static_words(ffdhe2048_p, kFFDHE2048Data,
473                       OPENSSL_ARRAY_SIZE(kFFDHE2048Data));
474 
475   if (!BN_rshift1(ffdhe2048_q, ffdhe2048_p) ||
476       !BN_set_word(ffdhe2048_g, 2) ||
477       !DH_set0_pqg(dh, ffdhe2048_p, ffdhe2048_q, ffdhe2048_g)) {
478     goto err;
479   }
480 
481   return dh;
482 
483  err:
484     BN_free(ffdhe2048_p);
485     BN_free(ffdhe2048_q);
486     BN_free(ffdhe2048_g);
487     DH_free(dh);
488     return NULL;
489 }
490