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