]> git.ipfire.org Git - people/ms/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
credentials: Added void *params to public_key encrypt() and private_key decrypt(...
[people/ms/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_ec_private_key.c
CommitLineData
ea0823df 1/*
4a6f97d0 2 * Copyright (C) 2008-2016 Tobias Brunner
e35c3e2a 3 * Copyright (C) 2009 Martin Willi
4a6f97d0 4 * HSR Hochschule fuer Technik Rapperswil
ea0823df
TB
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.
ea0823df
TB
15 */
16
5a367e99
TB
17#include <openssl/opensslconf.h>
18
a3a190b7 19#ifndef OPENSSL_NO_ECDSA
5a367e99 20
ea0823df
TB
21#include "openssl_ec_private_key.h"
22#include "openssl_ec_public_key.h"
23#include "openssl_util.h"
24
f05b4272 25#include <utils/debug.h>
ea0823df
TB
26
27#include <openssl/evp.h>
28#include <openssl/ecdsa.h>
e35c3e2a 29#include <openssl/x509.h>
ea0823df 30
6688f798
TB
31#if OPENSSL_VERSION_NUMBER < 0x10100000L
32OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
33#endif
34
ea0823df
TB
35typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
36
37/**
38 * Private data of a openssl_ec_private_key_t object.
39 */
40struct private_openssl_ec_private_key_t {
41 /**
42 * Public interface for this signer.
43 */
44 openssl_ec_private_key_t public;
7daf5226 45
ea0823df
TB
46 /**
47 * EC key object
48 */
49 EC_KEY *ec;
7daf5226 50
b2266280
TB
51 /**
52 * TRUE if the key is from an OpenSSL ENGINE and might not be readable
53 */
54 bool engine;
55
ea0823df
TB
56 /**
57 * reference count
58 */
472cb4ce 59 refcount_t ref;
ea0823df
TB
60};
61
b12c6d16 62/* from ec public key */
da9724e6 63bool openssl_ec_fingerprint(EC_KEY *ec, cred_encoding_type_t type, chunk_t *fp);
b12c6d16 64
ea0823df 65/**
472cb4ce 66 * Build a signature as in RFC 4754
ea0823df
TB
67 */
68static bool build_signature(private_openssl_ec_private_key_t *this,
11e6d285 69 chunk_t hash, chunk_t *signature)
ea0823df 70{
6688f798 71 const BIGNUM *r, *s;
e35c3e2a 72 ECDSA_SIG *sig;
6688f798 73 bool built = FALSE;
7daf5226 74
e35c3e2a 75 sig = ECDSA_do_sign(hash.ptr, hash.len, this->ec);
472cb4ce 76 if (sig)
ea0823df 77 {
6688f798 78 ECDSA_SIG_get0(sig, &r, &s);
472cb4ce
MW
79 /* concatenate BNs r/s to a signature chunk */
80 built = openssl_bn_cat(EC_FIELD_ELEMENT_LEN(EC_KEY_get0_group(this->ec)),
6688f798 81 r, s, signature);
472cb4ce 82 ECDSA_SIG_free(sig);
ea0823df 83 }
472cb4ce 84 return built;
ea0823df
TB
85}
86
87/**
472cb4ce 88 * Build a RFC 4754 signature for a specified curve and hash algorithm
ea0823df 89 */
472cb4ce
MW
90static bool build_curve_signature(private_openssl_ec_private_key_t *this,
91 signature_scheme_t scheme, int nid_hash,
92 int nid_curve, chunk_t data, chunk_t *signature)
ea0823df 93{
472cb4ce
MW
94 const EC_GROUP *my_group;
95 EC_GROUP *req_group;
96 chunk_t hash;
97 bool built;
7daf5226 98
472cb4ce
MW
99 req_group = EC_GROUP_new_by_curve_name(nid_curve);
100 if (!req_group)
101 {
8b0e0910 102 DBG1(DBG_LIB, "signature scheme %N not supported in EC (required curve "
472cb4ce
MW
103 "not supported)", signature_scheme_names, scheme);
104 return FALSE;
105 }
106 my_group = EC_KEY_get0_group(this->ec);
107 if (EC_GROUP_cmp(my_group, req_group, NULL) != 0)
108 {
8b0e0910 109 DBG1(DBG_LIB, "signature scheme %N not supported by private key",
472cb4ce
MW
110 signature_scheme_names, scheme);
111 return FALSE;
112 }
113 EC_GROUP_free(req_group);
114 if (!openssl_hash_chunk(nid_hash, data, &hash))
115 {
116 return FALSE;
117 }
e201f53e 118 built = build_signature(this, hash, signature);
472cb4ce
MW
119 chunk_free(&hash);
120 return built;
ea0823df
TB
121}
122
123/**
472cb4ce 124 * Build a DER encoded signature as in RFC 3279
ea0823df 125 */
472cb4ce
MW
126static bool build_der_signature(private_openssl_ec_private_key_t *this,
127 int hash_nid, chunk_t data, chunk_t *signature)
ea0823df 128{
472cb4ce
MW
129 chunk_t hash, sig;
130 int siglen = 0;
131 bool built;
7daf5226 132
472cb4ce
MW
133 if (!openssl_hash_chunk(hash_nid, data, &hash))
134 {
135 return FALSE;
136 }
137 sig = chunk_alloc(ECDSA_size(this->ec));
138 built = ECDSA_sign(0, hash.ptr, hash.len, sig.ptr, &siglen, this->ec) == 1;
139 sig.len = siglen;
140 if (built)
ea0823df 141 {
472cb4ce 142 *signature = sig;
ea0823df 143 }
11e6d285 144 else
ea0823df 145 {
472cb4ce
MW
146 free(sig.ptr);
147 }
148 free(hash.ptr);
149 return built;
150}
151
57202484
MW
152METHOD(private_key_t, sign, bool,
153 private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
de280c2e 154 void *params, chunk_t data, chunk_t *signature)
472cb4ce
MW
155{
156 switch (scheme)
157 {
158 case SIGN_ECDSA_WITH_NULL:
159 return build_signature(this, data, signature);
160 case SIGN_ECDSA_WITH_SHA1_DER:
161 return build_der_signature(this, NID_sha1, data, signature);
162 case SIGN_ECDSA_WITH_SHA256_DER:
163 return build_der_signature(this, NID_sha256, data, signature);
164 case SIGN_ECDSA_WITH_SHA384_DER:
165 return build_der_signature(this, NID_sha384, data, signature);
166 case SIGN_ECDSA_WITH_SHA512_DER:
167 return build_der_signature(this, NID_sha512, data, signature);
168 case SIGN_ECDSA_256:
7daf5226 169 return build_curve_signature(this, scheme, NID_sha256,
1dbaec21 170 NID_X9_62_prime256v1, data, signature);
472cb4ce 171 case SIGN_ECDSA_384:
1dbaec21
AS
172 return build_curve_signature(this, scheme, NID_sha384,
173 NID_secp384r1, data, signature);
472cb4ce 174 case SIGN_ECDSA_521:
1dbaec21
AS
175 return build_curve_signature(this, scheme, NID_sha512,
176 NID_secp521r1, data, signature);
472cb4ce 177 default:
8b0e0910 178 DBG1(DBG_LIB, "signature scheme %N not supported",
472cb4ce 179 signature_scheme_names, scheme);
11e6d285 180 return FALSE;
472cb4ce 181 }
ea0823df
TB
182}
183
57202484 184METHOD(private_key_t, decrypt, bool,
33ddaaab 185 private_openssl_ec_private_key_t *this, encryption_scheme_t scheme,
4abb29f6 186 void *params, chunk_t crypto, chunk_t *plain)
ea0823df 187{
8b0e0910 188 DBG1(DBG_LIB, "EC private key decryption not implemented");
ea0823df
TB
189 return FALSE;
190}
191
a944d209 192METHOD(private_key_t, get_keysize, int,
57202484 193 private_openssl_ec_private_key_t *this)
ea0823df 194{
58184676 195 return EC_GROUP_get_degree(EC_KEY_get0_group(this->ec));
ea0823df
TB
196}
197
57202484
MW
198METHOD(private_key_t, get_type, key_type_t,
199 private_openssl_ec_private_key_t *this)
472cb4ce
MW
200{
201 return KEY_ECDSA;
202}
203
57202484
MW
204METHOD(private_key_t, get_public_key, public_key_t*,
205 private_openssl_ec_private_key_t *this)
ea0823df 206{
e35c3e2a
MW
207 public_key_t *public;
208 chunk_t key;
209 u_char *p;
7daf5226 210
e35c3e2a
MW
211 key = chunk_alloc(i2d_EC_PUBKEY(this->ec, NULL));
212 p = key.ptr;
213 i2d_EC_PUBKEY(this->ec, &p);
7daf5226 214
e35c3e2a
MW
215 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
216 BUILD_BLOB_ASN1_DER, key, BUILD_END);
217 free(key.ptr);
218 return public;
ea0823df
TB
219}
220
57202484
MW
221METHOD(private_key_t, get_fingerprint, bool,
222 private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
223 chunk_t *fingerprint)
ea0823df 224{
b12c6d16 225 return openssl_ec_fingerprint(this->ec, type, fingerprint);
ea0823df
TB
226}
227
57202484
MW
228METHOD(private_key_t, get_encoding, bool,
229 private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
230 chunk_t *encoding)
ea0823df 231{
e35c3e2a 232 u_char *p;
7daf5226 233
b2266280
TB
234 if (this->engine)
235 {
236 return FALSE;
237 }
238
b12c6d16
MW
239 switch (type)
240 {
da9724e6
MW
241 case PRIVKEY_ASN1_DER:
242 case PRIVKEY_PEM:
b12c6d16 243 {
29cf15a9
AS
244 bool success = TRUE;
245
b12c6d16
MW
246 *encoding = chunk_alloc(i2d_ECPrivateKey(this->ec, NULL));
247 p = encoding->ptr;
248 i2d_ECPrivateKey(this->ec, &p);
29cf15a9 249
da9724e6 250 if (type == PRIVKEY_PEM)
29cf15a9
AS
251 {
252 chunk_t asn1_encoding = *encoding;
253
da9724e6
MW
254 success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
255 NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
256 asn1_encoding, CRED_PART_END);
29cf15a9 257 chunk_clear(&asn1_encoding);
0a4dc787 258 }
29cf15a9 259 return success;
b12c6d16
MW
260 }
261 default:
262 return FALSE;
263 }
ea0823df
TB
264}
265
57202484
MW
266METHOD(private_key_t, get_ref, private_key_t*,
267 private_openssl_ec_private_key_t *this)
ea0823df
TB
268{
269 ref_get(&this->ref);
57202484 270 return &this->public.key;
ea0823df
TB
271}
272
57202484
MW
273METHOD(private_key_t, destroy, void,
274 private_openssl_ec_private_key_t *this)
ea0823df
TB
275{
276 if (ref_put(&this->ref))
277 {
278 if (this->ec)
279 {
b12c6d16 280 lib->encoding->clear_cache(lib->encoding, this->ec);
ea0823df
TB
281 EC_KEY_free(this->ec);
282 }
ea0823df
TB
283 free(this);
284 }
285}
286
287/**
288 * Internal generic constructor
289 */
e35c3e2a 290static private_openssl_ec_private_key_t *create_empty(void)
ea0823df 291{
57202484
MW
292 private_openssl_ec_private_key_t *this;
293
294 INIT(this,
ba31fe1f
MW
295 .public = {
296 .key = {
297 .get_type = _get_type,
298 .sign = _sign,
299 .decrypt = _decrypt,
300 .get_keysize = _get_keysize,
301 .get_public_key = _get_public_key,
302 .equals = private_key_equals,
303 .belongs_to = private_key_belongs_to,
304 .get_fingerprint = _get_fingerprint,
305 .has_fingerprint = private_key_has_fingerprint,
306 .get_encoding = _get_encoding,
307 .get_ref = _get_ref,
308 .destroy = _destroy,
309 },
57202484
MW
310 },
311 .ref = 1,
312 );
7daf5226 313
ea0823df
TB
314 return this;
315}
316
4a6f97d0
TB
317/*
318 * See header.
319 */
b2266280 320private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine)
4a6f97d0
TB
321{
322 private_openssl_ec_private_key_t *this;
323 EC_KEY *ec;
324
325 ec = EVP_PKEY_get1_EC_KEY(key);
326 EVP_PKEY_free(key);
327 if (!ec)
328 {
329 return NULL;
330 }
331 this = create_empty();
332 this->ec = ec;
b2266280 333 this->engine = engine;
4a6f97d0
TB
334 return &this->public.key;
335}
336
337/*
30c06407 338 * See header.
08ed551c 339 */
30c06407
MW
340openssl_ec_private_key_t *openssl_ec_private_key_gen(key_type_t type,
341 va_list args)
08ed551c 342{
30c06407
MW
343 private_openssl_ec_private_key_t *this;
344 u_int key_size = 0;
7daf5226 345
30c06407
MW
346 while (TRUE)
347 {
348 switch (va_arg(args, builder_part_t))
349 {
350 case BUILD_KEY_SIZE:
351 key_size = va_arg(args, u_int);
352 continue;
353 case BUILD_END:
354 break;
355 default:
356 return NULL;
357 }
358 break;
359 }
360 if (!key_size)
361 {
362 return NULL;
363 }
364 this = create_empty();
08ed551c
MW
365 switch (key_size)
366 {
367 case 256:
368 this->ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
369 break;
370 case 384:
371 this->ec = EC_KEY_new_by_curve_name(NID_secp384r1);
372 break;
373 case 521:
374 this->ec = EC_KEY_new_by_curve_name(NID_secp521r1);
375 break;
376 default:
8b0e0910 377 DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
08ed551c
MW
378 destroy(this);
379 return NULL;
380 }
381 if (EC_KEY_generate_key(this->ec) != 1)
382 {
8b0e0910 383 DBG1(DBG_LIB, "EC private key generation failed", key_size);
08ed551c
MW
384 destroy(this);
385 return NULL;
386 }
387 /* encode as a named curve key (no parameters), uncompressed public key */
388 EC_KEY_set_asn1_flag(this->ec, OPENSSL_EC_NAMED_CURVE);
389 EC_KEY_set_conv_form(this->ec, POINT_CONVERSION_UNCOMPRESSED);
390 return &this->public;
391}
392
ea0823df 393/**
30c06407 394 * See header.
ea0823df 395 */
30c06407
MW
396openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
397 va_list args)
ea0823df 398{
30c06407 399 private_openssl_ec_private_key_t *this;
27f8a61d 400 chunk_t par = chunk_empty, key = chunk_empty;
7daf5226 401
30c06407 402 while (TRUE)
ea0823df 403 {
30c06407 404 switch (va_arg(args, builder_part_t))
ea0823df 405 {
27f8a61d
TB
406 case BUILD_BLOB_ALGID_PARAMS:
407 par = va_arg(args, chunk_t);
408 continue;
f7c17aa1 409 case BUILD_BLOB_ASN1_DER:
27f8a61d 410 key = va_arg(args, chunk_t);
30c06407
MW
411 continue;
412 case BUILD_END:
f7c17aa1 413 break;
30c06407
MW
414 default:
415 return NULL;
ea0823df 416 }
30c06407 417 break;
ea0823df 418 }
30c06407
MW
419
420 this = create_empty();
27f8a61d
TB
421
422 if (par.ptr)
f7c17aa1 423 {
27f8a61d
TB
424 this->ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
425 if (!this->ec)
426 {
427 goto error;
428 }
429 if (!d2i_ECPrivateKey(&this->ec, (const u_char**)&key.ptr, key.len))
430 {
431 goto error;
432 }
433 }
434 else
435 {
436 this->ec = d2i_ECPrivateKey(NULL, (const u_char**)&key.ptr, key.len);
437 if (!this->ec)
438 {
439 goto error;
440 }
f7c17aa1 441 }
30c06407 442 if (!EC_KEY_check_key(this->ec))
ea0823df 443 {
27f8a61d 444 goto error;
ea0823df 445 }
ea0823df 446 return &this->public;
27f8a61d
TB
447
448error:
449 destroy(this);
450 return NULL;
ea0823df 451}
a3a190b7 452#endif /* OPENSSL_NO_ECDSA */