ECDSA with OpenSSL
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_ec_private_key.c
1 /*
2 * Copyright (C) 2008 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 *
15 * $Id$
16 */
17
18 #include "openssl_ec_private_key.h"
19 #include "openssl_ec_public_key.h"
20 #include "openssl_util.h"
21
22 #include <debug.h>
23
24 #include <openssl/evp.h>
25 #include <openssl/ecdsa.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 * Keyid formed as a SHA-1 hash of a privateKey object
45 */
46 identification_t* keyid;
47
48 /**
49 * Keyid formed as a SHA-1 hash of a privateKeyInfo object
50 */
51 identification_t* keyid_info;
52
53 /**
54 * reference count
55 */
56 refcount_t ref;
57 };
58
59 /**
60 * Mapping from the signature scheme defined in (RFC 4754) to the elliptic
61 * curve and the hash algorithm
62 */
63 typedef struct {
64 /**
65 * Scheme specified in RFC 4754
66 */
67 int scheme;
68
69 /**
70 * NID of the hash
71 */
72 int hash;
73
74 /**
75 * NID of the curve
76 */
77 int curve;
78 } openssl_ecdsa_scheme_t;
79
80 #define END_OF_LIST -1
81
82 /**
83 * Signature schemes
84 */
85 static openssl_ecdsa_scheme_t ecdsa_schemes[] = {
86 {SIGN_ECDSA_256, NID_sha256, NID_X9_62_prime256v1},
87 {SIGN_ECDSA_384, NID_sha384, NID_secp384r1},
88 {SIGN_ECDSA_521, NID_sha512, NID_secp521r1},
89 {END_OF_LIST, 0, 0},
90 };
91
92 /**
93 * Look up the hash and curve of a signature scheme
94 */
95 static bool lookup_scheme(int scheme, int *hash, int *curve)
96 {
97 openssl_ecdsa_scheme_t *ecdsa_scheme = ecdsa_schemes;
98 while (ecdsa_scheme->scheme != END_OF_LIST)
99 {
100 if (scheme == ecdsa_scheme->scheme)
101 {
102 *hash = ecdsa_scheme->hash;
103 *curve = ecdsa_scheme->curve;
104 return TRUE;
105 }
106 ecdsa_scheme++;
107 }
108 return FALSE;
109 }
110
111 /**
112 * shared functions, implemented in openssl_ec_public_key.c
113 */
114 bool openssl_ec_public_key_build_id(EC_KEY *ec, identification_t **keyid,
115 identification_t **keyid_info);
116
117 openssl_ec_public_key_t *openssl_ec_public_key_create_from_private_key(EC_KEY *ec);
118
119
120 /**
121 * Convert an ECDSA_SIG to a chunk by concatenating r and s.
122 * This function allocates memory for the chunk.
123 */
124 static bool sig2chunk(const EC_GROUP *group, ECDSA_SIG *sig, chunk_t *chunk)
125 {
126 return openssl_bn_cat(EC_FIELD_ELEMENT_LEN(group), sig->r, sig->s, chunk);
127 }
128
129 /**
130 * Build the signature
131 */
132 static bool build_signature(private_openssl_ec_private_key_t *this,
133 int hash_type, chunk_t data, chunk_t *signature)
134 {
135 chunk_t hash = chunk_empty;
136 ECDSA_SIG *sig;
137 bool ret = FALSE;
138
139 if (!openssl_hash_chunk(hash_type, data, &hash))
140 {
141 return FALSE;
142 }
143
144 sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
145 if (!sig)
146 {
147 goto error;
148 }
149
150 if (!sig2chunk(EC_KEY_get0_group(this->ec), sig, signature))
151 {
152 goto error;
153 }
154
155 ret = TRUE;
156 error:
157 chunk_free(&hash);
158 if (sig)
159 {
160 ECDSA_SIG_free(sig);
161 }
162 return ret;
163 }
164
165 /**
166 * Implementation of private_key_t.get_type.
167 */
168 static key_type_t get_type(private_openssl_ec_private_key_t *this)
169 {
170 return KEY_ECDSA;
171 }
172
173 /**
174 * Implementation of private_key_t.sign.
175 */
176 static bool sign(private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
177 chunk_t data, chunk_t *signature)
178 {
179 EC_GROUP *req_group;
180 const EC_GROUP *my_group;
181 int hash, curve;
182
183 if (!lookup_scheme(scheme, &hash, &curve))
184 {
185 DBG1("signature scheme %N not supported in EC",
186 signature_scheme_names, scheme);
187 return FALSE;
188 }
189
190 req_group = EC_GROUP_new_by_curve_name(curve);
191 if (!req_group)
192 {
193 DBG1("signature scheme %N not supported in EC (required curve not supported)",
194 signature_scheme_names, scheme);
195 return FALSE;
196 }
197
198 my_group = EC_KEY_get0_group(this->ec);
199 if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
200 {
201 DBG1("signature scheme %N not supported by private key",
202 signature_scheme_names, scheme);
203 return FALSE;
204 }
205
206 EC_GROUP_free(req_group);
207
208 return build_signature(this, hash, data, signature);
209 }
210
211 /**
212 * Implementation of private_key_t.destroy.
213 */
214 static bool decrypt(private_openssl_ec_private_key_t *this,
215 chunk_t crypto, chunk_t *plain)
216 {
217 DBG1("EC private key decryption not implemented");
218 return FALSE;
219 }
220
221 /**
222 * Implementation of private_key_t.get_keysize.
223 */
224 static size_t get_keysize(private_openssl_ec_private_key_t *this)
225 {
226 return EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec));
227 }
228
229 /**
230 * Implementation of private_key_t.get_id.
231 */
232 static identification_t* get_id(private_openssl_ec_private_key_t *this,
233 id_type_t type)
234 {
235 switch (type)
236 {
237 case ID_PUBKEY_INFO_SHA1:
238 return this->keyid_info;
239 case ID_PUBKEY_SHA1:
240 return this->keyid;
241 default:
242 return NULL;
243 }
244 }
245
246 /**
247 * Implementation of private_key_t.get_public_key.
248 */
249 static openssl_ec_public_key_t* get_public_key(private_openssl_ec_private_key_t *this)
250 {
251 return openssl_ec_public_key_create_from_private_key(this->ec);
252 }
253
254 /**
255 * Implementation of private_key_t.belongs_to.
256 */
257 static bool belongs_to(private_openssl_ec_private_key_t *this, public_key_t *public)
258 {
259 identification_t *keyid;
260
261 if (public->get_type(public) != KEY_ECDSA)
262 {
263 return FALSE;
264 }
265 keyid = public->get_id(public, ID_PUBKEY_SHA1);
266 if (keyid && keyid->equals(keyid, this->keyid))
267 {
268 return TRUE;
269 }
270 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
271 if (keyid && keyid->equals(keyid, this->keyid_info))
272 {
273 return TRUE;
274 }
275 return FALSE;
276 }
277
278 /**
279 * Implementation of private_key_t.get_encoding.
280 */
281 static chunk_t get_encoding(private_openssl_ec_private_key_t *this)
282 {
283 chunk_t enc = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
284 u_char *p = enc.ptr;
285 i2d_ECPrivateKey(this->ec, &p);
286 return enc;
287 }
288
289 /**
290 * Implementation of private_key_t.get_ref.
291 */
292 static private_openssl_ec_private_key_t* get_ref(private_openssl_ec_private_key_t *this)
293 {
294 ref_get(&this->ref);
295 return this;
296
297 }
298
299 /**
300 * Implementation of private_key_t.destroy.
301 */
302 static void destroy(private_openssl_ec_private_key_t *this)
303 {
304 if (ref_put(&this->ref))
305 {
306 if (this->ec)
307 {
308 EC_KEY_free(this->ec);
309 }
310 DESTROY_IF(this->keyid);
311 DESTROY_IF(this->keyid_info);
312 free(this);
313 }
314 }
315
316 /**
317 * Internal generic constructor
318 */
319 static private_openssl_ec_private_key_t *openssl_ec_private_key_create_empty(void)
320 {
321 private_openssl_ec_private_key_t *this = malloc_thing(private_openssl_ec_private_key_t);
322
323 this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type;
324 this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign;
325 this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt;
326 this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize;
327 this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id;
328 this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
329 this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to;
330 this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding;
331 this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
332 this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
333
334 this->ec = NULL;
335 this->keyid = NULL;
336 this->keyid_info = NULL;
337 this->ref = 1;
338
339 return this;
340 }
341
342 /**
343 * load private key from an ASN1 encoded blob
344 */
345 static openssl_ec_private_key_t *load(chunk_t blob)
346 {
347 u_char *p = blob.ptr;
348 private_openssl_ec_private_key_t *this = openssl_ec_private_key_create_empty();
349
350 this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&p, blob.len);
351
352 chunk_clear(&blob);
353
354 if (!this->ec)
355 {
356 destroy(this);
357 return NULL;
358 }
359
360 if (!openssl_ec_public_key_build_id(this->ec, &this->keyid, &this->keyid_info))
361 {
362 destroy(this);
363 return NULL;
364 }
365
366 if (!EC_KEY_check_key(this->ec))
367 {
368 destroy(this);
369 return NULL;
370 }
371
372 return &this->public;
373 }
374
375 typedef struct private_builder_t private_builder_t;
376 /**
377 * Builder implementation for key loading/generation
378 */
379 struct private_builder_t {
380 /** implements the builder interface */
381 builder_t public;
382 /** loaded/generated private key */
383 openssl_ec_private_key_t *key;
384 };
385
386 /**
387 * Implementation of builder_t.build
388 */
389 static openssl_ec_private_key_t *build(private_builder_t *this)
390 {
391 openssl_ec_private_key_t *key = this->key;
392
393 free(this);
394 return key;
395 }
396
397 /**
398 * Implementation of builder_t.add
399 */
400 static void add(private_builder_t *this, builder_part_t part, ...)
401 {
402 va_list args;
403
404 if (this->key)
405 {
406 DBG1("ignoring surplus build part %N", builder_part_names, part);
407 return;
408 }
409
410 switch (part)
411 {
412 case BUILD_BLOB_ASN1_DER:
413 {
414 va_start(args, part);
415 this->key = load(va_arg(args, chunk_t));
416 va_end(args);
417 break;
418 }
419 default:
420 DBG1("ignoring unsupported build part %N", builder_part_names, part);
421 break;
422 }
423 }
424
425 /**
426 * Builder construction function
427 */
428 builder_t *openssl_ec_private_key_builder(key_type_t type)
429 {
430 private_builder_t *this;
431
432 if (type != KEY_ECDSA)
433 {
434 return NULL;
435 }
436
437 this = malloc_thing(private_builder_t);
438
439 this->key = NULL;
440 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
441 this->public.build = (void*(*)(builder_t *this))build;
442
443 return &this->public;
444 }
445