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