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