Adapt existing KEYMGMT implementations to the redesigned interface
[openssl.git] / providers / implementations / keymgmt / dsa_kmgmt.c
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/params.h>
14 #include "internal/param_build.h"
15 #include "crypto/dsa.h"
16 #include "prov/implementations.h"
17 #include "prov/providercommon.h"
18 #include "prov/provider_ctx.h"
19 #include "crypto/dsa.h"
20
21 static OSSL_OP_keymgmt_new_fn dsa_newdata;
22 static OSSL_OP_keymgmt_free_fn dsa_freedata;
23 static OSSL_OP_keymgmt_has_fn dsa_has;
24 static OSSL_OP_keymgmt_import_fn dsa_import;
25 static OSSL_OP_keymgmt_export_fn dsa_export;
26 static OSSL_OP_keymgmt_get_params_fn dsa_get_params;
27
28 #define DSA_DEFAULT_MD "SHA256"
29 #define DSA_POSSIBLE_SELECTIONS                 \
30     (OSSL_KEYMGMT_SELECT_KEY | OSSL_KEYMGMT_FLAG_DOMAIN_PARAMETERS)
31
32 static int params_to_domparams(DSA *dsa, const OSSL_PARAM params[])
33 {
34     const OSSL_PARAM *param_p, *param_q, *param_g;
35     BIGNUM *p = NULL, *q = NULL, *g = NULL;
36
37     if (dsa == NULL)
38         return 0;
39
40     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
41     param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
42     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
43
44     if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
45         || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
46         || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
47         goto err;
48
49     if (!DSA_set0_pqg(dsa, p, q, g))
50         goto err;
51
52     return 1;
53
54  err:
55     BN_free(p);
56     BN_free(q);
57     BN_free(g);
58     return 0;
59 }
60
61 static int domparams_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
62 {
63     const BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
64
65     if (dsa == NULL)
66         return 0;
67
68     DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
69     if (dsa_p != NULL
70         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_P, dsa_p))
71         return 0;
72     if (dsa_q != NULL
73         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_Q, dsa_q))
74         return 0;
75     if (dsa_g != NULL
76         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_FFC_G, dsa_g))
77         return 0;
78
79     return 1;
80 }
81
82 static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
83 {
84     const OSSL_PARAM *param_priv_key, *param_pub_key;
85     BIGNUM *priv_key = NULL, *pub_key = NULL;
86
87     if (dsa == NULL)
88         return 0;
89
90     if (!params_to_domparams(dsa, params))
91         return 0;
92
93     param_priv_key =
94         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY);
95     param_pub_key =
96         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY);
97
98     /*
99      * DSA documentation says that a public key must be present if a private key
100      * is.
101      */
102     if (param_priv_key != NULL && param_pub_key == NULL)
103         return 0;
104
105     if ((param_priv_key != NULL
106          && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
107         || (param_pub_key != NULL
108             && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
109         goto err;
110
111     if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key))
112         goto err;
113
114     return 1;
115
116  err:
117     BN_free(priv_key);
118     BN_free(pub_key);
119     return 0;
120 }
121
122 static int key_to_params(DSA *dsa, OSSL_PARAM_BLD *tmpl)
123 {
124     const BIGNUM *priv_key = NULL, *pub_key = NULL;
125
126     if (dsa == NULL)
127         return 0;
128     if (!domparams_to_params(dsa, tmpl))
129         return 0;
130
131     DSA_get0_key(dsa, &pub_key, &priv_key);
132     if (priv_key != NULL
133         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_DSA_PRIV_KEY, priv_key))
134         return 0;
135     if (pub_key != NULL
136         && !ossl_param_bld_push_BN(tmpl, OSSL_PKEY_PARAM_DSA_PUB_KEY, pub_key))
137         return 0;
138
139     return 1;
140 }
141
142 static void *dsa_newdata(void *provctx)
143 {
144     return DSA_new();
145 }
146
147 static void dsa_freedata(void *keydata)
148 {
149     DSA_free(keydata);
150 }
151
152 static int dsa_has(void *keydata, int selection)
153 {
154     DSA *dsa = keydata;
155     int ok = 0;
156
157     if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
158         ok = 1;
159
160     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
161         ok = ok && (DSA_get0_pub_key(dsa) != NULL);
162     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
163         ok = ok && (DSA_get0_priv_key(dsa) != NULL);
164     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
165         ok = ok && (DSA_get0_p(dsa) != NULL && DSA_get0_g(dsa) != NULL);
166     return ok;
167 }
168
169 static int dsa_import(void *keydata, int selection, const OSSL_PARAM params[])
170 {
171     DSA *dsa = keydata;
172     int ok = 0;
173
174     if (dsa == NULL)
175         return 0;
176
177     if ((selection & DSA_POSSIBLE_SELECTIONS) != 0)
178         ok = 1;
179
180     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
181         ok = ok && params_to_domparams(dsa, params);
182     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
183         ok = ok && params_to_key(dsa, params);
184
185     return ok;
186 }
187
188 static int dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
189                       void *cbarg)
190 {
191     DSA *dsa = keydata;
192     OSSL_PARAM_BLD tmpl;
193     OSSL_PARAM *params = NULL;
194     int ok = 1;
195
196     if (dsa == NULL)
197         return 0;
198
199     ossl_param_bld_init(&tmpl);
200
201     if ((selection & OSSL_KEYMGMT_SELECT_ALL_PARAMETERS) != 0)
202         ok = ok && domparams_to_params(dsa, &tmpl);
203     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
204         ok = ok && key_to_params(dsa, &tmpl);
205
206     if (!ok
207         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
208         return 0;
209
210     ok = param_cb(params, cbarg);
211     ossl_param_bld_free(params);
212     return ok;
213 }
214
215 static ossl_inline int dsa_get_params(void *key, OSSL_PARAM params[])
216 {
217     DSA *dsa = key;
218     OSSL_PARAM *p;
219
220     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
221         && !OSSL_PARAM_set_int(p, DSA_bits(dsa)))
222         return 0;
223     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
224         && !OSSL_PARAM_set_int(p, DSA_security_bits(dsa)))
225         return 0;
226     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
227         && !OSSL_PARAM_set_int(p, DSA_size(dsa)))
228         return 0;
229     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DEFAULT_DIGEST)) != NULL
230         && !OSSL_PARAM_set_utf8_string(p, DSA_DEFAULT_MD))
231         return 0;
232     return 1;
233 }
234
235 const OSSL_DISPATCH dsa_keymgmt_functions[] = {
236     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))dsa_newdata },
237     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))dsa_freedata },
238     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))dsa_has },
239     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))dsa_import },
240     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))dsa_export },
241     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))dsa_get_params },
242     { 0, NULL }
243 };