]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libstrongswan/plugins/wolfssl/wolfssl_ec_public_key.c
cred-encoding: Avoid potential use after free when caching encodings
[thirdparty/strongswan.git] / src / libstrongswan / plugins / wolfssl / wolfssl_ec_public_key.c
CommitLineData
c92eade8
SP
1/*
2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "wolfssl_common.h"
24
25#ifdef HAVE_ECC_VERIFY
26
27#include "wolfssl_ec_public_key.h"
28#include "wolfssl_util.h"
29
30#include <utils/debug.h>
31
32#include <wolfssl/wolfcrypt/ecc.h>
33#include <wolfssl/wolfcrypt/hash.h>
d3329ee5 34#include <wolfssl/wolfcrypt/asn.h>
c92eade8
SP
35
36typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t;
37
38/**
39 * Private data structure with signing context.
40 */
41struct private_wolfssl_ec_public_key_t {
d3329ee5 42
c92eade8 43 /**
d3329ee5 44 * Public interface
c92eade8
SP
45 */
46 wolfssl_ec_public_key_t public;
47
48 /**
49 * Key size
50 */
51 int keysize;
52
53 /**
54 * EC key object
55 */
56 ecc_key ec;
57
58 /**
d3329ee5 59 * Reference count
c92eade8
SP
60 */
61 refcount_t ref;
62};
63
64/**
65 * Verification of a signature as in RFC 4754
66 */
67static bool verify_signature(private_wolfssl_ec_public_key_t *this,
68 chunk_t hash, chunk_t signature)
69{
d3329ee5 70 int stat = 1, ret = -1;
c92eade8
SP
71 mp_int r, s;
72
73 if (mp_init(&r) < 0)
74 {
75 return FALSE;
76 }
77 if (mp_init(&s) < 0)
78 {
79 mp_free(&r);
80 return FALSE;
81 }
82
83 if (wolfssl_mp_split(signature, &r, &s))
84 {
85 ret = wc_ecc_verify_hash_ex(&r, &s, hash.ptr, hash.len, &stat,
86 &this->ec);
87 }
c92eade8
SP
88 mp_free(&s);
89 mp_free(&r);
c92eade8
SP
90 return ret == 0 && stat == 1;
91}
92
93/**
94 * Verify a RFC 4754 signature for a specified curve and hash algorithm
95 */
96static bool verify_curve_signature(private_wolfssl_ec_public_key_t *this,
d3329ee5
TB
97 signature_scheme_t scheme,
98 enum wc_HashType hash, ecc_curve_id curve_id,
99 chunk_t data, chunk_t signature)
c92eade8
SP
100{
101 bool success = FALSE;
102 chunk_t dgst;
103
104 if (curve_id != this->ec.dp->id)
105 {
106 DBG1(DBG_LIB, "signature scheme %N not supported by private key",
107 signature_scheme_names, scheme);
108 return FALSE;
109 }
110
111 if (wolfssl_hash_chunk(hash, data, &dgst))
112 {
113 success = verify_signature(this, dgst, signature);
114 }
115
116 chunk_free(&dgst);
117 return success;
118}
119
120/**
121 * Verification of a DER encoded signature as in RFC 3279
122 */
123static bool verify_der_signature(private_wolfssl_ec_public_key_t *this,
d3329ee5
TB
124 enum wc_HashType hash, chunk_t data,
125 chunk_t signature)
c92eade8 126{
c92eade8 127 chunk_t dgst;
d3329ee5 128 int stat = 1, ret = -1;
c92eade8 129
d3329ee5 130 signature = chunk_skip_zero(signature);
c92eade8
SP
131 if (wolfssl_hash_chunk(hash, data, &dgst))
132 {
133 ret = wc_ecc_verify_hash(signature.ptr, signature.len, dgst.ptr,
134 dgst.len, &stat, &this->ec);
c92eade8 135 }
c92eade8 136 chunk_free(&dgst);
d3329ee5 137 return ret == 0 && stat == 1;
c92eade8
SP
138}
139
140METHOD(public_key_t, get_type, key_type_t,
141 private_wolfssl_ec_public_key_t *this)
142{
143 return KEY_ECDSA;
144}
145
146METHOD(public_key_t, verify, bool,
147 private_wolfssl_ec_public_key_t *this, signature_scheme_t scheme,
148 void *params, chunk_t data, chunk_t signature)
149{
150 switch (scheme)
151 {
d3329ee5 152#ifndef NO_SHA
c92eade8
SP
153 case SIGN_ECDSA_WITH_SHA1_DER:
154 return verify_der_signature(this, WC_HASH_TYPE_SHA, data,
155 signature);
d3329ee5
TB
156#endif
157#ifndef NO_SHA256
c92eade8
SP
158 case SIGN_ECDSA_WITH_SHA256_DER:
159 return verify_der_signature(this, WC_HASH_TYPE_SHA256, data,
160 signature);
d3329ee5
TB
161#endif
162#ifdef WOLFSSL_SHA384
c92eade8
SP
163 case SIGN_ECDSA_WITH_SHA384_DER:
164 return verify_der_signature(this, WC_HASH_TYPE_SHA384, data,
165 signature);
d3329ee5
TB
166#endif
167#ifdef WOLFSSL_SHA512
c92eade8
SP
168 case SIGN_ECDSA_WITH_SHA512_DER:
169 return verify_der_signature(this, WC_HASH_TYPE_SHA512, data,
170 signature);
d3329ee5 171#endif
c92eade8
SP
172 case SIGN_ECDSA_WITH_NULL:
173 return verify_signature(this, data, signature);
d3329ee5 174#ifndef NO_SHA256
c92eade8
SP
175 case SIGN_ECDSA_256:
176 return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA256,
177 ECC_SECP256R1, data, signature);
d3329ee5
TB
178#endif
179#ifdef WOLFSSL_SHA384
c92eade8
SP
180 case SIGN_ECDSA_384:
181 return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA384,
182 ECC_SECP384R1, data, signature);
d3329ee5
TB
183#endif
184#ifdef WOLFSSL_SHA512
c92eade8
SP
185 case SIGN_ECDSA_521:
186 return verify_curve_signature(this, scheme, WC_HASH_TYPE_SHA512,
187 ECC_SECP521R1, data, signature);
d3329ee5 188#endif
c92eade8 189 default:
d3329ee5 190 DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl",
c92eade8
SP
191 signature_scheme_names, scheme);
192 return FALSE;
193 }
194}
195
5900426a 196METHOD(public_key_t, encrypt_, bool,
c92eade8 197 private_wolfssl_ec_public_key_t *this, encryption_scheme_t scheme,
4abb29f6 198 void *params, chunk_t crypto, chunk_t *plain)
c92eade8
SP
199{
200 DBG1(DBG_LIB, "EC public key encryption not implemented");
201 return FALSE;
202}
203
204METHOD(public_key_t, get_keysize, int,
205 private_wolfssl_ec_public_key_t *this)
206{
207 return this->keysize;
208}
209
210/**
d3329ee5 211 * Calculate fingerprint from an EC key, also used in ec private key.
c92eade8
SP
212 */
213bool wolfssl_ec_fingerprint(ecc_key *ec, cred_encoding_type_t type, chunk_t *fp)
214{
215 hasher_t *hasher;
216 chunk_t key;
d3329ee5 217 int len;
c92eade8
SP
218
219 if (lib->encoding->get_cache(lib->encoding, type, ec, fp))
220 {
221 return TRUE;
222 }
223
c92eade8
SP
224 switch (type)
225 {
226 case KEYID_PUBKEY_SHA1:
d3329ee5
TB
227 case KEYID_PUBKEY_INFO_SHA1:
228 /* need an additional byte for the point type */
229 len = ec->dp->size * 2 + 1;
230 if (type == KEYID_PUBKEY_INFO_SHA1)
231 {
232 /* additional space for algorithmIdentifier/bitString */
233 len += 2 * MAX_SEQ_SZ + 2 * MAX_ALGO_SZ + TRAILING_ZERO;
234 }
235 key = chunk_alloca(len);
236 len = wc_EccPublicKeyToDer(ec, key.ptr, key.len,
237 type == KEYID_PUBKEY_INFO_SHA1);
c92eade8
SP
238 break;
239 default:
d3329ee5 240 return FALSE;
c92eade8 241 }
d3329ee5
TB
242 if (len < 0)
243 {
244 return FALSE;
245 }
246 key.len = len;
c92eade8
SP
247
248 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
249 if (!hasher || !hasher->allocate_hash(hasher, key, fp))
250 {
d3329ee5 251 DBG1(DBG_LIB, "SHA1 not supported, fingerprinting failed");
c92eade8 252 DESTROY_IF(hasher);
c92eade8
SP
253 return FALSE;
254 }
255 hasher->destroy(hasher);
48e9267d 256 lib->encoding->cache(lib->encoding, type, ec, fp);
c92eade8
SP
257 return TRUE;
258}
259
260METHOD(public_key_t, get_fingerprint, bool,
261 private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
262 chunk_t *fingerprint)
263{
264 return wolfssl_ec_fingerprint(&this->ec, type, fingerprint);
265}
266
267METHOD(public_key_t, get_encoding, bool,
268 private_wolfssl_ec_public_key_t *this, cred_encoding_type_t type,
269 chunk_t *encoding)
270{
271 bool success = TRUE;
d3329ee5 272 int len;
c92eade8 273
d3329ee5
TB
274 /* space for algorithmIdentifier/bitString + one byte for the point type */
275 *encoding = chunk_alloc(2 * this->ec.dp->size + 2 * MAX_SEQ_SZ +
276 2 * MAX_ALGO_SZ + TRAILING_ZERO + 1);
277 len = wc_EccPublicKeyToDer(&this->ec, encoding->ptr, encoding->len, 1);
278 if (len < 0)
c92eade8
SP
279 {
280 chunk_free(encoding);
281 return FALSE;
282 }
d3329ee5 283 encoding->len = len;
c92eade8 284
d3329ee5 285 if (type != PUBKEY_SPKI_ASN1_DER)
c92eade8
SP
286 {
287 chunk_t asn1_encoding = *encoding;
288
289 success = lib->encoding->encode(lib->encoding, type,
290 NULL, encoding, CRED_PART_ECDSA_PUB_ASN1_DER,
291 asn1_encoding, CRED_PART_END);
292 chunk_clear(&asn1_encoding);
293 }
294 return success;
295}
296
297METHOD(public_key_t, get_ref, public_key_t*,
298 private_wolfssl_ec_public_key_t *this)
299{
300 ref_get(&this->ref);
301 return &this->public.key;
302}
303
304METHOD(public_key_t, destroy, void,
305 private_wolfssl_ec_public_key_t *this)
306{
307 if (ref_put(&this->ref))
308 {
309 lib->encoding->clear_cache(lib->encoding, &this->ec);
310 wc_ecc_free(&this->ec);
311 free(this);
312 }
313}
314
315/**
316 * Generic private constructor
317 */
318static private_wolfssl_ec_public_key_t *create_empty()
319{
320 private_wolfssl_ec_public_key_t *this;
321
322 INIT(this,
323 .public = {
324 .key = {
325 .get_type = _get_type,
326 .verify = _verify,
5900426a 327 .encrypt = _encrypt_,
c92eade8
SP
328 .get_keysize = _get_keysize,
329 .equals = public_key_equals,
330 .get_fingerprint = _get_fingerprint,
331 .has_fingerprint = public_key_has_fingerprint,
332 .get_encoding = _get_encoding,
333 .get_ref = _get_ref,
334 .destroy = _destroy,
335 },
336 },
337 .ref = 1,
338 );
339
340 if (wc_ecc_init(&this->ec) < 0)
341 {
342 free(this);
343 return NULL;
344 }
c92eade8
SP
345 return this;
346}
347
d3329ee5
TB
348/*
349 * Described in header
c92eade8
SP
350 */
351wolfssl_ec_public_key_t *wolfssl_ec_public_key_load(key_type_t type,
352 va_list args)
353{
354 private_wolfssl_ec_public_key_t *this;
355 chunk_t blob = chunk_empty;
356 word32 idx;
357 int ret;
358
c92eade8
SP
359 while (TRUE)
360 {
361 switch (va_arg(args, builder_part_t))
362 {
363 case BUILD_BLOB_ASN1_DER:
364 blob = va_arg(args, chunk_t);
365 continue;
366 case BUILD_END:
367 break;
368 default:
369 return NULL;
370 }
371 break;
372 }
373 this = create_empty();
d3329ee5
TB
374 if (!this)
375 {
376 return NULL;
377 }
378
c92eade8
SP
379 idx = 0;
380 ret = wc_EccPublicKeyDecode(blob.ptr, &idx, &this->ec, blob.len);
381 if (ret < 0)
382 {
383 destroy(this);
384 return NULL;
385 }
386 switch (this->ec.dp->id)
387 {
388 case ECC_SECP256R1:
389 this->keysize = 256;
390 break;
391 case ECC_SECP384R1:
392 this->keysize = 384;
393 break;
394 case ECC_SECP521R1:
395 this->keysize = 521;
396 break;
397 default:
398 break;
399 }
400 return &this->public;
401}
c92eade8 402
d3329ee5 403#endif /* HAVE_ECC_VERIFY */