wolfSSL: Implement crypto_ec_key wrappers
These are needed to support SAEK-PK with the wolfSSL backend. Signed-off-by: Juliusz Sosinowicz <juliusz@wolfssl.com>
This commit is contained in:
parent
1f7e10177a
commit
8f36e6c0f4
1 changed files with 258 additions and 0 deletions
|
@ -26,6 +26,7 @@
|
|||
#include <wolfssl/wolfcrypt/dh.h>
|
||||
#include <wolfssl/wolfcrypt/cmac.h>
|
||||
#include <wolfssl/wolfcrypt/ecc.h>
|
||||
#include <wolfssl/wolfcrypt/asn_public.h>
|
||||
#include <wolfssl/openssl/bn.h>
|
||||
|
||||
|
||||
|
@ -1835,6 +1836,263 @@ size_t crypto_ecdh_prime_len(struct crypto_ecdh *ecdh)
|
|||
return crypto_ec_prime_len(ecdh->ec);
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_key {
|
||||
ecc_key *eckey;
|
||||
WC_RNG *rng; /* Needs to be initialized before use.
|
||||
* *NOT* initialized in crypto_ec_key_init */
|
||||
};
|
||||
|
||||
|
||||
static struct crypto_ec_key * crypto_ec_key_init(void)
|
||||
{
|
||||
struct crypto_ec_key *key;
|
||||
|
||||
key = os_zalloc(sizeof(struct crypto_ec_key));
|
||||
if (key) {
|
||||
#ifdef CONFIG_FIPS
|
||||
key->eckey = os_zalloc(sizeof(ecc_key));
|
||||
#else /* CONFIG_FIPS */
|
||||
key->eckey = wc_ecc_key_new(NULL);
|
||||
#endif /* CONFIG_FIPS */
|
||||
/* Omit key->rng initialization because it seeds itself and thus
|
||||
* consumes entropy that may never be used. Lazy initialize when
|
||||
* necessary. */
|
||||
if (!key->eckey) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"wolfSSL: crypto_ec_key_init() failed");
|
||||
crypto_ec_key_deinit(key);
|
||||
key = NULL;
|
||||
}
|
||||
#ifdef CONFIG_FIPS
|
||||
else if (wc_ecc_init_ex(key->eckey, NULL, INVALID_DEVID) != 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_init_ex failed");
|
||||
crypto_ec_key_deinit(key);
|
||||
key = NULL;
|
||||
}
|
||||
#endif /* CONFIG_FIPS */
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
void crypto_ec_key_deinit(struct crypto_ec_key *key)
|
||||
{
|
||||
if (key) {
|
||||
#ifdef CONFIG_FIPS
|
||||
os_free(key->rng);
|
||||
os_free(key->eckey);
|
||||
#else /* CONFIG_FIPS */
|
||||
wc_rng_free(key->rng);
|
||||
wc_ecc_key_free(key->eckey);
|
||||
#endif /* CONFIG_FIPS */
|
||||
os_free(key);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len)
|
||||
{
|
||||
struct crypto_ec_key *ret;
|
||||
word32 idx = 0;
|
||||
|
||||
ret = crypto_ec_key_init();
|
||||
if (!ret) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: crypto_ec_key_init failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (wc_EccPrivateKeyDecode(der, &idx, ret->eckey, (word32) der_len) !=
|
||||
0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPrivateKeyDecode failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
if (ret)
|
||||
crypto_ec_key_deinit(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_ec_key_group(struct crypto_ec_key *key)
|
||||
{
|
||||
|
||||
if (!key || !key->eckey || !key->eckey->dp) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: %s: invalid input parameters",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (key->eckey->dp->id) {
|
||||
case ECC_SECP256R1:
|
||||
return 19;
|
||||
case ECC_SECP384R1:
|
||||
return 20;
|
||||
case ECC_SECP521R1:
|
||||
return 21;
|
||||
case ECC_BRAINPOOLP256R1:
|
||||
return 28;
|
||||
case ECC_BRAINPOOLP384R1:
|
||||
return 29;
|
||||
case ECC_BRAINPOOLP512R1:
|
||||
return 30;
|
||||
}
|
||||
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: Unsupported curve (id=%d) in EC key",
|
||||
key->eckey->dp->id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
|
||||
{
|
||||
byte *der = NULL;
|
||||
int der_len;
|
||||
struct wpabuf *ret = NULL;
|
||||
|
||||
if (!key || !key->eckey) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: %s: invalid input parameters",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
der_len = wc_EccPublicKeyDerSize(key->eckey, 1);
|
||||
if (der_len <= 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyDerSize failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
der = os_malloc(der_len);
|
||||
if (!der)
|
||||
goto fail;
|
||||
|
||||
der_len = wc_EccPublicKeyToDer(key->eckey, der, der_len, 1);
|
||||
if (der_len <= 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyToDer failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = wpabuf_alloc_copy(der, der_len);
|
||||
os_free(der);
|
||||
return ret;
|
||||
|
||||
fail:
|
||||
os_free(der);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
|
||||
{
|
||||
word32 idx = 0;
|
||||
struct crypto_ec_key *ret = NULL;
|
||||
|
||||
ret = crypto_ec_key_init();
|
||||
if (!ret) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: crypto_ec_key_init failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (wc_EccPublicKeyDecode(der, &idx, ret->eckey, (word32) der_len) != 0)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_EccPublicKeyDecode failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return ret;
|
||||
fail:
|
||||
crypto_ec_key_deinit(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
|
||||
size_t len)
|
||||
{
|
||||
byte *der = NULL;
|
||||
int der_len;
|
||||
word32 w32_der_len;
|
||||
struct wpabuf *ret = NULL;
|
||||
|
||||
if (!key || !key->eckey || !data || len == 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: %s: invalid input parameters",
|
||||
__func__);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!key->rng) {
|
||||
/* Lazy init key->rng */
|
||||
#ifdef CONFIG_FIPS
|
||||
key->rng = os_zalloc(sizeof(WC_RNG));
|
||||
#else /* CONFIG_FIPS */
|
||||
key->rng = wc_rng_new(NULL, 0, NULL);
|
||||
#endif /* CONFIG_FIPS */
|
||||
if (!key->rng) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_rng_new failed");
|
||||
goto fail;
|
||||
}
|
||||
#ifdef CONFIG_FIPS
|
||||
if (wc_InitRng(key->rng) != 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_InitRng failed");
|
||||
goto fail;
|
||||
}
|
||||
#endif /* CONFIG_FIPS */
|
||||
}
|
||||
|
||||
der_len = wc_ecc_sig_size(key->eckey);
|
||||
if (der_len <= 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_sig_size failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
der = os_malloc(der_len);
|
||||
if (!der)
|
||||
goto fail;
|
||||
|
||||
w32_der_len = (word32) der_len;
|
||||
if (wc_ecc_sign_hash(data, len, der, &w32_der_len, key->rng, key->eckey)
|
||||
!= 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_sign_hash failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = wpabuf_alloc_copy(der, der_len);
|
||||
os_free(der);
|
||||
if (!ret)
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wpabuf_alloc_copy failed");
|
||||
return ret;
|
||||
fail:
|
||||
os_free(der);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data,
|
||||
size_t len, const u8 *sig, size_t sig_len)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (!key || !key->eckey || !data || len == 0 || !sig || sig_len == 0) {
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: %s: invalid input parameters",
|
||||
__func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wc_ecc_verify_hash(sig, sig_len, data, len, &res, key->eckey) != 0)
|
||||
{
|
||||
wpa_printf(MSG_ERROR, "wolfSSL: wc_ecc_verify_hash failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res != 1)
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"wolfSSL: crypto_ec_key_verify_signature failed");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ECC */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue