]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/wolfssl/wolfssl_diffie_hellman.c
wolfssl: Fixes, code style changes and some refactorings
[thirdparty/strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_diffie_hellman.c
CommitLineData
c92eade8
SP
1/*
2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "wolfssl_common.h"
24
25#ifndef NO_DH
26
27#include <wolfssl/wolfcrypt/dh.h>
28
29#include "wolfssl_diffie_hellman.h"
30#include "wolfssl_util.h"
31
32#include <utils/debug.h>
33
34typedef struct private_wolfssl_diffie_hellman_t private_wolfssl_diffie_hellman_t;
35
36/**
37 * Private data of an wolfssl_diffie_hellman_t object.
38 */
39struct private_wolfssl_diffie_hellman_t {
d3329ee5 40
c92eade8
SP
41 /**
42 * Public wolfssl_diffie_hellman_t interface.
43 */
44 wolfssl_diffie_hellman_t public;
45
46 /**
47 * Diffie Hellman group number.
48 */
49 diffie_hellman_group_t group;
50
51 /**
52 * Diffie Hellman object
53 */
54 DhKey dh;
55
c92eade8
SP
56 /**
57 * Length of public values
58 */
59 int len;
60
61 /**
62 * Private key
63 */
64 chunk_t priv;
65
66 /**
67 * Public key
68 */
69 chunk_t pub;
70
71 /**
72 * Shared secret
73 */
74 chunk_t shared_secret;
c92eade8
SP
75};
76
77METHOD(diffie_hellman_t, get_my_public_value, bool,
78 private_wolfssl_diffie_hellman_t *this, chunk_t *value)
79{
d3329ee5 80 *value = chunk_copy_pad(chunk_alloc(this->len), this->pub, 0x00);
c92eade8
SP
81 return TRUE;
82}
83
84METHOD(diffie_hellman_t, get_shared_secret, bool,
85 private_wolfssl_diffie_hellman_t *this, chunk_t *secret)
86{
d3329ee5 87 if (!this->shared_secret.len)
c92eade8
SP
88 {
89 return FALSE;
90 }
d3329ee5 91 *secret = chunk_copy_pad(chunk_alloc(this->len), this->shared_secret, 0x00);
c92eade8
SP
92 return TRUE;
93}
94
c92eade8
SP
95METHOD(diffie_hellman_t, set_other_public_value, bool,
96 private_wolfssl_diffie_hellman_t *this, chunk_t value)
97{
98 word32 len;
99
100 if (!diffie_hellman_verify_value(this->group, value))
101 {
102 return FALSE;
103 }
104
105 chunk_clear(&this->shared_secret);
d3329ee5 106 this->shared_secret = chunk_alloc(this->len);
c92eade8
SP
107 if (wc_DhAgree(&this->dh, this->shared_secret.ptr, &len, this->priv.ptr,
108 this->priv.len, value.ptr, value.len) != 0)
109 {
110 DBG1(DBG_LIB, "DH shared secret computation failed");
d3329ee5 111 chunk_free(&this->shared_secret);
c92eade8
SP
112 return FALSE;
113 }
114 this->shared_secret.len = len;
c92eade8
SP
115 return TRUE;
116}
117
118METHOD(diffie_hellman_t, set_private_value, bool,
119 private_wolfssl_diffie_hellman_t *this, chunk_t value)
120{
121 bool success = FALSE;
122 chunk_t g;
123 word32 len;
c92eade8
SP
124
125 chunk_clear(&this->priv);
126 this->priv = chunk_clone(value);
127
d3329ee5 128 /* calculate public value - g^priv mod p */
c92eade8
SP
129 if (wolfssl_mp2chunk(&this->dh.g, &g))
130 {
131 len = this->pub.len;
d3329ee5
TB
132 if (wc_DhAgree(&this->dh, this->pub.ptr, &len, this->priv.ptr,
133 this->priv.len, g.ptr, g.len) == 0)
134 {
c92eade8
SP
135 this->pub.len = len;
136 success = TRUE;
137 }
138 }
139
140 free(g.ptr);
141 return success;
142}
143
144METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
145 private_wolfssl_diffie_hellman_t *this)
146{
147 return this->group;
148}
149
c92eade8
SP
150METHOD(diffie_hellman_t, destroy, void,
151 private_wolfssl_diffie_hellman_t *this)
152{
c92eade8
SP
153 wc_FreeDhKey(&this->dh);
154 chunk_clear(&this->pub);
155 chunk_clear(&this->priv);
156 chunk_clear(&this->shared_secret);
157 free(this);
158}
159
160/**
161 * Maximum private key length when generating key
162 */
163static int wolfssl_priv_key_size(int len)
164{
165 if (len <= 128)
166 {
167 return 21;
168 }
169 if (len <= 256)
170 {
171 return 29;
172 }
173 if (len <= 384)
174 {
175 return 34;
176 }
177 if (len <= 512)
178 {
179 return 39;
180 }
181 if (len <= 640)
182 {
183 return 42;
184 }
185 if (len <= 768)
186 {
187 return 46;
188 }
189 if (len <= 896)
190 {
191 return 49;
192 }
193 if (len <= 1024)
194 {
195 return 52;
196 }
197 return len / 20;
198}
199
d3329ee5
TB
200/**
201 * Generic internal constructor
c92eade8 202 */
d3329ee5
TB
203static wolfssl_diffie_hellman_t *create_generic(diffie_hellman_group_t group,
204 chunk_t g, chunk_t p)
c92eade8
SP
205{
206 private_wolfssl_diffie_hellman_t *this;
207 word32 privLen, pubLen;
d3329ee5 208 WC_RNG rng;
c92eade8
SP
209
210 INIT(this,
211 .public = {
212 .dh = {
213 .get_shared_secret = _get_shared_secret,
214 .set_other_public_value = _set_other_public_value,
215 .get_my_public_value = _get_my_public_value,
216 .set_private_value = _set_private_value,
217 .get_dh_group = _get_dh_group,
218 .destroy = _destroy,
219 },
220 },
d3329ee5
TB
221 .group = group,
222 .len = p.len,
c92eade8
SP
223 );
224
c92eade8
SP
225 if (wc_InitDhKey(&this->dh) != 0)
226 {
c92eade8
SP
227 free(this);
228 return NULL;
229 }
230
d3329ee5 231 if (wc_DhSetKey(&this->dh, p.ptr, p.len, g.ptr, g.len) != 0)
c92eade8 232 {
d3329ee5
TB
233 destroy(this);
234 return NULL;
c92eade8 235 }
d3329ee5
TB
236
237 if (wc_InitRng(&rng) != 0)
c92eade8 238 {
d3329ee5
TB
239 destroy(this);
240 return NULL;
c92eade8
SP
241 }
242
243 this->priv = chunk_alloc(wolfssl_priv_key_size(this->len));
244 this->pub = chunk_alloc(this->len);
245 privLen = this->priv.len;
246 pubLen = this->pub.len;
247 /* generate my public and private values */
d3329ee5 248 if (wc_DhGenerateKeyPair(&this->dh, &rng, this->priv.ptr, &privLen,
c92eade8
SP
249 this->pub.ptr, &pubLen) != 0)
250 {
d3329ee5 251 wc_FreeRng(&rng);
c92eade8
SP
252 destroy(this);
253 return NULL;
254 }
255 this->pub.len = pubLen;
256 this->priv.len = privLen;
d3329ee5 257 wc_FreeRng(&rng);
c92eade8
SP
258
259 return &this->public;
260}
261
d3329ee5
TB
262/*
263 * Described in header
264 */
265wolfssl_diffie_hellman_t *wolfssl_diffie_hellman_create(
266 diffie_hellman_group_t group, ...)
267{
268 diffie_hellman_params_t *params;
269 chunk_t g, p;
270
271 if (group == MODP_CUSTOM)
272 {
273 VA_ARGS_GET(group, g, p);
274 return create_generic(group, g, p);
275 }
276 params = diffie_hellman_get_params(group);
277 if (!params)
278 {
279 return NULL;
280 }
281 /* wolfSSL doesn't support optimized exponent sizes according to RFC 3526 */
282 return create_generic(group, params->generator, params->prime);
283}
284
c92eade8 285#endif /* NO_DH */