wolfssl: Fixes, code style changes and some refactorings
[strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_ed_private_key.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_ED25519
26
27 #include "wolfssl_ed_private_key.h"
28
29 #include <utils/debug.h>
30
31 #include <wolfssl/wolfcrypt/ed25519.h>
32 #include <wolfssl/wolfcrypt/asn.h>
33
34 typedef struct private_private_key_t private_private_key_t;
35
36 /**
37 * Private data
38 */
39 struct private_private_key_t {
40
41 /**
42 * Public interface
43 */
44 private_key_t public;
45
46 /**
47 * Key object
48 */
49 ed25519_key key;
50
51 /**
52 * Reference count
53 */
54 refcount_t ref;
55 };
56
57 /* from ed public key */
58 bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
59 chunk_t *fp);
60
61 METHOD(private_key_t, sign, bool,
62 private_private_key_t *this, signature_scheme_t scheme,
63 void *params, chunk_t data, chunk_t *signature)
64 {
65 word32 len;
66 byte dummy[1];
67 int ret;
68
69 if (scheme != SIGN_ED25519)
70 {
71 DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
72 signature_scheme_names, scheme, key_type_names, KEY_ED25519);
73 return FALSE;
74 }
75
76 if (!data.ptr && !data.len)
77 {
78 data.ptr = dummy;
79 }
80
81 len = ED25519_SIG_SIZE;
82 *signature = chunk_alloc(len);
83 ret = wc_ed25519_sign_msg(data.ptr, data.len, signature->ptr, &len,
84 &this->key);
85 return ret == 0;
86 }
87
88 METHOD(private_key_t, decrypt, bool,
89 private_private_key_t *this, encryption_scheme_t scheme,
90 chunk_t crypto, chunk_t *plain)
91 {
92 DBG1(DBG_LIB, "EdDSA private key decryption not implemented");
93 return FALSE;
94 }
95
96 METHOD(private_key_t, get_keysize, int,
97 private_private_key_t *this)
98 {
99 return ED25519_KEY_SIZE * 8;
100 }
101
102 METHOD(private_key_t, get_type, key_type_t,
103 private_private_key_t *this)
104 {
105 return KEY_ED25519;
106 }
107
108 METHOD(private_key_t, get_public_key, public_key_t*,
109 private_private_key_t *this)
110 {
111 public_key_t *public;
112 chunk_t key;
113 word32 len = ED25519_PUB_KEY_SIZE;
114
115 key = chunk_alloca(len);
116 if (wc_ed25519_export_public(&this->key, key.ptr, &len) != 0)
117 {
118 return NULL;
119 }
120 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ED25519,
121 BUILD_EDDSA_PUB, key, BUILD_END);
122 return public;
123 }
124
125 METHOD(private_key_t, get_fingerprint, bool,
126 private_private_key_t *this, cred_encoding_type_t type,
127 chunk_t *fingerprint)
128 {
129 return wolfssl_ed_fingerprint(&this->key, type, fingerprint);
130 }
131
132 METHOD(private_key_t, get_encoding, bool,
133 private_private_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
134 {
135 int ret;
136
137 switch (type)
138 {
139 case PRIVKEY_ASN1_DER:
140 case PRIVKEY_PEM:
141 {
142 bool success = TRUE;
143
144 /* +4 is for the two octet strings */
145 *encoding = chunk_alloc(ED25519_PRV_KEY_SIZE + 2 * MAX_SEQ_SZ +
146 MAX_VERSION_SZ + MAX_ALGO_SZ + 4);
147 ret = wc_Ed25519PrivateKeyToDer(&this->key, encoding->ptr,
148 encoding->len);
149 if (ret < 0)
150 {
151 chunk_free(encoding);
152 return FALSE;
153 }
154 encoding->len = ret;
155
156 if (type == PRIVKEY_PEM)
157 {
158 chunk_t asn1_encoding = *encoding;
159
160 success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
161 NULL, encoding, CRED_PART_EDDSA_PRIV_ASN1_DER,
162 asn1_encoding, CRED_PART_END);
163 chunk_clear(&asn1_encoding);
164 }
165 return success;
166 }
167 default:
168 return FALSE;
169 }
170 }
171
172 METHOD(private_key_t, get_ref, private_key_t*,
173 private_private_key_t *this)
174 {
175 ref_get(&this->ref);
176 return &this->public;
177 }
178
179 METHOD(private_key_t, destroy, void,
180 private_private_key_t *this)
181 {
182 if (ref_put(&this->ref))
183 {
184 lib->encoding->clear_cache(lib->encoding, &this->key);
185 wc_ed25519_free(&this->key);
186 free(this);
187 }
188 }
189
190 /**
191 * Internal generic constructor
192 */
193 static private_private_key_t *create_internal()
194 {
195 private_private_key_t *this;
196
197 INIT(this,
198 .public = {
199 .get_type = _get_type,
200 .sign = _sign,
201 .decrypt = _decrypt,
202 .get_keysize = _get_keysize,
203 .get_public_key = _get_public_key,
204 .equals = private_key_equals,
205 .belongs_to = private_key_belongs_to,
206 .get_fingerprint = _get_fingerprint,
207 .has_fingerprint = private_key_has_fingerprint,
208 .get_encoding = _get_encoding,
209 .get_ref = _get_ref,
210 .destroy = _destroy,
211 },
212 .ref = 1,
213 );
214
215 if (wc_ed25519_init(&this->key) != 0)
216 {
217 free(this);
218 this = NULL;
219 }
220 return this;
221 }
222
223 /*
224 * Described in header
225 */
226 private_key_t *wolfssl_ed_private_key_gen(key_type_t type, va_list args)
227 {
228 private_private_key_t *this;
229 WC_RNG rng;
230 int ret;
231
232 while (TRUE)
233 {
234 switch (va_arg(args, builder_part_t))
235 {
236 case BUILD_KEY_SIZE:
237 /* just ignore the key size */
238 va_arg(args, u_int);
239 continue;
240 case BUILD_END:
241 break;
242 default:
243 return NULL;
244 }
245 break;
246 }
247
248 this = create_internal();
249 if (!this)
250 {
251 return NULL;
252 }
253
254 if (wc_InitRng(&rng) != 0)
255 {
256 DBG1(DBG_LIB, "initializing random failed");
257 destroy(this);
258 return NULL;
259 }
260 ret = wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &this->key);
261 wc_FreeRng(&rng);
262
263 if (ret < 0)
264 {
265 DBG1(DBG_LIB, "generating %N key failed", key_type_names, type);
266 destroy(this);
267 return NULL;
268 }
269 return &this->public;
270 }
271
272 /**
273 * Fix the internal state if only the private key is set
274 */
275 static int set_public_key(private_private_key_t *this)
276 {
277 int ret = 0;
278
279 if (!this->key.pubKeySet)
280 {
281 ret = wc_ed25519_make_public(&this->key, this->key.p,
282 ED25519_PUB_KEY_SIZE);
283 if (ret == 0)
284 {
285 /* put public key after private key in the same buffer */
286 memmove(this->key.k + ED25519_KEY_SIZE, this->key.p,
287 ED25519_PUB_KEY_SIZE);
288 this->key.pubKeySet = 1;
289 }
290 }
291 return ret;
292 }
293
294 /*
295 * Described in header
296 */
297 private_key_t *wolfssl_ed_private_key_load(key_type_t type, va_list args)
298 {
299 private_private_key_t *this;
300 chunk_t blob = chunk_empty, priv = chunk_empty;
301 int idx;
302 int ret = -1;
303
304 while (TRUE)
305 {
306 switch (va_arg(args, builder_part_t))
307 {
308 case BUILD_BLOB_ASN1_DER:
309 blob = va_arg(args, chunk_t);
310 continue;
311 case BUILD_EDDSA_PRIV_ASN1_DER:
312 priv = va_arg(args, chunk_t);
313 continue;
314 case BUILD_END:
315 break;
316 default:
317 return NULL;
318 }
319 break;
320 }
321 this = create_internal();
322 if (!this)
323 {
324 return NULL;
325 }
326
327 if (priv.len)
328 {
329 /* check for ASN.1 wrapped key (Octet String == 0x04) */
330 if (priv.len == ED25519_KEY_SIZE + 2 && priv.ptr[0] == 0x04 &&
331 priv.ptr[1] == ED25519_KEY_SIZE)
332 {
333 priv = chunk_skip(priv, 2);
334 }
335 ret = wc_ed25519_import_private_only(priv.ptr, priv.len, &this->key);
336 }
337 else if (blob.len)
338 {
339 idx = 0;
340 ret = wc_Ed25519PrivateKeyDecode(blob.ptr, &idx, &this->key, blob.len);
341 }
342 if (ret == 0)
343 {
344 ret = set_public_key(this);
345 }
346 if (ret != 0)
347 {
348 destroy(this);
349 return NULL;
350 }
351 return &this->public;
352 }
353
354 #endif /* HAVE_ED25519 */