[PATCH 05/21] dpp: factorize conversion to ASN.1 ECPrivateKey

Cedric Izoard cedric.izoard at ceva-dsp.com
Mon Jun 28 09:25:22 PDT 2021


From: Cedric Izoard <cedric.izoard at laposte.net>

Add crypto_ec_key_get_ecprivate_key function in crypto.h and use it
when possible in DPP code.

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

Signed-off-by: Cedric Izoard <cedric.izoard at ceva-dsp.com>
---
 src/common/dpp.c            | 34 ++++++++++--------------------
 src/common/dpp_backup.c     | 42 ++++---------------------------------
 src/common/dpp_crypto.c     | 37 +++++++++++++-------------------
 src/crypto/crypto.h         |  9 ++++++++
 src/crypto/crypto_openssl.c | 29 +++++++++++++++++++++++++
 5 files changed, 67 insertions(+), 84 deletions(-)

diff --git a/src/common/dpp.c b/src/common/dpp.c
index 14783ba74..f85eb2d4d 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -2446,9 +2446,7 @@ static void dpp_copy_ppkey(struct dpp_config_obj *conf, struct crypto_ec_key *pp
 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;
@@ -2457,19 +2455,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;
 }
 
 
@@ -3406,23 +3398,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;
 }
 
diff --git a/src/common/dpp_backup.c b/src/common/dpp_backup.c
index 1e03e0fb9..65fe12afc 100644
--- a/src/common/dpp_backup.c
+++ b/src/common/dpp_backup.c
@@ -19,21 +19,6 @@
 
 #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 } } */
diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
index 5e4d213ac..222d15368 100644
--- a/src/common/dpp_crypto.c
+++ b/src/common/dpp_crypto.c
@@ -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,18 @@ 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);
 }
 
 
@@ -2669,7 +2667,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;
@@ -2682,18 +2680,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))
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index 382b34622..b4e3ae530 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -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()
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 648c1cbf6..a10746f41 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -2334,6 +2334,35 @@ 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 = NULL;
+	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)
 {
-- 
2.17.0




More information about the Hostap mailing list