]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DPP: Factorize conversion to ASN.1 ECPrivateKey
authorCedric Izoard <cedric.izoard@laposte.net>
Mon, 28 Jun 2021 16:25:22 +0000 (18:25 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 26 Oct 2021 14:08:39 +0000 (17:08 +0300)
Add crypto_ec_key_get_ecprivate_key() function in crypto.h and use it
when possible in DPP code.

This function converts a struct crypto_ec_key into a DER encoded ASN.1
ECPrivateKey.

Signed-off-by: Cedric Izoard <cedric.izoard@ceva-dsp.com>
src/common/dpp.c
src/common/dpp_backup.c
src/common/dpp_crypto.c
src/crypto/crypto.h
src/crypto/crypto_openssl.c

index 1245c58533bf4c4edb06604121fc64b832770482..787ceeaff34af67c25d77e573acf3af5241a5247 100644 (file)
@@ -2450,9 +2450,7 @@ static void dpp_copy_ppkey(struct dpp_config_obj *conf,
 static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
                                  struct dpp_config_obj *conf)
 {
-       unsigned char *der = NULL;
-       int der_len;
-       EC_KEY *eckey;
+       struct wpabuf *net_access_key;
        struct crypto_ec_key *own_key;
 
        own_key = auth->own_protocol_key;
@@ -2461,19 +2459,13 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
            auth->reconfig_old_protocol_key)
                own_key = auth->reconfig_old_protocol_key;
 #endif /* CONFIG_DPP2 */
-       eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) own_key);
-       if (!eckey)
-               return;
 
-       der_len = i2d_ECPrivateKey(eckey, &der);
-       if (der_len <= 0) {
-               EC_KEY_free(eckey);
+       net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
+       if (!net_access_key)
                return;
-       }
+
        wpabuf_free(auth->net_access_key);
-       auth->net_access_key = wpabuf_alloc_copy(der, der_len);
-       OPENSSL_free(der);
-       EC_KEY_free(eckey);
+       auth->net_access_key = net_access_key;
 }
 
 
@@ -3410,23 +3402,19 @@ void dpp_configurator_free(struct dpp_configurator *conf)
 int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
                             size_t buflen)
 {
-       EC_KEY *eckey;
-       int key_len, ret = -1;
-       unsigned char *key = NULL;
+       struct wpabuf *key;
+       int ret = -1;
 
        if (!conf->csign)
                return -1;
 
-       eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) conf->csign);
-       if (!eckey)
+       key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
+       if (!key)
                return -1;
 
-       key_len = i2d_ECPrivateKey(eckey, &key);
-       if (key_len > 0)
-               ret = wpa_snprintf_hex(buf, buflen, key, key_len);
+       ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
 
-       EC_KEY_free(eckey);
-       OPENSSL_free(key);
+       wpabuf_clear_free(key);
        return ret;
 }
 
index dac1601db93aac3c9e6743c47cb2ed34f4d0beef..836e70e672f4670359d3906e9ce7dc37fc3e0ce7 100644 (file)
 
 #ifdef CONFIG_DPP2
 
-#if OPENSSL_VERSION_NUMBER < 0x10100000L || \
-       (defined(LIBRESSL_VERSION_NUMBER) && \
-        LIBRESSL_VERSION_NUMBER < 0x20700000L)
-/* Compatibility wrappers for older versions. */
-
-static EC_KEY * EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
-{
-       if (pkey->type != EVP_PKEY_EC)
-               return NULL;
-       return pkey->pkey.ec;
-}
-
-#endif
-
-
 void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
 {
        while (key) {
@@ -56,23 +41,13 @@ static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf)
        /* TODO: proper template values */
        const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
        const char *connector_template = NULL;
-       EC_KEY *eckey;
-       unsigned char *der = NULL;
-       int der_len;
 
        if (!conf->pp_key)
                return NULL;
-       eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) conf->pp_key);
-       if (!eckey)
-               return NULL;
 
-       EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
-       der_len = i2d_ECPrivateKey(eckey, &der);
-       if (der_len > 0)
-               priv_key = wpabuf_alloc_copy(der, der_len);
-       OPENSSL_free(der);
+       priv_key = crypto_ec_key_get_ecprivate_key(conf->pp_key, false);
        if (!priv_key)
-               goto fail;
+               return NULL;
 
        len = 100 + os_strlen(conf_template);
        if (connector_template)
@@ -178,20 +153,11 @@ static struct wpabuf * dpp_build_key_alg(const struct dpp_curve_params *curve)
 static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
 {
        struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL;
-       EC_KEY *eckey;
-       unsigned char *der = NULL;
-       int der_len;
 
-       eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) auth->conf->csign);
-       if (!eckey)
+       priv_key = crypto_ec_key_get_ecprivate_key(auth->conf->csign, false);
+       if (!priv_key)
                return NULL;
 
