[PATCH 3/4] DPP: replace dpp_bootstrap_key_der with crypto_ec_key_get_subject_public_key

Cedric Izoard cedric.izoard at ceva-dsp.com
Fri Oct 29 02:05:32 PDT 2021


From: "(4401 440) Cedric Izoard (France)" <cedric.izoard at ceva-dsp.com>

As BoringSSL version of i2d_PUBKEY doesn't respect the
POINT_CONVERSION_COMPRESSED flag redefine specific
crypto_ec_key_get_subject_public_key version for BoringSSL (based on
dpp_bootstrap_key_der)

The only other "user" of crypto_ec_key_get_subject_public_key is SAE
PK for which Public Key should also be formatted using compressed
format.

Signed-off-by: Cedric Izoard <cedric.izoard at ceva-dsp.com>
---
 src/common/dpp.c            |  2 -
 src/common/dpp_crypto.c     | 89 +-----------------------------------
 src/crypto/crypto_openssl.c | 91 ++++++++++++++++++++++++++++++++++++-
 tests/hwsim/test_dpp.py     |  2 +-
 4 files changed, 93 insertions(+), 91 deletions(-)

diff --git a/src/common/dpp.c b/src/common/dpp.c
index 63189c169..1fd074f05 100644
--- a/src/common/dpp.c
+++ b/src/common/dpp.c
@@ -8,8 +8,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/evp.h>
-#include <openssl/x509.h>
 
 #include "utils/common.h"
 #include "utils/base64.h"
diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c
index 77782b9e2..964a27ef9 100644
--- a/src/common/dpp_crypto.c
+++ b/src/common/dpp_crypto.c
@@ -8,10 +8,6 @@
  */
 
 #include "utils/includes.h"
-#include <openssl/err.h>
-#include <openssl/asn1.h>
-#include <openssl/asn1t.h>
-#include <openssl/pem.h>
 
 #include "utils/common.h"
 #include "utils/base64.h"
@@ -295,93 +291,12 @@ struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve,
 }
 
 
-typedef struct {
-	/* AlgorithmIdentifier ecPublicKey with optional parameters present
-	 * as an OID identifying the curve */
-	X509_ALGOR *alg;
-	/* Compressed format public key per ANSI X9.63 */
-	ASN1_BIT_STRING *pub_key;
-} DPP_BOOTSTRAPPING_KEY;
-
-ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = {
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR),
-	ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING)
-} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY);
-
-IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY);
-
-
-static struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key)
-{
-	unsigned char *der = NULL;
-	int der_len;
-	const EC_KEY *eckey;
-	struct wpabuf *ret = NULL;
-	size_t len;
-	const EC_GROUP *group;
-	const EC_POINT *point;
-	BN_CTX *ctx;
-	DPP_BOOTSTRAPPING_KEY *bootstrap = NULL;
-	int nid;
-
-	ctx = BN_CTX_new();
-	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) key);
-	if (!ctx || !eckey)
-		goto fail;
-
-	group = EC_KEY_get0_group(eckey);
-	point = EC_KEY_get0_public_key(eckey);
-	if (!group || !point)
-		goto fail;
-	nid = EC_GROUP_get_curve_name(group);
-
-	bootstrap = DPP_BOOTSTRAPPING_KEY_new();
-	if (!bootstrap ||
-	    X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC),
-			    V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
-		goto fail;
-
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 NULL, 0, ctx);
-	if (len == 0)
-		goto fail;
-
-	der = OPENSSL_malloc(len);
-	if (!der)
-		goto fail;
-	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
-				 der, len, ctx);
-
-	OPENSSL_free(bootstrap->pub_key->data);
-	bootstrap->pub_key->data = der;
-	der = NULL;
-	bootstrap->pub_key->length = len;
-	/* No unused bits */
-	bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
-	bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
-
-	der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der);
-	if (der_len <= 0) {
-		wpa_printf(MSG_ERROR,
-			   "DDP: Failed to build DER encoded public key");
-		goto fail;
-	}
-
-	ret = wpabuf_alloc_copy(der, der_len);
-fail:
-	DPP_BOOTSTRAPPING_KEY_free(bootstrap);
-	OPENSSL_free(der);
-	BN_CTX_free(ctx);
-	return ret;
-}
-
-
 int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi)
 {
 	struct wpabuf *der;
 	int res;
 
-	der = dpp_bootstrap_key_der(bi->pubkey);
+	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
 	if (!der)
 		return -1;
 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
@@ -416,7 +331,7 @@ int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve,
 		goto fail;
 	bi->own = 1;
 
-	der = dpp_bootstrap_key_der(bi->pubkey);
+	der = crypto_ec_key_get_subject_public_key(bi->pubkey);
 	if (!der)
 		goto fail;
 	wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)",
diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c
index 4cd99978b..30ea36d75 100644
--- a/src/crypto/crypto_openssl.c
+++ b/src/crypto/crypto_openssl.c
@@ -2502,13 +2502,102 @@ void crypto_ec_key_deinit(struct crypto_ec_key *key)
 	EVP_PKEY_free((EVP_PKEY *) key);
 }
 
