11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved. 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License"). You may not use 51cb0ef41Sopenharmony_ci * this file except in compliance with the License. You can obtain a copy 61cb0ef41Sopenharmony_ci * in the file LICENSE in the source distribution or at 71cb0ef41Sopenharmony_ci * https://www.openssl.org/source/license.html 81cb0ef41Sopenharmony_ci */ 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci/* 111cb0ef41Sopenharmony_ci * DH low level APIs are deprecated for public use, but still ok for 121cb0ef41Sopenharmony_ci * internal use. 131cb0ef41Sopenharmony_ci */ 141cb0ef41Sopenharmony_ci#include "internal/deprecated.h" 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include <stdio.h> 171cb0ef41Sopenharmony_ci#include "internal/cryptlib.h" 181cb0ef41Sopenharmony_ci#include "dh_local.h" 191cb0ef41Sopenharmony_ci#include "crypto/bn.h" 201cb0ef41Sopenharmony_ci#include "crypto/dh.h" 211cb0ef41Sopenharmony_ci#include "crypto/security_bits.h" 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE 241cb0ef41Sopenharmony_ci# define MIN_STRENGTH 112 251cb0ef41Sopenharmony_ci#else 261cb0ef41Sopenharmony_ci# define MIN_STRENGTH 80 271cb0ef41Sopenharmony_ci#endif 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_cistatic int generate_key(DH *dh); 301cb0ef41Sopenharmony_cistatic int dh_bn_mod_exp(const DH *dh, BIGNUM *r, 311cb0ef41Sopenharmony_ci const BIGNUM *a, const BIGNUM *p, 321cb0ef41Sopenharmony_ci const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx); 331cb0ef41Sopenharmony_cistatic int dh_init(DH *dh); 341cb0ef41Sopenharmony_cistatic int dh_finish(DH *dh); 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_ci/* 371cb0ef41Sopenharmony_ci * See SP800-56Ar3 Section 5.7.1.1 381cb0ef41Sopenharmony_ci * Finite Field Cryptography Diffie-Hellman (FFC DH) Primitive 391cb0ef41Sopenharmony_ci */ 401cb0ef41Sopenharmony_ciint ossl_dh_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) 411cb0ef41Sopenharmony_ci{ 421cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 431cb0ef41Sopenharmony_ci BN_MONT_CTX *mont = NULL; 441cb0ef41Sopenharmony_ci BIGNUM *z = NULL, *pminus1; 451cb0ef41Sopenharmony_ci int ret = -1; 461cb0ef41Sopenharmony_ci 471cb0ef41Sopenharmony_ci if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { 481cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 491cb0ef41Sopenharmony_ci goto err; 501cb0ef41Sopenharmony_ci } 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci if (dh->params.q != NULL 531cb0ef41Sopenharmony_ci && BN_num_bits(dh->params.q) > OPENSSL_DH_MAX_MODULUS_BITS) { 541cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_Q_TOO_LARGE); 551cb0ef41Sopenharmony_ci goto err; 561cb0ef41Sopenharmony_ci } 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_ci if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) { 591cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL); 601cb0ef41Sopenharmony_ci return 0; 611cb0ef41Sopenharmony_ci } 621cb0ef41Sopenharmony_ci 631cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(dh->libctx); 641cb0ef41Sopenharmony_ci if (ctx == NULL) 651cb0ef41Sopenharmony_ci goto err; 661cb0ef41Sopenharmony_ci BN_CTX_start(ctx); 671cb0ef41Sopenharmony_ci pminus1 = BN_CTX_get(ctx); 681cb0ef41Sopenharmony_ci z = BN_CTX_get(ctx); 691cb0ef41Sopenharmony_ci if (z == NULL) 701cb0ef41Sopenharmony_ci goto err; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci if (dh->priv_key == NULL) { 731cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_NO_PRIVATE_VALUE); 741cb0ef41Sopenharmony_ci goto err; 751cb0ef41Sopenharmony_ci } 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci if (dh->flags & DH_FLAG_CACHE_MONT_P) { 781cb0ef41Sopenharmony_ci mont = BN_MONT_CTX_set_locked(&dh->method_mont_p, 791cb0ef41Sopenharmony_ci dh->lock, dh->params.p, ctx); 801cb0ef41Sopenharmony_ci BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME); 811cb0ef41Sopenharmony_ci if (!mont) 821cb0ef41Sopenharmony_ci goto err; 831cb0ef41Sopenharmony_ci } 841cb0ef41Sopenharmony_ci 851cb0ef41Sopenharmony_ci /* (Step 1) Z = pub_key^priv_key mod p */ 861cb0ef41Sopenharmony_ci if (!dh->meth->bn_mod_exp(dh, z, pub_key, dh->priv_key, dh->params.p, ctx, 871cb0ef41Sopenharmony_ci mont)) { 881cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB); 891cb0ef41Sopenharmony_ci goto err; 901cb0ef41Sopenharmony_ci } 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci /* (Step 2) Error if z <= 1 or z = p - 1 */ 931cb0ef41Sopenharmony_ci if (BN_copy(pminus1, dh->params.p) == NULL 941cb0ef41Sopenharmony_ci || !BN_sub_word(pminus1, 1) 951cb0ef41Sopenharmony_ci || BN_cmp(z, BN_value_one()) <= 0 961cb0ef41Sopenharmony_ci || BN_cmp(z, pminus1) == 0) { 971cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_INVALID_SECRET); 981cb0ef41Sopenharmony_ci goto err; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci /* return the padded key, i.e. same number of bytes as the modulus */ 1021cb0ef41Sopenharmony_ci ret = BN_bn2binpad(z, key, BN_num_bytes(dh->params.p)); 1031cb0ef41Sopenharmony_ci err: 1041cb0ef41Sopenharmony_ci BN_clear(z); /* (Step 2) destroy intermediate values */ 1051cb0ef41Sopenharmony_ci BN_CTX_end(ctx); 1061cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 1071cb0ef41Sopenharmony_ci return ret; 1081cb0ef41Sopenharmony_ci} 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci/*- 1111cb0ef41Sopenharmony_ci * NB: This function is inherently not constant time due to the 1121cb0ef41Sopenharmony_ci * RFC 5246 (8.1.2) padding style that strips leading zero bytes. 1131cb0ef41Sopenharmony_ci */ 1141cb0ef41Sopenharmony_ciint DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh) 1151cb0ef41Sopenharmony_ci{ 1161cb0ef41Sopenharmony_ci int ret = 0, i; 1171cb0ef41Sopenharmony_ci volatile size_t npad = 0, mask = 1; 1181cb0ef41Sopenharmony_ci 1191cb0ef41Sopenharmony_ci /* compute the key; ret is constant unless compute_key is external */ 1201cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE 1211cb0ef41Sopenharmony_ci ret = ossl_dh_compute_key(key, pub_key, dh); 1221cb0ef41Sopenharmony_ci#else 1231cb0ef41Sopenharmony_ci ret = dh->meth->compute_key(key, pub_key, dh); 1241cb0ef41Sopenharmony_ci#endif 1251cb0ef41Sopenharmony_ci if (ret <= 0) 1261cb0ef41Sopenharmony_ci return ret; 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci /* count leading zero bytes, yet still touch all bytes */ 1291cb0ef41Sopenharmony_ci for (i = 0; i < ret; i++) { 1301cb0ef41Sopenharmony_ci mask &= !key[i]; 1311cb0ef41Sopenharmony_ci npad += mask; 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci /* unpad key */ 1351cb0ef41Sopenharmony_ci ret -= npad; 1361cb0ef41Sopenharmony_ci /* key-dependent memory access, potentially leaking npad / ret */ 1371cb0ef41Sopenharmony_ci memmove(key, key + npad, ret); 1381cb0ef41Sopenharmony_ci /* key-dependent memory access, potentially leaking npad / ret */ 1391cb0ef41Sopenharmony_ci memset(key + ret, 0, npad); 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_ci return ret; 1421cb0ef41Sopenharmony_ci} 1431cb0ef41Sopenharmony_ci 1441cb0ef41Sopenharmony_ciint DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh) 1451cb0ef41Sopenharmony_ci{ 1461cb0ef41Sopenharmony_ci int rv, pad; 1471cb0ef41Sopenharmony_ci 1481cb0ef41Sopenharmony_ci /* rv is constant unless compute_key is external */ 1491cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE 1501cb0ef41Sopenharmony_ci rv = ossl_dh_compute_key(key, pub_key, dh); 1511cb0ef41Sopenharmony_ci#else 1521cb0ef41Sopenharmony_ci rv = dh->meth->compute_key(key, pub_key, dh); 1531cb0ef41Sopenharmony_ci#endif 1541cb0ef41Sopenharmony_ci if (rv <= 0) 1551cb0ef41Sopenharmony_ci return rv; 1561cb0ef41Sopenharmony_ci pad = BN_num_bytes(dh->params.p) - rv; 1571cb0ef41Sopenharmony_ci /* pad is constant (zero) unless compute_key is external */ 1581cb0ef41Sopenharmony_ci if (pad > 0) { 1591cb0ef41Sopenharmony_ci memmove(key + pad, key, rv); 1601cb0ef41Sopenharmony_ci memset(key, 0, pad); 1611cb0ef41Sopenharmony_ci } 1621cb0ef41Sopenharmony_ci return rv + pad; 1631cb0ef41Sopenharmony_ci} 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_cistatic DH_METHOD dh_ossl = { 1661cb0ef41Sopenharmony_ci "OpenSSL DH Method", 1671cb0ef41Sopenharmony_ci generate_key, 1681cb0ef41Sopenharmony_ci ossl_dh_compute_key, 1691cb0ef41Sopenharmony_ci dh_bn_mod_exp, 1701cb0ef41Sopenharmony_ci dh_init, 1711cb0ef41Sopenharmony_ci dh_finish, 1721cb0ef41Sopenharmony_ci DH_FLAG_FIPS_METHOD, 1731cb0ef41Sopenharmony_ci NULL, 1741cb0ef41Sopenharmony_ci NULL 1751cb0ef41Sopenharmony_ci}; 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_cistatic const DH_METHOD *default_DH_method = &dh_ossl; 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ciconst DH_METHOD *DH_OpenSSL(void) 1801cb0ef41Sopenharmony_ci{ 1811cb0ef41Sopenharmony_ci return &dh_ossl; 1821cb0ef41Sopenharmony_ci} 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ciconst DH_METHOD *DH_get_default_method(void) 1851cb0ef41Sopenharmony_ci{ 1861cb0ef41Sopenharmony_ci return default_DH_method; 1871cb0ef41Sopenharmony_ci} 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_cistatic int dh_bn_mod_exp(const DH *dh, BIGNUM *r, 1901cb0ef41Sopenharmony_ci const BIGNUM *a, const BIGNUM *p, 1911cb0ef41Sopenharmony_ci const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx) 1921cb0ef41Sopenharmony_ci{ 1931cb0ef41Sopenharmony_ci return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx); 1941cb0ef41Sopenharmony_ci} 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_cistatic int dh_init(DH *dh) 1971cb0ef41Sopenharmony_ci{ 1981cb0ef41Sopenharmony_ci dh->flags |= DH_FLAG_CACHE_MONT_P; 1991cb0ef41Sopenharmony_ci dh->dirty_cnt++; 2001cb0ef41Sopenharmony_ci return 1; 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_cistatic int dh_finish(DH *dh) 2041cb0ef41Sopenharmony_ci{ 2051cb0ef41Sopenharmony_ci BN_MONT_CTX_free(dh->method_mont_p); 2061cb0ef41Sopenharmony_ci return 1; 2071cb0ef41Sopenharmony_ci} 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE 2101cb0ef41Sopenharmony_civoid DH_set_default_method(const DH_METHOD *meth) 2111cb0ef41Sopenharmony_ci{ 2121cb0ef41Sopenharmony_ci default_DH_method = meth; 2131cb0ef41Sopenharmony_ci} 2141cb0ef41Sopenharmony_ci#endif /* FIPS_MODULE */ 2151cb0ef41Sopenharmony_ci 2161cb0ef41Sopenharmony_ciint DH_generate_key(DH *dh) 2171cb0ef41Sopenharmony_ci{ 2181cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE 2191cb0ef41Sopenharmony_ci return generate_key(dh); 2201cb0ef41Sopenharmony_ci#else 2211cb0ef41Sopenharmony_ci return dh->meth->generate_key(dh); 2221cb0ef41Sopenharmony_ci#endif 2231cb0ef41Sopenharmony_ci} 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ciint ossl_dh_generate_public_key(BN_CTX *ctx, const DH *dh, 2261cb0ef41Sopenharmony_ci const BIGNUM *priv_key, BIGNUM *pub_key) 2271cb0ef41Sopenharmony_ci{ 2281cb0ef41Sopenharmony_ci int ret = 0; 2291cb0ef41Sopenharmony_ci BIGNUM *prk = BN_new(); 2301cb0ef41Sopenharmony_ci BN_MONT_CTX *mont = NULL; 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci if (prk == NULL) 2331cb0ef41Sopenharmony_ci return 0; 2341cb0ef41Sopenharmony_ci 2351cb0ef41Sopenharmony_ci if (dh->flags & DH_FLAG_CACHE_MONT_P) { 2361cb0ef41Sopenharmony_ci /* 2371cb0ef41Sopenharmony_ci * We take the input DH as const, but we lie, because in some cases we 2381cb0ef41Sopenharmony_ci * want to get a hold of its Montgomery context. 2391cb0ef41Sopenharmony_ci * 2401cb0ef41Sopenharmony_ci * We cast to remove the const qualifier in this case, it should be 2411cb0ef41Sopenharmony_ci * fine... 2421cb0ef41Sopenharmony_ci */ 2431cb0ef41Sopenharmony_ci BN_MONT_CTX **pmont = (BN_MONT_CTX **)&dh->method_mont_p; 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci mont = BN_MONT_CTX_set_locked(pmont, dh->lock, dh->params.p, ctx); 2461cb0ef41Sopenharmony_ci if (mont == NULL) 2471cb0ef41Sopenharmony_ci goto err; 2481cb0ef41Sopenharmony_ci } 2491cb0ef41Sopenharmony_ci BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME); 2501cb0ef41Sopenharmony_ci 2511cb0ef41Sopenharmony_ci /* pub_key = g^priv_key mod p */ 2521cb0ef41Sopenharmony_ci if (!dh->meth->bn_mod_exp(dh, pub_key, dh->params.g, prk, dh->params.p, 2531cb0ef41Sopenharmony_ci ctx, mont)) 2541cb0ef41Sopenharmony_ci goto err; 2551cb0ef41Sopenharmony_ci ret = 1; 2561cb0ef41Sopenharmony_cierr: 2571cb0ef41Sopenharmony_ci BN_clear_free(prk); 2581cb0ef41Sopenharmony_ci return ret; 2591cb0ef41Sopenharmony_ci} 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_cistatic int generate_key(DH *dh) 2621cb0ef41Sopenharmony_ci{ 2631cb0ef41Sopenharmony_ci int ok = 0; 2641cb0ef41Sopenharmony_ci int generate_new_key = 0; 2651cb0ef41Sopenharmony_ci#ifndef FIPS_MODULE 2661cb0ef41Sopenharmony_ci unsigned l; 2671cb0ef41Sopenharmony_ci#endif 2681cb0ef41Sopenharmony_ci BN_CTX *ctx = NULL; 2691cb0ef41Sopenharmony_ci BIGNUM *pub_key = NULL, *priv_key = NULL; 2701cb0ef41Sopenharmony_ci 2711cb0ef41Sopenharmony_ci if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) { 2721cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 2731cb0ef41Sopenharmony_ci return 0; 2741cb0ef41Sopenharmony_ci } 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci if (dh->params.q != NULL 2771cb0ef41Sopenharmony_ci && BN_num_bits(dh->params.q) > OPENSSL_DH_MAX_MODULUS_BITS) { 2781cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_Q_TOO_LARGE); 2791cb0ef41Sopenharmony_ci return 0; 2801cb0ef41Sopenharmony_ci } 2811cb0ef41Sopenharmony_ci 2821cb0ef41Sopenharmony_ci if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) { 2831cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL); 2841cb0ef41Sopenharmony_ci return 0; 2851cb0ef41Sopenharmony_ci } 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci ctx = BN_CTX_new_ex(dh->libctx); 2881cb0ef41Sopenharmony_ci if (ctx == NULL) 2891cb0ef41Sopenharmony_ci goto err; 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci if (dh->priv_key == NULL) { 2921cb0ef41Sopenharmony_ci priv_key = BN_secure_new(); 2931cb0ef41Sopenharmony_ci if (priv_key == NULL) 2941cb0ef41Sopenharmony_ci goto err; 2951cb0ef41Sopenharmony_ci generate_new_key = 1; 2961cb0ef41Sopenharmony_ci } else { 2971cb0ef41Sopenharmony_ci priv_key = dh->priv_key; 2981cb0ef41Sopenharmony_ci } 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci if (dh->pub_key == NULL) { 3011cb0ef41Sopenharmony_ci pub_key = BN_new(); 3021cb0ef41Sopenharmony_ci if (pub_key == NULL) 3031cb0ef41Sopenharmony_ci goto err; 3041cb0ef41Sopenharmony_ci } else { 3051cb0ef41Sopenharmony_ci pub_key = dh->pub_key; 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci if (generate_new_key) { 3081cb0ef41Sopenharmony_ci /* Is it an approved safe prime ?*/ 3091cb0ef41Sopenharmony_ci if (DH_get_nid(dh) != NID_undef) { 3101cb0ef41Sopenharmony_ci int max_strength = 3111cb0ef41Sopenharmony_ci ossl_ifc_ffc_compute_security_bits(BN_num_bits(dh->params.p)); 3121cb0ef41Sopenharmony_ci 3131cb0ef41Sopenharmony_ci if (dh->params.q == NULL 3141cb0ef41Sopenharmony_ci || dh->length > BN_num_bits(dh->params.q)) 3151cb0ef41Sopenharmony_ci goto err; 3161cb0ef41Sopenharmony_ci /* dh->length = maximum bit length of generated private key */ 3171cb0ef41Sopenharmony_ci if (!ossl_ffc_generate_private_key(ctx, &dh->params, dh->length, 3181cb0ef41Sopenharmony_ci max_strength, priv_key)) 3191cb0ef41Sopenharmony_ci goto err; 3201cb0ef41Sopenharmony_ci } else { 3211cb0ef41Sopenharmony_ci#ifdef FIPS_MODULE 3221cb0ef41Sopenharmony_ci if (dh->params.q == NULL) 3231cb0ef41Sopenharmony_ci goto err; 3241cb0ef41Sopenharmony_ci#else 3251cb0ef41Sopenharmony_ci if (dh->params.q == NULL) { 3261cb0ef41Sopenharmony_ci /* secret exponent length, must satisfy 2^(l-1) <= p */ 3271cb0ef41Sopenharmony_ci if (dh->length != 0 3281cb0ef41Sopenharmony_ci && dh->length >= BN_num_bits(dh->params.p)) 3291cb0ef41Sopenharmony_ci goto err; 3301cb0ef41Sopenharmony_ci l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1; 3311cb0ef41Sopenharmony_ci if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE, 3321cb0ef41Sopenharmony_ci BN_RAND_BOTTOM_ANY, 0, ctx)) 3331cb0ef41Sopenharmony_ci goto err; 3341cb0ef41Sopenharmony_ci /* 3351cb0ef41Sopenharmony_ci * We handle just one known case where g is a quadratic non-residue: 3361cb0ef41Sopenharmony_ci * for g = 2: p % 8 == 3 3371cb0ef41Sopenharmony_ci */ 3381cb0ef41Sopenharmony_ci if (BN_is_word(dh->params.g, DH_GENERATOR_2) 3391cb0ef41Sopenharmony_ci && !BN_is_bit_set(dh->params.p, 2)) { 3401cb0ef41Sopenharmony_ci /* clear bit 0, since it won't be a secret anyway */ 3411cb0ef41Sopenharmony_ci if (!BN_clear_bit(priv_key, 0)) 3421cb0ef41Sopenharmony_ci goto err; 3431cb0ef41Sopenharmony_ci } 3441cb0ef41Sopenharmony_ci } else 3451cb0ef41Sopenharmony_ci#endif 3461cb0ef41Sopenharmony_ci { 3471cb0ef41Sopenharmony_ci /* Do a partial check for invalid p, q, g */ 3481cb0ef41Sopenharmony_ci if (!ossl_ffc_params_simple_validate(dh->libctx, &dh->params, 3491cb0ef41Sopenharmony_ci FFC_PARAM_TYPE_DH, NULL)) 3501cb0ef41Sopenharmony_ci goto err; 3511cb0ef41Sopenharmony_ci /* 3521cb0ef41Sopenharmony_ci * For FFC FIPS 186-4 keygen 3531cb0ef41Sopenharmony_ci * security strength s = 112, 3541cb0ef41Sopenharmony_ci * Max Private key size N = len(q) 3551cb0ef41Sopenharmony_ci */ 3561cb0ef41Sopenharmony_ci if (!ossl_ffc_generate_private_key(ctx, &dh->params, 3571cb0ef41Sopenharmony_ci BN_num_bits(dh->params.q), 3581cb0ef41Sopenharmony_ci MIN_STRENGTH, 3591cb0ef41Sopenharmony_ci priv_key)) 3601cb0ef41Sopenharmony_ci goto err; 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci } 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci if (!ossl_dh_generate_public_key(ctx, dh, priv_key, pub_key)) 3661cb0ef41Sopenharmony_ci goto err; 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci dh->pub_key = pub_key; 3691cb0ef41Sopenharmony_ci dh->priv_key = priv_key; 3701cb0ef41Sopenharmony_ci dh->dirty_cnt++; 3711cb0ef41Sopenharmony_ci ok = 1; 3721cb0ef41Sopenharmony_ci err: 3731cb0ef41Sopenharmony_ci if (ok != 1) 3741cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_BN_LIB); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci if (pub_key != dh->pub_key) 3771cb0ef41Sopenharmony_ci BN_free(pub_key); 3781cb0ef41Sopenharmony_ci if (priv_key != dh->priv_key) 3791cb0ef41Sopenharmony_ci BN_free(priv_key); 3801cb0ef41Sopenharmony_ci BN_CTX_free(ctx); 3811cb0ef41Sopenharmony_ci return ok; 3821cb0ef41Sopenharmony_ci} 3831cb0ef41Sopenharmony_ci 3841cb0ef41Sopenharmony_ciint ossl_dh_buf2key(DH *dh, const unsigned char *buf, size_t len) 3851cb0ef41Sopenharmony_ci{ 3861cb0ef41Sopenharmony_ci int err_reason = DH_R_BN_ERROR; 3871cb0ef41Sopenharmony_ci BIGNUM *pubkey = NULL; 3881cb0ef41Sopenharmony_ci const BIGNUM *p; 3891cb0ef41Sopenharmony_ci int ret; 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci if ((pubkey = BN_bin2bn(buf, len, NULL)) == NULL) 3921cb0ef41Sopenharmony_ci goto err; 3931cb0ef41Sopenharmony_ci DH_get0_pqg(dh, &p, NULL, NULL); 3941cb0ef41Sopenharmony_ci if (p == NULL || BN_num_bytes(p) == 0) { 3951cb0ef41Sopenharmony_ci err_reason = DH_R_NO_PARAMETERS_SET; 3961cb0ef41Sopenharmony_ci goto err; 3971cb0ef41Sopenharmony_ci } 3981cb0ef41Sopenharmony_ci /* Prevent small subgroup attacks per RFC 8446 Section 4.2.8.1 */ 3991cb0ef41Sopenharmony_ci if (!ossl_dh_check_pub_key_partial(dh, pubkey, &ret)) { 4001cb0ef41Sopenharmony_ci err_reason = DH_R_INVALID_PUBKEY; 4011cb0ef41Sopenharmony_ci goto err; 4021cb0ef41Sopenharmony_ci } 4031cb0ef41Sopenharmony_ci if (DH_set0_key(dh, pubkey, NULL) != 1) 4041cb0ef41Sopenharmony_ci goto err; 4051cb0ef41Sopenharmony_ci return 1; 4061cb0ef41Sopenharmony_cierr: 4071cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, err_reason); 4081cb0ef41Sopenharmony_ci BN_free(pubkey); 4091cb0ef41Sopenharmony_ci return 0; 4101cb0ef41Sopenharmony_ci} 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_cisize_t ossl_dh_key2buf(const DH *dh, unsigned char **pbuf_out, size_t size, 4131cb0ef41Sopenharmony_ci int alloc) 4141cb0ef41Sopenharmony_ci{ 4151cb0ef41Sopenharmony_ci const BIGNUM *pubkey; 4161cb0ef41Sopenharmony_ci unsigned char *pbuf = NULL; 4171cb0ef41Sopenharmony_ci const BIGNUM *p; 4181cb0ef41Sopenharmony_ci int p_size; 4191cb0ef41Sopenharmony_ci 4201cb0ef41Sopenharmony_ci DH_get0_pqg(dh, &p, NULL, NULL); 4211cb0ef41Sopenharmony_ci DH_get0_key(dh, &pubkey, NULL); 4221cb0ef41Sopenharmony_ci if (p == NULL || pubkey == NULL 4231cb0ef41Sopenharmony_ci || (p_size = BN_num_bytes(p)) == 0 4241cb0ef41Sopenharmony_ci || BN_num_bytes(pubkey) == 0) { 4251cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_INVALID_PUBKEY); 4261cb0ef41Sopenharmony_ci return 0; 4271cb0ef41Sopenharmony_ci } 4281cb0ef41Sopenharmony_ci if (pbuf_out != NULL && (alloc || *pbuf_out != NULL)) { 4291cb0ef41Sopenharmony_ci if (!alloc) { 4301cb0ef41Sopenharmony_ci if (size >= (size_t)p_size) 4311cb0ef41Sopenharmony_ci pbuf = *pbuf_out; 4321cb0ef41Sopenharmony_ci } else { 4331cb0ef41Sopenharmony_ci pbuf = OPENSSL_malloc(p_size); 4341cb0ef41Sopenharmony_ci } 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci if (pbuf == NULL) { 4371cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 4381cb0ef41Sopenharmony_ci return 0; 4391cb0ef41Sopenharmony_ci } 4401cb0ef41Sopenharmony_ci /* 4411cb0ef41Sopenharmony_ci * As per Section 4.2.8.1 of RFC 8446 left pad public 4421cb0ef41Sopenharmony_ci * key with zeros to the size of p 4431cb0ef41Sopenharmony_ci */ 4441cb0ef41Sopenharmony_ci if (BN_bn2binpad(pubkey, pbuf, p_size) < 0) { 4451cb0ef41Sopenharmony_ci if (alloc) 4461cb0ef41Sopenharmony_ci OPENSSL_free(pbuf); 4471cb0ef41Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_BN_ERROR); 4481cb0ef41Sopenharmony_ci return 0; 4491cb0ef41Sopenharmony_ci } 4501cb0ef41Sopenharmony_ci *pbuf_out = pbuf; 4511cb0ef41Sopenharmony_ci } 4521cb0ef41Sopenharmony_ci return p_size; 4531cb0ef41Sopenharmony_ci} 454