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