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 * DSA 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 <openssl/bn.h>
17e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
18e1051a39Sopenharmony_ci# include <openssl/engine.h>
19e1051a39Sopenharmony_ci#endif
20e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
21e1051a39Sopenharmony_ci#include "internal/refcount.h"
22e1051a39Sopenharmony_ci#include "crypto/dsa.h"
23e1051a39Sopenharmony_ci#include "crypto/dh.h" /* required by DSA_dup_DH() */
24e1051a39Sopenharmony_ci#include "dsa_local.h"
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_cistatic DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx);
27e1051a39Sopenharmony_ci
28e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ciint DSA_set_ex_data(DSA *d, int idx, void *arg)
31e1051a39Sopenharmony_ci{
32e1051a39Sopenharmony_ci    return CRYPTO_set_ex_data(&d->ex_data, idx, arg);
33e1051a39Sopenharmony_ci}
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_civoid *DSA_get_ex_data(const DSA *d, int idx)
36e1051a39Sopenharmony_ci{
37e1051a39Sopenharmony_ci    return CRYPTO_get_ex_data(&d->ex_data, idx);
38e1051a39Sopenharmony_ci}
39e1051a39Sopenharmony_ci
40e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_DH
41e1051a39Sopenharmony_ciDH *DSA_dup_DH(const DSA *r)
42e1051a39Sopenharmony_ci{
43e1051a39Sopenharmony_ci    /*
44e1051a39Sopenharmony_ci     * DSA has p, q, g, optional pub_key, optional priv_key.
45e1051a39Sopenharmony_ci     * DH has p, optional length, g, optional pub_key,
46e1051a39Sopenharmony_ci     * optional priv_key, optional q.
47e1051a39Sopenharmony_ci     */
48e1051a39Sopenharmony_ci    DH *ret = NULL;
49e1051a39Sopenharmony_ci    BIGNUM *pub_key = NULL, *priv_key = NULL;
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ci    if (r == NULL)
52e1051a39Sopenharmony_ci        goto err;
53e1051a39Sopenharmony_ci    ret = DH_new();
54e1051a39Sopenharmony_ci    if (ret == NULL)
55e1051a39Sopenharmony_ci        goto err;
56e1051a39Sopenharmony_ci
57e1051a39Sopenharmony_ci    if (!ossl_ffc_params_copy(ossl_dh_get0_params(ret), &r->params))
58e1051a39Sopenharmony_ci        goto err;
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_ci    if (r->pub_key != NULL) {
61e1051a39Sopenharmony_ci        pub_key = BN_dup(r->pub_key);
62e1051a39Sopenharmony_ci        if (pub_key == NULL)
63e1051a39Sopenharmony_ci            goto err;
64e1051a39Sopenharmony_ci        if (r->priv_key != NULL) {
65e1051a39Sopenharmony_ci            priv_key = BN_dup(r->priv_key);
66e1051a39Sopenharmony_ci            if (priv_key == NULL)
67e1051a39Sopenharmony_ci                goto err;
68e1051a39Sopenharmony_ci        }
69e1051a39Sopenharmony_ci        if (!DH_set0_key(ret, pub_key, priv_key))
70e1051a39Sopenharmony_ci            goto err;
71e1051a39Sopenharmony_ci    } else if (r->priv_key != NULL) {
72e1051a39Sopenharmony_ci        /* Shouldn't happen */
73e1051a39Sopenharmony_ci        goto err;
74e1051a39Sopenharmony_ci    }
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci    return ret;
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci err:
79e1051a39Sopenharmony_ci    BN_free(pub_key);
80e1051a39Sopenharmony_ci    BN_free(priv_key);
81e1051a39Sopenharmony_ci    DH_free(ret);
82e1051a39Sopenharmony_ci    return NULL;
83e1051a39Sopenharmony_ci}
84e1051a39Sopenharmony_ci# endif /*  OPENSSL_NO_DH */
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_civoid DSA_clear_flags(DSA *d, int flags)
87e1051a39Sopenharmony_ci{
88e1051a39Sopenharmony_ci    d->flags &= ~flags;
89e1051a39Sopenharmony_ci}
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ciint DSA_test_flags(const DSA *d, int flags)
92e1051a39Sopenharmony_ci{
93e1051a39Sopenharmony_ci    return d->flags & flags;
94e1051a39Sopenharmony_ci}
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_civoid DSA_set_flags(DSA *d, int flags)
97e1051a39Sopenharmony_ci{
98e1051a39Sopenharmony_ci    d->flags |= flags;
99e1051a39Sopenharmony_ci}
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ciENGINE *DSA_get0_engine(DSA *d)
102e1051a39Sopenharmony_ci{
103e1051a39Sopenharmony_ci    return d->engine;
104e1051a39Sopenharmony_ci}
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_ciint DSA_set_method(DSA *dsa, const DSA_METHOD *meth)
107e1051a39Sopenharmony_ci{
108e1051a39Sopenharmony_ci    /*
109e1051a39Sopenharmony_ci     * NB: The caller is specifically setting a method, so it's not up to us
110e1051a39Sopenharmony_ci     * to deal with which ENGINE it comes from.
111e1051a39Sopenharmony_ci     */
112e1051a39Sopenharmony_ci    const DSA_METHOD *mtmp;
113e1051a39Sopenharmony_ci    mtmp = dsa->meth;
114e1051a39Sopenharmony_ci    if (mtmp->finish)
115e1051a39Sopenharmony_ci        mtmp->finish(dsa);
116e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_ENGINE
117e1051a39Sopenharmony_ci    ENGINE_finish(dsa->engine);
118e1051a39Sopenharmony_ci    dsa->engine = NULL;
119e1051a39Sopenharmony_ci#endif
120e1051a39Sopenharmony_ci    dsa->meth = meth;
121e1051a39Sopenharmony_ci    if (meth->init)
122e1051a39Sopenharmony_ci        meth->init(dsa);
123e1051a39Sopenharmony_ci    return 1;
124e1051a39Sopenharmony_ci}
125e1051a39Sopenharmony_ci#endif /* FIPS_MODULE */
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ciconst DSA_METHOD *DSA_get_method(DSA *d)
129e1051a39Sopenharmony_ci{
130e1051a39Sopenharmony_ci    return d->meth;
131e1051a39Sopenharmony_ci}
132e1051a39Sopenharmony_ci
133e1051a39Sopenharmony_cistatic DSA *dsa_new_intern(ENGINE *engine, OSSL_LIB_CTX *libctx)
134e1051a39Sopenharmony_ci{
135e1051a39Sopenharmony_ci    DSA *ret = OPENSSL_zalloc(sizeof(*ret));
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci    if (ret == NULL) {
138e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
139e1051a39Sopenharmony_ci        return NULL;
140e1051a39Sopenharmony_ci    }
141e1051a39Sopenharmony_ci
142e1051a39Sopenharmony_ci    ret->references = 1;
143e1051a39Sopenharmony_ci    ret->lock = CRYPTO_THREAD_lock_new();
144e1051a39Sopenharmony_ci    if (ret->lock == NULL) {
145e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
146e1051a39Sopenharmony_ci        OPENSSL_free(ret);
147e1051a39Sopenharmony_ci        return NULL;
148e1051a39Sopenharmony_ci    }
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci    ret->libctx = libctx;
151e1051a39Sopenharmony_ci    ret->meth = DSA_get_default_method();
152e1051a39Sopenharmony_ci#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
153e1051a39Sopenharmony_ci    ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */
154e1051a39Sopenharmony_ci    if (engine) {
155e1051a39Sopenharmony_ci        if (!ENGINE_init(engine)) {
156e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_DSA, ERR_R_ENGINE_LIB);
157e1051a39Sopenharmony_ci            goto err;
158e1051a39Sopenharmony_ci        }
159e1051a39Sopenharmony_ci        ret->engine = engine;
160e1051a39Sopenharmony_ci    } else
161e1051a39Sopenharmony_ci        ret->engine = ENGINE_get_default_DSA();
162e1051a39Sopenharmony_ci    if (ret->engine) {
163e1051a39Sopenharmony_ci        ret->meth = ENGINE_get_DSA(ret->engine);
164e1051a39Sopenharmony_ci        if (ret->meth == NULL) {
165e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_DSA, ERR_R_ENGINE_LIB);
166e1051a39Sopenharmony_ci            goto err;
167e1051a39Sopenharmony_ci        }
168e1051a39Sopenharmony_ci    }
169e1051a39Sopenharmony_ci#endif
170e1051a39Sopenharmony_ci
171e1051a39Sopenharmony_ci    ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW;
172e1051a39Sopenharmony_ci
173e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
174e1051a39Sopenharmony_ci    if (!ossl_crypto_new_ex_data_ex(libctx, CRYPTO_EX_INDEX_DSA, ret,
175e1051a39Sopenharmony_ci                                    &ret->ex_data))
176e1051a39Sopenharmony_ci        goto err;
177e1051a39Sopenharmony_ci#endif
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
180e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_INIT_FAIL);
181e1051a39Sopenharmony_ci        goto err;
182e1051a39Sopenharmony_ci    }
183e1051a39Sopenharmony_ci
184e1051a39Sopenharmony_ci    return ret;
185e1051a39Sopenharmony_ci
186e1051a39Sopenharmony_ci err:
187e1051a39Sopenharmony_ci    DSA_free(ret);
188e1051a39Sopenharmony_ci    return NULL;
189e1051a39Sopenharmony_ci}
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_ciDSA *DSA_new_method(ENGINE *engine)
192e1051a39Sopenharmony_ci{
193e1051a39Sopenharmony_ci    return dsa_new_intern(engine, NULL);
194e1051a39Sopenharmony_ci}
195e1051a39Sopenharmony_ci
196e1051a39Sopenharmony_ciDSA *ossl_dsa_new(OSSL_LIB_CTX *libctx)
197e1051a39Sopenharmony_ci{
198e1051a39Sopenharmony_ci    return dsa_new_intern(NULL, libctx);
199e1051a39Sopenharmony_ci}
200e1051a39Sopenharmony_ci
201e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
202e1051a39Sopenharmony_ciDSA *DSA_new(void)
203e1051a39Sopenharmony_ci{
204e1051a39Sopenharmony_ci    return dsa_new_intern(NULL, NULL);
205e1051a39Sopenharmony_ci}
206e1051a39Sopenharmony_ci#endif
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_civoid DSA_free(DSA *r)
209e1051a39Sopenharmony_ci{
210e1051a39Sopenharmony_ci    int i;
211e1051a39Sopenharmony_ci
212e1051a39Sopenharmony_ci    if (r == NULL)
213e1051a39Sopenharmony_ci        return;
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci    CRYPTO_DOWN_REF(&r->references, &i, r->lock);
216e1051a39Sopenharmony_ci    REF_PRINT_COUNT("DSA", r);
217e1051a39Sopenharmony_ci    if (i > 0)
218e1051a39Sopenharmony_ci        return;
219e1051a39Sopenharmony_ci    REF_ASSERT_ISNT(i < 0);
220e1051a39Sopenharmony_ci
221e1051a39Sopenharmony_ci    if (r->meth != NULL && r->meth->finish != NULL)
222e1051a39Sopenharmony_ci        r->meth->finish(r);
223e1051a39Sopenharmony_ci#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_ENGINE)
224e1051a39Sopenharmony_ci    ENGINE_finish(r->engine);
225e1051a39Sopenharmony_ci#endif
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
228e1051a39Sopenharmony_ci    CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DSA, r, &r->ex_data);
229e1051a39Sopenharmony_ci#endif
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(r->lock);
232e1051a39Sopenharmony_ci
233e1051a39Sopenharmony_ci    ossl_ffc_params_cleanup(&r->params);
234e1051a39Sopenharmony_ci    BN_clear_free(r->pub_key);
235e1051a39Sopenharmony_ci    BN_clear_free(r->priv_key);
236e1051a39Sopenharmony_ci    OPENSSL_free(r);
237e1051a39Sopenharmony_ci}
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_ciint DSA_up_ref(DSA *r)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    int i;
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ci    if (CRYPTO_UP_REF(&r->references, &i, r->lock) <= 0)
244e1051a39Sopenharmony_ci        return 0;
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci    REF_PRINT_COUNT("DSA", r);
247e1051a39Sopenharmony_ci    REF_ASSERT_ISNT(i < 2);
248e1051a39Sopenharmony_ci    return ((i > 1) ? 1 : 0);
249e1051a39Sopenharmony_ci}
250e1051a39Sopenharmony_ci
251e1051a39Sopenharmony_civoid ossl_dsa_set0_libctx(DSA *d, OSSL_LIB_CTX *libctx)
252e1051a39Sopenharmony_ci{
253e1051a39Sopenharmony_ci    d->libctx = libctx;
254e1051a39Sopenharmony_ci}
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_civoid DSA_get0_pqg(const DSA *d,
257e1051a39Sopenharmony_ci                  const BIGNUM **p, const BIGNUM **q, const BIGNUM **g)
258e1051a39Sopenharmony_ci{
259e1051a39Sopenharmony_ci    ossl_ffc_params_get0_pqg(&d->params, p, q, g);
260e1051a39Sopenharmony_ci}
261e1051a39Sopenharmony_ci
262e1051a39Sopenharmony_ciint DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g)
263e1051a39Sopenharmony_ci{
264e1051a39Sopenharmony_ci    /* If the fields p, q and g in d are NULL, the corresponding input
265e1051a39Sopenharmony_ci     * parameters MUST be non-NULL.
266e1051a39Sopenharmony_ci     */
267e1051a39Sopenharmony_ci    if ((d->params.p == NULL && p == NULL)
268e1051a39Sopenharmony_ci        || (d->params.q == NULL && q == NULL)
269e1051a39Sopenharmony_ci        || (d->params.g == NULL && g == NULL))
270e1051a39Sopenharmony_ci        return 0;
271e1051a39Sopenharmony_ci
272e1051a39Sopenharmony_ci    ossl_ffc_params_set0_pqg(&d->params, p, q, g);
273e1051a39Sopenharmony_ci    d->dirty_cnt++;
274e1051a39Sopenharmony_ci
275e1051a39Sopenharmony_ci    return 1;
276e1051a39Sopenharmony_ci}
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_ciconst BIGNUM *DSA_get0_p(const DSA *d)
279e1051a39Sopenharmony_ci{
280e1051a39Sopenharmony_ci    return d->params.p;
281e1051a39Sopenharmony_ci}
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_ciconst BIGNUM *DSA_get0_q(const DSA *d)
284e1051a39Sopenharmony_ci{
285e1051a39Sopenharmony_ci    return d->params.q;
286e1051a39Sopenharmony_ci}
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ciconst BIGNUM *DSA_get0_g(const DSA *d)
289e1051a39Sopenharmony_ci{
290e1051a39Sopenharmony_ci    return d->params.g;
291e1051a39Sopenharmony_ci}
292e1051a39Sopenharmony_ci
293e1051a39Sopenharmony_ciconst BIGNUM *DSA_get0_pub_key(const DSA *d)
294e1051a39Sopenharmony_ci{
295e1051a39Sopenharmony_ci    return d->pub_key;
296e1051a39Sopenharmony_ci}
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ciconst BIGNUM *DSA_get0_priv_key(const DSA *d)
299e1051a39Sopenharmony_ci{
300e1051a39Sopenharmony_ci    return d->priv_key;
301e1051a39Sopenharmony_ci}
302e1051a39Sopenharmony_ci
303e1051a39Sopenharmony_civoid DSA_get0_key(const DSA *d,
304e1051a39Sopenharmony_ci                  const BIGNUM **pub_key, const BIGNUM **priv_key)
305e1051a39Sopenharmony_ci{
306e1051a39Sopenharmony_ci    if (pub_key != NULL)
307e1051a39Sopenharmony_ci        *pub_key = d->pub_key;
308e1051a39Sopenharmony_ci    if (priv_key != NULL)
309e1051a39Sopenharmony_ci        *priv_key = d->priv_key;
310e1051a39Sopenharmony_ci}
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_ciint DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key)
313e1051a39Sopenharmony_ci{
314e1051a39Sopenharmony_ci    if (pub_key != NULL) {
315e1051a39Sopenharmony_ci        BN_free(d->pub_key);
316e1051a39Sopenharmony_ci        d->pub_key = pub_key;
317e1051a39Sopenharmony_ci    }
318e1051a39Sopenharmony_ci    if (priv_key != NULL) {
319e1051a39Sopenharmony_ci        BN_free(d->priv_key);
320e1051a39Sopenharmony_ci        d->priv_key = priv_key;
321e1051a39Sopenharmony_ci    }
322e1051a39Sopenharmony_ci    d->dirty_cnt++;
323e1051a39Sopenharmony_ci
324e1051a39Sopenharmony_ci    return 1;
325e1051a39Sopenharmony_ci}
326e1051a39Sopenharmony_ci
327e1051a39Sopenharmony_ciint DSA_security_bits(const DSA *d)
328e1051a39Sopenharmony_ci{
329e1051a39Sopenharmony_ci    if (d->params.p != NULL && d->params.q != NULL)
330e1051a39Sopenharmony_ci        return BN_security_bits(BN_num_bits(d->params.p),
331e1051a39Sopenharmony_ci                                BN_num_bits(d->params.q));
332e1051a39Sopenharmony_ci    return -1;
333e1051a39Sopenharmony_ci}
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_ciint DSA_bits(const DSA *dsa)
336e1051a39Sopenharmony_ci{
337e1051a39Sopenharmony_ci    if (dsa->params.p != NULL)
338e1051a39Sopenharmony_ci        return BN_num_bits(dsa->params.p);
339e1051a39Sopenharmony_ci    return -1;
340e1051a39Sopenharmony_ci}
341e1051a39Sopenharmony_ci
342e1051a39Sopenharmony_ciFFC_PARAMS *ossl_dsa_get0_params(DSA *dsa)
343e1051a39Sopenharmony_ci{
344e1051a39Sopenharmony_ci    return &dsa->params;
345e1051a39Sopenharmony_ci}
346e1051a39Sopenharmony_ci
347e1051a39Sopenharmony_ciint ossl_dsa_ffc_params_fromdata(DSA *dsa, const OSSL_PARAM params[])
348e1051a39Sopenharmony_ci{
349e1051a39Sopenharmony_ci    int ret;
350e1051a39Sopenharmony_ci    FFC_PARAMS *ffc;
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci    if (dsa == NULL)
353e1051a39Sopenharmony_ci        return 0;
354e1051a39Sopenharmony_ci    ffc = ossl_dsa_get0_params(dsa);
355e1051a39Sopenharmony_ci    if (ffc == NULL)
356e1051a39Sopenharmony_ci        return 0;
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci    ret = ossl_ffc_params_fromdata(ffc, params);
359e1051a39Sopenharmony_ci    if (ret)
360e1051a39Sopenharmony_ci        dsa->dirty_cnt++;
361e1051a39Sopenharmony_ci    return ret;
362e1051a39Sopenharmony_ci}
363