]>
Commit | Line | Data |
---|---|---|
89e29174 MC |
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/crypto.h> | |
11 | #include <openssl/core_numbers.h> | |
12 | #include <openssl/core_names.h> | |
13 | #include <openssl/dh.h> | |
14 | #include <openssl/params.h> | |
15 | #include "internal/provider_algs.h" | |
16 | ||
17 | static OSSL_OP_keyexch_newctx_fn dh_newctx; | |
18 | static OSSL_OP_keyexch_init_fn dh_init; | |
19 | static OSSL_OP_keyexch_set_peer_fn dh_set_peer; | |
20 | static OSSL_OP_keyexch_derive_fn dh_derive; | |
21 | static OSSL_OP_keyexch_freectx_fn dh_freectx; | |
22 | static OSSL_OP_keyexch_dupctx_fn dh_dupctx; | |
23 | ||
24 | ||
25 | typedef struct { | |
26 | DH *dh; | |
27 | DH *dhpeer; | |
35aca9ec | 28 | int pad; |
89e29174 MC |
29 | } PROV_DH_CTX; |
30 | ||
31 | static void *dh_newctx(void *provctx) | |
32 | { | |
33 | return OPENSSL_zalloc(sizeof(PROV_DH_CTX)); | |
34 | } | |
35 | ||
36 | static DH *param_to_dh(OSSL_PARAM params[], int priv) | |
37 | { | |
38 | DH *dh = DH_new(); | |
39 | OSSL_PARAM *paramptr; | |
40 | BIGNUM *p = NULL, *g = NULL, *pub_key = NULL, *priv_key = NULL; | |
41 | ||
42 | if (dh == NULL) | |
43 | return NULL; | |
44 | ||
45 | paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_P); | |
46 | if (paramptr == NULL | |
47 | || !OSSL_PARAM_get_BN(paramptr, &p)) | |
48 | goto err; | |
49 | ||
50 | paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_G); | |
51 | if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &g)) | |
52 | goto err; | |
53 | ||
54 | if (!DH_set0_pqg(dh, p, NULL, g)) | |
55 | goto err; | |
56 | p = g = NULL; | |
57 | ||
58 | paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PUB_KEY); | |
59 | if (paramptr == NULL || !OSSL_PARAM_get_BN(paramptr, &pub_key)) | |
60 | goto err; | |
61 | ||
62 | /* Private key is optional */ | |
63 | if (priv) { | |
64 | paramptr = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_DH_PRIV_KEY); | |
65 | if (paramptr == NULL | |
66 | || (priv_key = BN_secure_new()) == NULL | |
67 | || !OSSL_PARAM_get_BN(paramptr, &priv_key)) | |
68 | goto err; | |
69 | } | |
70 | ||
71 | if (!DH_set0_key(dh, pub_key, priv_key)) | |
72 | goto err; | |
73 | ||
74 | return dh; | |
75 | ||
76 | err: | |
77 | BN_free(p); | |
78 | BN_free(g); | |
79 | BN_free(pub_key); | |
80 | BN_free(priv_key); | |
81 | DH_free(dh); | |
82 | return NULL; | |
83 | } | |
84 | ||
85 | static int dh_init(void *vpdhctx, OSSL_PARAM params[]) | |
86 | { | |
87 | PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; | |
88 | ||
89 | DH_free(pdhctx->dh); | |
90 | pdhctx->dh = param_to_dh(params, 1); | |
91 | ||
92 | return pdhctx->dh != NULL; | |
93 | } | |
94 | ||
95 | static int dh_set_peer(void *vpdhctx, OSSL_PARAM params[]) | |
96 | { | |
97 | PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; | |
98 | ||
99 | DH_free(pdhctx->dhpeer); | |
100 | pdhctx->dhpeer = param_to_dh(params, 0); | |
101 | ||
102 | return pdhctx->dhpeer != NULL; | |
103 | } | |
104 | ||
105 | static int dh_derive(void *vpdhctx, unsigned char *key, size_t *keylen, | |
106 | size_t outlen) | |
107 | { | |
108 | PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; | |
109 | int ret; | |
110 | size_t dhsize; | |
111 | const BIGNUM *pub_key = NULL; | |
112 | ||
113 | /* TODO(3.0): Add errors to stack */ | |
114 | if (pdhctx->dh == NULL || pdhctx->dhpeer == NULL) | |
115 | return 0; | |
116 | ||
117 | dhsize = (size_t)DH_size(pdhctx->dh); | |
118 | if (key == NULL) { | |
119 | *keylen = dhsize; | |
120 | return 1; | |
121 | } | |
122 | if (outlen < dhsize) | |
123 | return 0; | |
124 | ||
125 | DH_get0_key(pdhctx->dhpeer, &pub_key, NULL); | |
35aca9ec MC |
126 | ret = (pdhctx->pad) ? DH_compute_key_padded(key, pub_key, pdhctx->dh) |
127 | : DH_compute_key(key, pub_key, pdhctx->dh); | |
89e29174 MC |
128 | if (ret <= 0) |
129 | return 0; | |
130 | ||
131 | *keylen = ret; | |
132 | return 1; | |
133 | } | |
134 | ||
135 | static void dh_freectx(void *vpdhctx) | |
136 | { | |
137 | PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; | |
138 | ||
139 | DH_free(pdhctx->dh); | |
140 | DH_free(pdhctx->dhpeer); | |
141 | ||
142 | OPENSSL_free(pdhctx); | |
143 | } | |
144 | ||
145 | static void *dh_dupctx(void *vpdhctx) | |
146 | { | |
147 | PROV_DH_CTX *srcctx = (PROV_DH_CTX *)vpdhctx; | |
148 | PROV_DH_CTX *dstctx; | |
149 | ||
150 | dstctx = OPENSSL_zalloc(sizeof(*srcctx)); | |
151 | ||
152 | *dstctx = *srcctx; | |
153 | if (dstctx->dh != NULL && !DH_up_ref(dstctx->dh)) { | |
154 | OPENSSL_free(dstctx); | |
155 | return NULL; | |
156 | } | |
157 | ||
158 | if (dstctx->dhpeer != NULL && !DH_up_ref(dstctx->dhpeer)) { | |
159 | DH_free(dstctx->dh); | |
160 | OPENSSL_free(dstctx); | |
161 | return NULL; | |
162 | } | |
163 | ||
164 | return dstctx; | |
165 | } | |
166 | ||
35aca9ec MC |
167 | static int dh_set_params(void *vpdhctx, OSSL_PARAM params[]) |
168 | { | |
169 | PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; | |
170 | const OSSL_PARAM *p; | |
171 | int pad; | |
172 | ||
173 | if (pdhctx == NULL || params == NULL) | |
174 | return 0; | |
175 | ||
176 | p = OSSL_PARAM_locate(params, OSSL_EXCHANGE_PARAM_PAD); | |
177 | if (p == NULL || !OSSL_PARAM_get_int(p, &pad)) | |
178 | return 0; | |
179 | ||
180 | pdhctx->pad = pad; | |
181 | ||
182 | return 1; | |
183 | } | |
184 | ||
89e29174 MC |
185 | const OSSL_DISPATCH dh_functions[] = { |
186 | { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))dh_newctx }, | |
187 | { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))dh_init }, | |
188 | { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))dh_derive }, | |
189 | { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))dh_set_peer }, | |
190 | { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))dh_freectx }, | |
191 | { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))dh_dupctx }, | |
35aca9ec | 192 | { OSSL_FUNC_KEYEXCH_SET_PARAMS, (void (*)(void))dh_set_params }, |
89e29174 MC |
193 | { 0, NULL } |
194 | }; |