mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
wpa_supplicant: Use 'mbedtls_pk_parse_public_key' to parse compressed EC public key and remove unnecessary code
Support to parse compressed EC public key is added from 'mbedtls-3.4.0'
This commit is contained in:
parent
9e4915b81b
commit
cd0d42d43b
@ -1222,273 +1222,22 @@ cleanup:
|
||||
return sh_secret;
|
||||
}
|
||||
|
||||
static int crypto_ec_key_load_group_from_der_params(mbedtls_asn1_buf *params, mbedtls_ecp_group *group)
|
||||
{
|
||||
if (params == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group_id grp_id;
|
||||
if (params->tag == MBEDTLS_ASN1_OID) {
|
||||
if (mbedtls_oid_get_ec_grp(params, &grp_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (group->id != MBEDTLS_ECP_DP_NONE && group->id != grp_id) {
|
||||
return -1;
|
||||
}
|
||||
if (mbedtls_ecp_group_load(group, grp_id) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool crypto_ec_key_is_compressed(const u8 *der, size_t der_len)
|
||||
{
|
||||
size_t len;
|
||||
size_t prime_len;
|
||||
const unsigned char *end = der + der_len;
|
||||
const unsigned char *p;
|
||||
*(const unsigned char **)&p = der;
|
||||
|
||||
|
||||
if (mbedtls_asn1_get_tag((unsigned char **)&p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
end = p + len;
|
||||
mbedtls_asn1_buf alg_oid;
|
||||
mbedtls_asn1_buf params;
|
||||
memset(¶ms, 0, sizeof(mbedtls_asn1_buf));
|
||||
if (mbedtls_asn1_get_alg((unsigned char **)&p, end, &alg_oid, ¶ms) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (mbedtls_asn1_get_bitstring_null((unsigned char **)&p, end, &len) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group *group = os_malloc(sizeof(mbedtls_ecp_group));
|
||||
if (!group) {
|
||||
return false;
|
||||
}
|
||||
mbedtls_ecp_group_init(group);
|
||||
if (crypto_ec_key_load_group_from_der_params(¶ms, group) != 0) {
|
||||
goto _err;
|
||||
}
|
||||
|
||||
prime_len = mbedtls_mpi_size(&group->P);
|
||||
|
||||
if (mbedtls_ecp_get_type(group) == MBEDTLS_ECP_TYPE_SHORT_WEIERSTRASS
|
||||
&& (end - p) == 1+prime_len
|
||||
&& (*p == 0x02 || *p == 0x03)) {
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
return true;
|
||||
}
|
||||
|
||||
_err:
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* See https://github.com/Mbed-TLS/mbedtls/pull/6282 and https://github.com/mwarning/mbedtls_ecp_compression for more details*/
|
||||
static struct crypto_ec_key* crypto_ec_key_parse_compressed_pub(const u8 *der, size_t der_len)
|
||||
{
|
||||
|
||||
mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE;
|
||||
const mbedtls_pk_info_t *pk_info;
|
||||
mbedtls_pk_context *pkey = NULL;
|
||||
int ret;
|
||||
size_t len;
|
||||
size_t prime_len;
|
||||
const unsigned char *end = der + der_len;
|
||||
const unsigned char *p;
|
||||
*(const unsigned char **)&p = der;
|
||||
int parity_bit;
|
||||
|
||||
|
||||
if ((ret = mbedtls_asn1_get_tag((unsigned char **)&p, end, &len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
end = p + len;
|
||||
mbedtls_asn1_buf alg_oid;
|
||||
mbedtls_asn1_buf params;
|
||||
memset(¶ms, 0, sizeof(mbedtls_asn1_buf));
|
||||
if ((ret = mbedtls_asn1_get_alg((unsigned char **)&p, end, &alg_oid, ¶ms)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((ret = mbedtls_asn1_get_bitstring_null((unsigned char **)&p, end, &len)) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p + len != end) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((pk_info = mbedtls_pk_info_from_type(pk_alg)) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!(pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_ecp_group *group = os_malloc(sizeof(mbedtls_ecp_group));
|
||||
if (!group) {
|
||||
return NULL;
|
||||
}
|
||||
mbedtls_ecp_group_init(group);
|
||||
|
||||
if ((ret = crypto_ec_key_load_group_from_der_params(¶ms, group)) != 0) {
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check prerequisite p = 3 mod 4 */
|
||||
if (mbedtls_mpi_get_bit(&group->P, 0) != 1 ||
|
||||
mbedtls_mpi_get_bit(&group->P, 1) != 1) {
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prime_len = mbedtls_mpi_size(&group->P);
|
||||
|
||||
unsigned char *new_der = os_malloc(sizeof(unsigned char)*(der_len+prime_len));
|
||||
if (!new_der) {
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
return NULL;
|
||||
}
|
||||
os_memcpy(new_der, der, der_len);
|
||||
int offset = p - (unsigned char *)der ;
|
||||
unsigned char *key_start = (unsigned char *)new_der + offset;
|
||||
unsigned int new_der_len = der_len + prime_len;
|
||||
|
||||
mbedtls_mpi y;
|
||||
mbedtls_mpi x;
|
||||
mbedtls_mpi n;
|
||||
|
||||
|
||||
mbedtls_mpi_init(&y);
|
||||
mbedtls_mpi_init(&x);
|
||||
mbedtls_mpi_init(&n);
|
||||
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&x, key_start + 1, prime_len));
|
||||
parity_bit = key_start[0] & 1;
|
||||
|
||||
/* w = y^2 = x^3 + ax + b
|
||||
* y = sqrt(w) = w^((p+1)/4) mod p (for prime p where p = 3 mod 4)
|
||||
* use y to store intermediate results*/
|
||||
|
||||
/* y = x^2 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&y, &x, &x));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&y, &y, &group->P));
|
||||
|
||||
/* y = x^2 + a */
|
||||
if (group->A.MBEDTLS_PRIVATE(p) == NULL) {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&n, -3));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&y, &y, &n));
|
||||
} else {
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&y, &y, &group->A));
|
||||
}
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&y, &y, &group->P));
|
||||
|
||||
/* y = x^3 + ax */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&y, &y, &x));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&y, &y, &group->P));
|
||||
|
||||
/* y = x^3 + ax + b */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&y, &y, &group->B));
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&y, &y, &group->P));
|
||||
|
||||
/* n = P + 1 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_add_int(&n, &group->P, 1));
|
||||
|
||||
/* n = (P + 1) / 4 */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&n, 2));
|
||||
|
||||
/* y ^ ((P + 1) / 4) (mod p) */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&y, &y, &n, &group->P, NULL));
|
||||
|
||||
/* check parity bit match or else invert Y */
|
||||
/* This quick inversion implementation is valid because Y != 0 for all
|
||||
* Short Weierstrass curves supported by mbedtls, as each supported curve
|
||||
* has an order that is a large prime, so each supported curve does not
|
||||
* have any point of order 2, and a point with Y == 0 would be of order 2 */
|
||||
|
||||
if (mbedtls_mpi_get_bit(&y, 0) != parity_bit) {
|
||||
/* y = p - y */
|
||||
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(&y, &group->P, &y));
|
||||
}
|
||||
|
||||
/* y => output */
|
||||
ret = mbedtls_mpi_write_binary(&y, key_start + 1 + prime_len, prime_len);
|
||||
|
||||
key_start[0] = 0x04;
|
||||
|
||||
pkey = os_zalloc(sizeof(*pkey));
|
||||
if (!pkey) {
|
||||
goto cleanup;
|
||||
}
|
||||
mbedtls_pk_init(pkey);
|
||||
mbedtls_pk_setup(pkey, pk_info);
|
||||
|
||||
mbedtls_ecp_group_copy(&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(grp), (const mbedtls_ecp_group *)group);
|
||||
|
||||
if ((ret = mbedtls_ecp_point_read_binary(group, &mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(Q),
|
||||
(const unsigned char *)key_start, (new_der + new_der_len - key_start))) == 0) {
|
||||
ret = mbedtls_ecp_check_pubkey(&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(grp), &mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(Q));
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to parse ec public key");
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
os_free(new_der);
|
||||
mbedtls_pk_free(pkey);
|
||||
os_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
mbedtls_mpi_free(&y);
|
||||
mbedtls_mpi_free(&x);
|
||||
mbedtls_mpi_free(&n);
|
||||
mbedtls_ecp_group_free(group);
|
||||
os_free(group);
|
||||
os_free(new_der);
|
||||
|
||||
return (struct crypto_ec_key *)pkey;
|
||||
}
|
||||
|
||||
struct crypto_ec_key *crypto_ec_key_parse_pub(const u8 *der, size_t der_len)
|
||||
{
|
||||
mbedtls_pk_context *pkey = NULL;
|
||||
int ret;
|
||||
mbedtls_pk_context *pkey = os_zalloc(sizeof(*pkey));
|
||||
|
||||
if (crypto_ec_key_is_compressed(der, der_len)) {
|
||||
pkey = (mbedtls_pk_context *)crypto_ec_key_parse_compressed_pub(der, der_len);
|
||||
if (!pkey) {
|
||||
wpa_printf(MSG_ERROR, "failed to parse ec public key");
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
wpa_printf(MSG_ERROR, "failed to parse ec public key. expected compressed format");
|
||||
if (!pkey) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mbedtls_pk_init(pkey);
|
||||
ret = mbedtls_pk_parse_public_key(pkey, der, der_len);
|
||||
|
||||
if (ret < 0) {
|
||||
wpa_printf(MSG_ERROR, "failed to parse ec public key");
|
||||
os_free(pkey);
|
||||
return NULL;
|
||||
}
|
||||
return (struct crypto_ec_key *)pkey;
|
||||
|
Loading…
Reference in New Issue
Block a user