Implement DSA in the default provider
[openssl.git] / providers / common / 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 "internal/provider_algs.h"
16
17 static OSSL_OP_keymgmt_importkey_fn dsa_importkey;
18
19 static int params_to_key(DSA *dsa, const OSSL_PARAM params[])
20 {
21     const OSSL_PARAM *param_p, *param_q, *param_g, *param_priv_key;
22     const OSSL_PARAM *param_pub_key;
23     BIGNUM *p = NULL, *q = NULL, *g = NULL, *priv_key = NULL, *pub_key = NULL;
24
25     if (dsa == NULL)
26         return 0;
27
28     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
29     param_q = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_Q);
30     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
31     param_priv_key =
32         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PRIV_KEY);
33     param_pub_key =
34         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DSA_PUB_KEY);
35
36     /*
37      * DSA documentation says that a public key must be present if a private key
38      * is.
39      */
40     if (param_priv_key != NULL && param_pub_key == NULL)
41         return 0;
42
43     if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
44         || (param_q != NULL && !OSSL_PARAM_get_BN(param_q, &q))
45         || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g))
46         || (param_priv_key != NULL
47             && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
48         || (param_pub_key != NULL
49             && !OSSL_PARAM_get_BN(param_pub_key, &pub_key)))
50         goto err;
51
52     if (!DSA_set0_pqg(dsa, p, q, g))
53         goto err;
54     p = q = g = NULL;
55
56     if (pub_key != NULL && !DSA_set0_key(dsa, pub_key, priv_key))
57         goto err;
58     priv_key = pub_key = NULL;
59
60     return 1;
61
62  err:
63     BN_free(p);
64     BN_free(q);
65     BN_free(g);
66     BN_free(priv_key);
67     BN_free(pub_key);
68     return 0;
69 }
70
71 static void *dsa_importkey(void *provctx, const OSSL_PARAM params[])
72 {
73     DSA *dsa;
74
75     if ((dsa = DSA_new()) == NULL
76         || !params_to_key(dsa, params)) {
77         DSA_free(dsa);
78         dsa = NULL;
79     }
80     return dsa;
81 }
82
83 const OSSL_DISPATCH dsa_keymgmt_functions[] = {
84     /*
85      * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
86      * implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
87      */
88     { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dsa_importkey },
89     { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DSA_free },
90     { 0, NULL }
91 };