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>
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
{
43 * Public interface for this signer.
45 wolfssl_ec_public_key_t
public;
64 * Verification of a signature as in RFC 4754
66 static bool verify_signature(private_wolfssl_ec_public_key_t
*this,
67 chunk_t hash
, chunk_t signature
)
83 if (wolfssl_mp_split(signature
, &r
, &s
))
85 ret
= wc_ecc_verify_hash_ex(&r
, &s
, hash
.ptr
, hash
.len
, &stat
,
92 return ret
== 0 && stat
== 1;
96 * Verify a RFC 4754 signature for a specified curve and hash algorithm
98 static bool verify_curve_signature(private_wolfssl_ec_public_key_t
*this,
99 signature_scheme_t scheme
, enum wc_HashType hash
, ecc_curve_id curve_id
,
100 chunk_t data
, chunk_t signature
)
102 bool success
= FALSE
;
105 if (curve_id
!= this->ec
.dp
->id
)
107 DBG1(DBG_LIB
, "signature scheme %N not supported by private key",
108 signature_scheme_names
, scheme
);
112 if (wolfssl_hash_chunk(hash
, data
, &dgst
))
114 success
= verify_signature(this, dgst
, signature
);
122 * Verification of a DER encoded signature as in RFC 3279
124 static bool verify_der_signature(private_wolfssl_ec_public_key_t
*this,
125 enum wc_HashType hash
, chunk_t data
, chunk_t signature
)
127 bool success
= FALSE
;
132 /* remove any preceding 0-bytes from signature */
133 while (signature
.len
&& signature
.ptr
[0] == 0x00)
135 signature
= chunk_skip(signature
, 1);
137 if (wolfssl_hash_chunk(hash
, data
, &dgst
))
139 ret
= wc_ecc_verify_hash(signature
.ptr
, signature
.len
, dgst
.ptr
,
140 dgst
.len
, &stat
, &this->ec
);
141 if (ret
== 0 && stat
== 1)
151 METHOD(public_key_t
, get_type
, key_type_t
,
152 private_wolfssl_ec_public_key_t
*this)
157 METHOD(public_key_t
, verify
, bool,
158 private_wolfssl_ec_public_key_t
*this, signature_scheme_t scheme
,
159 void *params
, chunk_t data
, chunk_t signature
)
164 case SIGN_ECDSA_WITH_SHA1_DER
:
165 return verify_der_signature(this, WC_HASH_TYPE_SHA
, data
,
169 case SIGN_ECDSA_WITH_SHA256_DER
:
170 return verify_der_signature(this, WC_HASH_TYPE_SHA256
, data
,
173 #ifdef WOLFSSL_SHA384
174 case SIGN_ECDSA_WITH_SHA384_DER
:
175 return verify_der_signature(this, WC_HASH_TYPE_SHA384
, data
,
178 #ifdef WOLFSSL_SHA512
179 case SIGN_ECDSA_WITH_SHA512_DER
:
180 return verify_der_signature(this, WC_HASH_TYPE_SHA512
, data
,
183 case SIGN_ECDSA_WITH_NULL
:
184 return verify_signature(this, data
, signature
);
187 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA256
,
188 ECC_SECP256R1
, data
, signature
);
190 #ifdef WOLFSSL_SHA384
192 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA384
,
193 ECC_SECP384R1
, data
, signature
);
195 #ifdef WOLFSSL_SHA512
197 return verify_curve_signature(this, scheme
, WC_HASH_TYPE_SHA512
,
198 ECC_SECP521R1
, data
, signature
);
201 DBG1(DBG_LIB
, "signature scheme %N not supported in EC",
202 signature_scheme_names
, scheme
);
207 METHOD(public_key_t
, encrypt
, bool,
208 private_wolfssl_ec_public_key_t
*this, encryption_scheme_t scheme
,
209 chunk_t crypto
, chunk_t
*plain
)
211 DBG1(DBG_LIB
, "EC public key encryption not implemented");
215 METHOD(public_key_t
, get_keysize
, int,
216 private_wolfssl_ec_public_key_t
*this)
218 return this->keysize
;
222 * Calculate fingerprint from a EC_KEY, also used in ec private key.
224 bool wolfssl_ec_fingerprint(ecc_key
*ec
, cred_encoding_type_t type
, chunk_t
*fp
)
231 if (lib
->encoding
->get_cache(lib
->encoding
, type
, ec
, fp
))
236 key
= chunk_alloc(ec
->dp
->size
* 4 + 30);
237 ret
= wc_EccPublicKeyToDer(ec
, key
.ptr
, key
.len
, 1);
247 case KEYID_PUBKEY_SHA1
:
250 success
= lib
->encoding
->encode(lib
->encoding
, type
, ec
, fp
,
251 CRED_PART_ECDSA_PUB_ASN1_DER
, key
,
257 hasher
= lib
->crypto
->create_hasher(lib
->crypto
, HASH_SHA1
);
258 if (!hasher
|| !hasher
->allocate_hash(hasher
, key
, fp
))
260 DBG1(DBG_LIB
, "SHA1 hash algorithm not supported, fingerprinting failed");
265 hasher
->destroy(hasher
);
267 lib
->encoding
->cache(lib
->encoding
, type
, ec
, *fp
);
271 METHOD(public_key_t
, get_fingerprint
, bool,
272 private_wolfssl_ec_public_key_t
*this, cred_encoding_type_t type
,
273 chunk_t
*fingerprint
)
275 return wolfssl_ec_fingerprint(&this->ec
, type
, fingerprint
);
278 METHOD(public_key_t
, get_encoding
, bool,
279 private_wolfssl_ec_public_key_t
*this, cred_encoding_type_t type
,
285 *encoding
= chunk_alloc(this->ec
.dp
->size
* 2 + 30);
286 ret
= wc_EccPublicKeyToDer(&this->ec
, encoding
->ptr
, encoding
->len
, 1);
289 chunk_free(encoding
);
294 if (type
!= PUBKEY_ASN1_DER
)
296 chunk_t asn1_encoding
= *encoding
;
298 success
= lib
->encoding
->encode(lib
->encoding
, type
,
299 NULL
, encoding
, CRED_PART_ECDSA_PUB_ASN1_DER
,
300 asn1_encoding
, CRED_PART_END
);
301 chunk_clear(&asn1_encoding
);
306 METHOD(public_key_t
, get_ref
, public_key_t
*,
307 private_wolfssl_ec_public_key_t
*this)
310 return &this->public.key
;
313 METHOD(public_key_t
, destroy
, void,
314 private_wolfssl_ec_public_key_t
*this)
316 if (ref_put(&this->ref
))
318 lib
->encoding
->clear_cache(lib
->encoding
, &this->ec
);
319 wc_ecc_free(&this->ec
);
325 * Generic private constructor
327 static private_wolfssl_ec_public_key_t
*create_empty()
329 private_wolfssl_ec_public_key_t
*this;
334 .get_type
= _get_type
,
337 .get_keysize
= _get_keysize
,
338 .equals
= public_key_equals
,
339 .get_fingerprint
= _get_fingerprint
,
340 .has_fingerprint
= public_key_has_fingerprint
,
341 .get_encoding
= _get_encoding
,
349 if (wc_ecc_init(&this->ec
) < 0)
361 wolfssl_ec_public_key_t
*wolfssl_ec_public_key_load(key_type_t type
,
364 private_wolfssl_ec_public_key_t
*this;
365 chunk_t blob
= chunk_empty
;
369 if (type
!= KEY_ECDSA
)
376 switch (va_arg(args
, builder_part_t
))
378 case BUILD_BLOB_ASN1_DER
:
379 blob
= va_arg(args
, chunk_t
);
388 this = create_empty();
390 ret
= wc_EccPublicKeyDecode(blob
.ptr
, &idx
, &this->ec
, blob
.len
);
396 switch (this->ec
.dp
->id
)
410 return &this->public;
412 #endif /* HAVE_ECC_VERIFY */