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