wolfssl: Add wolfSSL plugin for cryptographic implementations
[strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_ec_private_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_ECC_SIGN
26
27 #include "wolfssl_ec_private_key.h"
28 #include "wolfssl_ec_public_key.h"
29 #include "wolfssl_util.h"
30
31 #include <asn1/asn1.h>
32 #include <asn1/oid.h>
33
34 #include <utils/debug.h>
35
36 #include <wolfssl/wolfcrypt/ecc.h>
37
38
39 typedef struct private_wolfssl_ec_private_key_t private_wolfssl_ec_private_key_t;
40
41 /**
42 * Private data of a wolfssl_ec_private_key_t object.
43 */
44 struct private_wolfssl_ec_private_key_t {
45 /**
46 * Public interface for this signer.
47 */
48 wolfssl_ec_private_key_t public;
49
50 /**
51 * Key size
52 */
53 int keysize;
54
55 /**
56 * EC key object
57 */
58 ecc_key ec;
59
60 /**
61 * Random number generator
62 */
63 WC_RNG rng;
64
65 /**
66 * reference count
67 */
68 refcount_t ref;
69 };
70
71 /* from ec public key */
72 bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp);
73
74 /**
75 * Build a signature as in RFC 4754
76 */
77 static bool build_signature(private_wolfssl_ec_private_key_t *this,
78 chunk_t hash, chunk_t *signature)
79 {
80 bool success = FALSE;
81 mp_int r, s;
82
83 if (mp_init(&r) != 0)
84 {
85 return FALSE;
86 }
87 if (mp_init(&s) != 0)
88 {
89 mp_free(&r);
90 return FALSE;
91 }
92 if (wc_ecc_sign_hash_ex(hash.ptr, hash.len, &this->rng, &this->ec, &r,
93 &s) == 0)
94 {
95 success = wolfssl_mp_cat(this->ec.dp->size * 2, &r, &s, signature);
96 }
97
98 mp_free(&s);
99 mp_free(&r);
100
101 return success;
102 }
103
104 /**
105 * Build a RFC 4754 signature for a specified curve and hash algorithm
106 */
107 static bool build_curve_signature(private_wolfssl_ec_private_key_t *this,
108 signature_scheme_t scheme, enum wc_HashType hash, ecc_curve_id curve_id,
109 chunk_t data, chunk_t *signature)
110 {
111 bool success = FALSE;
112 chunk_t dgst = chunk_empty;
113
114 if (curve_id != this->ec.dp->id)
115 {
116 DBG1(DBG_LIB, "signature scheme %N not supported by private key",
117 signature_scheme_names, scheme);
118 return FALSE;
119 }
120 if (wolfssl_hash_chunk(hash, data, &dgst))
121 {
122 success = build_signature(this, dgst, signature);
123 }
124 chunk_free(&dgst);
125 return success;
126 }
127
128 /**
129 * Build a DER encoded signature as in RFC 3279
130 */
131 static bool build_der_signature(private_wolfssl_ec_private_key_t *this,
132 enum wc_HashType hash, chunk_t data, chunk_t *signature)
133 {
134 bool success = FALSE;
135 chunk_t dgst = chunk_empty;
136 int ret;
137 word32 len;
138
139 if (wolfssl_hash_chunk(hash, data, &dgst))
140 {
141 *signature = chunk_alloc(this->ec.dp->size * 2 + 10);
142 len = signature->len;
143 ret = wc_ecc_sign_hash(dgst.ptr, dgst.len, signature->ptr, &len,
144 &this->rng, &this->ec);
145 if (ret == 0)
146 {
147 signature->len = len;
148 success = TRUE;
149 }
150 else
151 {
152 chunk_free(signature);
153 }
154 }
155
156 chunk_free(&dgst);
157 return success;
158 }
159
160 METHOD(private_key_t, sign, bool,
161 private_wolfssl_ec_private_key_t *this, signature_scheme_t scheme,
162 void *params, chunk_t data, chunk_t *signature)
163 {
164 switch (scheme)
165 {
166 case SIGN_ECDSA_WITH_NULL:
167 return build_signature(this, data, signature);
168 #ifndef NO_SHA
169 case SIGN_ECDSA_WITH_SHA1_DER:
170 return build_der_signature(this, WC_HASH_TYPE_SHA, data, signature);
171 #endif
172 #ifndef NO_SHA256
173 case SIGN_ECDSA_WITH_SHA256_DER:
174 return build_der_signature(this, WC_HASH_TYPE_SHA256, data,
175 signature);
176 #endif
177 #ifdef WOLFSSL_SHA384
178 case SIGN_ECDSA_WITH_SHA384_DER:
179 return build_der_signature(this, WC_HASH_TYPE_SHA384, data,
180 signature);
181 #endif
182 #ifdef WOLFSSL_SHA512
183 case SIGN_ECDSA_WITH_SHA512_DER:
184 return build_der_signature(this, WC_HASH_TYPE_SHA512, data,
185 signature);
186 #endif
187 #ifndef NO_SHA256
188 case SIGN_ECDSA_256:
189 return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
190 ECC_SECP256R1, data, signature);
191 #endif
192 #ifdef WOLFSSL_SHA384
193 case SIGN_ECDSA_384:
194 return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
195 ECC_SECP384R1, data, signature);
196 #endif
197 #ifdef WOLFSSL_SHA512
198 case SIGN_ECDSA_521:
199 return build_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
200 ECC_SECP521R1, data, signature);
201 #endif
202 default:
203 DBG1(DBG_LIB, "signature scheme %N not supported",
204 signature_scheme_names, scheme);
205 return FALSE;
206 }
207 }
208
209 METHOD(private_key_t, decrypt, bool,
210 private_wolfssl_ec_private_key_t *this, encryption_scheme_t scheme,
211 chunk_t crypto, chunk_t *plain)
212 {
213 DBG1(DBG_LIB, "EC private key decryption not implemented");
214 return FALSE;
215 }
216
217 METHOD(private_key_t, get_keysize, int,
218 private_wolfssl_ec_private_key_t *this)
219 {
220 return this->keysize;
221 }
222
223 METHOD(private_key_t, get_type, key_type_t,
224 private_wolfssl_ec_private_key_t *this)
225 {
226 return KEY_ECDSA;
227 }
228
229 METHOD(private_key_t, get_public_key, public_key_t*,
230 private_wolfssl_ec_private_key_t *this)
231 {
232 public_key_t *public;
233 chunk_t key;
234 int ret;
235
236 key = chunk_alloc((this->keysize + 7) / 8 * 5);
237 ret = wc_EccPublicKeyToDer(&this->ec, key.ptr, key.len, 1);
238 if (ret < 0)
239 {
240 chunk_free(&key);
241 return NULL;
242 }
243 key.len = ret;
244
245 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
246 BUILD_BLOB_ASN1_DER, key, BUILD_END);
247 free(key.ptr);
248 return public;
249 }
250
251 METHOD(private_key_t, get_fingerprint, bool,
252 private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type,
253 chunk_t *fingerprint)
254 {
255 return wolfssl_ec_fingerprint(&this->ec, type, fingerprint);
256 }
257
258 METHOD(private_key_t, get_encoding, bool,
259 private_wolfssl_ec_private_key_t *this, cred_encoding_type_t type,
260 chunk_t *encoding)
261 {
262 switch (type)
263 {
264 case PRIVKEY_ASN1_DER:
265 case PRIVKEY_PEM:
266 {
267 bool success = TRUE;
268
269 *encoding = chunk_alloc(this->keysize * 4 + 30);
270 if (wc_EccPrivateKeyToDer(&this->ec, encoding->ptr,
271 encoding->len) < 0)
272 {
273 chunk_free(encoding);
274 return FALSE;
275 }
276
277 if (type == PRIVKEY_PEM)
278 {
279 chunk_t asn1_encoding = *encoding;
280
281 success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
282 NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
283 asn1_encoding, CRED_PART_END);
284 chunk_clear(&asn1_encoding);
285 }
286 return success;
287 }
288 default:
289 return FALSE;
290 }
291 }
292
293 METHOD(private_key_t, get_ref, private_key_t*,
294 private_wolfssl_ec_private_key_t *this)
295 {
296 ref_get(&this->ref);
297 return &this->public.key;
298 }
299
300 METHOD(private_key_t, destroy, void,
301 private_wolfssl_ec_private_key_t *this)
302 {
303 if (ref_put(&this->ref))
304 {
305 lib->encoding->clear_cache(lib->encoding, &this->ec);
306 wc_FreeRng(&this->rng);
307 wc_ecc_free(&this->ec);
308 free(this);
309 }
310 }
311
312 /**
313 * Internal generic constructor
314 */
315 static private_wolfssl_ec_private_key_t *create_empty(void)
316 {
317 private_wolfssl_ec_private_key_t *this;
318
319 INIT(this,
320 .public = {
321 .key = {
322 .get_type = _get_type,
323 .sign = _sign,
324 .decrypt = _decrypt,
325 .get_keysize = _get_keysize,
326 .get_public_key = _get_public_key,
327 .equals = private_key_equals,
328 .belongs_to = private_key_belongs_to,
329 .get_fingerprint = _get_fingerprint,
330 .has_fingerprint = private_key_has_fingerprint,
331 .get_encoding = _get_encoding,
332 .get_ref = _get_ref,
333 .destroy = _destroy,
334 },
335 },
336 .ref = 1,
337 );
338
339 if (wc_InitRng(&this->rng) < 0)
340 {
341 DBG1(DBG_LIB, "Random number generation init failed");
342 free(this);
343 return NULL;
344 }
345
346 return this;
347 }
348
349 /*
350 * See header.
351 */
352 wolfssl_ec_private_key_t *wolfssl_ec_private_key_gen(key_type_t type,
353 va_list args)
354 {
355 private_wolfssl_ec_private_key_t *this;
356 u_int key_size = 0;
357 ecc_curve_id curve_id;
358
359 while (TRUE)
360 {
361 switch (va_arg(args, builder_part_t))
362 {
363 case BUILD_KEY_SIZE:
364 key_size = va_arg(args, u_int);
365 continue;
366 case BUILD_END:
367 break;
368 default:
369 return NULL;
370 }
371 break;
372 }
373 if (!key_size)
374 {
375 return NULL;
376 }
377 this = create_empty();
378 this->keysize = key_size;
379 switch (key_size)
380 {
381 case 256:
382 curve_id = ECC_SECP256R1;
383 break;
384 case 384:
385 curve_id = ECC_SECP384R1;
386 break;
387 case 521:
388 curve_id = ECC_SECP521R1;
389 break;
390 default:
391 DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
392 destroy(this);
393 return NULL;
394 }
395
396 if (wc_ecc_make_key_ex(&this->rng, (key_size + 7) / 8, &this->ec,
397 curve_id) < 0)
398 {
399 DBG1(DBG_LIB, "EC private key generation failed", key_size);
400 destroy(this);
401 return NULL;
402 }
403 return &this->public;
404 }
405
406 /**
407 * See header.
408 */
409 wolfssl_ec_private_key_t *wolfssl_ec_private_key_load(key_type_t type,
410 va_list args)
411 {
412 private_wolfssl_ec_private_key_t *this;
413 chunk_t params = chunk_empty;
414 chunk_t key = chunk_empty;
415 chunk_t alg_id = chunk_empty;
416 word32 idx;
417 int oid;
418
419 while (TRUE)
420 {
421 switch (va_arg(args, builder_part_t))
422 {
423 case BUILD_BLOB_ALGID_PARAMS:
424 params = va_arg(args, chunk_t);
425 continue;
426 case BUILD_BLOB_ASN1_DER:
427 key = va_arg(args, chunk_t);
428 continue;
429 case BUILD_END:
430 break;
431 default:
432 return NULL;
433 }
434 break;
435 }
436 if (key.ptr == NULL)
437 {
438 return NULL;
439 }
440
441 this = create_empty();
442
443 idx = 0;
444 if (wc_EccPrivateKeyDecode(key.ptr, &idx, &this->ec, key.len) < 0)
445 {
446 destroy(this);
447 return NULL;
448 }
449 switch (this->ec.dp->id)
450 {
451 case ECC_SECP256R1:
452 this->keysize = 256;
453 break;
454 case ECC_SECP384R1:
455 this->keysize = 384;
456 break;
457 case ECC_SECP521R1:
458 this->keysize = 521;
459 break;
460 default:
461 break;
462 }
463
464 if (params.ptr)
465 {
466 /* if ECParameters is passed, check we guessed correct */
467 alg_id = asn1_algorithmIdentifier_params(OID_EC_PUBLICKEY,
468 chunk_clone(params));
469 if (asn1_unwrap(&params, &params) == ASN1_OID)
470 {
471 oid = asn1_known_oid(params);
472 switch (oid)
473 {
474 case OID_PRIME256V1:
475 if (this->ec.dp->id != ECC_SECP256R1)
476 {
477 oid = OID_UNKNOWN;
478 }
479 break;
480 case OID_SECT384R1:
481 if (this->ec.dp->id != ECC_SECP384R1)
482 {
483 oid = OID_UNKNOWN;
484 }
485 break;
486 case OID_SECT521R1:
487 if (this->ec.dp->id != ECC_SECP521R1)
488 {
489 oid = OID_UNKNOWN;
490 }
491 break;
492 default:
493 oid = OID_UNKNOWN;
494 break;
495 }
496 }
497 chunk_free(&alg_id);
498 if (oid == OID_UNKNOWN)
499 {
500 DBG1(DBG_LIB, "parameters do not match private key data");
501 destroy(this);
502 return NULL;
503 }
504 }
505
506 return &this->public;
507 }
508 #endif /* HAVE_ECC_SIGN */