diff --git a/src/common/dpp.c b/src/common/dpp.c index 2d944f088..bb3b35db8 100644 --- a/src/common/dpp.c +++ b/src/common/dpp.c @@ -2167,8 +2167,7 @@ struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk, struct json_token *token; const struct dpp_curve_params *curve; struct wpabuf *x = NULL, *y = NULL; - EC_GROUP *group; - struct crypto_ec_key *pkey = NULL; + struct crypto_ec_key *key = NULL; token = json_get_member(jwk, "kty"); if (!token || token->type != JSON_STRING) { @@ -2221,22 +2220,18 @@ struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk, goto fail; } - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) { - wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK"); + key = crypto_ec_key_set_pub(curve->ike_group, wpabuf_head(x), + wpabuf_head(y), wpabuf_len(x)); + if (!key) goto fail; - } - pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y), - wpabuf_len(x)); - EC_GROUP_free(group); *key_curve = curve; fail: wpabuf_free(x); wpabuf_free(y); - return pkey; + return key; } diff --git a/src/common/dpp_crypto.c b/src/common/dpp_crypto.c index 8d68fc72d..a2b63936d 100644 --- a/src/common/dpp_crypto.c +++ b/src/common/dpp_crypto.c @@ -374,101 +374,20 @@ int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) } -struct crypto_ec_key * dpp_set_pubkey_point_group(const EC_GROUP *group, - const u8 *buf_x, - const u8 *buf_y, - size_t len) -{ - EC_KEY *eckey = NULL; - BN_CTX *ctx; - EC_POINT *point = NULL; - BIGNUM *x = NULL, *y = NULL; - EVP_PKEY *pkey = NULL; - - ctx = BN_CTX_new(); - if (!ctx) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - return NULL; - } - - point = EC_POINT_new(group); - x = BN_bin2bn(buf_x, len, NULL); - y = BN_bin2bn(buf_y, len, NULL); - if (!point || !x || !y) { - wpa_printf(MSG_ERROR, "DPP: Out of memory"); - goto fail; - } - - if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { - wpa_printf(MSG_ERROR, - "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - - if (!EC_POINT_is_on_curve(group, point, ctx) || - EC_POINT_is_at_infinity(group, point)) { - wpa_printf(MSG_ERROR, "DPP: Invalid point"); - goto fail; - } - dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); - - eckey = EC_KEY_new(); - if (!eckey || - EC_KEY_set_group(eckey, group) != 1 || - EC_KEY_set_public_key(eckey, point) != 1) { - wpa_printf(MSG_ERROR, - "DPP: Failed to set EC_KEY: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto fail; - } - EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); - - pkey = EVP_PKEY_new(); - if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { - wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); - goto fail; - } - -out: - BN_free(x); - BN_free(y); - EC_KEY_free(eckey); - EC_POINT_free(point); - BN_CTX_free(ctx); - return (struct crypto_ec_key *) pkey; -fail: - EVP_PKEY_free(pkey); - pkey = NULL; - goto out; -} - - struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, const u8 *buf, size_t len) { - const EC_KEY *eckey; - const EC_GROUP *group; - struct crypto_ec_key *pkey = NULL; + int ike_group = crypto_ec_key_group(group_key); if (len & 1) return NULL; - eckey = EVP_PKEY_get0_EC_KEY((EVP_PKEY *) group_key); - if (!eckey) { - wpa_printf(MSG_ERROR, - "DPP: Could not get EC_KEY from group_key"); + if (ike_group < 0) { + wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); return NULL; } - group = EC_KEY_get0_group(eckey); - if (group) - pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, - len / 2); - else - wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); - - return pkey; + return crypto_ec_key_set_pub(ike_group, buf, buf + len / 2, len / 2); } @@ -1914,10 +1833,7 @@ static const u8 pkex_resp_y_bp_p512r1[64] = { static struct crypto_ec_key * dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init) { - EC_GROUP *group; - size_t len = curve->prime_len; const u8 *x, *y; - struct crypto_ec_key *res; switch (curve->ike_group) { case 19: @@ -1948,12 +1864,7 @@ dpp_pkex_get_role_elem(const struct dpp_curve_params *curve, int init) return NULL; } - group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); - if (!group) - return NULL; - res = dpp_set_pubkey_point_group(group, x, y, len); - EC_GROUP_free(group); - return res; + return crypto_ec_key_set_pub(curve->ike_group, x, y, curve->prime_len); } diff --git a/src/common/dpp_i.h b/src/common/dpp_i.h index 03862bb7a..87beade3d 100644 --- a/src/common/dpp_i.h +++ b/src/common/dpp_i.h @@ -78,10 +78,6 @@ const struct dpp_curve_params * dpp_get_curve_nid(int nid); const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group); int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); -struct crypto_ec_key * dpp_set_pubkey_point_group(const EC_GROUP *group, - const u8 *buf_x, - const u8 *buf_y, - size_t len); struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, const u8 *buf, size_t len); int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len); diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h index c51fded64..e98d1d816 100644 --- a/src/crypto/crypto.h +++ b/src/crypto/crypto.h @@ -994,6 +994,20 @@ struct crypto_ec_key * crypto_ec_key_parse_priv(const u8 *der, size_t der_len); */ struct crypto_ec_key * crypto_ec_key_parse_pub(const u8 *der, size_t der_len); +/** + * crypto_ec_key_set_pub - Initialize an EC public key from EC point coordinates + * @group: Identifying number for the ECC group + * @x: X coordinate of the public key + * @y: Y coordinate of the public key + * @len: Length of @x and @y buffer + * Returns: EC key or %NULL on failure + * + * This function initialize an EC key from public key coordinates, in big endian + * byte order padded to the length of the prime defining the group. + */ +struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *x, + const u8 *y, size_t len); + /** * crypto_ec_key_gen - Generate EC key pair * @group: Identifying number for the ECC group @@ -1009,7 +1023,7 @@ void crypto_ec_key_deinit(struct crypto_ec_key *key); /** * crypto_ec_key_get_subject_public_key - Get SubjectPublicKeyInfo ASN.1 for an EC key - * @key: EC key from crypto_ec_key_parse_pub/priv() or crypto_ec_key_gen() + * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() * Returns: Buffer with DER encoding of ASN.1 SubjectPublicKeyInfo or %NULL on failure */ struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key); @@ -1046,7 +1060,7 @@ struct wpabuf * crypto_ec_key_sign(struct crypto_ec_key *key, const u8 *data, /** * crypto_ec_key_verify_signature - Verify ECDSA signature - * @key: EC key from crypto_ec_key_parse_pub() or crypto_ec_key_gen() + * @key: EC key from crypto_ec_key_parse/set_pub() or crypto_ec_key_gen() * @data: Data to be signed * @len: Length of @data buffer * @sig: DER encoding of ASN.1 Ecdsa-Sig-Value @@ -1058,7 +1072,7 @@ int crypto_ec_key_verify_signature(struct crypto_ec_key *key, const u8 *data, /** * crypto_ec_key_group - Get IANA group identifier for an EC key - * @key: EC key from crypto_ec_key_parse_pub/priv() or crypto_ec_key_gen() + * @key: EC key from crypto_ec_key_parse/set_pub/priv() or crypto_ec_key_gen() * Returns: IANA group identifier and -1 on failure */ int crypto_ec_key_group(struct crypto_ec_key *key); diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index 3eb492dc1..c640b0fa9 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -2242,6 +2242,86 @@ fail: } +struct crypto_ec_key * crypto_ec_key_set_pub(int group, const u8 *buf_x, + const u8 *buf_y, size_t len) +{ + EC_KEY *eckey = NULL; + EVP_PKEY *pkey = NULL; + EC_GROUP *ec_group = NULL; + BN_CTX *ctx; + EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + int nid; + + if (!buf_x || !buf_y) + return NULL; + + nid = crypto_ec_group_2_nid(group); + if (nid < 0) { + wpa_printf(MSG_ERROR, "OpenSSL: Unsupported group %d", group); + return NULL; + } + + ctx = BN_CTX_new(); + if (!ctx) + goto fail; + + ec_group = EC_GROUP_new_by_curve_name(nid); + if (!ec_group) + goto fail; + + x = BN_bin2bn(buf_x, len, NULL); + y = BN_bin2bn(buf_y, len, NULL); + point = EC_POINT_new(ec_group); + if (!x || !y || !point) + goto fail; + + if (!EC_POINT_set_affine_coordinates_GFp(ec_group, point, x, y, ctx)) { + wpa_printf(MSG_ERROR, + "OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (!EC_POINT_is_on_curve(ec_group, point, ctx) || + EC_POINT_is_at_infinity(ec_group, point)) { + wpa_printf(MSG_ERROR, "OpenSSL: Invalid point"); + goto fail; + } + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, ec_group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "OpenSSL: Could not create EVP_PKEY"); + goto fail; + } + +out: + EC_GROUP_free(ec_group); + BN_free(x); + BN_free(y); + EC_POINT_free(point); + BN_CTX_free(ctx); + return (struct crypto_ec_key *) pkey; + +fail: + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + pkey = NULL; + goto out; +} + + struct crypto_ec_key * crypto_ec_key_gen(int group) { EVP_PKEY_CTX *kctx = NULL;