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