1e1051a39Sopenharmony_ci/* 2e1051a39Sopenharmony_ci * Copyright 1995-2021 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 <openssl/bn.h> 18e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 19e1051a39Sopenharmony_ci# include <openssl/engine.h> 20e1051a39Sopenharmony_ci#endif 21e1051a39Sopenharmony_ci#include <openssl/obj_mac.h> 22e1051a39Sopenharmony_ci#include <openssl/core_names.h> 23e1051a39Sopenharmony_ci#include "internal/cryptlib.h" 24e1051a39Sopenharmony_ci#include "internal/refcount.h" 25e1051a39Sopenharmony_ci#include "crypto/evp.h" 26e1051a39Sopenharmony_ci#include "crypto/dh.h" 27e1051a39Sopenharmony_ci#include "dh_local.h" 28e1051a39Sopenharmony_ci 29e1051a39Sopenharmony_cistatic DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx); 30e1051a39Sopenharmony_ci 31e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 32e1051a39Sopenharmony_ciint DH_set_method(DH *dh, const DH_METHOD *meth) 33e1051a39Sopenharmony_ci{ 34e1051a39Sopenharmony_ci /* 35e1051a39Sopenharmony_ci * NB: The caller is specifically setting a method, so it's not up to us 36e1051a39Sopenharmony_ci * to deal with which ENGINE it comes from. 37e1051a39Sopenharmony_ci */ 38e1051a39Sopenharmony_ci const DH_METHOD *mtmp; 39e1051a39Sopenharmony_ci mtmp = dh->meth; 40e1051a39Sopenharmony_ci if (mtmp->finish) 41e1051a39Sopenharmony_ci mtmp->finish(dh); 42e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE 43e1051a39Sopenharmony_ci ENGINE_finish(dh->engine); 44e1051a39Sopenharmony_ci dh->engine = NULL; 45e1051a39Sopenharmony_ci#endif 46e1051a39Sopenharmony_ci dh->meth = meth; 47e1051a39Sopenharmony_ci if (meth->init) 48e1051a39Sopenharmony_ci meth->init(dh); 49e1051a39Sopenharmony_ci return 1; 50e1051a39Sopenharmony_ci} 51e1051a39Sopenharmony_ci 52e1051a39Sopenharmony_ciconst DH_METHOD *ossl_dh_get_method(const DH *dh) 53e1051a39Sopenharmony_ci{ 54e1051a39Sopenharmony_ci return dh->meth; 55e1051a39Sopenharmony_ci} 56e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DEPRECATED_3_0 57e1051a39Sopenharmony_ciDH *DH_new(void) 58e1051a39Sopenharmony_ci{ 59e1051a39Sopenharmony_ci return dh_new_intern(NULL, NULL); 60e1051a39Sopenharmony_ci} 61e1051a39Sopenharmony_ci# endif 62e1051a39Sopenharmony_ci 63e1051a39Sopenharmony_ciDH *DH_new_method(ENGINE *engine) 64e1051a39Sopenharmony_ci{ 65e1051a39Sopenharmony_ci return dh_new_intern(engine, NULL); 66e1051a39Sopenharmony_ci} 67e1051a39Sopenharmony_ci#endif /* !FIPS_MODULE */ 68e1051a39Sopenharmony_ci 69e1051a39Sopenharmony_ciDH *ossl_dh_new_ex(OSSL_LIB_CTX *libctx) 70e1051a39Sopenharmony_ci{ 71e1051a39Sopenharmony_ci return dh_new_intern(NULL, libctx); 72e1051a39Sopenharmony_ci} 73e1051a39Sopenharmony_ci 74e1051a39Sopenharmony_cistatic DH *dh_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx) 75e1051a39Sopenharmony_ci{ 76e1051a39Sopenharmony_ci DH *ret = OPENSSL_zalloc(sizeof(*ret)); 77e1051a39Sopenharmony_ci 78e1051a39Sopenharmony_ci if (ret == NULL) { 79e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 80e1051a39Sopenharmony_ci return NULL; 81e1051a39Sopenharmony_ci } 82e1051a39Sopenharmony_ci 83e1051a39Sopenharmony_ci ret->references = 1; 84e1051a39Sopenharmony_ci ret->lock = CRYPTO_THREAD_lock_new(); 85e1051a39Sopenharmony_ci if (ret->lock == NULL) { 86e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); 87e1051a39Sopenharmony_ci OPENSSL_free(ret); 88e1051a39Sopenharmony_ci return NULL; 89e1051a39Sopenharmony_ci } 90e1051a39Sopenharmony_ci 91e1051a39Sopenharmony_ci ret->libctx = libctx; 92e1051a39Sopenharmony_ci ret->meth = DH_get_default_method(); 93e1051a39Sopenharmony_ci#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE) 94e1051a39Sopenharmony_ci ret->flags = ret->meth->flags; /* early default init */ 95e1051a39Sopenharmony_ci if (engine) { 96e1051a39Sopenharmony_ci if (!ENGINE_init(engine)) { 97e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_ENGINE_LIB); 98e1051a39Sopenharmony_ci goto err; 99e1051a39Sopenharmony_ci } 100e1051a39Sopenharmony_ci ret->engine = engine; 101e1051a39Sopenharmony_ci } else 102e1051a39Sopenharmony_ci ret->engine = ENGINE_get_default_DH(); 103e1051a39Sopenharmony_ci if (ret->engine) { 104e1051a39Sopenharmony_ci ret->meth = ENGINE_get_DH(ret->engine); 105e1051a39Sopenharmony_ci if (ret->meth == NULL) { 106e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_ENGINE_LIB); 107e1051a39Sopenharmony_ci goto err; 108e1051a39Sopenharmony_ci } 109e1051a39Sopenharmony_ci } 110e1051a39Sopenharmony_ci#endif 111e1051a39Sopenharmony_ci 112e1051a39Sopenharmony_ci ret->flags = ret->meth->flags; 113e1051a39Sopenharmony_ci 114e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 115e1051a39Sopenharmony_ci if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_DH, ret, &ret->ex_data)) 116e1051a39Sopenharmony_ci goto err; 117e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */ 118e1051a39Sopenharmony_ci 119e1051a39Sopenharmony_ci if ((ret->meth->init != NULL) && !ret->meth->init(ret)) { 120e1051a39Sopenharmony_ci ERR_raise(ERR_LIB_DH, ERR_R_INIT_FAIL); 121e1051a39Sopenharmony_ci goto err; 122e1051a39Sopenharmony_ci } 123e1051a39Sopenharmony_ci 124e1051a39Sopenharmony_ci return ret; 125e1051a39Sopenharmony_ci 126e1051a39Sopenharmony_ci err: 127e1051a39Sopenharmony_ci DH_free(ret); 128e1051a39Sopenharmony_ci return NULL; 129e1051a39Sopenharmony_ci} 130e1051a39Sopenharmony_ci 131e1051a39Sopenharmony_civoid DH_free(DH *r) 132e1051a39Sopenharmony_ci{ 133e1051a39Sopenharmony_ci int i; 134e1051a39Sopenharmony_ci 135e1051a39Sopenharmony_ci if (r == NULL) 136e1051a39Sopenharmony_ci return; 137e1051a39Sopenharmony_ci 138e1051a39Sopenharmony_ci CRYPTO_DOWN_REF(&r->references, &i, r->lock); 139e1051a39Sopenharmony_ci REF_PRINT_COUNT("DH", r); 140e1051a39Sopenharmony_ci if (i > 0) 141e1051a39Sopenharmony_ci return; 142e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 0); 143e1051a39Sopenharmony_ci 144e1051a39Sopenharmony_ci if (r->meth != NULL && r->meth->finish != NULL) 145e1051a39Sopenharmony_ci r->meth->finish(r); 146e1051a39Sopenharmony_ci#if !defined(FIPS_MODULE) 147e1051a39Sopenharmony_ci# if !defined(OPENSSL_NO_ENGINE) 148e1051a39Sopenharmony_ci ENGINE_finish(r->engine); 149e1051a39Sopenharmony_ci# endif 150e1051a39Sopenharmony_ci CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DH, r, &r->ex_data); 151e1051a39Sopenharmony_ci#endif 152e1051a39Sopenharmony_ci 153e1051a39Sopenharmony_ci CRYPTO_THREAD_lock_free(r->lock); 154e1051a39Sopenharmony_ci 155e1051a39Sopenharmony_ci ossl_ffc_params_cleanup(&r->params); 156e1051a39Sopenharmony_ci BN_clear_free(r->pub_key); 157e1051a39Sopenharmony_ci BN_clear_free(r->priv_key); 158e1051a39Sopenharmony_ci OPENSSL_free(r); 159e1051a39Sopenharmony_ci} 160e1051a39Sopenharmony_ci 161e1051a39Sopenharmony_ciint DH_up_ref(DH *r) 162e1051a39Sopenharmony_ci{ 163e1051a39Sopenharmony_ci int i; 164e1051a39Sopenharmony_ci 165e1051a39Sopenharmony_ci if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0) 166e1051a39Sopenharmony_ci return 0; 167e1051a39Sopenharmony_ci 168e1051a39Sopenharmony_ci REF_PRINT_COUNT("DH", r); 169e1051a39Sopenharmony_ci REF_ASSERT_ISNT(i < 2); 170e1051a39Sopenharmony_ci return ((i > 1) ? 1 : 0); 171e1051a39Sopenharmony_ci} 172e1051a39Sopenharmony_ci 173e1051a39Sopenharmony_civoid ossl_dh_set0_libctx(DH *d, OSSL_LIB_CTX *libctx) 174e1051a39Sopenharmony_ci{ 175e1051a39Sopenharmony_ci d->libctx = libctx; 176e1051a39Sopenharmony_ci} 177e1051a39Sopenharmony_ci 178e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 179e1051a39Sopenharmony_ciint DH_set_ex_data(DH *d, int idx, void *arg) 180e1051a39Sopenharmony_ci{ 181e1051a39Sopenharmony_ci return CRYPTO_set_ex_data(&d->ex_data, idx, arg); 182e1051a39Sopenharmony_ci} 183e1051a39Sopenharmony_ci 184e1051a39Sopenharmony_civoid *DH_get_ex_data(const DH *d, int idx) 185e1051a39Sopenharmony_ci{ 186e1051a39Sopenharmony_ci return CRYPTO_get_ex_data(&d->ex_data, idx); 187e1051a39Sopenharmony_ci} 188e1051a39Sopenharmony_ci#endif 189e1051a39Sopenharmony_ci 190e1051a39Sopenharmony_ciint DH_bits(const DH *dh) 191e1051a39Sopenharmony_ci{ 192e1051a39Sopenharmony_ci if (dh->params.p != NULL) 193e1051a39Sopenharmony_ci return BN_num_bits(dh->params.p); 194e1051a39Sopenharmony_ci return -1; 195e1051a39Sopenharmony_ci} 196e1051a39Sopenharmony_ci 197e1051a39Sopenharmony_ciint DH_size(const DH *dh) 198e1051a39Sopenharmony_ci{ 199e1051a39Sopenharmony_ci if (dh->params.p != NULL) 200e1051a39Sopenharmony_ci return BN_num_bytes(dh->params.p); 201e1051a39Sopenharmony_ci return -1; 202e1051a39Sopenharmony_ci} 203e1051a39Sopenharmony_ci 204e1051a39Sopenharmony_ciint DH_security_bits(const DH *dh) 205e1051a39Sopenharmony_ci{ 206e1051a39Sopenharmony_ci int N; 207e1051a39Sopenharmony_ci 208e1051a39Sopenharmony_ci if (dh->params.q != NULL) 209e1051a39Sopenharmony_ci N = BN_num_bits(dh->params.q); 210e1051a39Sopenharmony_ci else if (dh->length) 211e1051a39Sopenharmony_ci N = dh->length; 212e1051a39Sopenharmony_ci else 213e1051a39Sopenharmony_ci N = -1; 214e1051a39Sopenharmony_ci if (dh->params.p != NULL) 215e1051a39Sopenharmony_ci return BN_security_bits(BN_num_bits(dh->params.p), N); 216e1051a39Sopenharmony_ci return -1; 217e1051a39Sopenharmony_ci} 218e1051a39Sopenharmony_ci 219e1051a39Sopenharmony_civoid DH_get0_pqg(const DH *dh, 220e1051a39Sopenharmony_ci const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) 221e1051a39Sopenharmony_ci{ 222e1051a39Sopenharmony_ci ossl_ffc_params_get0_pqg(&dh->params, p, q, g); 223e1051a39Sopenharmony_ci} 224e1051a39Sopenharmony_ci 225e1051a39Sopenharmony_ciint DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) 226e1051a39Sopenharmony_ci{ 227e1051a39Sopenharmony_ci /* 228e1051a39Sopenharmony_ci * If the fields p and g in dh are NULL, the corresponding input 229e1051a39Sopenharmony_ci * parameters MUST be non-NULL. q may remain NULL. 230e1051a39Sopenharmony_ci */ 231e1051a39Sopenharmony_ci if ((dh->params.p == NULL && p == NULL) 232e1051a39Sopenharmony_ci || (dh->params.g == NULL && g == NULL)) 233e1051a39Sopenharmony_ci return 0; 234e1051a39Sopenharmony_ci 235e1051a39Sopenharmony_ci ossl_ffc_params_set0_pqg(&dh->params, p, q, g); 236e1051a39Sopenharmony_ci ossl_dh_cache_named_group(dh); 237e1051a39Sopenharmony_ci dh->dirty_cnt++; 238e1051a39Sopenharmony_ci return 1; 239e1051a39Sopenharmony_ci} 240e1051a39Sopenharmony_ci 241e1051a39Sopenharmony_cilong DH_get_length(const DH *dh) 242e1051a39Sopenharmony_ci{ 243e1051a39Sopenharmony_ci return dh->length; 244e1051a39Sopenharmony_ci} 245e1051a39Sopenharmony_ci 246e1051a39Sopenharmony_ciint DH_set_length(DH *dh, long length) 247e1051a39Sopenharmony_ci{ 248e1051a39Sopenharmony_ci dh->length = length; 249e1051a39Sopenharmony_ci dh->dirty_cnt++; 250e1051a39Sopenharmony_ci return 1; 251e1051a39Sopenharmony_ci} 252e1051a39Sopenharmony_ci 253e1051a39Sopenharmony_civoid DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) 254e1051a39Sopenharmony_ci{ 255e1051a39Sopenharmony_ci if (pub_key != NULL) 256e1051a39Sopenharmony_ci *pub_key = dh->pub_key; 257e1051a39Sopenharmony_ci if (priv_key != NULL) 258e1051a39Sopenharmony_ci *priv_key = dh->priv_key; 259e1051a39Sopenharmony_ci} 260e1051a39Sopenharmony_ci 261e1051a39Sopenharmony_ciint DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) 262e1051a39Sopenharmony_ci{ 263e1051a39Sopenharmony_ci if (pub_key != NULL) { 264e1051a39Sopenharmony_ci BN_clear_free(dh->pub_key); 265e1051a39Sopenharmony_ci dh->pub_key = pub_key; 266e1051a39Sopenharmony_ci } 267e1051a39Sopenharmony_ci if (priv_key != NULL) { 268e1051a39Sopenharmony_ci BN_clear_free(dh->priv_key); 269e1051a39Sopenharmony_ci dh->priv_key = priv_key; 270e1051a39Sopenharmony_ci } 271e1051a39Sopenharmony_ci 272e1051a39Sopenharmony_ci dh->dirty_cnt++; 273e1051a39Sopenharmony_ci return 1; 274e1051a39Sopenharmony_ci} 275e1051a39Sopenharmony_ci 276e1051a39Sopenharmony_ciconst BIGNUM *DH_get0_p(const DH *dh) 277e1051a39Sopenharmony_ci{ 278e1051a39Sopenharmony_ci return dh->params.p; 279e1051a39Sopenharmony_ci} 280e1051a39Sopenharmony_ci 281e1051a39Sopenharmony_ciconst BIGNUM *DH_get0_q(const DH *dh) 282e1051a39Sopenharmony_ci{ 283e1051a39Sopenharmony_ci return dh->params.q; 284e1051a39Sopenharmony_ci} 285e1051a39Sopenharmony_ci 286e1051a39Sopenharmony_ciconst BIGNUM *DH_get0_g(const DH *dh) 287e1051a39Sopenharmony_ci{ 288e1051a39Sopenharmony_ci return dh->params.g; 289e1051a39Sopenharmony_ci} 290e1051a39Sopenharmony_ci 291e1051a39Sopenharmony_ciconst BIGNUM *DH_get0_priv_key(const DH *dh) 292e1051a39Sopenharmony_ci{ 293e1051a39Sopenharmony_ci return dh->priv_key; 294e1051a39Sopenharmony_ci} 295e1051a39Sopenharmony_ci 296e1051a39Sopenharmony_ciconst BIGNUM *DH_get0_pub_key(const DH *dh) 297e1051a39Sopenharmony_ci{ 298e1051a39Sopenharmony_ci return dh->pub_key; 299e1051a39Sopenharmony_ci} 300e1051a39Sopenharmony_ci 301e1051a39Sopenharmony_civoid DH_clear_flags(DH *dh, int flags) 302e1051a39Sopenharmony_ci{ 303e1051a39Sopenharmony_ci dh->flags &= ~flags; 304e1051a39Sopenharmony_ci} 305e1051a39Sopenharmony_ci 306e1051a39Sopenharmony_ciint DH_test_flags(const DH *dh, int flags) 307e1051a39Sopenharmony_ci{ 308e1051a39Sopenharmony_ci return dh->flags & flags; 309e1051a39Sopenharmony_ci} 310e1051a39Sopenharmony_ci 311e1051a39Sopenharmony_civoid DH_set_flags(DH *dh, int flags) 312e1051a39Sopenharmony_ci{ 313e1051a39Sopenharmony_ci dh->flags |= flags; 314e1051a39Sopenharmony_ci} 315e1051a39Sopenharmony_ci 316e1051a39Sopenharmony_ci#ifndef FIPS_MODULE 317e1051a39Sopenharmony_ciENGINE *DH_get0_engine(DH *dh) 318e1051a39Sopenharmony_ci{ 319e1051a39Sopenharmony_ci return dh->engine; 320e1051a39Sopenharmony_ci} 321e1051a39Sopenharmony_ci#endif /*FIPS_MODULE */ 322e1051a39Sopenharmony_ci 323e1051a39Sopenharmony_ciFFC_PARAMS *ossl_dh_get0_params(DH *dh) 324e1051a39Sopenharmony_ci{ 325e1051a39Sopenharmony_ci return &dh->params; 326e1051a39Sopenharmony_ci} 327e1051a39Sopenharmony_ciint ossl_dh_get0_nid(const DH *dh) 328e1051a39Sopenharmony_ci{ 329e1051a39Sopenharmony_ci return dh->params.nid; 330e1051a39Sopenharmony_ci} 331