1 | /* |
2 | * Copyright 2019 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 | #include <openssl/core_numbers.h> |
11 | #include <openssl/core_names.h> |
12 | #include <openssl/bn.h> |
13 | #include <openssl/dsa.h> |
14 | #include <openssl/params.h> |
15 | #include "internal/param_build.h" |
16 | #include "prov/implementations.h" |
17 | #include "prov/providercommon.h" |
18 | |
19 | static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams; |
20 | static OSSL_OP_keymgmt_exportdomparams_fn dsa_exportdomparams; |
21 | static OSSL_OP_keymgmt_importkey_fn dsa_importkey; |
22 | static OSSL_OP_keymgmt_exportkey_fn dsa_exportkey; |
23 | |
24 | static int params_to_domparams(DSA *dsa, const OSSL_PARAM params[]) |
25 | { |
26 | const OSSL_PARAM *param_p, *param_q, *param_g; |
27 | BIGNUM *p = NULL, *q = NULL, *g = NULL; |
28 | |
29 | if (dsa == NULL) |
30 | return 0; |
31 | |
32 | param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P); |
33 | param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q); |
34 | param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G); |
35 | |
36 | if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p)) |
37 | || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q)) |
38 | || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))) |
39 | goto err; |
40 | |
41 | if (!DSA_set0_pqg(dsa, p, q, g)) |
42 | goto err; |
43 | |
44 | return 1; |
45 | |
46 | err: |
47 | BN_free(p); |
48 | BN_free(q); |
49 | BN_free(g); |
50 | return 0; |
51 | } |
52 | |
53 | static int domparams_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl) |
54 | { |
55 | const BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL; |
56 | |
57 | if (dsa == NULL) |
58 | return 0; |
59 | |
60 | DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g); |
61 | if (dsa_p != NULL |
62 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dsa_p)) |
63 | return 0; |
64 | if (dsa_q != NULL |
65 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, dsa_q)) |
66 | return 0; |
67 | if (dsa_g != NULL |
68 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dsa_g)) |
69 | return 0; |
70 | |
71 | return 1; |
72 | } |
73 | |
74 | static int params_to_key(DSA *dsa, const OSSL_PARAM params[]) |
75 | { |
76 | const OSSL_PARAM *param_priv_key, *param_pub_key; |
77 | BIGNUM *priv_key = NULL, *pub_key = NULL; |
78 | |
79 | if (dsa == NULL) |
80 | return 0; |
81 | |
82 | if (!params_to_domparams(dsa, params)) |
83 | return 0; |
84 | |
85 | param_priv_key = |
86 | OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY); |
87 | param_pub_key = |
88 | OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY); |
89 | |
90 | /* |
91 | * DSA documentation says that a public key must be present if a private key |
92 | * is. |
93 | */ |
94 | if (param_priv_key != NULL && param_pub_key == NULL) |
95 | return 0; |
96 | |
97 | if ((param_priv_key != NULL |
98 | && !OSSL_PARAM_get_BN(param_priv_key, &priv_key)) |
99 | || (param_pub_key != NULL |
100 | && !OSSL_PARAM_get_BN(param_pub_key, &pub_key))) |
101 | goto err; |
102 | |
103 | if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key)) |
104 | goto err; |
105 | |
106 | return 1; |
107 | |
108 | err: |
109 | BN_free(priv_key); |
110 | BN_free(pub_key); |
111 | return 0; |
112 | } |
113 | |
114 | static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl) |
115 | { |
116 | const BIGNUM *priv_key = NULL, *pub_key = NULL; |
117 | |
118 | if (dsa == NULL) |
119 | return 0; |
120 | if (!domparams_to_params(dsa, tmpl)) |
121 | return 0; |
122 | |
123 | DSA_get0_key(dsa, &pub_key, &priv_key); |
124 | if (priv_key != NULL |
125 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY, priv_key)) |
126 | return 0; |
127 | if (pub_key != NULL |
128 | && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY, pub_key)) |
129 | return 0; |
130 | |
131 | return 1; |
132 | } |
133 | |
134 | static void *dsa_importdomparams(void *provctx, const OSSL_PARAM params[]) |
135 | { |
136 | DSA *dsa; |
137 | |
138 | if ((dsa = DSA_new()) == NULL |
139 | || !params_to_domparams(dsa, params)) { |
140 | DSA_free(dsa); |
141 | dsa = NULL; |
142 | } |
143 | return dsa; |
144 | } |
145 | |
146 | static int dsa_exportdomparams(void *domparams, |
147 | OSSL_CALLBACK *param_cb, void *cbarg) |
148 | { |
149 | DSA *dsa = domparams; |
150 | OSSL_PARAM_BLD tmpl; |
151 | OSSL_PARAM *params = NULL; |
152 | int ret; |
153 | |
154 | ossl_param_bld_init(&tmpl); |
155 | if (dsa == NULL |
156 | || !domparams_to_params(dsa, &tmpl) |
157 | || (params = ossl_param_bld_to_param(&tmpl)) == NULL) |
158 | return 0; |
159 | ret = param_cb(params, cbarg); |
160 | ossl_param_bld_free(params); |
161 | return ret; |
162 | } |
163 | |
164 | static void *dsa_importkey(void *provctx, const OSSL_PARAM params[]) |
165 | { |
166 | DSA *dsa; |
167 | |
168 | if ((dsa = DSA_new()) == NULL |
169 | || !params_to_key(dsa, params)) { |
170 | DSA_free(dsa); |
171 | dsa = NULL; |
172 | } |
173 | return dsa; |
174 | } |
175 | |
176 | static int dsa_exportkey(void *key, OSSL_CALLBACK *param_cb, void *cbarg) |
177 | { |
178 | DSA *dsa = key; |
179 | OSSL_PARAM_BLD tmpl; |
180 | OSSL_PARAM *params = NULL; |
181 | int ret; |
182 | |
183 | ossl_param_bld_init(&tmpl); |
184 | if (dsa == NULL |
185 | || !key_to_params(dsa, &tmpl) |
186 | || (params = ossl_param_bld_to_param(&tmpl)) == NULL) |
187 | return 0; |
188 | ret = param_cb(params, cbarg); |
189 | ossl_param_bld_free(params); |
190 | return ret; |
191 | } |
192 | |
193 | const OSSL_DISPATCH dsa_keymgmt_functions[] = { |
194 | /* |
195 | * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also |
196 | * implement OSSL_FUNC_KEYMGMT_EXPORTKEY. |
197 | */ |
198 | { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dsa_importdomparams }, |
199 | { OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS, (void (*)(void))dsa_exportdomparams }, |
200 | { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DSA_free }, |
201 | { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey }, |
202 | { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))dsa_exportkey }, |
203 | { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free }, |
204 | { 0, NULL } |
205 | }; |
206 | |