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