2 * Copyright (C) 2020 Tobias Brunner
3 * HSR Hochschule fuer Technik Rapperswil
5 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
26 #include "wolfssl_common.h"
28 #if defined(HAVE_ED25519) || defined(HAVE_ED448)
30 #include "wolfssl_ed_public_key.h"
32 #include <utils/debug.h>
33 #include <asn1/asn1.h>
36 #include <wolfssl/wolfcrypt/ed25519.h>
39 #include <wolfssl/wolfcrypt/ed448.h>
42 #include <wolfssl/wolfcrypt/asn.h>
44 typedef struct private_public_key_t private_public_key_t
;
49 struct private_public_key_t
{
72 METHOD(public_key_t
, get_type
, key_type_t
,
73 private_public_key_t
*this)
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
)
83 int ret
= -1, res
= 0;
85 if ((this->type
== KEY_ED25519
&& scheme
!= SIGN_ED25519
) ||
86 (this->type
== KEY_ED448
&& scheme
!= SIGN_ED448
))
88 DBG1(DBG_LIB
, "signature scheme %N not supported by %N key",
89 signature_scheme_names
, scheme
, key_type_names
, this->type
);
93 if (!data
.ptr
&& !data
.len
)
98 if (this->type
== KEY_ED25519
)
101 ret
= wc_ed25519_verify_msg(signature
.ptr
, signature
.len
, data
.ptr
,
102 data
.len
, &res
, &this->key
.ed25519
);
105 else if (this->type
== KEY_ED448
)
108 ret
= wc_ed448_verify_msg(signature
.ptr
, signature
.len
, data
.ptr
,
109 data
.len
, &res
, &this->key
.ed448
, NULL
, 0);
112 return ret
== 0 && res
== 1;
115 METHOD(public_key_t
, encrypt
, bool,
116 private_public_key_t
*this, encryption_scheme_t scheme
,
117 chunk_t crypto
, chunk_t
*plain
)
119 DBG1(DBG_LIB
, "encryption scheme %N not supported", encryption_scheme_names
,
125 * Returns the key size in bytes for the given type, also used in private key.
127 int wolfssl_ed_keysize(key_type_t type
)
129 if (type
== KEY_ED25519
)
132 return ED25519_KEY_SIZE
* 8;
135 else if (type
== KEY_ED448
)
138 return ED448_KEY_SIZE
* 8;
144 METHOD(public_key_t
, get_keysize
, int,
145 private_public_key_t
*this)
147 return wolfssl_ed_keysize(this->type
);
151 * Encode the given public key as ASN.1 DER with algorithm identifier
153 static bool encode_pubkey(wolfssl_ed_key
*key
, key_type_t type
,
158 /* account for algorithmIdentifier/bitString */
159 if (type
== KEY_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
,
168 else if (type
== KEY_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
,
186 * Export the raw public key of the given key, also used in ed private key.
188 bool wolfssl_ed_public_key(wolfssl_ed_key
*key
, key_type_t type
, chunk_t
*raw
)
193 if (type
== KEY_ED25519
)
196 len
= ED25519_PUB_KEY_SIZE
;
197 *raw
= chunk_alloc(len
);
198 if (wc_ed25519_export_public(&key
->ed25519
, raw
->ptr
, &len
) != 0)
205 else if (type
== KEY_ED448
)
208 len
= ED448_PUB_KEY_SIZE
;
209 *raw
= chunk_alloc(len
);
210 if (wc_ed448_export_public(&key
->ed448
, raw
->ptr
, &len
) != 0)
221 * Calculate fingerprint from an EdDSA key, also used in ed private key.
223 bool wolfssl_ed_fingerprint(wolfssl_ed_key
*key
, key_type_t key_type
,
224 cred_encoding_type_t type
, chunk_t
*fp
)
228 bool success
= FALSE
;
230 if (lib
->encoding
->get_cache(lib
->encoding
, type
, key
, fp
))
236 case KEYID_PUBKEY_SHA1
:
237 if (!wolfssl_ed_public_key(key
, key_type
, &blob
))
242 case KEYID_PUBKEY_INFO_SHA1
:
243 if (!encode_pubkey(key
, key_type
, &blob
))
251 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
252 if (!hasher
|| !hasher
->allocate_hash(hasher
, blob
, fp
))
254 DBG1(DBG_LIB
, "SHA1 not supported, fingerprinting failed");
258 lib
->encoding
->cache(lib
->encoding
, type
, key
, *fp
);
266 METHOD(public_key_t
, get_fingerprint
, bool,
267 private_public_key_t
*this, cred_encoding_type_t type
, chunk_t
*fingerprint
)
269 return wolfssl_ed_fingerprint(&this->key
, this->type
, type
, fingerprint
);
272 METHOD(public_key_t
, get_encoding
, bool,
273 private_public_key_t
*this, cred_encoding_type_t type
, chunk_t
*encoding
)
277 if (!encode_pubkey(&this->key
, this->type
, encoding
))
282 if (type
!= PUBKEY_SPKI_ASN1_DER
)
284 chunk_t asn1_encoding
= *encoding
;
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
);
294 METHOD(public_key_t
, get_ref
, public_key_t
*,
295 private_public_key_t
*this)
298 return &this->public;
302 * Destroy an EdDSA key of the given type, also used by ed private key.
304 void wolfssl_ed_destroy(wolfssl_ed_key
*key
, key_type_t type
)
306 if (type
== KEY_ED25519
)
309 wc_ed25519_free(&key
->ed25519
);
312 else if (type
== KEY_ED448
)
315 wc_ed448_free(&key
->ed448
);
320 METHOD(public_key_t
, destroy
, void,
321 private_public_key_t
*this)
323 if (ref_put(&this->ref
))
325 lib
->encoding
->clear_cache(lib
->encoding
, &this->key
);
326 wolfssl_ed_destroy(&this->key
, this->type
);
332 * Initialized an EdDSA key of the given type, also used by ed private key.
334 bool wolfssl_ed_create(wolfssl_ed_key
*key
, key_type_t type
)
336 if (type
== KEY_ED25519
)
339 if (wc_ed25519_init(&key
->ed25519
) != 0)
345 else if (type
== KEY_ED448
)
348 if (wc_ed448_init(&key
->ed448
) != 0)
362 * Generic private constructor
364 static private_public_key_t
*create_empty(key_type_t type
)
366 private_public_key_t
*this;
370 .get_type
= _get_type
,
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
,
385 if (!wolfssl_ed_create(&this->key
, type
))
394 * Described in header
396 public_key_t
*wolfssl_ed_public_key_load(key_type_t type
, va_list args
)
398 private_public_key_t
*this;
399 chunk_t blob
= chunk_empty
, pub
= chunk_empty
;
405 switch (va_arg(args
, builder_part_t
))
407 case BUILD_BLOB_ASN1_DER
:
408 blob
= va_arg(args
, chunk_t
);
410 case BUILD_EDDSA_PUB
:
411 pub
= va_arg(args
, chunk_t
);
421 this = create_empty(type
);
427 if (type
== KEY_ED25519
)
432 ret
= wc_ed25519_import_public(pub
.ptr
, pub
.len
,
438 ret
= wc_Ed25519PublicKeyDecode(blob
.ptr
, &idx
, &this->key
.ed25519
,
443 else if (type
== KEY_ED448
)
448 ret
= wc_ed448_import_public(pub
.ptr
, pub
.len
, &this->key
.ed448
);
453 ret
= wc_Ed448PublicKeyDecode(blob
.ptr
, &idx
, &this->key
.ed448
,
464 return &this->public;
467 #endif /* HAVE_ED25519 */