wolfssl: Fixes, code style changes and some refactorings
[strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_ed_public_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_public_key.h"
28
29 #include <utils/debug.h>
30 #include <asn1/asn1.h>
31
32 #include <wolfssl/wolfcrypt/ed25519.h>
33 #include <wolfssl/wolfcrypt/asn.h>
34
35 typedef struct private_public_key_t private_public_key_t;
36
37 /**
38 * Private data
39 */
40 struct private_public_key_t {
41
42 /**
43 * Public interface
44 */
45 public_key_t public;
46
47 /**
48 * Key object
49 */
50 ed25519_key key;
51
52 /**
53 * Reference count
54 */
55 refcount_t ref;
56 };
57
58 METHOD(public_key_t, get_type, key_type_t,
59 private_public_key_t *this)
60 {
61 return KEY_ED25519;
62 }
63
64 METHOD(public_key_t, verify, bool,
65 private_public_key_t *this, signature_scheme_t scheme,
66 void *params, chunk_t data, chunk_t signature)
67 {
68 byte dummy[1];
69 int ret, res;
70
71 if (scheme != SIGN_ED25519)
72 {
73 DBG1(DBG_LIB, "signature scheme %N not supported by %N key",
74 signature_scheme_names, scheme, key_type_names, KEY_ED25519);
75 return FALSE;
76 }
77
78 if (!data.ptr && !data.len)
79 {
80 data.ptr = dummy;
81 }
82
83 ret = wc_ed25519_verify_msg(signature.ptr, signature.len, data.ptr,
84 data.len, &res, &this->key);
85 return ret == 0 && res == 1;
86 }
87
88 METHOD(public_key_t, encrypt, bool,
89 private_public_key_t *this, encryption_scheme_t scheme,
90 chunk_t crypto, chunk_t *plain)
91 {
92 DBG1(DBG_LIB, "encryption scheme %N not supported", encryption_scheme_names,
93 scheme);
94 return FALSE;
95 }
96
97 METHOD(public_key_t, get_keysize, int,
98 private_public_key_t *this)
99 {
100 return ED25519_KEY_SIZE * 8;
101 }
102
103 /**
104 * Encode the given public key as ASN.1 DER with algorithm identifier
105 */
106 static bool encode_pubkey(ed25519_key *key, chunk_t *encoding)
107 {
108 int ret;
109
110 /* account for algorithmIdentifier/bitString */
111 *encoding = chunk_alloc(ED25519_PUB_KEY_SIZE + 2 * MAX_SEQ_SZ +
112 MAX_ALGO_SZ + TRAILING_ZERO);
113 ret = wc_Ed25519PublicKeyToDer(key, encoding->ptr, encoding->len, 1);
114 if (ret < 0)
115 {
116 return FALSE;
117 }
118 encoding->len = ret;
119 return TRUE;
120 }
121
122 /**
123 * Calculate fingerprint from an EdDSA key, also used in ed private key.
124 */
125 bool wolfssl_ed_fingerprint(ed25519_key *key, cred_encoding_type_t type,
126 chunk_t *fp)
127 {
128 hasher_t *hasher;
129 chunk_t blob;
130 word32 len;
131 bool success = FALSE;
132
133 if (lib->encoding->get_cache(lib->encoding, type, key, fp))
134 {
135 return TRUE;
136 }
137 switch (type)
138 {
139 case KEYID_PUBKEY_SHA1:
140 len = ED25519_PUB_KEY_SIZE;
141 blob = chunk_alloc(len);
142 if (wc_ed25519_export_public(key, blob.ptr, &len) != 0)
143 {
144 return FALSE;
145 }
146 break;
147 case KEYID_PUBKEY_INFO_SHA1:
148 if (!encode_pubkey(key, &blob))
149 {
150 return FALSE;
151 }
152 break;
153 default:
154 return FALSE;
155 }
156 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
157 if (!hasher || !hasher->allocate_hash(hasher, blob, fp))
158 {
159 DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
160 }
161 else
162 {
163 lib->encoding->cache(lib->encoding, type, key, *fp);
164 success = TRUE;
165 }
166 DESTROY_IF(hasher);
167 chunk_free(&blob);
168 return success;
169 }
170
171 METHOD(public_key_t, get_fingerprint, bool,
172 private_public_key_t *this, cred_encoding_type_t type, chunk_t *fingerprint)
173 {
174 return wolfssl_ed_fingerprint(&this->key, type, fingerprint);
175 }
176
177 METHOD(public_key_t, get_encoding, bool,
178 private_public_key_t *this, cred_encoding_type_t type, chunk_t *encoding)
179 {
180 bool success = TRUE;
181
182 if (!encode_pubkey(&this->key, encoding))
183 {
184 return FALSE;
185 }
186
187 if (type != PUBKEY_SPKI_ASN1_DER)
188 {
189 chunk_t asn1_encoding = *encoding;
190
191 success = lib->encoding->encode(lib->encoding, type,
192 NULL, encoding, CRED_PART_EDDSA_PUB_ASN1_DER,
193 asn1_encoding, CRED_PART_END);
194 chunk_free(&asn1_encoding);
195 }
196 return success;
197 }
198
199 METHOD(public_key_t, get_ref, public_key_t*,
200 private_public_key_t *this)
201 {
202 ref_get(&this->ref);
203 return &this->public;
204 }
205
206 METHOD(public_key_t, destroy, void,
207 private_public_key_t *this)
208 {
209 if (ref_put(&this->ref))
210 {
211 lib->encoding->clear_cache(lib->encoding, &this->key);
212 wc_ed25519_free(&this->key);
213 free(this);
214 }
215 }
216
217 /**
218 * Generic private constructor
219 */
220 static private_public_key_t *create_empty()
221 {
222 private_public_key_t *this;
223
224 INIT(this,
225 .public = {
226 .get_type = _get_type,
227 .verify = _verify,
228 .encrypt = _encrypt,
229 .get_keysize = _get_keysize,
230 .equals = public_key_equals,
231 .get_fingerprint = _get_fingerprint,
232 .has_fingerprint = public_key_has_fingerprint,
233 .get_encoding = _get_encoding,
234 .get_ref = _get_ref,
235 .destroy = _destroy,
236 },
237 .ref = 1,
238 );
239
240 if (wc_ed25519_init(&this->key) != 0)
241 {
242 free(this);
243 return NULL;
244 }
245 return this;
246 }
247
248 /*
249 * Described in header
250 */
251 public_key_t *wolfssl_ed_public_key_load(key_type_t type, va_list args)
252 {
253 private_public_key_t *this;
254 chunk_t blob = chunk_empty, pub = chunk_empty;
255 int idx;
256 int ret = -1;
257
258 while (TRUE)
259 {
260 switch (va_arg(args, builder_part_t))
261 {
262 case BUILD_BLOB_ASN1_DER:
263 blob = va_arg(args, chunk_t);
264 continue;
265 case BUILD_EDDSA_PUB:
266 pub = va_arg(args, chunk_t);
267 continue;
268 case BUILD_END:
269 break;
270 default:
271 return NULL;
272 }
273 break;
274 }
275
276 this = create_empty();
277 if (!this)
278 {
279 return NULL;
280 }
281
282 if (pub.len)
283 {
284 ret = wc_ed25519_import_public(pub.ptr, pub.len, &this->key);
285 }
286 else if (blob.len)
287 {
288 idx = 0;
289 ret = wc_Ed25519PublicKeyDecode(blob.ptr, &idx, &this->key, blob.len);
290 }
291 if (ret != 0)
292 {
293 destroy(this);
294 return NULL;
295 }
296 return &this->public;
297 }
298
299 #endif /* HAVE_ED25519 */