1 | /*
|
---|
2 | * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | /*
|
---|
11 | * DH low level APIs are deprecated for public use, but still ok for
|
---|
12 | * internal use.
|
---|
13 | */
|
---|
14 | #include "internal/deprecated.h"
|
---|
15 |
|
---|
16 | #include <stdio.h>
|
---|
17 | #include "internal/cryptlib.h"
|
---|
18 | #include "dh_local.h"
|
---|
19 | #include "crypto/bn.h"
|
---|
20 | #include "crypto/dh.h"
|
---|
21 | #include "crypto/security_bits.h"
|
---|
22 |
|
---|
23 | #ifdef FIPS_MODULE
|
---|
24 | # define MIN_STRENGTH 112
|
---|
25 | #else
|
---|
26 | # define MIN_STRENGTH 80
|
---|
27 | #endif
|
---|
28 |
|
---|
29 | static int generate_key(DH *dh);
|
---|
30 | static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
|
---|
31 | const BIGNUM *a, const BIGNUM *p,
|
---|
32 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
---|
33 | static int dh_init(DH *dh);
|
---|
34 | static int dh_finish(DH *dh);
|
---|
35 |
|
---|
36 | /*
|
---|
37 | * See SP800-56Ar3 Section 5.7.1.1
|
---|
38 | * Finite Field Cryptography Diffie-Hellman (FFC DH) Primitive
|
---|
39 | */
|
---|
40 | int ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
---|
41 | {
|
---|
42 | BN_CTX *ctx = NULL;
|
---|
43 | BN_MONT_CTX *mont = NULL;
|
---|
44 | BIGNUM *z = NULL, *pminus1;
|
---|
45 | int ret = -1;
|
---|
46 |
|
---|
47 | if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) {
|
---|
48 | ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
|
---|
49 | goto err;
|
---|
50 | }
|
---|
51 |
|
---|
52 | if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) {
|
---|
53 | ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
|
---|
54 | return 0;
|
---|
55 | }
|
---|
56 |
|
---|
57 | ctx = BN_CTX_new_ex(dh->libctx);
|
---|
58 | if (ctx == NULL)
|
---|
59 | goto err;
|
---|
60 | BN_CTX_start(ctx);
|
---|
61 | pminus1 = BN_CTX_get(ctx);
|
---|
62 | z = BN_CTX_get(ctx);
|
---|
63 | if (z == NULL)
|
---|
64 | goto err;
|
---|
65 |
|
---|
66 | if (dh->priv_key == NULL) {
|
---|
67 | ERR_raise(ERR_LIB_DH, DH_R_NO_PRIVATE_VALUE);
|
---|
68 | goto err;
|
---|
69 | }
|
---|
70 |
|
---|
71 | if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
---|
72 | mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
|
---|
73 | dh->lock, dh->params.p, ctx);
|
---|
74 | BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
|
---|
75 | if (!mont)
|
---|
76 | goto err;
|
---|
77 | }
|
---|
78 |
|
---|
79 | /* (Step 1) Z = pub_key^priv_key mod p */
|
---|
80 | if (!dh->meth->bn_mod_exp(dh, z, pub_key, dh->priv_key, dh->params.p, ctx,
|
---|
81 | mont)) {
|
---|
82 | ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB);
|
---|
83 | goto err;
|
---|
84 | }
|
---|
85 |
|
---|
86 | /* (Step 2) Error if z <= 1 or z = p - 1 */
|
---|
87 | if (BN_copy(pminus1, dh->params.p) == NULL
|
---|
88 | || !BN_sub_word(pminus1, 1)
|
---|
89 | || BN_cmp(z, BN_value_one()) <= 0
|
---|
90 | || BN_cmp(z, pminus1) == 0) {
|
---|
91 | ERR_raise(ERR_LIB_DH, DH_R_INVALID_SECRET);
|
---|
92 | goto err;
|
---|
93 | }
|
---|
94 |
|
---|
95 | /* return the padded key, i.e. same number of bytes as the modulus */
|
---|
96 | ret = BN_bn2binpad(z, key, BN_num_bytes(dh->params.p));
|
---|
97 | err:
|
---|
98 | BN_clear(z); /* (Step 2) destroy intermediate values */
|
---|
99 | BN_CTX_end(ctx);
|
---|
100 | BN_CTX_free(ctx);
|
---|
101 | return ret;
|
---|
102 | }
|
---|
103 |
|
---|
104 | /*-
|
---|
105 | * NB: This function is inherently not constant time due to the
|
---|
106 | * RFC 5246 (8.1.2) padding style that strips leading zero bytes.
|
---|
107 | */
|
---|
108 | int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
---|
109 | {
|
---|
110 | int ret = 0, i;
|
---|
111 | volatile size_t npad = 0, mask = 1;
|
---|
112 |
|
---|
113 | /* compute the key; ret is constant unless compute_key is external */
|
---|
114 | #ifdef FIPS_MODULE
|
---|
115 | ret = ossl_dh_compute_key(key, pub_key, dh);
|
---|
116 | #else
|
---|
117 | ret = dh->meth->compute_key(key, pub_key, dh);
|
---|
118 | #endif
|
---|
119 | if (ret <= 0)
|
---|
120 | return ret;
|
---|
121 |
|
---|
122 | /* count leading zero bytes, yet still touch all bytes */
|
---|
123 | for (i = 0; i < ret; i++) {
|
---|
124 | mask &= !key[i];
|
---|
125 | npad += mask;
|
---|
126 | }
|
---|
127 |
|
---|
128 | /* unpad key */
|
---|
129 | ret -= npad;
|
---|
130 | /* key-dependent memory access, potentially leaking npad / ret */
|
---|
131 | memmove(key, key + npad, ret);
|
---|
132 | /* key-dependent memory access, potentially leaking npad / ret */
|
---|
133 | memset(key + ret, 0, npad);
|
---|
134 |
|
---|
135 | return ret;
|
---|
136 | }
|
---|
137 |
|
---|
138 | int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
|
---|
139 | {
|
---|
140 | int rv, pad;
|
---|
141 |
|
---|
142 | /* rv is constant unless compute_key is external */
|
---|
143 | #ifdef FIPS_MODULE
|
---|
144 | rv = ossl_dh_compute_key(key, pub_key, dh);
|
---|
145 | #else
|
---|
146 | rv = dh->meth->compute_key(key, pub_key, dh);
|
---|
147 | #endif
|
---|
148 | if (rv <= 0)
|
---|
149 | return rv;
|
---|
150 | pad = BN_num_bytes(dh->params.p) - rv;
|
---|
151 | /* pad is constant (zero) unless compute_key is external */
|
---|
152 | if (pad > 0) {
|
---|
153 | memmove(key + pad, key, rv);
|
---|
154 | memset(key, 0, pad);
|
---|
155 | }
|
---|
156 | return rv + pad;
|
---|
157 | }
|
---|
158 |
|
---|
159 | static DH_METHOD dh_ossl = {
|
---|
160 | "OpenSSL DH Method",
|
---|
161 | generate_key,
|
---|
162 | ossl_dh_compute_key,
|
---|
163 | dh_bn_mod_exp,
|
---|
164 | dh_init,
|
---|
165 | dh_finish,
|
---|
166 | DH_FLAG_FIPS_METHOD,
|
---|
167 | NULL,
|
---|
168 | NULL
|
---|
169 | };
|
---|
170 |
|
---|
171 | static const DH_METHOD *default_DH_method = &dh_ossl;
|
---|
172 |
|
---|
173 | const DH_METHOD *DH_OpenSSL(void)
|
---|
174 | {
|
---|
175 | return &dh_ossl;
|
---|
176 | }
|
---|
177 |
|
---|
178 | const DH_METHOD *DH_get_default_method(void)
|
---|
179 | {
|
---|
180 | return default_DH_method;
|
---|
181 | }
|
---|
182 |
|
---|
183 | static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
|
---|
184 | const BIGNUM *a, const BIGNUM *p,
|
---|
185 | const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
|
---|
186 | {
|
---|
187 | return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
|
---|
188 | }
|
---|
189 |
|
---|
190 | static int dh_init(DH *dh)
|
---|
191 | {
|
---|
192 | dh->flags |= DH_FLAG_CACHE_MONT_P;
|
---|
193 | ossl_ffc_params_init(&dh->params);
|
---|
194 | dh->dirty_cnt++;
|
---|
195 | return 1;
|
---|
196 | }
|
---|
197 |
|
---|
198 | static int dh_finish(DH *dh)
|
---|
199 | {
|
---|
200 | BN_MONT_CTX_free(dh->method_mont_p);
|
---|
201 | return 1;
|
---|
202 | }
|
---|
203 |
|
---|
204 | #ifndef FIPS_MODULE
|
---|
205 | void DH_set_default_method(const DH_METHOD *meth)
|
---|
206 | {
|
---|
207 | default_DH_method = meth;
|
---|
208 | }
|
---|
209 | #endif /* FIPS_MODULE */
|
---|
210 |
|
---|
211 | int DH_generate_key(DH *dh)
|
---|
212 | {
|
---|
213 | #ifdef FIPS_MODULE
|
---|
214 | return generate_key(dh);
|
---|
215 | #else
|
---|
216 | return dh->meth->generate_key(dh);
|
---|
217 | #endif
|
---|
218 | }
|
---|
219 |
|
---|
220 | int ossl_dh_generate_public_key(BN_CTX *ctx, const DH *dh,
|
---|
221 | const BIGNUM *priv_key, BIGNUM *pub_key)
|
---|
222 | {
|
---|
223 | int ret = 0;
|
---|
224 | BIGNUM *prk = BN_new();
|
---|
225 | BN_MONT_CTX *mont = NULL;
|
---|
226 |
|
---|
227 | if (prk == NULL)
|
---|
228 | return 0;
|
---|
229 |
|
---|
230 | if (dh->flags & DH_FLAG_CACHE_MONT_P) {
|
---|
231 | /*
|
---|
232 | * We take the input DH as const, but we lie, because in some cases we
|
---|
233 | * want to get a hold of its Montgomery context.
|
---|
234 | *
|
---|
235 | * We cast to remove the const qualifier in this case, it should be
|
---|
236 | * fine...
|
---|
237 | */
|
---|
238 | BN_MONT_CTX **pmont = (BN_MONT_CTX **)&dh->method_mont_p;
|
---|
239 |
|
---|
240 | mont = BN_MONT_CTX_set_locked(pmont, dh->lock, dh->params.p, ctx);
|
---|
241 | if (mont == NULL)
|
---|
242 | goto err;
|
---|
243 | }
|
---|
244 | BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
|
---|
245 |
|
---|
246 | /* pub_key = g^priv_key mod p */
|
---|
247 | if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p,
|
---|
248 | ctx, mont))
|
---|
249 | goto err;
|
---|
250 | ret = 1;
|
---|
251 | err:
|
---|
252 | BN_clear_free(prk);
|
---|
253 | return ret;
|
---|
254 | }
|
---|
255 |
|
---|
256 | static int generate_key(DH *dh)
|
---|
257 | {
|
---|
258 | int ok = 0;
|
---|
259 | int generate_new_key = 0;
|
---|
260 | #ifndef FIPS_MODULE
|
---|
261 | unsigned l;
|
---|
262 | #endif
|
---|
263 | BN_CTX *ctx = NULL;
|
---|
264 | BIGNUM *pub_key = NULL, *priv_key = NULL;
|
---|
265 |
|
---|
266 | if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) {
|
---|
267 | ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE);
|
---|
268 | return 0;
|
---|
269 | }
|
---|
270 |
|
---|
271 | if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) {
|
---|
272 | ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL);
|
---|
273 | return 0;
|
---|
274 | }
|
---|
275 |
|
---|
276 | ctx = BN_CTX_new_ex(dh->libctx);
|
---|
277 | if (ctx == NULL)
|
---|
278 | goto err;
|
---|
279 |
|
---|
280 | if (dh->priv_key == NULL) {
|
---|
281 | priv_key = BN_secure_new();
|
---|
282 | if (priv_key == NULL)
|
---|
283 | goto err;
|
---|
284 | generate_new_key = 1;
|
---|
285 | } else {
|
---|
286 | priv_key = dh->priv_key;
|
---|
287 | }
|
---|
288 |
|
---|
289 | if (dh->pub_key == NULL) {
|
---|
290 | pub_key = BN_new();
|
---|
291 | if (pub_key == NULL)
|
---|
292 | goto err;
|
---|
293 | } else {
|
---|
294 | pub_key = dh->pub_key;
|
---|
295 | }
|
---|
296 | if (generate_new_key) {
|
---|
297 | /* Is it an approved safe prime ?*/
|
---|
298 | if (DH_get_nid(dh) != NID_undef) {
|
---|
299 | int max_strength =
|
---|
300 | ossl_ifc_ffc_compute_security_bits(BN_num_bits(dh->params.p));
|
---|
301 |
|
---|
302 | if (dh->params.q == NULL
|
---|
303 | || dh->length > BN_num_bits(dh->params.q))
|
---|
304 | goto err;
|
---|
305 | /* dh->length = maximum bit length of generated private key */
|
---|
306 | if (!ossl_ffc_generate_private_key(ctx, &dh->params, dh->length,
|
---|
307 | max_strength, priv_key))
|
---|
308 | goto err;
|
---|
309 | } else {
|
---|
310 | #ifdef FIPS_MODULE
|
---|
311 | if (dh->params.q == NULL)
|
---|
312 | goto err;
|
---|
313 | #else
|
---|
314 | if (dh->params.q == NULL) {
|
---|
315 | /* secret exponent length, must satisfy 2^(l-1) <= p */
|
---|
316 | if (dh->length != 0
|
---|
317 | && dh->length >= BN_num_bits(dh->params.p))
|
---|
318 | goto err;
|
---|
319 | l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1;
|
---|
320 | if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE,
|
---|
321 | BN_RAND_BOTTOM_ANY, 0, ctx))
|
---|
322 | goto err;
|
---|
323 | /*
|
---|
324 | * We handle just one known case where g is a quadratic non-residue:
|
---|
325 | * for g = 2: p % 8 == 3
|
---|
326 | */
|
---|
327 | if (BN_is_word(dh->params.g, DH_GENERATOR_2)
|
---|
328 | && !BN_is_bit_set(dh->params.p, 2)) {
|
---|
329 | /* clear bit 0, since it won't be a secret anyway */
|
---|
330 | if (!BN_clear_bit(priv_key, 0))
|
---|
331 | goto err;
|
---|
332 | }
|
---|
333 | } else
|
---|
334 | #endif
|
---|
335 | {
|
---|
336 | /* Do a partial check for invalid p, q, g */
|
---|
337 | if (!ossl_ffc_params_simple_validate(dh->libctx, &dh->params,
|
---|
338 | FFC_PARAM_TYPE_DH, NULL))
|
---|
339 | goto err;
|
---|
340 | /*
|
---|
341 | * For FFC FIPS 186-4 keygen
|
---|
342 | * security strength s = 112,
|
---|
343 | * Max Private key size N = len(q)
|
---|
344 | */
|
---|
345 | if (!ossl_ffc_generate_private_key(ctx, &dh->params,
|
---|
346 | BN_num_bits(dh->params.q),
|
---|
347 | MIN_STRENGTH,
|
---|
348 | priv_key))
|
---|
349 | goto err;
|
---|
350 | }
|
---|
351 | }
|
---|
352 | }
|
---|
353 |
|
---|
354 | if (!ossl_dh_generate_public_key(ctx, dh, priv_key, pub_key))
|
---|
355 | goto err;
|
---|
356 |
|
---|
357 | dh->pub_key = pub_key;
|
---|
358 | dh->priv_key = priv_key;
|
---|
359 | dh->dirty_cnt++;
|
---|
360 | ok = 1;
|
---|
361 | err:
|
---|
362 | if (ok != 1)
|
---|
363 | ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB);
|
---|
364 |
|
---|
365 | if (pub_key != dh->pub_key)
|
---|
366 | BN_free(pub_key);
|
---|
367 | if (priv_key != dh->priv_key)
|
---|
368 | BN_free(priv_key);
|
---|
369 | BN_CTX_free(ctx);
|
---|
370 | return ok;
|
---|
371 | }
|
---|
372 |
|
---|
373 | int ossl_dh_buf2key(DH *dh, const unsigned char *buf, size_t len)
|
---|
374 | {
|
---|
375 | int err_reason = DH_R_BN_ERROR;
|
---|
376 | BIGNUM *pubkey = NULL;
|
---|
377 | const BIGNUM *p;
|
---|
378 | int ret;
|
---|
379 |
|
---|
380 | if ((pubkey = BN_bin2bn(buf, len, NULL)) == NULL)
|
---|
381 | goto err;
|
---|
382 | DH_get0_pqg(dh, &p, NULL, NULL);
|
---|
383 | if (p == NULL || BN_num_bytes(p) == 0) {
|
---|
384 | err_reason = DH_R_NO_PARAMETERS_SET;
|
---|
385 | goto err;
|
---|
386 | }
|
---|
387 | /* Prevent small subgroup attacks per RFC 8446 Section 4.2.8.1 */
|
---|
388 | if (!ossl_dh_check_pub_key_partial(dh, pubkey, &ret)) {
|
---|
389 | err_reason = DH_R_INVALID_PUBKEY;
|
---|
390 | goto err;
|
---|
391 | }
|
---|
392 | if (DH_set0_key(dh, pubkey, NULL) != 1)
|
---|
393 | goto err;
|
---|
394 | return 1;
|
---|
395 | err:
|
---|
396 | ERR_raise(ERR_LIB_DH, err_reason);
|
---|
397 | BN_free(pubkey);
|
---|
398 | return 0;
|
---|
399 | }
|
---|
400 |
|
---|
401 | size_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf_out, size_t size,
|
---|
402 | int alloc)
|
---|
403 | {
|
---|
404 | const BIGNUM *pubkey;
|
---|
405 | unsigned char *pbuf = NULL;
|
---|
406 | const BIGNUM *p;
|
---|
407 | int p_size;
|
---|
408 |
|
---|
409 | DH_get0_pqg(dh, &p, NULL, NULL);
|
---|
410 | DH_get0_key(dh, &pubkey, NULL);
|
---|
411 | if (p == NULL || pubkey == NULL
|
---|
412 | || (p_size = BN_num_bytes(p)) == 0
|
---|
413 | || BN_num_bytes(pubkey) == 0) {
|
---|
414 | ERR_raise(ERR_LIB_DH, DH_R_INVALID_PUBKEY);
|
---|
415 | return 0;
|
---|
416 | }
|
---|
417 | if (pbuf_out != NULL && (alloc || *pbuf_out != NULL)) {
|
---|
418 | if (!alloc) {
|
---|
419 | if (size >= (size_t)p_size)
|
---|
420 | pbuf = *pbuf_out;
|
---|
421 | } else {
|
---|
422 | pbuf = OPENSSL_malloc(p_size);
|
---|
423 | }
|
---|
424 |
|
---|
425 | if (pbuf == NULL) {
|
---|
426 | ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
|
---|
427 | return 0;
|
---|
428 | }
|
---|
429 | /*
|
---|
430 | * As per Section 4.2.8.1 of RFC 8446 left pad public
|
---|
431 | * key with zeros to the size of p
|
---|
432 | */
|
---|
433 | if (BN_bn2binpad(pubkey, pbuf, p_size) < 0) {
|
---|
434 | if (alloc)
|
---|
435 | OPENSSL_free(pbuf);
|
---|
436 | ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR);
|
---|
437 | return 0;
|
---|
438 | }
|
---|
439 | *pbuf_out = pbuf;
|
---|
440 | }
|
---|
441 | return p_size;
|
---|
442 | }
|
---|