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