2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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
23 #include "wolfssl_common.h"
25 #ifdef HAVE_ECC_VERIFY
27 #include "wolfssl_ec_public_key.h"
28 #include "wolfssl_util.h"
30 #include <utils/debug.h>
32 #include <wolfssl/wolfcrypt/ecc.h>
33 #include <wolfssl/wolfcrypt/hash.h>
34 #include <wolfssl/wolfcrypt/asn.h>
36 typedef struct private_wolfssl_ec_public_key_t private_wolfssl_ec_public_key_t
;
39 * Private data structure with signing context.
41 struct private_wolfssl_ec_public_key_t
{
46 wolfssl_ec_public_key_t
public;
65 * Verification of a signature as in RFC 4754
67 static bool verify_signature(private_wolfssl_ec_public_key_t
*this,
68 chunk_t hash
, chunk_t signature
)
70 int stat
= 1, ret
= -1;
83 if (wolfssl_mp_split(signature
, &r
, &s
))
85 ret
= wc_ecc_verify_hash_ex(&r
, &s
, hash
.ptr
, hash
.len
, &stat
,
90 return ret
== 0 && stat
== 1;
94 * Verify a RFC 4754 signature for a specified curve and hash algorithm
96 static bool verify_curve_signature(private_wolfssl_ec_public_key_t
*this,
97 signature_scheme_t scheme
,
98 enum wc_HashType hash
, ecc_curve_id curve_id
,
99 chunk_t data
, chunk_t signature
)
101 bool success
= FALSE
;
104 if (curve_id
!= this->ec
.dp
->id
)
106 DBG1(DBG_LIB
, "signature scheme %N not supported by private key",
107 signature_scheme_names
, scheme
);
111 if (wolfssl_hash_chunk(hash
, data
, &dgst
))
113 success
= verify_signature(this, dgst
, signature
);
121 * Verification of a DER encoded signature as in RFC 3279
123 static bool verify_der_signature(private_wolfssl_ec_public_key_t
*this,
124 enum wc_HashType hash
, chunk_t data
,
128 int stat
= 1, ret
= -1;
130 signature
= chunk_skip_zero(signature
);
131 if (wolfssl_hash_chunk(hash
, data
, &dgst
))
133 ret
= wc_ecc_verify_hash(signature
.ptr
, signature
.len
, dgst
.ptr
,
134 dgst
.len
, &stat
, &this->ec
);
137 return ret
== 0 && stat
== 1;
140 METHOD(public_key_t
, get_type
, key_type_t
,
141 private_wolfssl_ec_public_key_t
*this)
146 METHOD(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
)
153 case SIGN_ECDSA_WITH_SHA1_DER
:
154 return verify_der_signature(this, WC_HASH_TYPE_SHA
, data
,
158 case SIGN_ECDSA_WITH_SHA256_DER
:
159 return verify_der_signature(this, WC_HASH_TYPE_SHA256
, data
,
162 #ifdef WOLFSSL_SHA384
163 case SIGN_ECDSA_WITH_SHA384_DER
:
164 return verify_der_signature(this, WC_HASH_TYPE_SHA384
, data
,
167 #ifdef WOLFSSL_SHA512
168 case SIGN_ECDSA_WITH_SHA512_DER
:
169 return verify_der_signature(this, WC_HASH_TYPE_SHA512
, data
,
172 case SIGN_ECDSA_WITH_NULL
:
173 return verify_signature(this, data
, signature
);
176 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA256
,
177 ECC_SECP256R1
, data
, signature
);
179 #ifdef WOLFSSL_SHA384
181 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA384
,
182 ECC_SECP384R1
, data
, signature
);
184 #ifdef WOLFSSL_SHA512
186 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA512
,
187 ECC_SECP521R1
, data
, signature
);
190 DBG1(DBG_LIB
, "signature scheme %N not supported via wolfssl",
191 signature_scheme_names
, scheme
);
196 METHOD(public_key_t
, encrypt
, bool,
197 private_wolfssl_ec_public_key_t
*this, encryption_scheme_t scheme
,
198 void *params
, chunk_t crypto
, chunk_t
*plain
)
200 DBG1(DBG_LIB
, "EC public key encryption not implemented");
204 METHOD(public_key_t
, get_keysize
, int,
205 private_wolfssl_ec_public_key_t
*this)
207 return this->keysize
;
211 * Calculate fingerprint from an EC key, also used in ec private key.
213 bool wolfssl_ec_fingerprint(ecc_key
*ec
, cred_encoding_type_t type
, chunk_t
*fp
)
219 if (lib
->encoding
->get_cache(lib
->encoding
, type
, ec
, fp
))
226 case KEYID_PUBKEY_SHA1
:
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
)
232 /* additional space for algorithmIdentifier/bitString */
233 len
+= 2 * MAX_SEQ_SZ
+ 2 * MAX_ALGO_SZ
+ TRAILING_ZERO
;
235 key
= chunk_alloca(len
);
236 len
= wc_EccPublicKeyToDer(ec
, key
.ptr
, key
.len
,
237 type
== KEYID_PUBKEY_INFO_SHA1
);
248 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
249 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
251 DBG1(DBG_LIB
, "SHA1 not supported, fingerprinting failed");
255 hasher
->destroy(hasher
);
256 lib
->encoding
->cache(lib
->encoding
, type
, ec
, *fp
);
260 METHOD(public_key_t
, get_fingerprint
, bool,
261 private_wolfssl_ec_public_key_t
*this, cred_encoding_type_t type
,
262 chunk_t
*fingerprint
)
264 return wolfssl_ec_fingerprint(&this->ec
, type
, fingerprint
);
267 METHOD(public_key_t
, get_encoding
, bool,
268 private_wolfssl_ec_public_key_t
*this, cred_encoding_type_t type
,
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);
280 chunk_free(encoding
);
285 if (type
!= PUBKEY_SPKI_ASN1_DER
)
287 chunk_t asn1_encoding
= *encoding
;
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
);
297 METHOD(public_key_t
, get_ref
, public_key_t
*,
298 private_wolfssl_ec_public_key_t
*this)
301 return &this->public.key
;
304 METHOD(public_key_t
, destroy
, void,
305 private_wolfssl_ec_public_key_t
*this)
307 if (ref_put(&this->ref
))
309 lib
->encoding
->clear_cache(lib
->encoding
, &this->ec
);
310 wc_ecc_free(&this->ec
);
316 * Generic private constructor
318 static private_wolfssl_ec_public_key_t
*create_empty()
320 private_wolfssl_ec_public_key_t
*this;
325 .get_type
= _get_type
,
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
,
340 if (wc_ecc_init(&this->ec
) < 0)
349 * Described in header
351 wolfssl_ec_public_key_t
*wolfssl_ec_public_key_load(key_type_t type
,
354 private_wolfssl_ec_public_key_t
*this;
355 chunk_t blob
= chunk_empty
;
361 switch (va_arg(args
, builder_part_t
))
363 case BUILD_BLOB_ASN1_DER
:
364 blob
= va_arg(args
, chunk_t
);
373 this = create_empty();
380 ret
= wc_EccPublicKeyDecode(blob
.ptr
, &idx
, &this->ec
, blob
.len
);
386 switch (this->ec
.dp
->id
)
400 return &this->public;
403 #endif /* HAVE_ECC_VERIFY */