-       EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
-       der_len = i2d_ECPrivateKey(eckey, &der);
-       if (der_len > 0)
-               priv_key = wpabuf_alloc_copy(der, der_len);
-       OPENSSL_free(der);
-
        alg = dpp_build_key_alg(auth->conf->curve);
 
        /* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */
index 8d9fc5a5976cc2df1b88bb85c5b47b1f18fe5566..c4adc2d4fcbd1adec7cd4845cd7202382cf46f21 100644 (file)
@@ -183,8 +183,7 @@ void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
        size_t rlen;
        char *txt;
        int res;
-       unsigned char *der = NULL;
-       int der_len;
+       struct wpabuf *der = NULL;
        const EC_GROUP *group;
        const EC_POINT *point;
 
@@ -214,19 +213,17 @@ void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
        if (group && point)
                dpp_debug_print_point(title, group, point);
 
-       der_len = i2d_ECPrivateKey(eckey, &der);
-       if (der_len > 0)
-               wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len);
-       OPENSSL_free(der);
-       if (der_len <= 0) {
-               der = NULL;
-               der_len = i2d_EC_PUBKEY(eckey, &der);
-               if (der_len > 0)
-                       wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
-               OPENSSL_free(der);
+       der = crypto_ec_key_get_ecprivate_key(key, true);
+       if (der) {
+               wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
+       } else {
+               der = crypto_ec_key_get_subject_public_key(key);
+               if (der)
+                       wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
        }
 
        EC_KEY_free(eckey);
+       wpabuf_clear_free(der);
 }
 
 
@@ -2676,7 +2673,7 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
        struct crypto_ec_key *key;
        const EVP_MD *sign_md;
        unsigned int hash_len = auth->curve->hash_len;
-       EC_KEY *eckey;
+       struct wpabuf *priv_key;
        BIO *out = NULL;
        u8 cp[DPP_CP_LEN];
        char *password;
@@ -2689,18 +2686,11 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
         * a specific group to be used */
        key = auth->own_protocol_key;
 
-       eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key);
-       if (!eckey)
-               goto fail;
-       der = NULL;
-       der_len = i2d_ECPrivateKey(eckey, &der);
-       if (der_len <= 0)
+       priv_key = crypto_ec_key_get_ecprivate_key(key, true);
+       if (!priv_key)
                goto fail;
        wpabuf_free(auth->priv_key);
-       auth->priv_key = wpabuf_alloc_copy(der, der_len);
-       OPENSSL_free(der);
-       if (!auth->priv_key)
-               goto fail;
+       auth->priv_key = priv_key;
 
        req = X509_REQ_new();
        if (!req || !X509_REQ_set_pubkey(req, (EVP_PKEY *) key))
index 449b11525c007272da99be3eaa83f29ed39e3239..cae99db76db76da8208395beb68e0467f1a64b8c 100644 (file)
@@ -1014,6 +1014,15 @@ void crypto_ec_key_deinit(struct crypto_ec_key *key);
  */
 struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key);
 
+/**
+ * crypto_ec_key_get_ecprivate_key - Get ECPrivateKey ASN.1 for a EC key
+ * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen()
+ * @include_pub: Whether to include public key in the ASN.1 sequence
+ * Returns: Buffer with DER encoding of ASN.1 ECPrivateKey or %NULL on failure
+ */
+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
+                                               bool include_pub);
+
 /**
  * crypto_ec_key_sign - Sign a buffer with an EC key
  * @key: EC key from crypto_ec_key_parse_priv() or crypto_ec_key_gen()
index dd70ffc9a26217df23ca2d0fd94e756d8131b5ab..128142b70dcd7f7c90fbb9cdef95817ec267ece4 100644 (file)
@@ -2318,6 +2318,34 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
 }
 
 
+struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
+                                               bool include_pub)
+{
+       EC_KEY *eckey;
+       unsigned char *der = NULL;
+       int der_len;
+       struct wpabuf *buf;
+
+       eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
+       if (!eckey)
+               return NULL;
+
+       if (include_pub)
+               EC_KEY_clear_flags(eckey, EC_PKEY_NO_PUBKEY);
+       else
+               EC_KEY_set_enc_flags(eckey, EC_PKEY_NO_PUBKEY);
+
+       EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED);
+
+       der_len = i2d_ECPrivateKey(eckey, &der);
+       if (der_len <= 0)
+               return NULL;
+       buf = wpabuf_alloc_copy(der, der_len);
+       OPENSSL_free(der);
+       return buf;
+}
+
+
 struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
                                   size_t len)
 {