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