]> git.ipfire.org Git - thirdparty/strongswan.git/blob - src/libstrongswan/plugins/wolfssl/wolfssl_ed_public_key.c
wolfssl: Add support for Ed448
[thirdparty/strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_ed_public_key.c
1 /*
2 * Copyright (C) 2020 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
4 *
5 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
26 #include "wolfssl_common.h"
27
28 #if defined(HAVE_ED25519) || defined(HAVE_ED448)
29
30 #include "wolfssl_ed_public_key.h"
31
32 #include <utils/debug.h>
33 #include <asn1/asn1.h>
34
35 #ifdef HAVE_ED25519
36 #include <wolfssl/wolfcrypt/ed25519.h>
37 #endif
38 #ifdef HAVE_ED448
39 #include <wolfssl/wolfcrypt/ed448.h>
40 #endif
41
42 #include <wolfssl/wolfcrypt/asn.h>
43
44 typedef struct private_public_key_t private_public_key_t;
45
46 /**
47 * Private data
48 */
49 struct private_public_key_t {
50
51 /**
52 * Public interface
53 */
54 public_key_t public;
55
56 /**
57 * Key object
58 */
59 wolfssl_ed_key key;
60
61 /**
62 * Key type
63 */
64 key_type_t type;
65
66 /**
67 * Reference count
68 */
69 refcount_t ref;
70 };
71
72 METHOD(public_key_t, get_type, key_type_t,
73 private_public_key_t *this)
74 {
75 return this->type;
76 }
77
78 METHOD(public_key_t, verify, bool,
79 private_public_key_t *this, signature_scheme_t scheme,
80 void *params, chunk_t data, chunk_t signature)
81 {
82 byte dummy[1];
83 int ret = -1, res = 0;
84
85 if ((this->type == KEY_ED25519 && scheme != SIGN_ED25519) ||
86 (this->type == KEY_ED448 && scheme != SIGN_ED448))
87 {
88 DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
89 signature_scheme_names, scheme, key_type_names, this->type);
90 return FALSE;
91 }
92
93 if (!data.ptr && !data.len)
94 {
95 data.ptr = dummy;
96 }
97
98 if (this->type == KEY_ED25519)
99 {
100 #ifdef HAVE_ED25519
101 ret = wc_ed25519_verify_msg(signature.ptr, signature.len, data.ptr,
102 data.len, &res, &this->key.ed25519);
103 #endif
104 }
105 else if (this->type == KEY_ED448)
106 {
107 #ifdef HAVE_ED448
108 ret = wc_ed448_verify_msg(signature.ptr, signature.len, data.ptr,
109 data.len, &res, &this->key.ed448, NULL, 0);
110 #endif
111 }
112 return ret == 0 && res == 1;
113 }
114
115 METHOD(public_key_t, encrypt, bool,
116 private_public_key_t *this, encryption_scheme_t scheme,
117 chunk_t crypto, chunk_t *plain)
118 {
119 DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names,
120 scheme);
121 return FALSE;
122 }
123
124 /**
125 * Returns the key size in bytes for the given type, also used in private key.
126 */
127 int wolfssl_ed_keysize(key_type_t type)
128 {
129 if (type == KEY_ED25519)
130 {
131 #ifdef HAVE_ED25519
132 return ED25519_KEY_SIZE * 8;
133 #endif
134 }
135 else if (type == KEY_ED448)
136 {
137 #ifdef HAVE_ED448
138 return ED448_KEY_SIZE * 8;
139 #endif
140 }
141 return 0;
142 }
143
144 METHOD(public_key_t, get_keysize, int,
145 private_public_key_t *this)
146 {
147 return wolfssl_ed_keysize(this->type);
148 }
149
150 /**
151 * Encode the given public key as ASN.1 DER with algorithm identifier
152 */
153 static bool encode_pubkey(wolfssl_ed_key *key, key_type_t type,
154 chunk_t *encoding)
155 {
156 int ret = -1;
157
158 /* account for algorithmIdentifier/bitString */
159 if (type == KEY_ED25519)
160 {
161 #ifdef HAVE_ED25519
162 *encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
163 MAX_ALGO_SZ + TRAILING_ZERO);
164 ret = wc_Ed25519PublicKeyToDer(&key->ed25519, encoding->ptr,
165 encoding->len, 1);
166 #endif
167 }
168 else if (type == KEY_ED448)
169 {
170 #ifdef HAVE_ED448
171 *encoding = chunk_alloc(ED448_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
172 MAX_ALGO_SZ + TRAILING_ZERO);
173 ret = wc_Ed448PublicKeyToDer(&key->ed448, encoding->ptr,
174 encoding->len, 1);
175 #endif
176 }
177 if (ret < 0)
178 {
179 return FALSE;
180 }
181 encoding->len = ret;
182 return TRUE;
183 }
184
185 /**
186 * Export the raw public key of the given key, also used in ed private key.
187 */
188 bool wolfssl_ed_public_key(wolfssl_ed_key *key, key_type_t type, chunk_t *raw)
189 {
190 word32 len;
191
192 *raw = chunk_empty;
193 if (type == KEY_ED25519)
194 {
195 #ifdef HAVE_ED25519
196 len = ED25519_PUB_KEY_SIZE;
197 *raw = chunk_alloc(len);
198 if (wc_ed25519_export_public(&key->ed25519, raw->ptr, &len) != 0)
199 {
200 chunk_free(raw);
201 return FALSE;
202 }
203 #endif
204 }
205 else if (type == KEY_ED448)
206 {
207 #ifdef HAVE_ED448
208 len = ED448_PUB_KEY_SIZE;
209 *raw = chunk_alloc(len);
210 if (wc_ed448_export_public(&key->ed448, raw->ptr, &len) != 0)
211 {
212 chunk_free(raw);
213 return FALSE;
214 }
215 #endif
216 }
217 return TRUE;
218 }
219
220 /**
221 * Calculate fingerprint from an EdDSA key, also used in ed private key.
222 */
223 bool wolfssl_ed_fingerprint(wolfssl_ed_key *key, key_type_t key_type,
224 cred_encoding_type_t type, chunk_t *fp)
225 {
226 hasher_t *hasher;
227 chunk_t blob;
228 bool success = FALSE;
229
230 if (lib->encoding->get_cache(lib->encoding, type, key, fp))
231 {
232 return TRUE;
233 }
234 switch (type)
235 {
236 case KEYID_PUBKEY_SHA1:
237 if (!wolfssl_ed_public_key(key, key_type, &blob))
238 {
239 return FALSE;
240 }
241 break;
242 case KEYID_PUBKEY_INFO_SHA1:
243 if (!encode_pubkey(key, key_type, &blob))
244 {
245 return FALSE;
246 }
247 break;
248 default:
249 return FALSE;
250 }
251 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
252 if (!hasher || !hasher->allocate_hash(hasher, blob, fp))
253 {
254 DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
255 }
256 else
257 {
258 lib->encoding->cache(lib->encoding, type, key, *fp);
259 success = TRUE;
260 }
261 DESTROY_IF(hasher);
262 chunk_free(&blob);
263 return success;
264 }
265
266 METHOD(public_key_t, get_fingerprint, bool,
267 private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint)
268 {
269 return wolfssl_ed_fingerprint(&this->key, this->type, type, fingerprint);
270 }
271
272 METHOD(public_key_t, get_encoding, bool,
273 private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
274 {
275 bool success = TRUE;
276
277 if (!encode_pubkey(&this->key, this->type, encoding))
278 {
279 return FALSE;
280 }
281
282 if (type != PUBKEY_SPKI_ASN1_DER)
283 {
284 chunk_t asn1_encoding = *encoding;
285
286 success = lib->encoding->encode(lib->encoding, type,
287 NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER,
288 asn1_encoding, CRED_PART_END);
289 chunk_free(&asn1_encoding);
290 }
291 return success;
292 }
293
294 METHOD(public_key_t, get_ref, public_key_t*,
295 private_public_key_t *this)
296 {
297 ref_get(&this->ref);
298 return &this->public;
299 }
300
301 /**
302 * Destroy an EdDSA key of the given type, also used by ed private key.
303 */
304 void wolfssl_ed_destroy(wolfssl_ed_key *key, key_type_t type)
305 {
306 if (type == KEY_ED25519)
307 {
308 #ifdef HAVE_ED25519
309 wc_ed25519_free(&key->ed25519);
310 #endif
311 }
312 else if (type == KEY_ED448)
313 {
314 #ifdef HAVE_ED448
315 wc_ed448_free(&key->ed448);
316 #endif
317 }
318 }
319
320 METHOD(public_key_t, destroy, void,
321 private_public_key_t *this)
322 {
323 if (ref_put(&this->ref))
324 {
325 lib->encoding->clear_cache(lib->encoding, &this->key);
326 wolfssl_ed_destroy(&this->key, this->type);
327 free(this);
328 }
329 }
330
331 /**
332 * Initialized an EdDSA key of the given type, also used by ed private key.
333 */
334 bool wolfssl_ed_create(wolfssl_ed_key *key, key_type_t type)
335 {
336 if (type == KEY_ED25519)
337 {
338 #ifdef HAVE_ED25519
339 if (wc_ed25519_init(&key->ed25519) != 0)
340 {
341 return FALSE;
342 }
343 #endif
344 }
345 else if (type == KEY_ED448)
346 {
347 #ifdef HAVE_ED448
348 if (wc_ed448_init(&key->ed448) != 0)
349 {
350 return FALSE;
351 }
352 #endif
353 }
354 else
355 {
356 return FALSE;
357 }
358 return TRUE;
359 }
360
361 /**
362 * Generic private constructor
363 */
364 static private_public_key_t *create_empty(key_type_t type)
365 {
366 private_public_key_t *this;
367
368 INIT(this,
369 .public = {
370 .get_type = _get_type,
371 .verify = _verify,
372 .encrypt = _encrypt,
373 .get_keysize = _get_keysize,
374 .equals = public_key_equals,
375 .get_fingerprint = _get_fingerprint,
376 .has_fingerprint = public_key_has_fingerprint,
377 .get_encoding = _get_encoding,
378 .get_ref = _get_ref,
379 .destroy = _destroy,
380 },
381 .type = type,
382 .ref = 1,
383 );
384
385 if (!wolfssl_ed_create(&this->key, type))
386 {
387 free(this);
388 this = NULL;
389 }
390 return this;
391 }
392
393 /*
394 * Described in header
395 */
396 public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args)
397 {
398 private_public_key_t *this;
399 chunk_t blob = chunk_empty, pub = chunk_empty;
400 int idx;
401 int ret = -1;
402
403 while (TRUE)
404 {
405 switch (va_arg(args, builder_part_t))
406 {
407 case BUILD_BLOB_ASN1_DER:
408 blob = va_arg(args, chunk_t);
409 continue;
410 case BUILD_EDDSA_PUB:
411 pub = va_arg(args, chunk_t);
412 continue;
413 case BUILD_END:
414 break;
415 default:
416 return NULL;
417 }
418 break;
419 }
420
421 this = create_empty(type);
422 if (!this)
423 {
424 return NULL;
425 }
426
427 if (type == KEY_ED25519)
428 {
429 #ifdef HAVE_ED25519
430 if (pub.len)
431 {
432 ret = wc_ed25519_import_public(pub.ptr, pub.len,
433 &this->key.ed25519);
434 }
435 else if (blob.len)
436 {
437 idx = 0;
438 ret = wc_Ed25519PublicKeyDecode(blob.ptr, &idx, &this->key.ed25519,
439 blob.len);
440 }
441 #endif
442 }
443 else if (type == KEY_ED448)
444 {
445 #ifdef HAVE_ED448
446 if (pub.len)
447 {
448 ret = wc_ed448_import_public(pub.ptr, pub.len, &this->key.ed448);
449 }
450 else if (blob.len)
451 {
452 idx = 0;
453 ret = wc_Ed448PublicKeyDecode(blob.ptr, &idx, &this->key.ed448,
454 blob.len);
455 }
456 #endif
457 }
458
459 if (ret != 0)
460 {
461 destroy(this);
462 return NULL;
463 }
464 return &this->public;
465 }
466
467 #endif /* HAVE_ED25519 */