added support for SIGN_ECDSA_WITH_SHA1 signature scheme in openssl
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_ec_private_key.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * 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_ec_private_key.h"
18 #include "openssl_ec_public_key.h"
19 #include "openssl_util.h"
20
21 #include <debug.h>
22
23 #include <openssl/evp.h>
24 #include <openssl/ecdsa.h>
25 #include <openssl/x509.h>
26
27 typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
28
29 /**
30 * Private data of a openssl_ec_private_key_t object.
31 */
32 struct private_openssl_ec_private_key_t {
33 /**
34 * Public interface for this signer.
35 */
36 openssl_ec_private_key_t public;
37
38 /**
39 * EC key object
40 */
41 EC_KEY *ec;
42
43 /**
44 * reference count
45 */
46 refcount_t ref;
47 };
48
49 /**
50 * Mapping from the signature scheme defined in (RFC 4754) to the elliptic
51 * curve and the hash algorithm
52 */
53 typedef struct {
54 /**
55 * Scheme specified in RFC 4754
56 */
57 int scheme;
58
59 /**
60 * NID of the hash
61 */
62 int hash;
63
64 /**
65 * NID of the curve
66 */
67 int curve;
68 } openssl_ecdsa_scheme_t;
69
70 #define END_OF_LIST -1
71
72 /**
73 * Signature schemes
74 */
75 static openssl_ecdsa_scheme_t ecdsa_schemes[] = {
76 {SIGN_ECDSA_WITH_SHA1, NID_sha1, -1},
77 {SIGN_ECDSA_256, NID_sha256, NID_X9_62_prime256v1},
78 {SIGN_ECDSA_384, NID_sha384, NID_secp384r1},
79 {SIGN_ECDSA_521, NID_sha512, NID_secp521r1},
80 {END_OF_LIST, 0, 0},
81 };
82
83 /**
84 * Look up the hash and curve of a signature scheme
85 */
86 static bool lookup_scheme(int scheme, int *hash, int *curve)
87 {
88 openssl_ecdsa_scheme_t *ecdsa_scheme = ecdsa_schemes;
89 while (ecdsa_scheme->scheme != END_OF_LIST)
90 {
91 if (scheme == ecdsa_scheme->scheme)
92 {
93 *hash = ecdsa_scheme->hash;
94 *curve = ecdsa_scheme->curve;
95 return TRUE;
96 }
97 ecdsa_scheme++;
98 }
99 return FALSE;
100 }
101
102 /* from ec public key */
103 bool openssl_ec_fingerprint(EC_KEY *ec, key_encoding_type_t type, chunk_t *fp);
104
105 /**
106 * Convert an ECDSA_SIG to a chunk by concatenating r and s.
107 * This function allocates memory for the chunk.
108 */
109 static bool sig2chunk(const EC_GROUP *group, ECDSA_SIG *sig, chunk_t *chunk)
110 {
111 return openssl_bn_cat(EC_FIELD_ELEMENT_LEN(group), sig->r, sig->s, chunk);
112 }
113
114 /**
115 * Build the signature
116 */
117 static bool build_signature(private_openssl_ec_private_key_t *this,
118 chunk_t hash, chunk_t *signature)
119 {
120 ECDSA_SIG *sig;
121 bool success;
122
123 sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
124 if (!sig)
125 {
126 return FALSE;
127 }
128 success = sig2chunk(EC_KEY_get0_group(this->ec), sig, signature);
129 ECDSA_SIG_free(sig);
130 return success;
131 }
132
133 /**
134 * Implementation of private_key_t.get_type.
135 */
136 static key_type_t get_type(private_openssl_ec_private_key_t *this)
137 {
138 return KEY_ECDSA;
139 }
140
141 /**
142 * Implementation of private_key_t.sign.
143 */
144 static bool sign(private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
145 chunk_t data, chunk_t *signature)
146 {
147 bool success;
148
149 if (scheme == SIGN_ECDSA_WITH_NULL)
150 {
151 success = build_signature(this, data, signature);
152 }
153 else
154 {
155 EC_GROUP *req_group;
156 const EC_GROUP *my_group;
157 chunk_t hash = chunk_empty;
158 int hash_type, curve;
159
160 if (!lookup_scheme(scheme, &hash_type, &curve))
161 {
162 DBG1("signature scheme %N not supported in EC",
163 signature_scheme_names, scheme);
164 return FALSE;
165 }
166
167 if (curve != -1)
168 {
169 req_group = EC_GROUP_new_by_curve_name(curve);
170 if (!req_group)
171 {
172 DBG1("signature scheme %N not supported in EC (required curve "
173 "not supported)", signature_scheme_names, scheme);
174 return FALSE;
175 }
176 my_group = EC_KEY_get0_group(this->ec);
177 if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
178 {
179 DBG1("signature scheme %N not supported by private key",
180 signature_scheme_names, scheme);
181 return FALSE;
182 }
183 EC_GROUP_free(req_group);
184 }
185 if (!openssl_hash_chunk(hash_type, data, &hash))
186 {
187 return FALSE;
188 }
189 success = build_signature(this, hash, signature);
190 chunk_free(&hash);
191 }
192 return success;
193 }
194
195 /**
196 * Implementation of private_key_t.destroy.
197 */
198 static bool decrypt(private_openssl_ec_private_key_t *this,
199 chunk_t crypto, chunk_t *plain)
200 {
201 DBG1("EC private key decryption not implemented");
202 return FALSE;
203 }
204
205 /**
206 * Implementation of private_key_t.get_keysize.
207 */
208 static size_t get_keysize(private_openssl_ec_private_key_t *this)
209 {
210 return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec));
211 }
212
213 /**
214 * Implementation of private_key_t.get_public_key.
215 */
216 static public_key_t* get_public_key(private_openssl_ec_private_key_t *this)
217 {
218 public_key_t *public;
219 chunk_t key;
220 u_char *p;
221
222 key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
223 p = key.ptr;
224 i2d_EC_PUBKEY(this->ec, &p);
225
226 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
227 BUILD_BLOB_ASN1_DER, key, BUILD_END);
228 free(key.ptr);
229 return public;
230 }
231
232 /**
233 * Implementation of private_key_t.get_fingerprint.
234 */
235 static bool get_fingerprint(private_openssl_ec_private_key_t *this,
236 key_encoding_type_t type, chunk_t *fingerprint)
237 {
238 return openssl_ec_fingerprint(this->ec, type, fingerprint);
239 }
240
241 /**
242 * Implementation of private_key_t.get_encoding.
243 */
244 static bool get_encoding(private_openssl_ec_private_key_t *this,
245 key_encoding_type_t type, chunk_t *encoding)
246 {
247 u_char *p;
248
249 switch (type)
250 {
251 case KEY_PRIV_ASN1_DER:
252 {
253 *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
254 p = encoding->ptr;
255 i2d_ECPrivateKey(this->ec, &p);
256 return TRUE;
257 }
258 default:
259 return FALSE;
260 }
261 }
262
263 /**
264 * Implementation of private_key_t.get_ref.
265 */
266 static private_key_t* get_ref(private_openssl_ec_private_key_t *this)
267 {
268 ref_get(&this->ref);
269 return &this->public.interface;
270 }
271
272 /**
273 * Implementation of private_key_t.destroy.
274 */
275 static void destroy(private_openssl_ec_private_key_t *this)
276 {
277 if (ref_put(&this->ref))
278 {
279 if (this->ec)
280 {
281 lib->encoding->clear_cache(lib->encoding, this->ec);
282 EC_KEY_free(this->ec);
283 }
284 free(this);
285 }
286 }
287
288 /**
289 * Internal generic constructor
290 */
291 static private_openssl_ec_private_key_t *create_empty(void)
292 {
293 private_openssl_ec_private_key_t *this = malloc_thing(private_openssl_ec_private_key_t);
294
295 this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type;
296 this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign;
297 this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt;
298 this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize;
299 this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
300 this->public.interface.equals = private_key_equals;
301 this->public.interface.belongs_to = private_key_belongs_to;
302 this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
303 this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
304 this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
305 this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
306
307 this->ec = NULL;
308 this->ref = 1;
309
310 return this;
311 }
312
313 /**
314 * Generate an ECDSA key of specified key size
315 */
316 static openssl_ec_private_key_t *generate(size_t key_size)
317 {
318 private_openssl_ec_private_key_t *this = create_empty();
319
320 switch (key_size)
321 {
322 case 256:
323 this->ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
324 break;
325 case 384:
326 this->ec = EC_KEY_new_by_curve_name(NID_secp384r1);
327 break;
328 case 521:
329 this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
330 break;
331 default:
332 DBG1("EC private key size %d not supported", key_size);
333 destroy(this);
334 return NULL;
335 }
336 if (EC_KEY_generate_key(this->ec) != 1)
337 {
338 DBG1("EC private key generation failed", key_size);
339 destroy(this);
340 return NULL;
341 }
342 /* encode as a named curve key (no parameters), uncompressed public key */
343 EC_KEY_set_asn1_flag(this->ec, OPENSSL_EC_NAMED_CURVE);
344 EC_KEY_set_conv_form(this->ec, POINT_CONVERSION_UNCOMPRESSED);
345 return &this->public;
346 }
347
348 /**
349 * load private key from an ASN1 encoded blob
350 */
351 static openssl_ec_private_key_t *load(chunk_t blob)
352 {
353 private_openssl_ec_private_key_t *this = create_empty();
354
355 this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&blob.ptr, blob.len);
356
357 if (!this->ec)
358 {
359 destroy(this);
360 return NULL;
361 }
362 if (!EC_KEY_check_key(this->ec))
363 {
364 destroy(this);
365 return NULL;
366 }
367 return &this->public;
368 }
369
370 typedef struct private_builder_t private_builder_t;
371
372 /**
373 * Builder implementation for key loading/generation
374 */
375 struct private_builder_t {
376 /** implements the builder interface */
377 builder_t public;
378 /** loaded/generated private key */
379 openssl_ec_private_key_t *key;
380 };
381
382 /**
383 * Implementation of builder_t.build
384 */
385 static openssl_ec_private_key_t *build(private_builder_t *this)
386 {
387 openssl_ec_private_key_t *key = this->key;
388
389 free(this);
390 return key;
391 }
392
393 /**
394 * Implementation of builder_t.add
395 */
396 static void add(private_builder_t *this, builder_part_t part, ...)
397 {
398 if (!this->key)
399 {
400 va_list args;
401
402 switch (part)
403 {
404 case BUILD_KEY_SIZE:
405 {
406 va_start(args, part);
407 this->key = generate(va_arg(args, u_int));
408 va_end(args);
409 return;
410 }
411 case BUILD_BLOB_ASN1_DER:
412 {
413 va_start(args, part);
414 this->key = load(va_arg(args, chunk_t));
415 va_end(args);
416 return;
417 }
418 default:
419 break;
420 }
421 }
422 if (this->key)
423 {
424 destroy((private_openssl_ec_private_key_t*)this->key);
425 }
426 builder_cancel(&this->public);
427 }
428
429 /**
430 * Builder construction function
431 */
432 builder_t *openssl_ec_private_key_builder(key_type_t type)
433 {
434 private_builder_t *this;
435
436 if (type != KEY_ECDSA)
437 {
438 return NULL;
439 }
440
441 this = malloc_thing(private_builder_t);
442
443 this->key = NULL;
444 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
445 this->public.build = (void*(*)(builder_t *this))build;
446
447 return &this->public;
448 }
449