1 /* 2 * Copyright 1995-2023 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 dh->dirty_cnt++; 194 return 1; 195 } 196 197 static int dh_finish(DH *dh) 198 { 199 BN_MONT_CTX_free(dh->method_mont_p); 200 return 1; 201 } 202 203 #ifndef FIPS_MODULE 204 void DH_set_default_method(const DH_METHOD *meth) 205 { 206 default_DH_method = meth; 207 } 208 #endif /* FIPS_MODULE */ 209 210 int DH_generate_key(DH *dh) 211 { 212 #ifdef FIPS_MODULE 213 return generate_key(dh); 214 #else 215 return dh->meth->generate_key(dh); 216 #endif 217 } 218 219 int ossl_dh_generate_public_key(BN_CTX *ctx, const DH *dh, 220 const BIGNUM *priv_key, BIGNUM *pub_key) 221 { 222 int ret = 0; 223 BIGNUM *prk = BN_new(); 224 BN_MONT_CTX *mont = NULL; 225 226 if (prk == NULL) 227 return 0; 228 229 if (dh->flags & DH_FLAG_CACHE_MONT_P) { 230 /* 231 * We take the input DH as const, but we lie, because in some cases we 232 * want to get a hold of its Montgomery context. 233 * 234 * We cast to remove the const qualifier in this case, it should be 235 * fine... 236 */ 237 BN_MONT_CTX **pmont = (BN_MONT_CTX **)&dh->method_mont_p; 238 239 mont = BN_MONT_CTX_set_locked(pmont, dh->lock, dh->params.p, ctx); 240 if (mont == NULL) 241 goto err; 242 } 243 BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); 244 245 /* pub_key = g^priv_key mod p */ 246 if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p, 247 ctx, mont)) 248 goto err; 249 ret = 1; 250 err: 251 BN_clear_free(prk); 252 return ret; 253 } 254 255 static int generate_key(DH *dh) 256 { 257 int ok = 0; 258 int generate_new_key = 0; 259 #ifndef FIPS_MODULE 260 unsigned l; 261 #endif 262 BN_CTX *ctx = NULL; 263 BIGNUM *pub_key = NULL, *priv_key = NULL; 264 265 if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { 266 ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 267 return 0; 268 } 269 270 if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) { 271 ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL); 272 return 0; 273 } 274 275 ctx = BN_CTX_new_ex(dh->libctx); 276 if (ctx == NULL) 277 goto err; 278 279 if (dh->priv_key == NULL) { 280 priv_key = BN_secure_new(); 281 if (priv_key == NULL) 282 goto err; 283 generate_new_key = 1; 284 } else { 285 priv_key = dh->priv_key; 286 } 287 288 if (dh->pub_key == NULL) { 289 pub_key = BN_new(); 290 if (pub_key == NULL) 291 goto err; 292 } else { 293 pub_key = dh->pub_key; 294 } 295 if (generate_new_key) { 296 /* Is it an approved safe prime ?*/ 297 if (DH_get_nid(dh) != NID_undef) { 298 int max_strength = 299 ossl_ifc_ffc_compute_security_bits(BN_num_bits(dh->params.p)); 300 301 if (dh->params.q == NULL 302 || dh->length > BN_num_bits(dh->params.q)) 303 goto err; 304 /* dh->length = maximum bit length of generated private key */ 305 if (!ossl_ffc_generate_private_key(ctx, &dh->params, dh->length, 306 max_strength, priv_key)) 307 goto err; 308 } else { 309 #ifdef FIPS_MODULE 310 if (dh->params.q == NULL) 311 goto err; 312 #else 313 if (dh->params.q == NULL) { 314 /* secret exponent length, must satisfy 2^(l-1) <= p */ 315 if (dh->length != 0 316 && dh->length >= BN_num_bits(dh->params.p)) 317 goto err; 318 l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1; 319 if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE, 320 BN_RAND_BOTTOM_ANY, 0, ctx)) 321 goto err; 322 /* 323 * We handle just one known case where g is a quadratic non-residue: 324 * for g = 2: p % 8 == 3 325 */ 326 if (BN_is_word(dh->params.g, DH_GENERATOR_2) 327 && !BN_is_bit_set(dh->params.p, 2)) { 328 /* clear bit 0, since it won't be a secret anyway */ 329 if (!BN_clear_bit(priv_key, 0)) 330 goto err; 331 } 332 } else 333 #endif 334 { 335 /* Do a partial check for invalid p, q, g */ 336 if (!ossl_ffc_params_simple_validate(dh->libctx, &dh->params, 337 FFC_PARAM_TYPE_DH, NULL)) 338 goto err; 339 /* 340 * For FFC FIPS 186-4 keygen 341 * security strength s = 112, 342 * Max Private key size N = len(q) 343 */ 344 if (!ossl_ffc_generate_private_key(ctx, &dh->params, 345 BN_num_bits(dh->params.q), 346 MIN_STRENGTH, 347 priv_key)) 348 goto err; 349 } 350 } 351 } 352 353 if (!ossl_dh_generate_public_key(ctx, dh, priv_key, pub_key)) 354 goto err; 355 356 dh->pub_key = pub_key; 357 dh->priv_key = priv_key; 358 dh->dirty_cnt++; 359 ok = 1; 360 err: 361 if (ok != 1) 362 ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB); 363 364 if (pub_key != dh->pub_key) 365 BN_free(pub_key); 366 if (priv_key != dh->priv_key) 367 BN_free(priv_key); 368 BN_CTX_free(ctx); 369 return ok; 370 } 371 372 int ossl_dh_buf2key(DH *dh, const unsigned char *buf, size_t len) 373 { 374 int err_reason = DH_R_BN_ERROR; 375 BIGNUM *pubkey = NULL; 376 const BIGNUM *p; 377 int ret; 378 379 if ((pubkey = BN_bin2bn(buf, len, NULL)) == NULL) 380 goto err; 381 DH_get0_pqg(dh, &p, NULL, NULL); 382 if (p == NULL || BN_num_bytes(p) == 0) { 383 err_reason = DH_R_NO_PARAMETERS_SET; 384 goto err; 385 } 386 /* Prevent small subgroup attacks per RFC 8446 Section 4.2.8.1 */ 387 if (!ossl_dh_check_pub_key_partial(dh, pubkey, &ret)) { 388 err_reason = DH_R_INVALID_PUBKEY; 389 goto err; 390 } 391 if (DH_set0_key(dh, pubkey, NULL) != 1) 392 goto err; 393 return 1; 394 err: 395 ERR_raise(ERR_LIB_DH, err_reason); 396 BN_free(pubkey); 397 return 0; 398 } 399 400 size_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf_out, size_t size, 401 int alloc) 402 { 403 const BIGNUM *pubkey; 404 unsigned char *pbuf = NULL; 405 const BIGNUM *p; 406 int p_size; 407 408 DH_get0_pqg(dh, &p, NULL, NULL); 409 DH_get0_key(dh, &pubkey, NULL); 410 if (p == NULL || pubkey == NULL 411 || (p_size = BN_num_bytes(p)) == 0 412 || BN_num_bytes(pubkey) == 0) { 413 ERR_raise(ERR_LIB_DH, DH_R_INVALID_PUBKEY); 414 return 0; 415 } 416 if (pbuf_out != NULL && (alloc || *pbuf_out != NULL)) { 417 if (!alloc) { 418 if (size >= (size_t)p_size) 419 pbuf = *pbuf_out; 420 } else { 421 pbuf = OPENSSL_malloc(p_size); 422 } 423 424 if (pbuf == NULL) { 425 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 426 return 0; 427 } 428 /* 429 * As per Section 4.2.8.1 of RFC 8446 left pad public 430 * key with zeros to the size of p 431 */ 432 if (BN_bn2binpad(pubkey, pbuf, p_size) < 0) { 433 if (alloc) 434 OPENSSL_free(pbuf); 435 ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR); 436 return 0; 437 } 438 *pbuf_out = pbuf; 439 } 440 return p_size; 441 } 442