DH: Add export of domain parameters to provider
[openssl.git] / providers / implementations / keymgmt / dh_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/dh.h>
14 #include <openssl/params.h>
15 #include "prov/implementations.h"
16
17 static OSSL_OP_keymgmt_importdomparams_fn dh_importdomparams;
18 static OSSL_OP_keymgmt_importkey_fn dh_importkey;
19
20 static int params_to_domparams(DH *dh, const OSSL_PARAM params[])
21 {
22     const OSSL_PARAM *param_p, *param_g;
23     BIGNUM *p = NULL, *g = NULL;
24
25     if (dh == NULL)
26         return 0;
27
28     param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_P);
29     param_g = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_G);
30
31     if ((param_p != NULL && !OSSL_PARAM_get_BN(param_p, &p))
32         || (param_g != NULL && !OSSL_PARAM_get_BN(param_g, &g)))
33         goto err;
34
35     if (!DH_set0_pqg(dh, p, NULL, g))
36         goto err;
37
38     return 1;
39
40  err:
41     BN_free(p);
42     BN_free(g);
43     return 0;
44 }
45
46 static int params_to_key(DH *dh, const OSSL_PARAM params[])
47 {
48     const OSSL_PARAM *param_priv_key, *param_pub_key;
49     BIGNUM *priv_key = NULL, *pub_key = NULL;
50
51     if (dh == NULL)
52         return 0;
53
54     if (!params_to_domparams(dh, params))
55         return 0;
56
57     param_priv_key =
58         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PRIV_KEY);
59     param_pub_key =
60         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DH_PUB_KEY);
61
62     /*
63      * DH documentation says that a public key must be present if a
64      * private key is present.
65      * We want to have at least a public key either way, so we end up
66      * requiring it unconditionally.
67      */
68     if (param_pub_key == NULL)
69         return 0;
70
71     if ((param_priv_key != NULL
72          && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
73         || !OSSL_PARAM_get_BN(param_pub_key, &pub_key))
74         goto err;
75
76     if (!DH_set0_key(dh, pub_key, priv_key))
77         goto err;
78
79     return 1;
80
81  err:
82     BN_free(priv_key);
83     BN_free(pub_key);
84     return 0;
85 }
86
87 static void *dh_importdomparams(void *provctx, const OSSL_PARAM params[])
88 {
89     DH *dh;
90
91     if ((dh = DH_new()) == NULL
92         || !params_to_domparams(dh, params)) {
93         DH_free(dh);
94         dh = NULL;
95     }
96     return dh;
97 }
98
99 static void *dh_importkey(void *provctx, const OSSL_PARAM params[])
100 {
101     DH *dh;
102
103     if ((dh = DH_new()) == NULL
104         || !params_to_key(dh, params)) {
105         DH_free(dh);
106         dh = NULL;
107     }
108     return dh;
109 }
110
111 const OSSL_DISPATCH dh_keymgmt_functions[] = {
112     /*
113      * TODO(3.0) When implementing OSSL_FUNC_KEYMGMT_GENKEY, remember to also
114      * implement OSSL_FUNC_KEYMGMT_EXPORTKEY.
115      */
116     { OSSL_FUNC_KEYMGMT_IMPORTDOMPARAMS, (void (*)(void))dh_importdomparams },
117     { OSSL_FUNC_KEYMGMT_FREEDOMPARAMS, (void (*)(void))DH_free },
118     { OSSL_FUNC_KEYMGMT_IMPORTKEY, (void (*)(void))dh_importkey },
119     { OSSL_FUNC_KEYMGMT_FREEKEY, (void (*)(void))DH_free },
120     { 0, NULL }
121 };