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