]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
wolfSSL: Implement crypto_ec_key wrappers
authorJuliusz Sosinowicz <juliusz@wolfssl.com>
Mon, 25 Apr 2022 14:18:15 +0000 (16:18 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 1 May 2022 14:01:34 +0000 (17:01 +0300)
These are needed to support SAEK-PK with the wolfSSL backend.

Signed-off-by: Juliusz Sosinowicz <juliusz@wolfssl.com>
src/crypto/crypto_wolfssl.c

index 546f1288292c667a52a945934002f50c9f807395..88aad3eb29edf81d03e2a553444b1864d1868bd4 100644 (file)
@@ -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 */