]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/openssl/openssl_ec_public_key.c
nm: Don't set DL_LIBS to 'none required' in configure script
[thirdparty/strongswan.git] / src / libstrongswan / plugins / openssl / openssl_ec_public_key.c
CommitLineData
ea0823df 1/*
e35c3e2a 2 * Copyright (C) 2009 Martin Willi
ea0823df 3 * Copyright (C) 2008 Tobias Brunner
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_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>
29#include <openssl/x509.h>
30
293a912c
TB
31#if OPENSSL_VERSION_NUMBER >= 0x30000000L
32#include <openssl/core_names.h>
33#endif
34
6688f798
TB
35#if OPENSSL_VERSION_NUMBER < 0x10100000L
36OPENSSL_KEY_FALLBACK(ECDSA_SIG, r, s)
37#endif
38
ea0823df
TB
39typedef struct private_openssl_ec_public_key_t private_openssl_ec_public_key_t;
40
41/**
42 * Private data structure with signing context.
43 */
44struct private_openssl_ec_public_key_t {
45 /**
46 * Public interface for this signer.
47 */
48 openssl_ec_public_key_t public;
7daf5226 49
ea0823df
TB
50 /**
51 * EC key object
52 */
293a912c 53 EVP_PKEY *key;
7daf5226 54
ea0823df
TB
55 /**
56 * reference counter
57 */
58 refcount_t ref;
59};
60
293a912c
TB
61/**
62 * Verification of a DER encoded signature as in RFC 3279
63 */
64static bool verify_der_signature(private_openssl_ec_public_key_t *this,
65 int nid_hash, chunk_t data, chunk_t signature)
66{
67 EVP_MD_CTX *ctx;
68 const EVP_MD *md;
69
70 /* remove any preceding 0-bytes from signature */
71 while (signature.len && signature.ptr[0] == 0x00)
72 {
73 signature = chunk_skip(signature, 1);
74 }
75 md = EVP_get_digestbynid(nid_hash);
76 if (!md)
77 {
78 return FALSE;
79 }
80 ctx = EVP_MD_CTX_create();
81 if (!ctx ||
82 EVP_DigestVerifyInit(ctx, NULL, md, NULL, this->key) <= 0 ||
83 EVP_DigestVerifyUpdate(ctx, data.ptr, data.len) <= 0 ||
84 EVP_DigestVerifyFinal(ctx, signature.ptr, signature.len) != 1)
85 {
86 EVP_MD_CTX_destroy(ctx);
87 return FALSE;
88 }
89 EVP_MD_CTX_destroy(ctx);
90 return TRUE;
91}
92
ea0823df
TB
93/**
94 * Verification of a signature as in RFC 4754
95 */
96static bool verify_signature(private_openssl_ec_public_key_t *this,
293a912c 97 int nid_hash, chunk_t data, chunk_t signature)
ea0823df 98{
293a912c 99 EVP_PKEY_CTX *ctx;
6688f798 100 BIGNUM *r, *s;
472cb4ce 101 ECDSA_SIG *sig;
293a912c 102 chunk_t der_sig;
6688f798 103 bool valid = FALSE;
7daf5226 104
ea0823df 105 sig = ECDSA_SIG_new();
ea0823df
TB
106 if (sig)
107 {
6688f798
TB
108 r = BN_new();
109 s = BN_new();
110 if (!openssl_bn_split(signature, r, s))
111 {
112 BN_free(r);
113 BN_free(s);
114 ECDSA_SIG_free(sig);
115 return FALSE;
116 }
117 if (ECDSA_SIG_set0(sig, r, s))
472cb4ce 118 {
293a912c
TB
119 der_sig = openssl_i2chunk(ECDSA_SIG, sig);
120 if (!nid_hash)
121 { /* EVP_DigestVerify*() has issues with NULL EVP_MD */
122 ctx = EVP_PKEY_CTX_new(this->key, NULL);
123 valid = ctx && EVP_PKEY_verify_init(ctx) > 0 &&
124 EVP_PKEY_verify(ctx, der_sig.ptr, der_sig.len,
125 data.ptr, data.len) > 0;
126 EVP_PKEY_CTX_free(ctx);
127 }
128 else
129 {
130 valid = verify_der_signature(this, nid_hash, data, der_sig);
131 }
132 chunk_free(&der_sig);
472cb4ce 133 }
ea0823df
TB
134 ECDSA_SIG_free(sig);
135 }
10b2898d
MW
136 return valid;
137}
138
139/**
293a912c
TB
140 * Check that the given key's curve matches a specific one. Also used by
141 * private key.
10b2898d 142 */
293a912c 143bool openssl_check_ec_key_curve(EVP_PKEY *key, int nid_curve)
10b2898d 144{
293a912c
TB
145 EC_GROUP *req_group, *my_group = NULL;
146 bool matches = FALSE;
7daf5226 147
10b2898d
MW
148 req_group = EC_GROUP_new_by_curve_name(nid_curve);
149 if (!req_group)
150 {
293a912c 151 goto error;
10b2898d 152 }
293a912c
TB
153
154#if OPENSSL_VERSION_NUMBER >= 0x30000000L
155 char name[BUF_LEN];
156 OSSL_PARAM params[] = {
157 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, name, sizeof(name)),
158 OSSL_PARAM_END,
159 };
160
161 if (!EVP_PKEY_get_group_name(key, name, sizeof(name), NULL))
10b2898d 162 {
293a912c 163 goto error;
10b2898d 164 }
293a912c
TB
165 my_group = EC_GROUP_new_from_params(params, NULL, NULL);
166#elif OPENSSL_VERSION_NUMBER >= 0x1010000fL
167 EC_KEY *ec = EVP_PKEY_get0_EC_KEY(key);
168 my_group = EC_GROUP_dup(EC_KEY_get0_group(ec));
169#else
170 EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
171 my_group = EC_GROUP_dup(EC_KEY_get0_group(ec));
172 EC_KEY_free(ec);
173#endif
174
175 if (EC_GROUP_cmp(my_group, req_group, NULL) == 0)
11e6d285 176 {
293a912c 177 matches = TRUE;
11e6d285 178 }
293a912c
TB
179
180error:
181 EC_GROUP_free(my_group);
182 EC_GROUP_free(req_group);
183 return matches;
ea0823df
TB
184}
185
ea0823df 186/**
293a912c 187 * Verify a RFC 4754 signature for a specified curve and hash algorithm
ea0823df 188 */
293a912c
TB
189static bool verify_curve_signature(private_openssl_ec_public_key_t *this,
190 signature_scheme_t scheme, int nid_hash,
191 int nid_curve, chunk_t data, chunk_t signature)
ea0823df 192{
293a912c 193 if (!openssl_check_ec_key_curve(this->key, nid_curve))
ea0823df 194 {
293a912c
TB
195 DBG1(DBG_LIB, "signature scheme %N not supported by key",
196 signature_scheme_names, scheme);
197 return FALSE;
ea0823df 198 }
293a912c 199 return verify_signature(this, nid_hash, data, signature);
ea0823df
TB
200}
201
57202484
MW
202METHOD(public_key_t, get_type, key_type_t,
203 private_openssl_ec_public_key_t *this)
ea0823df
TB
204{
205 return KEY_ECDSA;
206}
207
57202484
MW
208METHOD(public_key_t, verify, bool,
209 private_openssl_ec_public_key_t *this, signature_scheme_t scheme,
a413571f 210 void *params, chunk_t data, chunk_t signature)
ea0823df
TB
211{
212 switch (scheme)
213 {
472cb4ce
MW
214 case SIGN_ECDSA_WITH_SHA1_DER:
215 return verify_der_signature(this, NID_sha1, data, signature);
216 case SIGN_ECDSA_WITH_SHA256_DER:
217 return verify_der_signature(this, NID_sha256, data, signature);
218 case SIGN_ECDSA_WITH_SHA384_DER:
219 return verify_der_signature(this, NID_sha384, data, signature);
220 case SIGN_ECDSA_WITH_SHA512_DER:
221 return verify_der_signature(this, NID_sha512, data, signature);
11e6d285 222 case SIGN_ECDSA_WITH_NULL:
293a912c 223 return verify_signature(this, 0, data, signature);
ea0823df 224 case SIGN_ECDSA_256:
c8128024
AS
225 return verify_curve_signature(this, scheme, NID_sha256,
226 NID_X9_62_prime256v1, data, signature);
ea0823df 227 case SIGN_ECDSA_384:
c8128024
AS
228 return verify_curve_signature(this, scheme, NID_sha384,
229 NID_secp384r1, data, signature);
ea0823df 230 case SIGN_ECDSA_521:
c8128024
AS
231 return verify_curve_signature(this, scheme, NID_sha512,
232 NID_secp521r1, data, signature);
ea0823df 233 default:
8b0e0910 234 DBG1(DBG_LIB, "signature scheme %N not supported in EC",
ea0823df
TB
235 signature_scheme_names, scheme);
236 return FALSE;
237 }
238}
239
57202484 240METHOD(public_key_t, encrypt, bool,
33ddaaab 241 private_openssl_ec_public_key_t *this, encryption_scheme_t scheme,
4abb29f6 242 void *params, chunk_t crypto, chunk_t *plain)
ea0823df 243{
8b0e0910 244 DBG1(DBG_LIB, "EC public key encryption not implemented");
ea0823df
TB
245 return FALSE;
246}
247
a944d209 248METHOD(public_key_t, get_keysize, int,
57202484 249 private_openssl_ec_public_key_t *this)
ea0823df 250{
293a912c 251 return EVP_PKEY_bits(this->key);
b12c6d16
MW
252}
253
57202484
MW
254METHOD(public_key_t, get_fingerprint, bool,
255 private_openssl_ec_public_key_t *this, cred_encoding_type_t type,
256 chunk_t *fingerprint)
b12c6d16 257{
293a912c 258 return openssl_fingerprint(this->key, type, fingerprint);
ea0823df
TB
259}
260
57202484
MW
261METHOD(public_key_t, get_encoding, bool,
262 private_openssl_ec_public_key_t *this, cred_encoding_type_t type,
263 chunk_t *encoding)
ea0823df 264{
d6b3cc87 265 bool success = TRUE;
7daf5226 266
293a912c 267 *encoding = openssl_i2chunk(PUBKEY, this->key);
29cf15a9 268
d6b3cc87
TB
269 if (type != PUBKEY_SPKI_ASN1_DER)
270 {
271 chunk_t asn1_encoding = *encoding;
29cf15a9 272
d6b3cc87
TB
273 success = lib->encoding->encode(lib->encoding, type,
274 NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
275 asn1_encoding, CRED_PART_END);
276 chunk_clear(&asn1_encoding);
b12c6d16 277 }
d6b3cc87 278 return success;
ea0823df
TB
279}
280
57202484
MW
281METHOD(public_key_t, get_ref, public_key_t*,
282 private_openssl_ec_public_key_t *this)
ea0823df
TB
283{
284 ref_get(&this->ref);
57202484 285 return &this->public.key;
ea0823df
TB
286}
287
57202484
MW
288METHOD(public_key_t, destroy, void,
289 private_openssl_ec_public_key_t *this)
ea0823df
TB
290{
291 if (ref_put(&this->ref))
292 {
293a912c 293 if (this->key)
ea0823df 294 {
293a912c
TB
295 lib->encoding->clear_cache(lib->encoding, this->key);
296 EVP_PKEY_free(this->key);
ea0823df 297 }
ea0823df
TB
298 free(this);
299 }
300}
301
2bccdefc
TB
302/**
303 * Check whether the EC key was decoded with explicit curve parameters instead
304 * of a named curve.
305 */
306bool openssl_check_explicit_params(const EVP_PKEY *key)
307{
308 int explicit = 0;
309
310#if OPENSSL_VERSION_NUMBER >= 0x30000000L
311 if (!EVP_PKEY_get_int_param(key, OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
312 &explicit))
313 {
314 return FALSE;
315 }
316#elif OPENSSL_VERSION_NUMBER >= 0x1010108fL
317 explicit = EC_KEY_decoded_from_explicit_params(EVP_PKEY_get0_EC_KEY((EVP_PKEY*)key));
318#endif
319 return explicit == 1;
320}
321
ea0823df 322/**
30c06407 323 * See header.
ea0823df 324 */
30c06407
MW
325openssl_ec_public_key_t *openssl_ec_public_key_load(key_type_t type,
326 va_list args)
ea0823df 327{
30c06407
MW
328 private_openssl_ec_public_key_t *this;
329 chunk_t blob = chunk_empty;
293a912c 330 EVP_PKEY *key;
e35c3e2a 331
30c06407 332 while (TRUE)
ea0823df 333 {
30c06407 334 switch (va_arg(args, builder_part_t))
ea0823df 335 {
f7c17aa1 336 case BUILD_BLOB_ASN1_DER:
30c06407
MW
337 blob = va_arg(args, chunk_t);
338 continue;
339 case BUILD_END:
f7c17aa1 340 break;
30c06407
MW
341 default:
342 return NULL;
ea0823df 343 }
30c06407 344 break;
ea0823df 345 }
293a912c 346 key = d2i_PUBKEY(NULL, (const u_char**)&blob.ptr, blob.len);
2bccdefc
TB
347 if (!key || EVP_PKEY_base_id(key) != EVP_PKEY_EC ||
348 openssl_check_explicit_params(key))
ea0823df 349 {
293a912c 350 EVP_PKEY_free(key);
ea0823df
TB
351 return NULL;
352 }
293a912c
TB
353
354 INIT(this,
355 .public = {
356 .key = {
357 .get_type = _get_type,
358 .verify = _verify,
359 .encrypt = _encrypt,
360 .get_keysize = _get_keysize,
361 .equals = public_key_equals,
362 .get_fingerprint = _get_fingerprint,
363 .has_fingerprint = public_key_has_fingerprint,
364 .get_encoding = _get_encoding,
365 .get_ref = _get_ref,
366 .destroy = _destroy,
367 },
368 },
369 .ref = 1,
370 .key = key,
371 );
ea0823df
TB
372 return &this->public;
373}
374
293a912c 375#endif /* OPENSSL_NO_ECDSA */