+#ifdef OPENSSL_IS_BORINGSSL
+/* BoringSSL version of i2d_PUBKEY always output public EC key using
+ * uncompressed form so define, as such define a custom function to
+ * export EC pubkey using compressed format */
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+typedef struct {
+	/* AlgorithmIdentifier ecPublicKey with optional parameters present
+	 * as an OID identifying the curve */
+	X509_ALGOR *alg;
+	/* Compressed format public key per ANSI X9.63 */
+	ASN1_BIT_STRING *pub_key;
+} EC_COMP_PUBKEY;
+
+ASN1_SEQUENCE(EC_COMP_PUBKEY) = {
+	ASN1_SIMPLE(EC_COMP_PUBKEY, alg, X509_ALGOR),
+	ASN1_SIMPLE(EC_COMP_PUBKEY, pub_key, ASN1_BIT_STRING)
+} ASN1_SEQUENCE_END(EC_COMP_PUBKEY);
+
+IMPLEMENT_ASN1_FUNCTIONS(EC_COMP_PUBKEY);
 
+struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
+{
+	unsigned char *der = NULL;
+	int der_len;
+	const EC_KEY *eckey;
+	struct wpabuf *ret = NULL;
+	size_t len;
+	const EC_GROUP *group;
+	const EC_POINT *point;
+	BN_CTX *ctx;
+	EC_COMP_PUBKEY *pubkey = NULL;
+	int nid;
+
+	ctx = BN_CTX_new();
+	eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *)key);
+	if (!ctx || !eckey)
+		goto fail;
+
+	group = EC_KEY_get0_group(eckey);
+	point = EC_KEY_get0_public_key(eckey);
+	if (!group || !point)
+		goto fail;
+	nid = EC_GROUP_get_curve_name(group);
+
+	pubkey = EC_COMP_PUBKEY_new();
+	if (!pubkey ||
+	    X509_ALGOR_set0(pubkey->alg, OBJ_nid2obj(EVP_PKEY_EC),
+			    V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1)
+		goto fail;
+
+	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
+				 NULL, 0, ctx);
+	if (len == 0)
+		goto fail;
+
+	der = OPENSSL_malloc(len);
+	if (!der)
+		goto fail;
+	len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED,
+				 der, len, ctx);
+
+	OPENSSL_free(pubkey->pub_key->data);
+	pubkey->pub_key->data = der;
+	der = NULL;
+	pubkey->pub_key->length = len;
+	/* No unused bits */
+	pubkey->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
+	pubkey->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
+
+	der_len = i2d_EC_COMP_PUBKEY(pubkey, &der);
+	if (der_len <= 0) {
+		wpa_printf(MSG_ERROR,
+			   "DDP: Failed to build DER encoded public key");
+		goto fail;
+	}
+
+	ret = wpabuf_alloc_copy(der, der_len);
+fail:
+	EC_COMP_PUBKEY_free(pubkey);
+	OPENSSL_free(der);
+	BN_CTX_free(ctx);
+	return ret;
+}
+
+#else
 struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
 {
 	unsigned char *der = NULL;
 	int der_len;
 	struct wpabuf *buf;
 
+	/* For now, all users expect COMPRESSED form */
+	EC_KEY_set_conv_form(EVP_PKEY_get0_EC_KEY((EVP_PKEY *)key),
+			     POINT_CONVERSION_COMPRESSED);
+
 	der_len = i2d_PUBKEY((EVP_PKEY *) key, &der);
 	if (der_len <= 0) {
 		wpa_printf(MSG_INFO, "OpenSSL: i2d_PUBKEY() failed: %s",
@@ -2520,7 +2609,7 @@ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key)
 	OPENSSL_free(der);
 	return buf;
 }
-
+#endif /* OPENSSL_IS_BORINGSSL */
 
 struct wpabuf * crypto_ec_key_get_ecprivate_key(struct crypto_ec_key *key,
 						bool include_pub)
diff --git a/tests/hwsim/test_dpp.py b/tests/hwsim/test_dpp.py
index 558f882cd..efcdb318c 100644
--- a/tests/hwsim/test_dpp.py
+++ b/tests/hwsim/test_dpp.py
@@ -214,7 +214,7 @@ def test_dpp_qr_code_keygen_fail(dev, apdev):
     """DPP QR Code and keygen failure"""
     check_dpp_capab(dev[0])
 
-    with alloc_fail(dev[0], 1, "dpp_bootstrap_key_der;dpp_keygen"):
+    with alloc_fail(dev[0], 1, "crypto_ec_key_get_subject_public_key;dpp_keygen"):
         if "FAIL" not in dev[0].request("DPP_BOOTSTRAP_GEN type=qrcode"):
             raise Exception("Failure not reported")
 
-- 
2.25.1




More information about the Hostap mailing list