DSA: Add export of keys and domain parameters from provider
[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/dsa.h>
14 #include <openssl/params.h>
15 #include "prov/implementations.h"
16
17 static OSSL_OP_keymgmt_importdomparams_fn dsa_importdomparams;
18 static OSSL_OP_keymgmt_exportdomparams_fn dsa_exportdomparams;
19 static OSSL_OP_keymgmt_importkey_fn dsa_importkey;
20 static OSSL_OP_keymgmt_exportkey_fn dsa_exportkey;
21
22 static int params_to_domparams(DSA *dsa, const OSSL_PARAM params[])
23 {
24     const OSSL_PARAM *param_p, *param_q, *param_g;
25     BIGNUM *p = NULL, *q = NULL, *g = NULL;
26
27     if (dsa == NULL)
28         return 0;
29
30     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
31     param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
32     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
33
34     if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
35         || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
36         || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
37         goto err;
38
39     if (!DSA_set0_pqg(dsa, p, q, g))
40         goto err;
41
42     return 1;
43
44  err:
45     BN_free(p);
46     BN_free(q);
47     BN_free(g);
48     return 0;
49 }
50
51 static int domparams_to_params(DSA *dsa, OSSL_PARAM params[])
52 {
53     OSSL_PARAM *p;
54     const BIGNUM *dsa_p = NULL, *dsa_q = NULL, *dsa_g = NULL;
55
56     if (dsa == NULL)
57         return 0;
58
59     DSA_get0_pqg(dsa, &dsa_p, &dsa_q, &dsa_g);
60     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_P)) != NULL
61         && !OSSL_PARAM_set_BN(p, dsa_p))
62         return 0;
63     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_Q)) != NULL
64         && !OSSL_PARAM_set_BN(p, dsa_q))
65         return 0;
66     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_FFC_G)) != NULL
67         && !OSSL_PARAM_set_BN(p, dsa_g))
68         return 0;
69
70     return 1;
71 }
72
73 static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
74 {
75     const OSSL_PARAM *param_priv_key, *param_pub_key;
76     BIGNUM *priv_key = NULL, *pub_key = NULL;
77
78     if (dsa == NULL)
79         return 0;
80
81     if (!params_to_domparams(dsa, params))
82         return 0;
83
84     param_priv_key =
85         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY);
86     param_pub_key =
87         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY);
88
89     /*
90      * DSA documentation says that a public key must be present if a private key
91      * is.
92      */
93     if (param_priv_key != NULL && param_pub_key == NULL)
94         return 0;
95
96     if ((param_priv_key != NULL
97          && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
98         || (param_pub_key != NULL
99             && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
100         goto err;
101
102     if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key))
103         goto err;
104
105     return 1;
106
107  err:
108     BN_free(priv_key);
109     BN_free(pub_key);
110     return 0;
111 }
112
113 static int key_to_params(DSA *dsa, OSSL_PARAM params[])
114 {
115     OSSL_PARAM *p;
116     const BIGNUM *priv_key = NULL, *pub_key = NULL;
117
118     if (dsa == NULL)
119         return 0;
120     if (!domparams_to_params(dsa, params))
121         return 0;
122
123     DSA_get0_key(dsa, &pub_key, &priv_key);
124     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY)) != NULL
125         && !OSSL_PARAM_set_BN(p, priv_key))
126         return 0;
127     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DSA_PUB_KEY)) != NULL
128         && !OSSL_PARAM_set_BN(p, 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, OSSL_PARAM params[])
147 {
148     DSA *dsa = domparams;
149
150     return dsa != NULL && !domparams_to_params(dsa, params);
151 }
152
153 static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
154 {
155     DSA *dsa;
156
157     if ((dsa = DSA_new()) == NULL
158         || !params_to_key(dsa, params)) {
159         DSA_free(dsa);
160         dsa = NULL;
161     }
162     return dsa;
163 }
164
165 static int dsa_exportkey(void *key, OSSL_PARAM params[])
166 {
167     DSA *dsa = key;
168
169     return dsa != NULL && !key_to_params(dsa, params);
170 }
171
172 const OSSL_DISPATCH dsa_keymgmt_functions[] = {
173     /*
174      * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
175      * implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
176      */
177     { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dsa_importdomparams },
178     { OSSL_FUNC_KEYMGMT_EXPORTDOMPARAMS, (void (*)(void))dsa_exportdomparams },
179     { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DSA_free },
180     { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey },
181     { OSSL_FUNC_KEYMGMT_EXPORTKEY, (void (*)(void))dsa_exportkey },
182     { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free },
183     { 0, NULL }
184 };