Annotation of embedaddon/strongswan/src/libstrongswan/plugins/wolfssl/wolfssl_ec_public_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_VERIFY
26:
27: #include "wolfssl_ec_public_key.h"
28: #include "wolfssl_util.h"
29:
30: #include <utils/debug.h>
31:
32: #include <wolfssl/wolfcrypt/ecc.h>
33: #include <wolfssl/wolfcrypt/hash.h>
34: #include <wolfssl/wolfcrypt/asn.h>
35:
36: typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t;
37:
38: /**
39: * Private data structure with signing context.
40: */
41: struct private_wolfssl_ec_public_key_t {
42:
43: /**
44: * Public interface
45: */
46: wolfssl_ec_public_key_t public;
47:
48: /**
49: * Key size
50: */
51: int keysize;
52:
53: /**
54: * EC key object
55: */
56: ecc_key ec;
57:
58: /**
59: * Reference count
60: */
61: refcount_t ref;
62: };
63:
64: /**
65: * Verification of a signature as in RFC 4754
66: */
67: static bool verify_signature(private_wolfssl_ec_public_key_t *this,
68: chunk_t hash, chunk_t signature)
69: {
70: int stat = 1, ret = -1;
71: mp_int r, s;
72:
73: if (mp_init(&r) < 0)
74: {
75: return FALSE;
76: }
77: if (mp_init(&s) < 0)
78: {
79: mp_free(&r);
80: return FALSE;
81: }
82:
83: if (wolfssl_mp_split(signature, &r, &s))
84: {
85: ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat,
86: &this->ec);
87: }
88: mp_free(&s);
89: mp_free(&r);
90: return ret == 0 && stat == 1;
91: }
92:
93: /**
94: * Verify a RFC 4754 signature for a specified curve and hash algorithm
95: */
96: static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this,
97: signature_scheme_t scheme,
98: enum wc_HashType hash, ecc_curve_id curve_id,
99: chunk_t data, chunk_t signature)
100: {
101: bool success = FALSE;
102: chunk_t dgst;
103:
104: if (curve_id != this->ec.dp->id)
105: {
106: DBG1(DBG_LIB, "signature scheme %N not supported by private key",
107: signature_scheme_names, scheme);
108: return FALSE;
109: }
110:
111: if (wolfssl_hash_chunk(hash, data, &dgst))
112: {
113: success = verify_signature(this, dgst, signature);
114: }
115:
116: chunk_free(&dgst);
117: return success;
118: }
119:
120: /**
121: * Verification of a DER encoded signature as in RFC 3279
122: */
123: static bool verify_der_signature(private_wolfssl_ec_public_key_t *this,
124: enum wc_HashType hash, chunk_t data,
125: chunk_t signature)
126: {
127: chunk_t dgst;
128: int stat = 1, ret = -1;
129:
130: signature = chunk_skip_zero(signature);
131: if (wolfssl_hash_chunk(hash, data, &dgst))
132: {
133: ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr,
134: dgst.len, &stat, &this->ec);
135: }
136: chunk_free(&dgst);
137: return ret == 0 && stat == 1;
138: }
139:
140: METHOD(public_key_t, get_type, key_type_t,
141: private_wolfssl_ec_public_key_t *this)
142: {
143: return KEY_ECDSA;
144: }
145:
146: METHOD(public_key_t, verify, bool,
147: private_wolfssl_ec_public_key_t *this, signature_scheme_t scheme,
148: void *params, chunk_t data, chunk_t signature)
149: {
150: switch (scheme)
151: {
152: #ifndef NO_SHA
153: case SIGN_ECDSA_WITH_SHA1_DER:
154: return verify_der_signature(this, WC_HASH_TYPE_SHA, data,
155: signature);
156: #endif
157: #ifndef NO_SHA256
158: case SIGN_ECDSA_WITH_SHA256_DER:
159: return verify_der_signature(this, WC_HASH_TYPE_SHA256, data,
160: signature);
161: #endif
162: #ifdef WOLFSSL_SHA384
163: case SIGN_ECDSA_WITH_SHA384_DER:
164: return verify_der_signature(this, WC_HASH_TYPE_SHA384, data,
165: signature);
166: #endif
167: #ifdef WOLFSSL_SHA512
168: case SIGN_ECDSA_WITH_SHA512_DER:
169: return verify_der_signature(this, WC_HASH_TYPE_SHA512, data,
170: signature);
171: #endif
172: case SIGN_ECDSA_WITH_NULL:
173: return verify_signature(this, data, signature);
174: #ifndef NO_SHA256
175: case SIGN_ECDSA_256:
176: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
177: ECC_SECP256R1, data, signature);
178: #endif
179: #ifdef WOLFSSL_SHA384
180: case SIGN_ECDSA_384:
181: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
182: ECC_SECP384R1, data, signature);
183: #endif
184: #ifdef WOLFSSL_SHA512
185: case SIGN_ECDSA_521:
186: return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
187: ECC_SECP521R1, data, signature);
188: #endif
189: default:
190: DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
191: signature_scheme_names, scheme);
192: return FALSE;
193: }
194: }
195:
196: METHOD(public_key_t, encrypt, bool,
197: private_wolfssl_ec_public_key_t *this, encryption_scheme_t scheme,
198: chunk_t crypto, chunk_t *plain)
199: {
200: DBG1(DBG_LIB, "EC public key encryption not implemented");
201: return FALSE;
202: }
203:
204: METHOD(public_key_t, get_keysize, int,
205: private_wolfssl_ec_public_key_t *this)
206: {
207: return this->keysize;
208: }
209:
210: /**
211: * Calculate fingerprint from an EC key, also used in ec private key.
212: */
213: bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp)
214: {
215: hasher_t *hasher;
216: chunk_t key;
217: int len;
218:
219: if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
220: {
221: return TRUE;
222: }
223:
224: switch (type)
225: {
226: case KEYID_PUBKEY_SHA1:
227: case KEYID_PUBKEY_INFO_SHA1:
228: /* need an additional byte for the point type */
229: len = ec->dp->size * 2 + 1;
230: if (type == KEYID_PUBKEY_INFO_SHA1)
231: {
232: /* additional space for algorithmIdentifier/bitString */
233: len += 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + TRAILING_ZERO;
234: }
235: key = chunk_alloca(len);
236: len = wc_EccPublicKeyToDer(ec, key.ptr, key.len,
237: type == KEYID_PUBKEY_INFO_SHA1);
238: break;
239: default:
240: return FALSE;
241: }
242: if (len < 0)
243: {
244: return FALSE;
245: }
246: key.len = len;
247:
248: hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
249: if (!hasher || !hasher->allocate_hash(hasher, key, fp))
250: {
251: DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
252: DESTROY_IF(hasher);
253: return FALSE;
254: }
255: hasher->destroy(hasher);
256: lib->encoding->cache(lib->encoding, type, ec, *fp);
257: return TRUE;
258: }
259:
260: METHOD(public_key_t, get_fingerprint, bool,
261: private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
262: chunk_t *fingerprint)
263: {
264: return wolfssl_ec_fingerprint(&this->ec, type, fingerprint);
265: }
266:
267: METHOD(public_key_t, get_encoding, bool,
268: private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
269: chunk_t *encoding)
270: {
271: bool success = TRUE;
272: int len;
273:
274: /* space for algorithmIdentifier/bitString + one byte for the point type */
275: *encoding = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ +
276: 2 * MAX_ALGO_SZ + TRAILING_ZERO + 1);
277: len = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1);
278: if (len < 0)
279: {
280: chunk_free(encoding);
281: return FALSE;
282: }
283: encoding->len = len;
284:
285: if (type != PUBKEY_SPKI_ASN1_DER)
286: {
287: chunk_t asn1_encoding = *encoding;
288:
289: success = lib->encoding->encode(lib->encoding, type,
290: NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
291: asn1_encoding, CRED_PART_END);
292: chunk_clear(&asn1_encoding);
293: }
294: return success;
295: }
296:
297: METHOD(public_key_t, get_ref, public_key_t*,
298: private_wolfssl_ec_public_key_t *this)
299: {
300: ref_get(&this->ref);
301: return &this->public.key;
302: }
303:
304: METHOD(public_key_t, destroy, void,
305: private_wolfssl_ec_public_key_t *this)
306: {
307: if (ref_put(&this->ref))
308: {
309: lib->encoding->clear_cache(lib->encoding, &this->ec);
310: wc_ecc_free(&this->ec);
311: free(this);
312: }
313: }
314:
315: /**
316: * Generic private constructor
317: */
318: static private_wolfssl_ec_public_key_t *create_empty()
319: {
320: private_wolfssl_ec_public_key_t *this;
321:
322: INIT(this,
323: .public = {
324: .key = {
325: .get_type = _get_type,
326: .verify = _verify,
327: .encrypt = _encrypt,
328: .get_keysize = _get_keysize,
329: .equals = public_key_equals,
330: .get_fingerprint = _get_fingerprint,
331: .has_fingerprint = public_key_has_fingerprint,
332: .get_encoding = _get_encoding,
333: .get_ref = _get_ref,
334: .destroy = _destroy,
335: },
336: },
337: .ref = 1,
338: );
339:
340: if (wc_ecc_init(&this->ec) < 0)
341: {
342: free(this);
343: return NULL;
344: }
345: return this;
346: }
347:
348: /*
349: * Described in header
350: */
351: wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
352: va_list args)
353: {
354: private_wolfssl_ec_public_key_t *this;
355: chunk_t blob = chunk_empty;
356: word32 idx;
357: int ret;
358:
359: while (TRUE)
360: {
361: switch (va_arg(args, builder_part_t))
362: {
363: case BUILD_BLOB_ASN1_DER:
364: blob = va_arg(args, chunk_t);
365: continue;
366: case BUILD_END:
367: break;
368: default:
369: return NULL;
370: }
371: break;
372: }
373: this = create_empty();
374: if (!this)
375: {
376: return NULL;
377: }
378:
379: idx = 0;
380: ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len);
381: if (ret < 0)
382: {
383: destroy(this);
384: return NULL;
385: }
386: switch (this->ec.dp->id)
387: {
388: case ECC_SECP256R1:
389: this->keysize = 256;
390: break;
391: case ECC_SECP384R1:
392: this->keysize = 384;
393: break;
394: case ECC_SECP521R1:
395: this->keysize = 521;
396: break;
397: default:
398: break;
399: }
400: return &this->public;
401: }
402:
403: #endif /* HAVE_ECC_VERIFY */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>