wolfssl: Fixes, code style changes and some refactorings
[strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_x_diffie_hellman.c
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 #ifdef HAVE_CURVE25519
26
27 #include "wolfssl_x_diffie_hellman.h"
28
29 #include <utils/debug.h>
30
31 #include <wolfssl/wolfcrypt/curve25519.h>
32 #include <wolfssl/wolfcrypt/fe_operations.h>
33
34 typedef struct private_diffie_hellman_t private_diffie_hellman_t;
35
36 /**
37 * Private data
38 */
39 struct private_diffie_hellman_t {
40 /**
41 * Public interface.
42 */
43 diffie_hellman_t public;
44
45 /**
46 * Diffie Hellman group number.
47 */
48 diffie_hellman_group_t group;
49
50 /**
51 * Private (public) key
52 */
53 curve25519_key key;
54
55 /**
56 * Shared secret
57 */
58 chunk_t shared_secret;
59 };
60
61 /**
62 * Compute the shared secret
63 */
64 static bool compute_shared_key(private_diffie_hellman_t *this,
65 curve25519_key *pub, chunk_t *shared_secret)
66 {
67 word32 len = CURVE25519_KEYSIZE;
68 int ret;
69
70 *shared_secret = chunk_alloc(len);
71 ret = wc_curve25519_shared_secret_ex(&this->key, pub, shared_secret->ptr,
72 &len, EC25519_LITTLE_ENDIAN);
73 return ret == 0;
74 }
75
76 METHOD(diffie_hellman_t, set_other_public_value, bool,
77 private_diffie_hellman_t *this, chunk_t value)
78 {
79 curve25519_key pub;
80 int ret;
81
82 if (!diffie_hellman_verify_value(this->group, value))
83 {
84 return FALSE;
85 }
86
87 ret = wc_curve25519_init(&pub);
88 if (ret != 0)
89 {
90 DBG1(DBG_LIB, "%N public key initialization failed",
91 diffie_hellman_group_names, this->group);
92 return FALSE;
93 }
94
95 ret = wc_curve25519_import_public_ex(value.ptr, value.len, &pub,
96 EC25519_LITTLE_ENDIAN);
97 if (ret != 0)
98 {
99 DBG1(DBG_LIB, "%N public value is malformed",
100 diffie_hellman_group_names, this->group);
101 return FALSE;
102 }
103
104 chunk_clear(&this->shared_secret);
105
106 if (!compute_shared_key(this, &pub, &this->shared_secret))
107 {
108 DBG1(DBG_LIB, "%N shared secret computation failed",
109 diffie_hellman_group_names, this->group);
110 chunk_clear(&this->shared_secret);
111 wc_curve25519_free(&pub);
112 return FALSE;
113 }
114 wc_curve25519_free(&pub);
115 return TRUE;
116 }
117
118 METHOD(diffie_hellman_t, get_my_public_value, bool,
119 private_diffie_hellman_t *this, chunk_t *value)
120 {
121 word32 len = CURVE25519_KEYSIZE;
122
123 *value = chunk_alloc(len);
124 if (wc_curve25519_export_public_ex(&this->key, value->ptr, &len,
125 EC25519_LITTLE_ENDIAN) != 0)
126 {
127 chunk_free(value);
128 return FALSE;
129 }
130 return TRUE;
131 }
132
133 METHOD(diffie_hellman_t, set_private_value, bool,
134 private_diffie_hellman_t *this, chunk_t value)
135 {
136 curve25519_key pub;
137 u_char basepoint[CURVE25519_KEYSIZE] = {9};
138 word32 len = CURVE25519_KEYSIZE;
139 int ret;
140
141 ret = wc_curve25519_init(&pub);
142 /* create base point for calculating public key */
143 if (ret == 0)
144 {
145 ret = wc_curve25519_import_public_ex(basepoint, CURVE25519_KEYSIZE,
146 &pub, EC25519_LITTLE_ENDIAN);
147 }
148 if (ret == 0)
149 {
150 ret = wc_curve25519_import_private_ex(value.ptr, value.len, &this->key,
151 EC25519_LITTLE_ENDIAN);
152 }
153 if (ret == 0)
154 {
155 ret = wc_curve25519_shared_secret_ex(&this->key, &pub,
156 this->key.p.point, &len, EC25519_LITTLE_ENDIAN);
157 }
158 return ret == 0;
159 }
160
161 METHOD(diffie_hellman_t, get_shared_secret, bool,
162 private_diffie_hellman_t *this, chunk_t *secret)
163 {
164 if (!this->shared_secret.len)
165 {
166 return FALSE;
167 }
168 *secret = chunk_clone(this->shared_secret);
169 return TRUE;
170 }
171
172 METHOD(diffie_hellman_t, get_dh_group, diffie_hellman_group_t,
173 private_diffie_hellman_t *this)
174 {
175 return this->group;
176 }
177
178 METHOD(diffie_hellman_t, destroy, void,
179 private_diffie_hellman_t *this)
180 {
181 wc_curve25519_free(&this->key);
182 chunk_clear(&this->shared_secret);
183 free(this);
184 }
185
186 /*
187 * Described in header
188 */
189 diffie_hellman_t *wolfssl_x_diffie_hellman_create(diffie_hellman_group_t group)
190 {
191 private_diffie_hellman_t *this;
192 WC_RNG rng;
193 int ret;
194
195 INIT(this,
196 .public = {
197 .get_shared_secret = _get_shared_secret,
198 .set_other_public_value = _set_other_public_value,
199 .get_my_public_value = _get_my_public_value,
200 .set_private_value = _set_private_value,
201 .get_dh_group = _get_dh_group,
202 .destroy = _destroy,
203 },
204 .group = group,
205 );
206
207 if (wc_curve25519_init(&this->key) != 0)
208 {
209 DBG1(DBG_LIB, "initializing key failed");
210 free(this);
211 return NULL;
212 }
213
214 if (wc_InitRng(&rng) != 0)
215 {
216 DBG1(DBG_LIB, "initializing a random number generator failed");
217 destroy(this);
218 return NULL;
219 }
220 ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, &this->key);
221 wc_FreeRng(&rng);
222 if (ret != 0)
223 {
224 DBG1(DBG_LIB, "making a key failed");
225 destroy(this);
226 return NULL;
227 }
228 return &this->public;
229 }
230
231 #endif /* HAVE_CURVE25519 */