DPP: Factorize conversion to ASN.1 ECPrivateKey

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>
This commit is contained in:
Cedric Izoard 2021-06-28 18:25:22 +02:00 committed by Jouni Malinen
parent 63bf3d25ab
commit 2d5772e691
5 changed files with 65 additions and 84 deletions

View 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)
net_access_key = crypto_ec_key_get_ecprivate_key(own_key, true);
if (!net_access_key)
return;
der_len = i2d_ECPrivateKey(eckey, &der);
if (der_len <= 0) {
EC_KEY_free(eckey);
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;
}

View file

@ -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 } } */

View 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))

View 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()

View 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)
{