1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2023 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/core_names.h>
17e1051a39Sopenharmony_ci#include <openssl/err.h>
18e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
19e1051a39Sopenharmony_ci# include <openssl/x509.h>
20e1051a39Sopenharmony_ci#endif
21e1051a39Sopenharmony_ci#include "crypto/dsa.h"
22e1051a39Sopenharmony_ci#include "dsa_local.h"
23e1051a39Sopenharmony_ci
24e1051a39Sopenharmony_ci/*
25e1051a39Sopenharmony_ci * The intention with the "backend" source file is to offer backend support
26e1051a39Sopenharmony_ci * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
27e1051a39Sopenharmony_ci * implementations alike.
28e1051a39Sopenharmony_ci */
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ciint ossl_dsa_key_fromdata(DSA *dsa, const OSSL_PARAM params[],
31e1051a39Sopenharmony_ci                          int include_private)
32e1051a39Sopenharmony_ci{
33e1051a39Sopenharmony_ci    const OSSL_PARAM *param_priv_key = NULL, *param_pub_key;
34e1051a39Sopenharmony_ci    BIGNUM *priv_key = NULL, *pub_key = NULL;
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci    if (dsa == NULL)
37e1051a39Sopenharmony_ci        return 0;
38e1051a39Sopenharmony_ci
39e1051a39Sopenharmony_ci    if (include_private) {
40e1051a39Sopenharmony_ci        param_priv_key =
41e1051a39Sopenharmony_ci            OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
42e1051a39Sopenharmony_ci    }
43e1051a39Sopenharmony_ci    param_pub_key =
44e1051a39Sopenharmony_ci        OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
45e1051a39Sopenharmony_ci
46e1051a39Sopenharmony_ci    /* It's ok if neither half is present */
47e1051a39Sopenharmony_ci    if (param_priv_key == NULL && param_pub_key == NULL)
48e1051a39Sopenharmony_ci        return 1;
49e1051a39Sopenharmony_ci
50e1051a39Sopenharmony_ci    if (param_pub_key != NULL && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
51e1051a39Sopenharmony_ci        goto err;
52e1051a39Sopenharmony_ci    if (param_priv_key != NULL && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
53e1051a39Sopenharmony_ci        goto err;
54e1051a39Sopenharmony_ci
55e1051a39Sopenharmony_ci    if (!DSA_set0_key(dsa, pub_key, priv_key))
56e1051a39Sopenharmony_ci        goto err;
57e1051a39Sopenharmony_ci
58e1051a39Sopenharmony_ci    return 1;
59e1051a39Sopenharmony_ci
60e1051a39Sopenharmony_ci err:
61e1051a39Sopenharmony_ci    BN_clear_free(priv_key);
62e1051a39Sopenharmony_ci    BN_free(pub_key);
63e1051a39Sopenharmony_ci    return 0;
64e1051a39Sopenharmony_ci}
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ciint ossl_dsa_is_foreign(const DSA *dsa)
67e1051a39Sopenharmony_ci{
68e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
69e1051a39Sopenharmony_ci    if (dsa->engine != NULL || DSA_get_method((DSA *)dsa) != DSA_OpenSSL())
70e1051a39Sopenharmony_ci        return 1;
71e1051a39Sopenharmony_ci#endif
72e1051a39Sopenharmony_ci    return 0;
73e1051a39Sopenharmony_ci}
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_cistatic ossl_inline int dsa_bn_dup_check(BIGNUM **out, const BIGNUM *f)
76e1051a39Sopenharmony_ci{
77e1051a39Sopenharmony_ci    if (f != NULL && (*out = BN_dup(f)) == NULL)
78e1051a39Sopenharmony_ci        return 0;
79e1051a39Sopenharmony_ci    return 1;
80e1051a39Sopenharmony_ci}
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ciDSA *ossl_dsa_dup(const DSA *dsa, int selection)
83e1051a39Sopenharmony_ci{
84e1051a39Sopenharmony_ci    DSA *dupkey = NULL;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    /* Do not try to duplicate foreign DSA keys */
87e1051a39Sopenharmony_ci    if (ossl_dsa_is_foreign(dsa))
88e1051a39Sopenharmony_ci        return NULL;
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    if ((dupkey = ossl_dsa_new(dsa->libctx)) == NULL)
91e1051a39Sopenharmony_ci        return NULL;
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0
94e1051a39Sopenharmony_ci        && !ossl_ffc_params_copy(&dupkey->params, &dsa->params))
95e1051a39Sopenharmony_ci        goto err;
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    dupkey->flags = dsa->flags;
98e1051a39Sopenharmony_ci
99e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
100e1051a39Sopenharmony_ci        && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
101e1051a39Sopenharmony_ci            || !dsa_bn_dup_check(&dupkey->pub_key, dsa->pub_key)))
102e1051a39Sopenharmony_ci        goto err;
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
105e1051a39Sopenharmony_ci        && ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0
106e1051a39Sopenharmony_ci            || !dsa_bn_dup_check(&dupkey->priv_key, dsa->priv_key)))
107e1051a39Sopenharmony_ci        goto err;
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
110e1051a39Sopenharmony_ci    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_DSA,
111e1051a39Sopenharmony_ci                            &dupkey->ex_data, &dsa->ex_data))
112e1051a39Sopenharmony_ci        goto err;
113e1051a39Sopenharmony_ci#endif
114e1051a39Sopenharmony_ci
115e1051a39Sopenharmony_ci    return dupkey;
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci err:
118e1051a39Sopenharmony_ci    DSA_free(dupkey);
119e1051a39Sopenharmony_ci    return NULL;
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
123e1051a39Sopenharmony_ciDSA *ossl_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
124e1051a39Sopenharmony_ci                             OSSL_LIB_CTX *libctx, const char *propq)
125e1051a39Sopenharmony_ci{
126e1051a39Sopenharmony_ci    const unsigned char *p, *pm;
127e1051a39Sopenharmony_ci    int pklen, pmlen;
128e1051a39Sopenharmony_ci    int ptype;
129e1051a39Sopenharmony_ci    const void *pval;
130e1051a39Sopenharmony_ci    const ASN1_STRING *pstr;
131e1051a39Sopenharmony_ci    const X509_ALGOR *palg;
132e1051a39Sopenharmony_ci    ASN1_INTEGER *privkey = NULL;
133e1051a39Sopenharmony_ci    const BIGNUM *dsa_p, *dsa_g;
134e1051a39Sopenharmony_ci    BIGNUM *dsa_pubkey = NULL, *dsa_privkey = NULL;
135e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci    DSA *dsa = NULL;
138e1051a39Sopenharmony_ci
139e1051a39Sopenharmony_ci    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
140e1051a39Sopenharmony_ci        return 0;
141e1051a39Sopenharmony_ci    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
142e1051a39Sopenharmony_ci
143e1051a39Sopenharmony_ci    if ((privkey = d2i_ASN1_INTEGER(NULL, &p, pklen)) == NULL)
144e1051a39Sopenharmony_ci        goto decerr;
145e1051a39Sopenharmony_ci    if (privkey->type == V_ASN1_NEG_INTEGER || ptype != V_ASN1_SEQUENCE)
146e1051a39Sopenharmony_ci        goto decerr;
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_ci    pstr = pval;
149e1051a39Sopenharmony_ci    pm = pstr->data;
150e1051a39Sopenharmony_ci    pmlen = pstr->length;
151e1051a39Sopenharmony_ci    if ((dsa = d2i_DSAparams(NULL, &pm, pmlen)) == NULL)
152e1051a39Sopenharmony_ci        goto decerr;
153e1051a39Sopenharmony_ci    /* We have parameters now set private key */
154e1051a39Sopenharmony_ci    if ((dsa_privkey = BN_secure_new()) == NULL
155e1051a39Sopenharmony_ci        || !ASN1_INTEGER_to_BN(privkey, dsa_privkey)) {
156e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
157e1051a39Sopenharmony_ci        goto dsaerr;
158e1051a39Sopenharmony_ci    }
159e1051a39Sopenharmony_ci    /* Calculate public key */
160e1051a39Sopenharmony_ci    if ((dsa_pubkey = BN_new()) == NULL) {
161e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
162e1051a39Sopenharmony_ci        goto dsaerr;
163e1051a39Sopenharmony_ci    }
164e1051a39Sopenharmony_ci    if ((ctx = BN_CTX_new()) == NULL) {
165e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_MALLOC_FAILURE);
166e1051a39Sopenharmony_ci        goto dsaerr;
167e1051a39Sopenharmony_ci    }
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    dsa_p = DSA_get0_p(dsa);
170e1051a39Sopenharmony_ci    dsa_g = DSA_get0_g(dsa);
171e1051a39Sopenharmony_ci    BN_set_flags(dsa_privkey, BN_FLG_CONSTTIME);
172e1051a39Sopenharmony_ci    if (!BN_mod_exp(dsa_pubkey, dsa_g, dsa_privkey, dsa_p, ctx)) {
173e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, DSA_R_BN_ERROR);
174e1051a39Sopenharmony_ci        goto dsaerr;
175e1051a39Sopenharmony_ci    }
176e1051a39Sopenharmony_ci    if (!DSA_set0_key(dsa, dsa_pubkey, dsa_privkey)) {
177e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DSA, ERR_R_INTERNAL_ERROR);
178e1051a39Sopenharmony_ci        goto dsaerr;
179e1051a39Sopenharmony_ci    }
180e1051a39Sopenharmony_ci
181e1051a39Sopenharmony_ci    goto done;
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ci decerr:
184e1051a39Sopenharmony_ci    ERR_raise(ERR_LIB_DSA, DSA_R_DECODE_ERROR);
185e1051a39Sopenharmony_ci dsaerr:
186e1051a39Sopenharmony_ci    BN_free(dsa_privkey);
187e1051a39Sopenharmony_ci    BN_free(dsa_pubkey);
188e1051a39Sopenharmony_ci    DSA_free(dsa);
189e1051a39Sopenharmony_ci    dsa = NULL;
190e1051a39Sopenharmony_ci done:
191e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
192e1051a39Sopenharmony_ci    ASN1_STRING_clear_free(privkey);
193e1051a39Sopenharmony_ci    return dsa;
194e1051a39Sopenharmony_ci}
195e1051a39Sopenharmony_ci#endif
196