Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2016 Tobias Brunner
3: * Copyright (C) 2009 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: #include <openssl/opensslconf.h>
18:
19: #ifndef OPENSSL_NO_ECDSA
20:
21: #include "openssl_ec_private_key.h"
22: #include "openssl_ec_public_key.h"
23: #include "openssl_util.h"
24:
25: #include <utils/debug.h>
26:
27: #include <openssl/evp.h>
28: #include <openssl/ecdsa.h>
29: #include <openssl/x509.h>
30:
31: #if OPENSSL_VERSION_NUMBER < 0x10100000L
32: OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
33: #endif
34:
35: typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
36:
37: /**
38: * Private data of a openssl_ec_private_key_t object.
39: */
40: struct private_openssl_ec_private_key_t {
41: /**
42: * Public interface for this signer.
43: */
44: openssl_ec_private_key_t public;
45:
46: /**
47: * EC key object
48: */
49: EC_KEY *ec;
50:
51: /**
52: * TRUE if the key is from an OpenSSL ENGINE and might not be readable
53: */
54: bool engine;
55:
56: /**
57: * reference count
58: */
59: refcount_t ref;
60: };
61:
62: /* from ec public key */
63: bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
64:
65: /**
66: * Build a signature as in RFC 4754
67: */
68: static bool build_signature(private_openssl_ec_private_key_t *this,
69: chunk_t hash, chunk_t *signature)
70: {
71: const BIGNUM *r, *s;
72: ECDSA_SIG *sig;
73: bool built = FALSE;
74:
75: sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
76: if (sig)
77: {
78: ECDSA_SIG_get0(sig, &r, &s);
79: /* concatenate BNs r/s to a signature chunk */
80: built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
81: r, s, signature);
82: ECDSA_SIG_free(sig);
83: }
84: return built;
85: }
86:
87: /**
88: * Build a RFC 4754 signature for a specified curve and hash algorithm
89: */
90: static bool build_curve_signature(private_openssl_ec_private_key_t *this,
91: signature_scheme_t scheme, int nid_hash,
92: int nid_curve, chunk_t data, chunk_t *signature)
93: {
94: const EC_GROUP *my_group;
95: EC_GROUP *req_group;
96: chunk_t hash;
97: bool built;
98:
99: req_group = EC_GROUP_new_by_curve_name(nid_curve);
100: if (!req_group)
101: {
102: DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
103: "not supported)", signature_scheme_names, scheme);
104: return FALSE;
105: }
106: my_group = EC_KEY_get0_group(this->ec);
107: if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
108: {
109: DBG1(DBG_LIB, "signature scheme %N not supported by private key",
110: signature_scheme_names, scheme);
111: return FALSE;
112: }
113: EC_GROUP_free(req_group);
114: if (!openssl_hash_chunk(nid_hash, data, &hash))
115: {
116: return FALSE;
117: }
118: built = build_signature(this, hash, signature);
119: chunk_free(&hash);
120: return built;
121: }
122:
123: /**
124: * Build a DER encoded signature as in RFC 3279
125: */
126: static bool build_der_signature(private_openssl_ec_private_key_t *this,
127: int hash_nid, chunk_t data, chunk_t *signature)
128: {
129: chunk_t hash, sig;
130: int siglen = 0;
131: bool built;
132:
133: if (!openssl_hash_chunk(hash_nid, data, &hash))
134: {
135: return FALSE;
136: }
137: sig = chunk_alloc(ECDSA_size(this->ec));
138: built = ECDSA_sign(0, hash.ptr, hash.len, sig.ptr, &siglen, this->ec) == 1;
139: sig.len = siglen;
140: if (built)
141: {
142: *signature = sig;
143: }
144: else
145: {
146: free(sig.ptr);
147: }
148: free(hash.ptr);
149: return built;
150: }
151:
152: METHOD(private_key_t, sign, bool,
153: private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
154: void *params, chunk_t data, chunk_t *signature)
155: {
156: switch (scheme)
157: {
158: case SIGN_ECDSA_WITH_NULL:
159: return build_signature(this, data, signature);
160: case SIGN_ECDSA_WITH_SHA1_DER:
161: return build_der_signature(this, NID_sha1, data, signature);
162: case SIGN_ECDSA_WITH_SHA256_DER:
163: return build_der_signature(this, NID_sha256, data, signature);
164: case SIGN_ECDSA_WITH_SHA384_DER:
165: return build_der_signature(this, NID_sha384, data, signature);
166: case SIGN_ECDSA_WITH_SHA512_DER:
167: return build_der_signature(this, NID_sha512, data, signature);
168: case SIGN_ECDSA_256:
169: return build_curve_signature(this, scheme, NID_sha256,
170: NID_X9_62_prime256v1, data, signature);
171: case SIGN_ECDSA_384:
172: return build_curve_signature(this, scheme, NID_sha384,
173: NID_secp384r1, data, signature);
174: case SIGN_ECDSA_521:
175: return build_curve_signature(this, scheme, NID_sha512,
176: NID_secp521r1, data, signature);
177: default:
178: DBG1(DBG_LIB, "signature scheme %N not supported",
179: signature_scheme_names, scheme);
180: return FALSE;
181: }
182: }
183:
184: METHOD(private_key_t, decrypt, bool,
185: private_openssl_ec_private_key_t *this, encryption_scheme_t scheme,
186: chunk_t crypto, chunk_t *plain)
187: {
188: DBG1(DBG_LIB, "EC private key decryption not implemented");
189: return FALSE;
190: }
191:
192: METHOD(private_key_t, get_keysize, int,
193: private_openssl_ec_private_key_t *this)
194: {
195: return EC_GROUP_get_degree(EC_KEY_get0_group(this->ec));
196: }
197:
198: METHOD(private_key_t, get_type, key_type_t,
199: private_openssl_ec_private_key_t *this)
200: {
201: return KEY_ECDSA;
202: }
203:
204: METHOD(private_key_t, get_public_key, public_key_t*,
205: private_openssl_ec_private_key_t *this)
206: {
207: public_key_t *public;
208: chunk_t key;
209: u_char *p;
210:
211: key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
212: p = key.ptr;
213: i2d_EC_PUBKEY(this->ec, &p);
214:
215: public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
216: BUILD_BLOB_ASN1_DER, key, BUILD_END);
217: free(key.ptr);
218: return public;
219: }
220:
221: METHOD(private_key_t, get_fingerprint, bool,
222: private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
223: chunk_t *fingerprint)
224: {
225: return openssl_ec_fingerprint(this->ec, type, fingerprint);
226: }
227:
228: METHOD(private_key_t, get_encoding, bool,
229: private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
230: chunk_t *encoding)
231: {
232: u_char *p;
233:
234: if (this->engine)
235: {
236: return FALSE;
237: }
238:
239: switch (type)
240: {
241: case PRIVKEY_ASN1_DER:
242: case PRIVKEY_PEM:
243: {
244: bool success = TRUE;
245:
246: *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
247: p = encoding->ptr;
248: i2d_ECPrivateKey(this->ec, &p);
249:
250: if (type == PRIVKEY_PEM)
251: {
252: chunk_t asn1_encoding = *encoding;
253:
254: success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
255: NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
256: asn1_encoding, CRED_PART_END);
257: chunk_clear(&asn1_encoding);
258: }
259: return success;
260: }
261: default:
262: return FALSE;
263: }
264: }
265:
266: METHOD(private_key_t, get_ref, private_key_t*,
267: private_openssl_ec_private_key_t *this)
268: {
269: ref_get(&this->ref);
270: return &this->public.key;
271: }
272:
273: METHOD(private_key_t, destroy, void,
274: private_openssl_ec_private_key_t *this)
275: {
276: if (ref_put(&this->ref))
277: {
278: if (this->ec)
279: {
280: lib->encoding->clear_cache(lib->encoding, this->ec);
281: EC_KEY_free(this->ec);
282: }
283: free(this);
284: }
285: }
286:
287: /**
288: * Internal generic constructor
289: */
290: static private_openssl_ec_private_key_t *create_empty(void)
291: {
292: private_openssl_ec_private_key_t *this;
293:
294: INIT(this,
295: .public = {
296: .key = {
297: .get_type = _get_type,
298: .sign = _sign,
299: .decrypt = _decrypt,
300: .get_keysize = _get_keysize,
301: .get_public_key = _get_public_key,
302: .equals = private_key_equals,
303: .belongs_to = private_key_belongs_to,
304: .get_fingerprint = _get_fingerprint,
305: .has_fingerprint = private_key_has_fingerprint,
306: .get_encoding = _get_encoding,
307: .get_ref = _get_ref,
308: .destroy = _destroy,
309: },
310: },
311: .ref = 1,
312: );
313:
314: return this;
315: }
316:
317: /*
318: * See header.
319: */
320: private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine)
321: {
322: private_openssl_ec_private_key_t *this;
323: EC_KEY *ec;
324:
325: ec = EVP_PKEY_get1_EC_KEY(key);
326: EVP_PKEY_free(key);
327: if (!ec)
328: {
329: return NULL;
330: }
331: this = create_empty();
332: this->ec = ec;
333: this->engine = engine;
334: return &this->public.key;
335: }
336:
337: /*
338: * See header.
339: */
340: openssl_ec_private_key_t *openssl_ec_private_key_gen(key_type_t type,
341: va_list args)
342: {
343: private_openssl_ec_private_key_t *this;
344: u_int key_size = 0;
345:
346: while (TRUE)
347: {
348: switch (va_arg(args, builder_part_t))
349: {
350: case BUILD_KEY_SIZE:
351: key_size = va_arg(args, u_int);
352: continue;
353: case BUILD_END:
354: break;
355: default:
356: return NULL;
357: }
358: break;
359: }
360: if (!key_size)
361: {
362: return NULL;
363: }
364: this = create_empty();
365: switch (key_size)
366: {
367: case 256:
368: this->ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
369: break;
370: case 384:
371: this->ec = EC_KEY_new_by_curve_name(NID_secp384r1);
372: break;
373: case 521:
374: this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
375: break;
376: default:
377: DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
378: destroy(this);
379: return NULL;
380: }
381: if (EC_KEY_generate_key(this->ec) != 1)
382: {
383: DBG1(DBG_LIB, "EC private key generation failed", key_size);
384: destroy(this);
385: return NULL;
386: }
387: /* encode as a named curve key (no parameters), uncompressed public key */
388: EC_KEY_set_asn1_flag(this->ec, OPENSSL_EC_NAMED_CURVE);
389: EC_KEY_set_conv_form(this->ec, POINT_CONVERSION_UNCOMPRESSED);
390: return &this->public;
391: }
392:
393: /**
394: * See header.
395: */
396: openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
397: va_list args)
398: {
399: private_openssl_ec_private_key_t *this;
400: chunk_t par = chunk_empty, key = chunk_empty;
401:
402: while (TRUE)
403: {
404: switch (va_arg(args, builder_part_t))
405: {
406: case BUILD_BLOB_ALGID_PARAMS:
407: par = va_arg(args, chunk_t);
408: continue;
409: case BUILD_BLOB_ASN1_DER:
410: key = va_arg(args, chunk_t);
411: continue;
412: case BUILD_END:
413: break;
414: default:
415: return NULL;
416: }
417: break;
418: }
419:
420: this = create_empty();
421:
422: if (par.ptr)
423: {
424: this->ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
425: if (!this->ec)
426: {
427: goto error;
428: }
429: if (!d2i_ECPrivateKey(&this->ec, (const u_char**)&key.ptr, key.len))
430: {
431: goto error;
432: }
433: }
434: else
435: {
436: this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&key.ptr, key.len);
437: if (!this->ec)
438: {
439: goto error;
440: }
441: }
442: if (!EC_KEY_check_key(this->ec))
443: {
444: goto error;
445: }
446: return &this->public;
447:
448: error:
449: destroy(this);
450: return NULL;
451: }
452: #endif /* OPENSSL_NO_ECDSA */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>