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, static void dpp_copy_netaccesskey(struct dpp_authentication *auth,
struct dpp_config_obj *conf) struct dpp_config_obj *conf)
{ {
unsigned char *der = NULL; struct wpabuf *net_access_key;
int der_len;
EC_KEY *eckey;
struct crypto_ec_key *own_key; struct crypto_ec_key *own_key;
own_key = auth->own_protocol_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) auth->reconfig_old_protocol_key)
own_key = auth->reconfig_old_protocol_key; own_key = auth->reconfig_old_protocol_key;
#endif /* CONFIG_DPP2 */ #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; return;
der_len = i2d_ECPrivateKey(eckey, &der);
if (der_len <= 0) {
EC_KEY_free(eckey);
return;
}
wpabuf_free(auth->net_access_key); wpabuf_free(auth->net_access_key);
auth->net_access_key = wpabuf_alloc_copy(der, der_len); auth->net_access_key = net_access_key;
OPENSSL_free(der);
EC_KEY_free(eckey);
} }
@ -3410,23 +3402,19 @@ void dpp_configurator_free(struct dpp_configurator *conf)
int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf,
size_t buflen) size_t buflen)
{ {
EC_KEY *eckey; struct wpabuf *key;
int key_len, ret = -1; int ret = -1;
unsigned char *key = NULL;
if (!conf->csign) if (!conf->csign)
return -1; return -1;
eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) conf->csign); key = crypto_ec_key_get_ecprivate_key(conf->csign, true);
if (!eckey) if (!key)
return -1; return -1;
key_len = i2d_ECPrivateKey(eckey, &key); ret = wpa_snprintf_hex(buf, buflen, wpabuf_head(key), wpabuf_len(key));
if (key_len > 0)
ret = wpa_snprintf_hex(buf, buflen, key, key_len);
EC_KEY_free(eckey); wpabuf_clear_free(key);
OPENSSL_free(key);
return ret; return ret;
} }

View file

@ -19,21 +19,6 @@
#ifdef CONFIG_DPP2 #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) void dpp_free_asymmetric_key(struct dpp_asymmetric_key *key)
{ {
while (key) { while (key) {
@ -56,23 +41,13 @@ static struct wpabuf * dpp_build_conf_params(struct dpp_configurator *conf)
/* TODO: proper template values */ /* TODO: proper template values */
const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}"; const char *conf_template = "{\"wi-fi_tech\":\"infra\",\"discovery\":{\"ssid\":\"test\"},\"cred\":{\"akm\":\"dpp\"}}";
const char *connector_template = NULL; const char *connector_template = NULL;
EC_KEY *eckey;
unsigned char *der = NULL;
int der_len;
if (!conf->pp_key) if (!conf->pp_key)
return NULL; 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); priv_key = crypto_ec_key_get_ecprivate_key(conf->pp_key, false);
der_len = i2d_ECPrivateKey(eckey, &der);
if (der_len > 0)
priv_key = wpabuf_alloc_copy(der, der_len);
OPENSSL_free(der);
if (!priv_key) if (!priv_key)
goto fail; return NULL;
len = 100 + os_strlen(conf_template); len = 100 + os_strlen(conf_template);
if (connector_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) static struct wpabuf * dpp_build_key_pkg(struct dpp_authentication *auth)
{ {
struct wpabuf *key = NULL, *attr, *alg, *priv_key = NULL; 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); priv_key = crypto_ec_key_get_ecprivate_key(auth->conf->csign, false);
if (!eckey) if (!priv_key)
return NULL; 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); alg = dpp_build_key_alg(auth->conf->curve);
/* Attributes ::= SET OF Attribute { { OneAsymmetricKeyAttributes } } */ /* 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; size_t rlen;
char *txt; char *txt;
int res; int res;
unsigned char *der = NULL; struct wpabuf *der = NULL;
int der_len;
const EC_GROUP *group; const EC_GROUP *group;
const EC_POINT *point; const EC_POINT *point;
@ -214,19 +213,17 @@ void dpp_debug_print_key(const char *title, struct crypto_ec_key *key)
if (group && point) if (group && point)
dpp_debug_print_point(title, group, point); dpp_debug_print_point(title, group, point);
der_len = i2d_ECPrivateKey(eckey, &der); der = crypto_ec_key_get_ecprivate_key(key, true);
if (der_len > 0) if (der) {
wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); wpa_hexdump_buf_key(MSG_DEBUG, "DPP: ECPrivateKey", der);
OPENSSL_free(der); } else {
if (der_len <= 0) { der = crypto_ec_key_get_subject_public_key(key);
der = NULL; if (der)
der_len = i2d_EC_PUBKEY(eckey, &der); wpa_hexdump_buf_key(MSG_DEBUG, "DPP: EC_PUBKEY", der);
if (der_len > 0)
wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len);
OPENSSL_free(der);
} }
EC_KEY_free(eckey); 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; struct crypto_ec_key *key;
const EVP_MD *sign_md; const EVP_MD *sign_md;
unsigned int hash_len = auth->curve->hash_len; unsigned int hash_len = auth->curve->hash_len;
EC_KEY *eckey; struct wpabuf *priv_key;
BIO *out = NULL; BIO *out = NULL;
u8 cp[DPP_CP_LEN]; u8 cp[DPP_CP_LEN];
char *password; char *password;
@ -2689,18 +2686,11 @@ struct wpabuf * dpp_build_csr(struct dpp_authentication *auth, const char *name)
* a specific group to be used */ * a specific group to be used */
key = auth->own_protocol_key; key = auth->own_protocol_key;
eckey = EVP_PKEY_get1_EC_KEY((EVP_PKEY *) key); priv_key = crypto_ec_key_get_ecprivate_key(key, true);
if (!eckey) if (!priv_key)
goto fail;
der = NULL;
der_len = i2d_ECPrivateKey(eckey, &der);
if (der_len <= 0)
goto fail; goto fail;
wpabuf_free(auth->priv_key); wpabuf_free(auth->priv_key);
auth->priv_key = wpabuf_alloc_copy(der, der_len); auth->priv_key = priv_key;
OPENSSL_free(der);
if (!auth->priv_key)
goto fail;
req = X509_REQ_new(); req = X509_REQ_new();
if (!req || !X509_REQ_set_pubkey(req, (EVP_PKEY *) key)) 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); 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 * 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() * @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, struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data,
size_t len) size_t len)
{ {