]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_ec_private_key.c
Update copyright headers after acquisition by secunet
[thirdparty/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
19ef2aec
TB
4 *
5 * Copyright (C) secunet Security Networks AG
ea0823df
TB
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
ea0823df
TB
16 */
17
5a367e99
TB
18#include <openssl/opensslconf.h>
19
a3a190b7 20#ifndef OPENSSL_NO_ECDSA
5a367e99 21
ea0823df
TB
22#include "openssl_ec_private_key.h"
23#include "openssl_ec_public_key.h"
24#include "openssl_util.h"
25
f05b4272 26#include <utils/debug.h>
ea0823df
TB
27
28#include <openssl/evp.h>
29#include <openssl/ecdsa.h>
e35c3e2a 30#include <openssl/x509.h>
ea0823df 31
6688f798
TB
32#if OPENSSL_VERSION_NUMBER < 0x10100000L
33OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
34#endif
35
ea0823df
TB
36typedef struct private_openssl_ec_private_key_t private_openssl_ec_private_key_t;
37
38/**
39 * Private data of a openssl_ec_private_key_t object.
40 */
41struct private_openssl_ec_private_key_t {
42 /**
43 * Public interface for this signer.
44 */
45 openssl_ec_private_key_t public;
7daf5226 46
ea0823df
TB
47 /**
48 * EC key object
49 */
293a912c 50 EVP_PKEY *key;
7daf5226 51
b2266280
TB
52 /**
53 * TRUE if the key is from an OpenSSL ENGINE and might not be readable
54 */
55 bool engine;
56
ea0823df
TB
57 /**
58 * reference count
59 */
472cb4ce 60 refcount_t ref;
ea0823df
TB
61};
62
293a912c
TB
63/* from openssl_ec_public_key */
64bool openssl_check_ec_key_curve(EVP_PKEY *key, int nid_curve);
65
66/**
67 * Build a DER encoded signature as in RFC 3279
68 */
69static bool build_der_signature(private_openssl_ec_private_key_t *this,
70 int nid_hash, chunk_t data, chunk_t *signature)
71{
72 EVP_MD_CTX *ctx;
73 const EVP_MD *md;
74
75 md = EVP_get_digestbynid(nid_hash);
76 if (!md)
77 {
78 return FALSE;
79 }
80 *signature = chunk_alloc(EVP_PKEY_size(this->key));
81 ctx = EVP_MD_CTX_create();
82 if (!ctx ||
83 EVP_DigestSignInit(ctx, NULL, md, NULL, this->key) <= 0 ||
84 EVP_DigestSignUpdate(ctx, data.ptr, data.len) <= 0 ||
85 EVP_DigestSignFinal(ctx, signature->ptr, &signature->len) != 1)
86 {
87 chunk_free(signature);
88 EVP_MD_CTX_destroy(ctx);
89 return FALSE;
90 }
91 EVP_MD_CTX_destroy(ctx);
92 return TRUE;
93}
b12c6d16 94
ea0823df 95/**
472cb4ce 96 * Build a signature as in RFC 4754
ea0823df
TB
97 */
98static bool build_signature(private_openssl_ec_private_key_t *this,
293a912c 99 int nid_hash, chunk_t data, chunk_t *signature)
ea0823df 100{
293a912c 101 EVP_PKEY_CTX *ctx;
e35c3e2a 102 ECDSA_SIG *sig;
293a912c
TB
103 const BIGNUM *r, *s;
104 const u_char *p;
105 chunk_t der_sig;
6688f798 106 bool built = FALSE;
7daf5226 107
293a912c
TB
108 if (!nid_hash)
109 { /* EVP_DigestSign*() has issues with NULL EVP_MD */
110 der_sig = chunk_alloc(EVP_PKEY_size(this->key));
111 ctx = EVP_PKEY_CTX_new(this->key, NULL);
112 if (!ctx ||
113 EVP_PKEY_sign_init(ctx) <= 0 ||
114 EVP_PKEY_sign(ctx, der_sig.ptr, &der_sig.len, data.ptr, data.len) <= 0)
115 {
116 chunk_free(&der_sig);
117 EVP_PKEY_CTX_free(ctx);
118 return FALSE;
119 }
120 EVP_PKEY_CTX_free(ctx);
121 }
122 else if (!build_der_signature(this, nid_hash, data, &der_sig))
123 {
124 return FALSE;
125 }
126 /* extract r and s from the DER-encoded signature */
127 p = der_sig.ptr;
128 sig = d2i_ECDSA_SIG(NULL, &p, der_sig.len);
129 chunk_free(&der_sig);
472cb4ce 130 if (sig)
ea0823df 131 {
6688f798 132 ECDSA_SIG_get0(sig, &r, &s);
472cb4ce 133 /* concatenate BNs r/s to a signature chunk */
293a912c 134 built = openssl_bn_cat((EVP_PKEY_bits(this->key) + 7) / 8,
6688f798 135 r, s, signature);
472cb4ce 136 ECDSA_SIG_free(sig);
ea0823df 137 }
472cb4ce 138 return built;
ea0823df
TB
139}
140
141/**
472cb4ce 142 * Build a RFC 4754 signature for a specified curve and hash algorithm
ea0823df 143 */
472cb4ce
MW
144static bool build_curve_signature(private_openssl_ec_private_key_t *this,
145 signature_scheme_t scheme, int nid_hash,
146 int nid_curve, chunk_t data, chunk_t *signature)
ea0823df 147{
293a912c 148 if (!openssl_check_ec_key_curve(this->key, nid_curve))
472cb4ce 149 {
293a912c 150 DBG1(DBG_LIB, "signature scheme %N not supported by key",
472cb4ce
MW
151 signature_scheme_names, scheme);
152 return FALSE;
153 }
293a912c 154 return build_signature(this, nid_hash, data, signature);
472cb4ce
MW
155}
156
57202484
MW
157METHOD(private_key_t, sign, bool,
158 private_openssl_ec_private_key_t *this, signature_scheme_t scheme,
de280c2e 159 void *params, chunk_t data, chunk_t *signature)
472cb4ce
MW
160{
161 switch (scheme)
162 {
163 case SIGN_ECDSA_WITH_NULL:
293a912c 164 return build_signature(this, 0, data, signature);
472cb4ce
MW
165 case SIGN_ECDSA_WITH_SHA1_DER:
166 return build_der_signature(this, NID_sha1, data, signature);
167 case SIGN_ECDSA_WITH_SHA256_DER:
168 return build_der_signature(this, NID_sha256, data, signature);
169 case SIGN_ECDSA_WITH_SHA384_DER:
170 return build_der_signature(this, NID_sha384, data, signature);
171 case SIGN_ECDSA_WITH_SHA512_DER:
172 return build_der_signature(this, NID_sha512, data, signature);
173 case SIGN_ECDSA_256:
7daf5226 174 return build_curve_signature(this, scheme, NID_sha256,
1dbaec21 175 NID_X9_62_prime256v1, data, signature);
472cb4ce 176 case SIGN_ECDSA_384:
1dbaec21
AS
177 return build_curve_signature(this, scheme, NID_sha384,
178 NID_secp384r1, data, signature);
472cb4ce 179 case SIGN_ECDSA_521:
1dbaec21
AS
180 return build_curve_signature(this, scheme, NID_sha512,
181 NID_secp521r1, data, signature);
472cb4ce 182 default:
8b0e0910 183 DBG1(DBG_LIB, "signature scheme %N not supported",
472cb4ce 184 signature_scheme_names, scheme);
11e6d285 185 return FALSE;
472cb4ce 186 }
ea0823df
TB
187}
188
57202484 189METHOD(private_key_t, decrypt, bool,
33ddaaab 190 private_openssl_ec_private_key_t *this, encryption_scheme_t scheme,
4abb29f6 191 void *params, chunk_t crypto, chunk_t *plain)
ea0823df 192{
8b0e0910 193 DBG1(DBG_LIB, "EC private key decryption not implemented");
ea0823df
TB
194 return FALSE;
195}
196
a944d209 197METHOD(private_key_t, get_keysize, int,
57202484 198 private_openssl_ec_private_key_t *this)
ea0823df 199{
293a912c 200 return EVP_PKEY_bits(this->key);
ea0823df
TB
201}
202
57202484
MW
203METHOD(private_key_t, get_type, key_type_t,
204 private_openssl_ec_private_key_t *this)
472cb4ce
MW
205{
206 return KEY_ECDSA;
207}
208
57202484
MW
209METHOD(private_key_t, get_public_key, public_key_t*,
210 private_openssl_ec_private_key_t *this)
ea0823df 211{
e35c3e2a
MW
212 public_key_t *public;
213 chunk_t key;
7daf5226 214
293a912c 215 key = openssl_i2chunk(PUBKEY, this->key);
e35c3e2a
MW
216 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ECDSA,
217 BUILD_BLOB_ASN1_DER, key, BUILD_END);
218 free(key.ptr);
219 return public;
ea0823df
TB
220}
221
57202484
MW
222METHOD(private_key_t, get_fingerprint, bool,
223 private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
224 chunk_t *fingerprint)
ea0823df 225{
293a912c 226 return openssl_fingerprint(this->key, type, fingerprint);
ea0823df
TB
227}
228
57202484
MW
229METHOD(private_key_t, get_encoding, bool,
230 private_openssl_ec_private_key_t *this, cred_encoding_type_t type,
231 chunk_t *encoding)
ea0823df 232{
b2266280
TB
233 if (this->engine)
234 {
235 return FALSE;
236 }
b12c6d16
MW
237 switch (type)
238 {
da9724e6
MW
239 case PRIVKEY_ASN1_DER:
240 case PRIVKEY_PEM:
b12c6d16 241 {
29cf15a9
AS
242 bool success = TRUE;
243
293a912c 244 *encoding = openssl_i2chunk(PrivateKey, this->key);
29cf15a9 245
da9724e6 246 if (type == PRIVKEY_PEM)
29cf15a9
AS
247 {
248 chunk_t asn1_encoding = *encoding;
249
da9724e6
MW
250 success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
251 NULL, encoding, CRED_PART_ECDSA_PRIV_ASN1_DER,
252 asn1_encoding, CRED_PART_END);
29cf15a9 253 chunk_clear(&asn1_encoding);
0a4dc787 254 }
29cf15a9 255 return success;
b12c6d16
MW
256 }
257 default:
258 return FALSE;
259 }
ea0823df
TB
260}
261
57202484
MW
262METHOD(private_key_t, get_ref, private_key_t*,
263 private_openssl_ec_private_key_t *this)
ea0823df
TB
264{
265 ref_get(&this->ref);
57202484 266 return &this->public.key;
ea0823df
TB
267}
268
57202484
MW
269METHOD(private_key_t, destroy, void,
270 private_openssl_ec_private_key_t *this)
ea0823df
TB
271{
272 if (ref_put(&this->ref))
273 {
293a912c 274 if (this->key)
ea0823df 275 {
293a912c
TB
276 lib->encoding->clear_cache(lib->encoding, this->key);
277 EVP_PKEY_free(this->key);
ea0823df 278 }
ea0823df
TB
279 free(this);
280 }
281}
282
283/**
284 * Internal generic constructor
285 */
293a912c 286static private_openssl_ec_private_key_t *create_internal(EVP_PKEY *key)
ea0823df 287{
57202484
MW
288 private_openssl_ec_private_key_t *this;
289
290 INIT(this,
ba31fe1f
MW
291 .public = {
292 .key = {
293 .get_type = _get_type,
294 .sign = _sign,
295 .decrypt = _decrypt,
296 .get_keysize = _get_keysize,
297 .get_public_key = _get_public_key,
298 .equals = private_key_equals,
299 .belongs_to = private_key_belongs_to,
300 .get_fingerprint = _get_fingerprint,
301 .has_fingerprint = private_key_has_fingerprint,
302 .get_encoding = _get_encoding,
303 .get_ref = _get_ref,
304 .destroy = _destroy,
305 },
57202484
MW
306 },
307 .ref = 1,
293a912c 308 .key = key,
57202484 309 );
7daf5226 310
ea0823df
TB
311 return this;
312}
313
4a6f97d0
TB
314/*
315 * See header.
316 */
b2266280 317private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine)
4a6f97d0
TB
318{
319 private_openssl_ec_private_key_t *this;
4a6f97d0 320
293a912c 321 if (EVP_PKEY_base_id(key) != EVP_PKEY_EC)
4a6f97d0 322 {
293a912c 323 EVP_PKEY_free(key);
4a6f97d0
TB
324 return NULL;
325 }
293a912c 326 this = create_internal(key);
b2266280 327 this->engine = engine;
4a6f97d0
TB
328 return &this->public.key;
329}
330
331/*
30c06407 332 * See header.
08ed551c 333 */
30c06407
MW
334openssl_ec_private_key_t *openssl_ec_private_key_gen(key_type_t type,
335 va_list args)
08ed551c 336{
30c06407 337 private_openssl_ec_private_key_t *this;
293a912c 338 EVP_PKEY *key = NULL;
30c06407 339 u_int key_size = 0;
7daf5226 340
30c06407
MW
341 while (TRUE)
342 {
343 switch (va_arg(args, builder_part_t))
344 {
345 case BUILD_KEY_SIZE:
346 key_size = va_arg(args, u_int);
347 continue;
348 case BUILD_END:
349 break;
350 default:
351 return NULL;
352 }
353 break;
354 }
355 if (!key_size)
356 {
357 return NULL;
358 }
293a912c
TB
359
360#if OPENSSL_VERSION_NUMBER >= 0x30000000L
08ed551c
MW
361 switch (key_size)
362 {
363 case 256:
293a912c 364 key = EVP_EC_gen("P-256");
08ed551c
MW
365 break;
366 case 384:
293a912c 367 key = EVP_EC_gen("P-384");
08ed551c
MW
368 break;
369 case 521:
293a912c 370 key = EVP_EC_gen("P-521");
08ed551c
MW
371 break;
372 default:
8b0e0910 373 DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
08ed551c
MW
374 return NULL;
375 }
293a912c
TB
376#else /* OPENSSL_VERSION_NUMBER */
377 EC_KEY *ec;
378
379 switch (key_size)
380 {
381 case 256:
382 ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
383 break;
384 case 384:
385 ec = EC_KEY_new_by_curve_name(NID_secp384r1);
386 break;
387 case 521:
388 ec = EC_KEY_new_by_curve_name(NID_secp521r1);
389 break;
390 default:
391 DBG1(DBG_LIB, "EC private key size %d not supported", key_size);
392 return NULL;
393 }
394 if (ec && EC_KEY_generate_key(ec) == 1)
395 {
396 key = EVP_PKEY_new();
397 if (!EVP_PKEY_assign_EC_KEY(key, ec))
398 {
399 EC_KEY_free(ec);
400 EVP_PKEY_free(key);
401 key = NULL;
402 }
403 }
404#endif /* OPENSSL_VERSION_NUMBER */
405
406 if (!key)
08ed551c 407 {
08ed551c
MW
408 return NULL;
409 }
293a912c 410 this = create_internal(key);
08ed551c
MW
411 return &this->public;
412}
413
ea0823df 414/**
30c06407 415 * See header.
ea0823df 416 */
30c06407
MW
417openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type,
418 va_list args)
ea0823df 419{
30c06407 420 private_openssl_ec_private_key_t *this;
293a912c
TB
421 chunk_t par = chunk_empty, blob = chunk_empty;
422 EVP_PKEY *key = NULL;
7daf5226 423
30c06407 424 while (TRUE)
ea0823df 425 {
30c06407 426 switch (va_arg(args, builder_part_t))
ea0823df 427 {
27f8a61d
TB
428 case BUILD_BLOB_ALGID_PARAMS:
429 par = va_arg(args, chunk_t);
430 continue;
f7c17aa1 431 case BUILD_BLOB_ASN1_DER:
293a912c 432 blob = va_arg(args, chunk_t);
30c06407
MW
433 continue;
434 case BUILD_END:
f7c17aa1 435 break;
30c06407
MW
436 default:
437 return NULL;
ea0823df 438 }
30c06407 439 break;
ea0823df 440 }
30c06407 441
27f8a61d 442 if (par.ptr)
f7c17aa1 443 {
293a912c
TB
444 /* for OpenSSL 3, the combination of d2i_KeyParams/d2i_PrivateKey, which
445 * are intended to replace the functions below, does currently not work
446 * because OpenSSL does not pass the internal EC_KEY that stores the
447 * parameters from the first call to the call that parses the private
448 * key. however, since parsing PKCS#8 is the only use case for this and
449 * OpenSSL 3 parses this format directly, there isn't really any need
450 * for it anyway */
451#if OPENSSL_VERSION_NUMBER < 0x30000000L
452 EC_KEY *ec;
453
454 ec = d2i_ECParameters(NULL, (const u_char**)&par.ptr, par.len);
455 if (ec && d2i_ECPrivateKey(&ec, (const u_char**)&blob.ptr, blob.len))
27f8a61d 456 {
293a912c
TB
457 key = EVP_PKEY_new();
458 if (!EVP_PKEY_assign_EC_KEY(key, ec))
459 {
460 EC_KEY_free(ec);
461 EVP_PKEY_free(key);
462 key = NULL;
463 }
27f8a61d 464 }
293a912c 465 else
27f8a61d 466 {
293a912c 467 EC_KEY_free(ec);
27f8a61d 468 }
293a912c 469#endif
27f8a61d
TB
470 }
471 else
472 {
293a912c
TB
473 key = d2i_PrivateKey(EVP_PKEY_EC, NULL, (const u_char**)&blob.ptr,
474 blob.len);
f7c17aa1 475 }
293a912c
TB
476
477 if (!key)
ea0823df 478 {
293a912c 479 return NULL;
ea0823df 480 }
293a912c 481 this = create_internal(key);
ea0823df
TB
482 return &this->public;
483}
a3a190b7 484#endif /* OPENSSL_NO_ECDSA */