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 <openssl/bn.h> 19e1051a39Sopenharmony_ci#include "dh_local.h" 20e1051a39Sopenharmony_ci#include "crypto/dh.h" 21e1051a39Sopenharmony_ci 22e1051a39Sopenharmony_ci/*- 23e1051a39Sopenharmony_ci * Check that p and g are suitable enough 24e1051a39Sopenharmony_ci * 25e1051a39Sopenharmony_ci * p is odd 26e1051a39Sopenharmony_ci * 1 < g < p - 1 27e1051a39Sopenharmony_ci */ 28e1051a39Sopenharmony_ciint DH_check_params_ex(const DH *dh) 29e1051a39Sopenharmony_ci{ 30e1051a39Sopenharmony_ci int errflags = 0; 31e1051a39Sopenharmony_ci 32e1051a39Sopenharmony_ci if (!DH_check_params(dh, &errflags)) 33e1051a39Sopenharmony_ci return 0; 34e1051a39Sopenharmony_ci 35e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) 36e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME); 37e1051a39Sopenharmony_ci if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) 38e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR); 39e1051a39Sopenharmony_ci if ((errflags & DH_MODULUS_TOO_SMALL) != 0) 40e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL); 41e1051a39Sopenharmony_ci if ((errflags & DH_MODULUS_TOO_LARGE) != 0) 42e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 43e1051a39Sopenharmony_ci 44e1051a39Sopenharmony_ci return errflags == 0; 45e1051a39Sopenharmony_ci} 46e1051a39Sopenharmony_ci 47e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 48e1051a39Sopenharmony_ciint DH_check_params(const DH *dh, int *ret) 49e1051a39Sopenharmony_ci{ 50e1051a39Sopenharmony_ci int nid; 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ci *ret = 0; 53e1051a39Sopenharmony_ci /* 54e1051a39Sopenharmony_ci * SP800-56A R3 Section 5.5.2 Assurances of Domain Parameter Validity 55e1051a39Sopenharmony_ci * (1a) The domain parameters correspond to any approved safe prime group. 56e1051a39Sopenharmony_ci */ 57e1051a39Sopenharmony_ci nid = DH_get_nid((DH *)dh); 58e1051a39Sopenharmony_ci if (nid != NID_undef) 59e1051a39Sopenharmony_ci return 1; 60e1051a39Sopenharmony_ci /* 61e1051a39Sopenharmony_ci * OR 62e1051a39Sopenharmony_ci * (2b) FFC domain params conform to FIPS-186-4 explicit domain param 63e1051a39Sopenharmony_ci * validity tests. 64e1051a39Sopenharmony_ci */ 65e1051a39Sopenharmony_ci return ossl_ffc_params_FIPS186_4_validate(dh->libctx, &dh->params, 66e1051a39Sopenharmony_ci FFC_PARAM_TYPE_DH, ret, NULL); 67e1051a39Sopenharmony_ci} 68e1051a39Sopenharmony_ci#else 69e1051a39Sopenharmony_ciint DH_check_params(const DH *dh, int *ret) 70e1051a39Sopenharmony_ci{ 71e1051a39Sopenharmony_ci int ok = 0; 72e1051a39Sopenharmony_ci BIGNUM *tmp = NULL; 73e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 74e1051a39Sopenharmony_ci 75e1051a39Sopenharmony_ci *ret = 0; 76e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(dh->libctx); 77e1051a39Sopenharmony_ci if (ctx == NULL) 78e1051a39Sopenharmony_ci goto err; 79e1051a39Sopenharmony_ci BN_CTX_start(ctx); 80e1051a39Sopenharmony_ci tmp = BN_CTX_get(ctx); 81e1051a39Sopenharmony_ci if (tmp == NULL) 82e1051a39Sopenharmony_ci goto err; 83e1051a39Sopenharmony_ci 84e1051a39Sopenharmony_ci if (!BN_is_odd(dh->params.p)) 85e1051a39Sopenharmony_ci *ret |= DH_CHECK_P_NOT_PRIME; 86e1051a39Sopenharmony_ci if (BN_is_negative(dh->params.g) 87e1051a39Sopenharmony_ci || BN_is_zero(dh->params.g) 88e1051a39Sopenharmony_ci || BN_is_one(dh->params.g)) 89e1051a39Sopenharmony_ci *ret |= DH_NOT_SUITABLE_GENERATOR; 90e1051a39Sopenharmony_ci if (BN_copy(tmp, dh->params.p) == NULL || !BN_sub_word(tmp, 1)) 91e1051a39Sopenharmony_ci goto err; 92e1051a39Sopenharmony_ci if (BN_cmp(dh->params.g, tmp) >= 0) 93e1051a39Sopenharmony_ci *ret |= DH_NOT_SUITABLE_GENERATOR; 94e1051a39Sopenharmony_ci if (BN_num_bits(dh->params.p) < DH_MIN_MODULUS_BITS) 95e1051a39Sopenharmony_ci *ret |= DH_MODULUS_TOO_SMALL; 96e1051a39Sopenharmony_ci if (BN_num_bits(dh->params.p) > OPENSSL_DH_MAX_MODULUS_BITS) 97e1051a39Sopenharmony_ci *ret |= DH_MODULUS_TOO_LARGE; 98e1051a39Sopenharmony_ci 99e1051a39Sopenharmony_ci ok = 1; 100e1051a39Sopenharmony_ci err: 101e1051a39Sopenharmony_ci BN_CTX_end(ctx); 102e1051a39Sopenharmony_ci BN_CTX_free(ctx); 103e1051a39Sopenharmony_ci return ok; 104e1051a39Sopenharmony_ci} 105e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 106e1051a39Sopenharmony_ci 107e1051a39Sopenharmony_ci/*- 108e1051a39Sopenharmony_ci * Check that p is a safe prime and 109e1051a39Sopenharmony_ci * g is a suitable generator. 110e1051a39Sopenharmony_ci */ 111e1051a39Sopenharmony_ciint DH_check_ex(const DH *dh) 112e1051a39Sopenharmony_ci{ 113e1051a39Sopenharmony_ci int errflags = 0; 114e1051a39Sopenharmony_ci 115e1051a39Sopenharmony_ci if (!DH_check(dh, &errflags)) 116e1051a39Sopenharmony_ci return 0; 117e1051a39Sopenharmony_ci 118e1051a39Sopenharmony_ci if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0) 119e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_NOT_SUITABLE_GENERATOR); 120e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0) 121e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_Q_NOT_PRIME); 122e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0) 123e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_Q_VALUE); 124e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0) 125e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_INVALID_J_VALUE); 126e1051a39Sopenharmony_ci if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0) 127e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_UNABLE_TO_CHECK_GENERATOR); 128e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_P_NOT_PRIME) != 0) 129e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_PRIME); 130e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0) 131e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_P_NOT_SAFE_PRIME); 132e1051a39Sopenharmony_ci if ((errflags & DH_MODULUS_TOO_SMALL) != 0) 133e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_SMALL); 134e1051a39Sopenharmony_ci if ((errflags & DH_MODULUS_TOO_LARGE) != 0) 135e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 136e1051a39Sopenharmony_ci 137e1051a39Sopenharmony_ci return errflags == 0; 138e1051a39Sopenharmony_ci} 139e1051a39Sopenharmony_ci 140e1051a39Sopenharmony_ci/* Note: according to documentation - this only checks the params */ 141e1051a39Sopenharmony_ciint DH_check(const DH *dh, int *ret) 142e1051a39Sopenharmony_ci{ 143e1051a39Sopenharmony_ci#ifdef FIPS_MODULE 144e1051a39Sopenharmony_ci return DH_check_params(dh, ret); 145e1051a39Sopenharmony_ci#else 146e1051a39Sopenharmony_ci int ok = 0, r, q_good = 0; 147e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 148e1051a39Sopenharmony_ci BIGNUM *t1 = NULL, *t2 = NULL; 149e1051a39Sopenharmony_ci int nid = DH_get_nid((DH *)dh); 150e1051a39Sopenharmony_ci 151e1051a39Sopenharmony_ci *ret = 0; 152e1051a39Sopenharmony_ci if (nid != NID_undef) 153e1051a39Sopenharmony_ci return 1; 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci /* Don't do any checks at all with an excessively large modulus */ 156e1051a39Sopenharmony_ci if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) { 157e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 158e1051a39Sopenharmony_ci return 0; 159e1051a39Sopenharmony_ci } 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ci if (!DH_check_params(dh, ret)) 162e1051a39Sopenharmony_ci return 0; 163e1051a39Sopenharmony_ci 164e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(dh->libctx); 165e1051a39Sopenharmony_ci if (ctx == NULL) 166e1051a39Sopenharmony_ci goto err; 167e1051a39Sopenharmony_ci BN_CTX_start(ctx); 168e1051a39Sopenharmony_ci t1 = BN_CTX_get(ctx); 169e1051a39Sopenharmony_ci t2 = BN_CTX_get(ctx); 170e1051a39Sopenharmony_ci if (t2 == NULL) 171e1051a39Sopenharmony_ci goto err; 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_ci if (dh->params.q != NULL) { 174e1051a39Sopenharmony_ci if (BN_ucmp(dh->params.p, dh->params.q) > 0) 175e1051a39Sopenharmony_ci q_good = 1; 176e1051a39Sopenharmony_ci else 177e1051a39Sopenharmony_ci *ret |= DH_CHECK_INVALID_Q_VALUE; 178e1051a39Sopenharmony_ci } 179e1051a39Sopenharmony_ci 180e1051a39Sopenharmony_ci if (q_good) { 181e1051a39Sopenharmony_ci if (BN_cmp(dh->params.g, BN_value_one()) <= 0) 182e1051a39Sopenharmony_ci *ret |= DH_NOT_SUITABLE_GENERATOR; 183e1051a39Sopenharmony_ci else if (BN_cmp(dh->params.g, dh->params.p) >= 0) 184e1051a39Sopenharmony_ci *ret |= DH_NOT_SUITABLE_GENERATOR; 185e1051a39Sopenharmony_ci else { 186e1051a39Sopenharmony_ci /* Check g^q == 1 mod p */ 187e1051a39Sopenharmony_ci if (!BN_mod_exp(t1, dh->params.g, dh->params.q, dh->params.p, ctx)) 188e1051a39Sopenharmony_ci goto err; 189e1051a39Sopenharmony_ci if (!BN_is_one(t1)) 190e1051a39Sopenharmony_ci *ret |= DH_NOT_SUITABLE_GENERATOR; 191e1051a39Sopenharmony_ci } 192e1051a39Sopenharmony_ci r = BN_check_prime(dh->params.q, ctx, NULL); 193e1051a39Sopenharmony_ci if (r < 0) 194e1051a39Sopenharmony_ci goto err; 195e1051a39Sopenharmony_ci if (!r) 196e1051a39Sopenharmony_ci *ret |= DH_CHECK_Q_NOT_PRIME; 197e1051a39Sopenharmony_ci /* Check p == 1 mod q i.e. q divides p - 1 */ 198e1051a39Sopenharmony_ci if (!BN_div(t1, t2, dh->params.p, dh->params.q, ctx)) 199e1051a39Sopenharmony_ci goto err; 200e1051a39Sopenharmony_ci if (!BN_is_one(t2)) 201e1051a39Sopenharmony_ci *ret |= DH_CHECK_INVALID_Q_VALUE; 202e1051a39Sopenharmony_ci if (dh->params.j != NULL 203e1051a39Sopenharmony_ci && BN_cmp(dh->params.j, t1)) 204e1051a39Sopenharmony_ci *ret |= DH_CHECK_INVALID_J_VALUE; 205e1051a39Sopenharmony_ci } 206e1051a39Sopenharmony_ci 207e1051a39Sopenharmony_ci r = BN_check_prime(dh->params.p, ctx, NULL); 208e1051a39Sopenharmony_ci if (r < 0) 209e1051a39Sopenharmony_ci goto err; 210e1051a39Sopenharmony_ci if (!r) 211e1051a39Sopenharmony_ci *ret |= DH_CHECK_P_NOT_PRIME; 212e1051a39Sopenharmony_ci else if (dh->params.q == NULL) { 213e1051a39Sopenharmony_ci if (!BN_rshift1(t1, dh->params.p)) 214e1051a39Sopenharmony_ci goto err; 215e1051a39Sopenharmony_ci r = BN_check_prime(t1, ctx, NULL); 216e1051a39Sopenharmony_ci if (r < 0) 217e1051a39Sopenharmony_ci goto err; 218e1051a39Sopenharmony_ci if (!r) 219e1051a39Sopenharmony_ci *ret |= DH_CHECK_P_NOT_SAFE_PRIME; 220e1051a39Sopenharmony_ci } 221e1051a39Sopenharmony_ci ok = 1; 222e1051a39Sopenharmony_ci err: 223e1051a39Sopenharmony_ci BN_CTX_end(ctx); 224e1051a39Sopenharmony_ci BN_CTX_free(ctx); 225e1051a39Sopenharmony_ci return ok; 226e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 227e1051a39Sopenharmony_ci} 228e1051a39Sopenharmony_ci 229e1051a39Sopenharmony_ciint DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key) 230e1051a39Sopenharmony_ci{ 231e1051a39Sopenharmony_ci int errflags = 0; 232e1051a39Sopenharmony_ci 233e1051a39Sopenharmony_ci if (!DH_check_pub_key(dh, pub_key, &errflags)) 234e1051a39Sopenharmony_ci return 0; 235e1051a39Sopenharmony_ci 236e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0) 237e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_SMALL); 238e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0) 239e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_TOO_LARGE); 240e1051a39Sopenharmony_ci if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0) 241e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_CHECK_PUBKEY_INVALID); 242e1051a39Sopenharmony_ci 243e1051a39Sopenharmony_ci return errflags == 0; 244e1051a39Sopenharmony_ci} 245e1051a39Sopenharmony_ci 246e1051a39Sopenharmony_ci/* 247e1051a39Sopenharmony_ci * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation. 248e1051a39Sopenharmony_ci */ 249e1051a39Sopenharmony_ciint DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret) 250e1051a39Sopenharmony_ci{ 251e1051a39Sopenharmony_ci /* Don't do any checks at all with an excessively large modulus */ 252e1051a39Sopenharmony_ci if (BN_num_bits(dh->params.p) > OPENSSL_DH_CHECK_MAX_MODULUS_BITS) { 253e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, DH_R_MODULUS_TOO_LARGE); 254e1051a39Sopenharmony_ci *ret = DH_MODULUS_TOO_LARGE | DH_CHECK_PUBKEY_INVALID; 255e1051a39Sopenharmony_ci return 0; 256e1051a39Sopenharmony_ci } 257e1051a39Sopenharmony_ci 258e1051a39Sopenharmony_ci if (dh->params.q != NULL && BN_ucmp(dh->params.p, dh->params.q) < 0) { 259e1051a39Sopenharmony_ci *ret |= DH_CHECK_INVALID_Q_VALUE | DH_CHECK_PUBKEY_INVALID; 260e1051a39Sopenharmony_ci return 1; 261e1051a39Sopenharmony_ci } 262e1051a39Sopenharmony_ci 263e1051a39Sopenharmony_ci return ossl_ffc_validate_public_key(&dh->params, pub_key, ret); 264e1051a39Sopenharmony_ci} 265e1051a39Sopenharmony_ci 266e1051a39Sopenharmony_ci/* 267e1051a39Sopenharmony_ci * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation. 268e1051a39Sopenharmony_ci * To only be used with ephemeral FFC public keys generated using the approved 269e1051a39Sopenharmony_ci * safe-prime groups. 270e1051a39Sopenharmony_ci */ 271e1051a39Sopenharmony_ciint ossl_dh_check_pub_key_partial(const DH *dh, const BIGNUM *pub_key, int *ret) 272e1051a39Sopenharmony_ci{ 273e1051a39Sopenharmony_ci return ossl_ffc_validate_public_key_partial(&dh->params, pub_key, ret); 274e1051a39Sopenharmony_ci} 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ciint ossl_dh_check_priv_key(const DH *dh, const BIGNUM *priv_key, int *ret) 277e1051a39Sopenharmony_ci{ 278e1051a39Sopenharmony_ci int ok = 0; 279e1051a39Sopenharmony_ci BIGNUM *two_powN = NULL, *upper; 280e1051a39Sopenharmony_ci 281e1051a39Sopenharmony_ci *ret = 0; 282e1051a39Sopenharmony_ci two_powN = BN_new(); 283e1051a39Sopenharmony_ci if (two_powN == NULL) 284e1051a39Sopenharmony_ci return 0; 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ci if (dh->params.q != NULL) { 287e1051a39Sopenharmony_ci upper = dh->params.q; 288e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 289e1051a39Sopenharmony_ci } else if (dh->params.p != NULL) { 290e1051a39Sopenharmony_ci /* 291e1051a39Sopenharmony_ci * We do not have q so we just check the key is within some 292e1051a39Sopenharmony_ci * reasonable range, or the number of bits is equal to dh->length. 293e1051a39Sopenharmony_ci */ 294e1051a39Sopenharmony_ci int length = dh->length; 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ci if (length == 0) { 297e1051a39Sopenharmony_ci length = BN_num_bits(dh->params.p) - 1; 298e1051a39Sopenharmony_ci if (BN_num_bits(priv_key) <= length 299e1051a39Sopenharmony_ci && BN_num_bits(priv_key) > 1) 300e1051a39Sopenharmony_ci ok = 1; 301e1051a39Sopenharmony_ci } else if (BN_num_bits(priv_key) == length) { 302e1051a39Sopenharmony_ci ok = 1; 303e1051a39Sopenharmony_ci } 304e1051a39Sopenharmony_ci goto end; 305e1051a39Sopenharmony_ci#endif 306e1051a39Sopenharmony_ci } else { 307e1051a39Sopenharmony_ci goto end; 308e1051a39Sopenharmony_ci } 309e1051a39Sopenharmony_ci 310e1051a39Sopenharmony_ci /* Is it from an approved Safe prime group ?*/ 311e1051a39Sopenharmony_ci if (DH_get_nid((DH *)dh) != NID_undef && dh->length != 0) { 312e1051a39Sopenharmony_ci if (!BN_lshift(two_powN, BN_value_one(), dh->length)) 313e1051a39Sopenharmony_ci goto end; 314e1051a39Sopenharmony_ci if (BN_cmp(two_powN, dh->params.q) < 0) 315e1051a39Sopenharmony_ci upper = two_powN; 316e1051a39Sopenharmony_ci } 317e1051a39Sopenharmony_ci if (!ossl_ffc_validate_private_key(upper, priv_key, ret)) 318e1051a39Sopenharmony_ci goto end; 319e1051a39Sopenharmony_ci 320e1051a39Sopenharmony_ci ok = 1; 321e1051a39Sopenharmony_ciend: 322e1051a39Sopenharmony_ci BN_free(two_powN); 323e1051a39Sopenharmony_ci return ok; 324e1051a39Sopenharmony_ci} 325e1051a39Sopenharmony_ci 326e1051a39Sopenharmony_ci/* 327e1051a39Sopenharmony_ci * FFC pairwise check from SP800-56A R3. 328e1051a39Sopenharmony_ci * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency 329e1051a39Sopenharmony_ci */ 330e1051a39Sopenharmony_ciint ossl_dh_check_pairwise(const DH *dh) 331e1051a39Sopenharmony_ci{ 332e1051a39Sopenharmony_ci int ret = 0; 333e1051a39Sopenharmony_ci BN_CTX *ctx = NULL; 334e1051a39Sopenharmony_ci BIGNUM *pub_key = NULL; 335e1051a39Sopenharmony_ci 336e1051a39Sopenharmony_ci if (dh->params.p == NULL 337e1051a39Sopenharmony_ci || dh->params.g == NULL 338e1051a39Sopenharmony_ci || dh->priv_key == NULL 339e1051a39Sopenharmony_ci || dh->pub_key == NULL) 340e1051a39Sopenharmony_ci return 0; 341e1051a39Sopenharmony_ci 342e1051a39Sopenharmony_ci ctx = BN_CTX_new_ex(dh->libctx); 343e1051a39Sopenharmony_ci if (ctx == NULL) 344e1051a39Sopenharmony_ci goto err; 345e1051a39Sopenharmony_ci pub_key = BN_new(); 346e1051a39Sopenharmony_ci if (pub_key == NULL) 347e1051a39Sopenharmony_ci goto err; 348e1051a39Sopenharmony_ci 349e1051a39Sopenharmony_ci /* recalculate the public key = (g ^ priv) mod p */ 350e1051a39Sopenharmony_ci if (!ossl_dh_generate_public_key(ctx, dh, dh->priv_key, pub_key)) 351e1051a39Sopenharmony_ci goto err; 352e1051a39Sopenharmony_ci /* check it matches the existing pubic_key */ 353e1051a39Sopenharmony_ci ret = BN_cmp(pub_key, dh->pub_key) == 0; 354e1051a39Sopenharmony_cierr: 355e1051a39Sopenharmony_ci BN_free(pub_key); 356e1051a39Sopenharmony_ci BN_CTX_free(ctx); 357e1051a39Sopenharmony_ci return ret; 358e1051a39Sopenharmony_ci} 359