From cab4dc15f46f34cfe0842cf369e30bce364d5358 Mon Sep 17 00:00:00 2001 From: aditi_lonkar Date: Fri, 12 Apr 2024 10:51:37 +0530 Subject: [PATCH 1/3] feat(esp_wifi): Restructure dpp crypto Layer APIs 1) Update dpp implementation as per upstram hostapd tag hostap_2_10. 2) Move dpp crypto routines into a separate source code file. --- components/wpa_supplicant/CMakeLists.txt | 1 + .../src/crypto/crypto_mbedtls-ec.c | 22 +- .../esp_supplicant/src/esp_dpp_i.h | 9 +- components/wpa_supplicant/src/common/dpp.c | 1265 +---------------- components/wpa_supplicant/src/common/dpp.h | 60 + .../wpa_supplicant/src/common/dpp_crypto.c | 1191 ++++++++++++++++ components/wpa_supplicant/src/crypto/crypto.h | 34 +- 7 files changed, 1331 insertions(+), 1251 deletions(-) create mode 100644 components/wpa_supplicant/src/common/dpp_crypto.c diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index f0a67dbceb..dc0197e15b 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -202,6 +202,7 @@ endif() if(CONFIG_ESP_WIFI_DPP_SUPPORT) set(dpp_src "src/common/dpp.c" + "src/common/dpp_crypto.c" "esp_supplicant/src/esp_dpp.c") else() set(dpp_src "") diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index a6468e0b26..0a86120dd2 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -564,7 +564,7 @@ void crypto_ec_free_key(struct crypto_key *key) os_free(key); } -struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key) +struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -614,7 +614,7 @@ int crypto_ec_key_group(struct crypto_ec_key *key) return iana_group; } -struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key) +struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -669,7 +669,7 @@ int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) return len; } -struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len) +struct crypto_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len) { int ret; mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); @@ -841,7 +841,7 @@ int crypto_edcsa_sign_verify(const unsigned char *hash, return ret; } -void crypto_debug_print_ec_key(const char *title, struct crypto_key *key) +void crypto_ec_key_debug_print(const char *title, struct crypto_key *key) { #ifdef DEBUG_PRINT mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -852,12 +852,12 @@ void crypto_debug_print_ec_key(const char *title, struct crypto_key *key) int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key))); wpa_printf(MSG_ERROR, "prime len is %d", len); - crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_get_public_key(key), x, y); - crypto_bignum_to_bin(crypto_ec_get_private_key(key), - d, len, len); - wpa_hexdump(MSG_ERROR, "Q_x:", x, 32); - wpa_hexdump(MSG_ERROR, "Q_y:", y, 32); - wpa_hexdump(MSG_ERROR, "d: ", d, 32); + crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_key_get_public_key(key), x, y); + crypto_bignum_to_bin(crypto_ec_key_get_private_key(key), + d, len, len); + wpa_hexdump(MSG_INFO, "Q_x:", x, 32); + wpa_hexdump(MSG_INFO, "Q_y:", y, 32); + wpa_hexdump(MSG_INFO, "d: ", d , 32); #endif } @@ -885,7 +885,7 @@ int crypto_is_ec_key(struct crypto_key *key) return ret; } -struct crypto_key * crypto_ec_gen_keypair(u16 ike_group) +struct crypto_key * crypto_ec_key_gen(u16 ike_group) { mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h index 6761e86ac2..b8e4c280ef 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +10,6 @@ #include "esp_err.h" #include "utils/includes.h" #include "utils/common.h" - #include "common/dpp.h" #include "esp_dpp.h" #include "esp_wifi_driver.h" @@ -59,6 +58,12 @@ struct esp_dpp_context_t { int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t channel); esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data); +#ifdef CONFIG_TESTING_OPTIONS +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve); +char * dpp_corrupt_connector_signature(const char *connector); +#endif /* CONFIG_TESTING_OPTIONS */ + #ifdef CONFIG_ESP_WIFI_DPP_SUPPORT bool is_dpp_enabled(void); #else diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index b5d57d1e01..968c7ff17b 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -40,17 +40,7 @@ struct dpp_global { struct dl_list configurator; /* struct dpp_configurator */ }; -static const struct dpp_curve_params dpp_curves[] = { - /* The mandatory to support and the default NIST P-256 curve needs to - * be the first entry on this list. */ - { "secp256r1", 32, 32, 16, 32, "P-256", 19, "ES256" }, - { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, - { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, - { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, - { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, - { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, - { NULL, 0, 0, 0, 0, NULL, 0, NULL } -}; +extern struct dpp_curve_params dpp_curves[]; #define TRANSACTION_ID_ATTR_SET_LEN 5 #define CONNECTOR_ATTR_SET_LEN 4 @@ -71,181 +61,30 @@ gas_build_req(u8 action, u8 dialog_token, size_t size) return buf; } - struct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size) { return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token, size); } -static void dpp_debug_print_key(const char *title, struct crypto_key *key) -{ - crypto_debug_print_ec_key(title, key); -} - void dpp_debug_print_point(const char *title, struct crypto_ec *e, const struct crypto_ec_point *point) { u8 x[64], y[64]; if (crypto_ec_point_to_bin(e, point, x, y) < 0) { - printf("error: failed to get corrdinates\n"); + printf("error: failed to get coordinates\n"); return; } wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x, y); } -static int dpp_hash_vector(const struct dpp_curve_params *curve, - size_t num_elem, const u8 *addr[], const size_t *len, - u8 *mac) -{ - if (curve->hash_len == 32) - return sha256_vector(num_elem, addr, len, mac); -#ifndef ESP_SUPPLICANT - if (curve->hash_len == 48) - return sha384_vector(num_elem, addr, len, mac); - if (curve->hash_len == 64) - return sha512_vector(num_elem, addr, len, mac); -#endif - return -1; -} - - -static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, - const char *label, u8 *out, size_t outlen) -{ - if (hash_len == 32) - return hmac_sha256_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); -#ifndef ESP_SUPPLICANT - if (hash_len == 48) - return hmac_sha384_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); - if (hash_len == 64) - return hmac_sha512_kdf(secret, secret_len, NULL, - (const u8 *) label, os_strlen(label), - out, outlen); -#endif - return -1; -} - - -static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256_vector(key, key_len, num_elem, addr, len, - mac); -#ifndef ESP_SUPPLICANT - if (hash_len == 48) - return hmac_sha384_vector(key, key_len, num_elem, addr, len, - mac); - if (hash_len == 64) - return hmac_sha512_vector(key, key_len, num_elem, addr, len, - mac); -#endif - return -1; -} - - -static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac) -{ - if (hash_len == 32) - return hmac_sha256(key, key_len, data, data_len, mac); -#ifndef ESP_SUPPLICANT - if (hash_len == 48) - return hmac_sha384(key, key_len, data, data_len, mac); - if (hash_len == 64) - return hmac_sha512(key, key_len, data, data_len, mac); -#endif - return -1; -} - - -static int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len) -{ - if (crypto_bignum_to_bin(bn, pos, len, 0) < 0) - return -1; - - return 0; -} - -static struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix) -{ - int len, res; - struct wpabuf *buf; - unsigned char *pos = NULL; - - len = crypto_ec_get_publickey_buf(pkey, pos, 0); - if (len <= 0) { - wpa_printf(MSG_ERROR, - "DDP: Failed to determine public key encoding length"); - return NULL; - } - - buf = wpabuf_alloc(len); - if (!buf) { - return NULL; - } - - pos = wpabuf_put(buf, len); - - res = crypto_ec_get_publickey_buf(pkey, pos, len); - if (res != len) { - wpa_printf(MSG_ERROR, - "DDP: Failed to encode public key (res=%d/%d)", - res, len); - wpabuf_free(buf); - return NULL; - } - - if (!prefix) { - /* Remove 0x04 prefix to match DPP definition */ - pos = wpabuf_mhead(buf); - os_memmove(pos, pos + 1, len - 1); - buf->used--; - } - - return buf; -} - -static struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, - const u8 *buf, size_t len) -{ - const struct crypto_ec_group *group; - struct crypto_key *pkey = NULL; - - if (len & 1) - return NULL; - - group = crypto_ec_get_group_from_key(group_key); - if (group) - pkey = crypto_ec_set_pubkey_point(group, buf, - len); - else - wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); - - return pkey; -} - -static int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer, - u8 *secret, size_t *secret_len) -{ - return crypto_ecdh(own, peer, secret, secret_len); -} - - static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) { wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); } - struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, size_t len) { @@ -263,7 +102,6 @@ struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, return msg; } - const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len) { u16 id, alen; @@ -286,7 +124,6 @@ const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len) return NULL; } - static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len, u16 req_id, u16 *ret_len) { @@ -314,7 +151,6 @@ static const u8 * dpp_get_attr_next(const u8 *prev, const u8 *buf, size_t len, return NULL; } - int dpp_check_attrs(const u8 *buf, size_t len) { const u8 *pos, *end; @@ -356,7 +192,6 @@ int dpp_check_attrs(const u8 *buf, size_t len) return 0; } - void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) { if (!info) @@ -367,7 +202,6 @@ void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) os_free(info); } - const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type) { switch (type) { @@ -381,7 +215,6 @@ const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type) return "??"; } - static int dpp_uri_valid_info(const char *info) { while (*info) { @@ -394,7 +227,6 @@ static int dpp_uri_valid_info(const char *info) return 1; } - static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri) { bi->uri = os_strdup(uri); @@ -455,7 +287,6 @@ fail: return 0; } - int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac) { if (!mac) @@ -495,29 +326,12 @@ int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info) return 0; } -static const struct dpp_curve_params * dpp_get_curve_group_id(int group_id) -{ - unsigned int i; - - if (!group_id) - return NULL; - - for (i = 0; dpp_curves[i].ike_group; i++) { - if (group_id == dpp_curves[i].ike_group) - return &dpp_curves[i]; - } - return NULL; -} - static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) { const char *end; u8 *data; size_t data_len; - struct crypto_key *pkey; - const unsigned char *p; - struct crypto_ec_group *group; - int id; + int res; end = os_strchr(info, ';'); if (!end) @@ -532,6 +346,10 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", data, data_len); + res = dpp_get_subject_public_key(bi, data, data_len); + os_free(data); + return res; +#if 0 if (sha256_vector(1, (const u8 **) &data, &data_len, bi->pubkey_hash) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); @@ -592,9 +410,9 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) fail: crypto_ec_free_key(pkey); return -1; +#endif } - static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) { const char *pos = uri; @@ -658,296 +476,6 @@ static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) return bi; } - -static struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve) -{ - struct crypto_key *key = crypto_ec_gen_keypair(curve->ike_group); - - wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); - dpp_debug_print_key("Own generated key", key); - - return key; -} - -static const struct dpp_curve_params *dpp_get_curve_name(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (os_strcmp(name, dpp_curves[i].name) == 0 || - (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) - return &dpp_curves[i]; - } - return NULL; -} - - -static const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name) -{ - int i; - - for (i = 0; dpp_curves[i].name; i++) { - if (dpp_curves[i].jwk_crv && - os_strcmp(name, dpp_curves[i].jwk_crv) == 0) - return &dpp_curves[i]; - } - - return NULL; -} - - -static struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, - const u8 *privkey, size_t privkey_len) -{ - struct crypto_ec_group *group; - struct crypto_key *pkey = crypto_ec_get_key(privkey, privkey_len); - int id; - - if (!pkey) { - wpa_printf(MSG_ERROR, "%s: failed to get pkey", __func__); - return NULL; - } - group = crypto_ec_get_group_from_key(pkey); - if (!group) { - return NULL; - } - id = crypto_ec_get_curve_id(group); - *curve = dpp_get_curve_group_id(id); - if (!*curve) { - wpa_printf(MSG_INFO, - "DPP: Unsupported curve (id=%d) in pre-assigned key", - id); - crypto_ec_free_key(pkey); - return NULL; - } - - return pkey; -} - -static struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key) -{ - unsigned char *der = NULL; - struct wpabuf *ret = NULL; - int der_len; - - der_len = crypto_ec_write_pub_key(key, &der); - if (!der) { - printf("failed to get der for bootstrapping key\n"); - return NULL; - } - ret = wpabuf_alloc_copy(der, der_len); - - os_free(der); - return ret; -} - -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) -{ - struct wpabuf *der; - int res; - const u8 *addr[1]; - size_t len[1]; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - return -1; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - - addr[0] = wpabuf_head(der); - len[0] = wpabuf_len(der); - res = sha256_vector(1, addr, len, bi->pubkey_hash); - if (res < 0) - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - else - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); - wpabuf_free(der); - return res; -} - - -char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, - u8 *privkey, size_t privkey_len) -{ - char *base64 = NULL; - char *pos, *end; - size_t len; - struct wpabuf *der = NULL; - const u8 *addr[1]; - int res; - - if (!curve) { - bi->curve = &dpp_curves[0]; - } else { - bi->curve = dpp_get_curve_name(curve); - if (!bi->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return NULL; - } - } - if (privkey) - bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); - else - bi->pubkey = dpp_gen_keypair(bi->curve); - if (!bi->pubkey) - goto fail; - bi->own = 1; - - der = dpp_bootstrap_key_der(bi->pubkey); - if (!der) - goto fail; - wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", - der); - - addr[0] = wpabuf_head(der); - len = wpabuf_len(der); - res = sha256_vector(1, addr, &len, bi->pubkey_hash); - if (res < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); - - base64 = (char *)base64_encode(wpabuf_head(der), wpabuf_len(der), &len); - wpabuf_free(der); - der = NULL; - if (!base64) - goto fail; - pos = base64; - end = pos + len; - for (;;) { - pos = os_strchr(pos, '\n'); - if (!pos) - break; - os_memmove(pos, pos + 1, end - pos); - } - return base64; -fail: - os_free(base64); - wpabuf_free(der); - return NULL; -} - -static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "first intermediate key"; - int res; - - /* k1 = HKDF(<>, "first intermediate key", M.x) */ - - /* HKDF-Extract(<>, M.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); - forced_memzero(prk, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", - k1, hash_len); - return 0; -} - - -static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, - unsigned int hash_len) -{ - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "second intermediate key"; - int res; - - /* k2 = HKDF(<>, "second intermediate key", N.x) */ - - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); - forced_memzero(prk, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", - k2, hash_len); - return 0; -} - - -static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, - unsigned int hash_len) -{ - size_t nonce_len; - u8 nonces[2 * DPP_MAX_NONCE_LEN]; - const char *info_ke = "DPP Key"; - u8 prk[DPP_MAX_HASH_LEN]; - int res; - const u8 *addr[3]; - size_t len[3]; - size_t num_elem = 0; - - if (!auth->Mx_len || !auth->Nx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Mx/Nx not available - cannot derive ke"); - return -1; - } - - /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */ - - /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ - nonce_len = auth->curve->nonce_len; - os_memcpy(nonces, auth->i_nonce, nonce_len); - os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); - addr[num_elem] = auth->Mx; - len[num_elem] = auth->Mx_len; - num_elem++; - addr[num_elem] = auth->Nx; - len[num_elem] = auth->Nx_len; - num_elem++; - if (auth->peer_bi && auth->own_bi) { - if (!auth->Lx_len) { - wpa_printf(MSG_DEBUG, - "DPP: Lx not available - cannot derive ke"); - return -1; - } - addr[num_elem] = auth->Lx; - len[num_elem] = auth->secret_len; - num_elem++; - } - res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, - num_elem, addr, len, prk); - if (res < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", - prk, hash_len); - - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len); - forced_memzero(prk, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)", - ke, hash_len); - return 0; -} - - static void dpp_build_attr_status(struct wpabuf *msg, enum dpp_status_error status) { @@ -957,7 +485,6 @@ static void dpp_build_attr_status(struct wpabuf *msg, wpabuf_put_u8(msg, status); } - static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash) { @@ -969,7 +496,6 @@ static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, } } - static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, const u8 *hash) { @@ -981,7 +507,6 @@ static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, } } - static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, const struct wpabuf *pi, size_t nonce_len, @@ -994,7 +519,6 @@ static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; u8 *pos; const u8 *addr[2]; - size_t len[2], siv_len, attr_len; u8 *attr_start, *attr_end; @@ -1136,7 +660,6 @@ skip_wrapped_data: return msg; } - static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, enum dpp_status_error status, const struct wpabuf *pr, @@ -1159,6 +682,7 @@ static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, auth->waiting_auth_conf = 1; auth->auth_resp_tries = 0; + auth->auth_resp_status = status; /* Build DPP Authentication Response frame attributes */ attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + @@ -1389,7 +913,6 @@ skip_connector: return msg; } - static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, u16 num_modes, unsigned int freq) { @@ -1419,7 +942,6 @@ static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, return 1; } - static int freq_included(const unsigned int freqs[], unsigned int num, unsigned int freq) { @@ -1446,7 +968,6 @@ static void freq_to_start(unsigned int freqs[], unsigned int num, freqs[0] = freq; } - static int dpp_channel_intersect(struct dpp_authentication *auth, struct hostapd_hw_modes *own_modes, u16 num_modes) @@ -1470,7 +991,6 @@ static int dpp_channel_intersect(struct dpp_authentication *auth, return 0; } - static int dpp_channel_local_list(struct dpp_authentication *auth, struct hostapd_hw_modes *own_modes, u16 num_modes) @@ -1514,7 +1034,6 @@ static int dpp_channel_local_list(struct dpp_authentication *auth, return auth->num_freq == 0 ? -1 : 0; } - static int dpp_prepare_channel_list(struct dpp_authentication *auth, struct hostapd_hw_modes *own_modes, u16 num_modes) @@ -1554,7 +1073,6 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth, return 0; } - static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) { struct dpp_bootstrap_info *bi; @@ -1593,7 +1111,6 @@ fail: return -1; } - struct dpp_authentication * dpp_auth_init(void *msg_ctx, struct dpp_bootstrap_info *peer_bi, struct dpp_bootstrap_info *own_bi, @@ -1734,7 +1251,6 @@ fail: goto out; } - static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth, const char *json) { @@ -1839,7 +1355,6 @@ fail: return NULL; } - static void dpp_write_adv_proto(struct wpabuf *buf) { /* Advertisement Protocol IE */ @@ -1853,7 +1368,6 @@ static void dpp_write_adv_proto(struct wpabuf *buf) wpabuf_put_u8(buf, 0x01); } - static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) { /* GAS Query */ @@ -1861,7 +1375,6 @@ static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) wpabuf_put_buf(buf, query); } - struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, const char *json) { @@ -1888,7 +1401,6 @@ struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, return buf; } - struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, const char *name, enum dpp_netrole netrole, @@ -1948,7 +1460,6 @@ struct wpabuf * dpp_build_conf_req_helper(struct dpp_authentication *auth, return buf; } - static void dpp_auth_success(struct dpp_authentication *auth) { wpa_printf(MSG_DEBUG, @@ -1965,265 +1476,6 @@ static void dpp_auth_success(struct dpp_authentication *auth) auth->auth_success = 1; } - -static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) -{ - struct wpabuf *pix, *prx, *bix, *brx; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 zero = 0; - int res = -1; - - /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - addr[num_elem] = &zero; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - -static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) -{ - struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; - const u8 *addr[7]; - size_t len[7]; - size_t i, num_elem = 0; - size_t nonce_len; - u8 one = 1; - int res = -1; - - /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ - nonce_len = auth->curve->nonce_len; - - if (auth->initiator) { - pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - if (auth->own_bi) - bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - else - bix = NULL; - if (!auth->peer_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - } else { - pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); - prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); - if (auth->peer_bi) - bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); - else - bix = NULL; - if (!auth->own_bi) - goto fail; - brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); - } - if (!pix || !prx || !brx) - goto fail; - - addr[num_elem] = auth->r_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = auth->i_nonce; - len[num_elem] = nonce_len; - num_elem++; - - addr[num_elem] = wpabuf_head(prx); - len[num_elem] = wpabuf_len(prx) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(pix); - len[num_elem] = wpabuf_len(pix) / 2; - num_elem++; - - addr[num_elem] = wpabuf_head(brx); - len[num_elem] = wpabuf_len(brx) / 2; - num_elem++; - - if (bix) { - addr[num_elem] = wpabuf_head(bix); - len[num_elem] = wpabuf_len(bix) / 2; - num_elem++; - } - - addr[num_elem] = &one; - len[num_elem] = 1; - num_elem++; - - wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); - for (i = 0; i < num_elem; i++) - wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); - res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); - if (res == 0) - wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, - auth->curve->hash_len); -fail: - wpabuf_free(pix); - wpabuf_free(prx); - wpabuf_free(bix); - wpabuf_free(brx); - return res; -} - - -static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) -{ - struct crypto_ec_group *group; - struct crypto_ec_point *l = NULL; - struct crypto_ec_point *BI_point; - struct crypto_bignum *lx, *sum, *q; - struct crypto_bignum *bR_bn, *pR_bn; - int ret = -1; - - /* L = ((bR + pR) modulo q) * BI */ - - sum = crypto_bignum_init(); - q = crypto_bignum_init(); - lx = crypto_bignum_init(); - if (!sum || !q || !lx) - goto fail; - - BI_point = crypto_ec_get_public_key(auth->peer_bi->pubkey); - group = crypto_ec_get_group_from_key(auth->peer_bi->pubkey); - bR_bn = crypto_ec_get_private_key(auth->own_bi->pubkey); - pR_bn = crypto_ec_get_private_key(auth->own_protocol_key); - - if (!bR_bn || !pR_bn) - goto fail; - - if ((crypto_get_order(group, q) != 0) || - (crypto_bignum_addmod(sum, bR_bn, pR_bn, q) != 0)) - goto fail; - - l = crypto_ec_point_init((struct crypto_ec *)group); - if (!l || (crypto_ec_point_mul((struct crypto_ec *)group, BI_point, sum, l) != 0) || - (crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0)) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", __func__); - goto fail; - } - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - crypto_ec_point_deinit(l, 1); - crypto_bignum_deinit(lx, 0); - crypto_bignum_deinit(sum, 0); - crypto_bignum_deinit(q, 0); - - return ret; -} - -static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) -{ - struct crypto_ec_group *group; - struct crypto_ec_point *l = NULL, *sum = NULL; - struct crypto_ec_point *BR_point, *PR_point; - struct crypto_bignum *lx; - struct crypto_bignum *bI_bn; - int ret = -1; - - /* L = bI * (BR + PR) */ - - lx = crypto_bignum_init(); - if (!lx) - goto fail; - BR_point = crypto_ec_get_public_key(auth->peer_bi->pubkey); - PR_point = crypto_ec_get_public_key(auth->peer_protocol_key); - - group = crypto_ec_get_group_from_key(auth->own_bi->pubkey); - bI_bn = crypto_ec_get_private_key(auth->own_bi->pubkey); - if (!group || !bI_bn) - goto fail; - sum = crypto_ec_point_init((struct crypto_ec *)group); - l = crypto_ec_point_init((struct crypto_ec *)group); - if (!sum || !l || - crypto_ec_point_add((struct crypto_ec *)group, BR_point, PR_point, sum) != 0 || - crypto_ec_point_mul((struct crypto_ec *)group, sum, bI_bn, l) != 0 || - crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0) { - wpa_printf(MSG_ERROR, - "OpenSSL: failed: %s", __func__); - goto fail; - } - - if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) - goto fail; - wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); - auth->Lx_len = auth->secret_len; - ret = 0; -fail: - crypto_ec_point_deinit(l, 1); - crypto_ec_point_deinit(sum, 1); - crypto_bignum_deinit(lx, 0); - - - return ret; -} - - static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) { size_t nonce_len; @@ -2307,7 +1559,7 @@ static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) goto fail; } - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + if (dpp_derive_bk_ke(auth) < 0) goto fail; /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ @@ -2407,7 +1659,6 @@ fail: return ret; } - static int dpp_auth_build_resp_status(struct dpp_authentication *auth, enum dpp_status_error status) { @@ -2472,7 +1723,6 @@ static int dpp_auth_build_resp_status(struct dpp_authentication *auth, return 0; } - struct dpp_authentication * dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, struct dpp_bootstrap_info *peer_bi, @@ -2728,7 +1978,6 @@ fail: return NULL; } - int dpp_notify_new_qr_code(struct dpp_authentication *auth, struct dpp_bootstrap_info *peer_bi) { @@ -2748,7 +1997,6 @@ int dpp_notify_new_qr_code(struct dpp_authentication *auth, return 1; } - static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, enum dpp_status_error status) { @@ -2926,7 +2174,6 @@ fail: return NULL; } - static void dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len, @@ -3024,7 +2271,6 @@ fail: bin_clear_free(unwrapped, unwrapped_len); } - struct wpabuf * dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) @@ -3273,7 +2519,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", wrapped2, wrapped2_len); - if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + if (dpp_derive_bk_ke(auth) < 0) goto fail; unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; @@ -3339,7 +2585,6 @@ fail: return NULL; } - static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len, @@ -3410,7 +2655,6 @@ fail: return -1; } - int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) { @@ -3569,13 +2813,11 @@ fail: return -1; } - static int bin_str_eq(const char *val, size_t len, const char *cmp) { return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0; } - struct dpp_configuration * dpp_configuration_alloc(const char *type) { struct dpp_configuration *conf; @@ -3616,41 +2858,35 @@ fail: return NULL; } - int dpp_akm_psk(enum dpp_akm akm) { return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || akm == DPP_AKM_PSK_SAE_DPP; } - int dpp_akm_sae(enum dpp_akm akm) { return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE || akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; } - int dpp_akm_legacy(enum dpp_akm akm) { return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || akm == DPP_AKM_SAE; } - int dpp_akm_dpp(enum dpp_akm akm) { return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; } - int dpp_akm_ver2(enum dpp_akm akm) { return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; } - int dpp_configuration_valid(const struct dpp_configuration *conf) { if (conf->ssid_len == 0) @@ -3662,7 +2898,6 @@ int dpp_configuration_valid(const struct dpp_configuration *conf) return 1; } - void dpp_configuration_free(struct dpp_configuration *conf) { if (!conf) @@ -3672,7 +2907,6 @@ void dpp_configuration_free(struct dpp_configuration *conf) bin_clear_free(conf, sizeof(*conf)); } - static int dpp_configuration_parse_helper(struct dpp_authentication *auth, const char *cmd, int idx) { @@ -3799,7 +3033,6 @@ fail: return -1; } - static int dpp_configuration_parse(struct dpp_authentication *auth, const char *cmd) { @@ -3834,7 +3067,6 @@ fail: return -1; } - static struct dpp_configurator * dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) { @@ -3851,7 +3083,6 @@ dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) return NULL; } - int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, struct dpp_authentication *auth, const char *cmd) @@ -3894,7 +3125,6 @@ int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, return 0; } - void dpp_auth_deinit(struct dpp_authentication *auth) { unsigned int i; @@ -3926,7 +3156,6 @@ void dpp_auth_deinit(struct dpp_authentication *auth) bin_clear_free(auth, sizeof(*auth)); } - static struct wpabuf * dpp_build_conf_start(struct dpp_authentication *auth, struct dpp_configuration *conf, size_t tailroom) @@ -3974,7 +3203,6 @@ dpp_build_conf_start(struct dpp_authentication *auth, return buf; } - static int dpp_build_jwk(struct wpabuf *buf, const char *name, struct crypto_key *key, const char *kid, const struct dpp_curve_params *curve) { @@ -4009,7 +3237,6 @@ fail: return ret; } - static void dpp_build_legacy_cred_params(struct wpabuf *buf, struct dpp_configuration *conf) { @@ -4026,7 +3253,6 @@ static void dpp_build_legacy_cred_params(struct wpabuf *buf, } } - static const char * dpp_netrole_str(enum dpp_netrole netrole) { switch (netrole) { @@ -4298,7 +3524,6 @@ dpp_build_conf_obj_legacy(struct dpp_authentication *auth, return buf; } - static struct wpabuf * dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, int idx) @@ -4339,7 +3564,6 @@ dpp_build_conf_obj(struct dpp_authentication *auth, enum dpp_netrole netrole, return dpp_build_conf_obj_legacy(auth, conf); } - static struct wpabuf * dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, u16 e_nonce_len, enum dpp_netrole netrole) @@ -4490,7 +3714,6 @@ fail: goto out; } - struct wpabuf * dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, size_t attr_len) @@ -4638,77 +3861,6 @@ fail: return resp; } - -static struct wpabuf * -dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func) -{ - struct json_token *root, *token; - struct wpabuf *kid = NULL; - - root = json_parse((const char *) prot_hdr, prot_hdr_len); - if (!root) { - wpa_printf(MSG_DEBUG, - "DPP: JSON parsing failed for JWS Protected Header"); - goto fail; - } - - if (root->type != JSON_OBJECT) { - wpa_printf(MSG_DEBUG, - "DPP: JWS Protected Header root is not an object"); - goto fail; - } - - token = json_get_member(root, "typ"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", - token->string); - if (os_strcmp(token->string, "dppCon") != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported JWS Protected Header typ=%s", - token->string); - goto fail; - } - - token = json_get_member(root, "alg"); - if (!token || token->type != JSON_STRING) { - wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); - goto fail; - } - wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", - token->string); - if (os_strcmp(token->string, curve->jws_alg) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", - token->string, curve->jws_alg); - goto fail; - } - - if (os_strcmp(token->string, "ES256") == 0 || - os_strcmp(token->string, "BS256") == 0) { - *hash_func = CRYPTO_HASH_ALG_SHA256; - } else { - *hash_func = -1; - wpa_printf(MSG_ERROR, "Unsupported JWS Protected Header alg=%s", token->string); - } - - kid = json_get_member_base64url(root, "kid"); - if (!kid) { - wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); - goto fail; - } - wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", - kid); - -fail: - json_free(root); - return kid; -} - - static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, struct json_token *cred) { @@ -4755,7 +3907,6 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, return 0; } - static struct crypto_key * dpp_parse_jwk(struct json_token *jwk, const struct dpp_curve_params **key_curve) { @@ -4841,7 +3992,6 @@ fail: return pkey; } - int dpp_key_expired(const char *timestamp, os_time_t *expiry) { struct os_time now; @@ -4920,7 +4070,6 @@ int dpp_key_expired(const char *timestamp, os_time_t *expiry) return 0; } - static int dpp_parse_connector(struct dpp_authentication *auth, struct dpp_config_obj *conf, const unsigned char *payload, @@ -5017,38 +4166,6 @@ fail: return ret; } -static int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash) -{ - struct wpabuf *uncomp; - int res; - u8 hash[SHA256_MAC_LEN]; - const u8 *addr[1]; - size_t len[1]; - - if (wpabuf_len(r_hash) != SHA256_MAC_LEN) - return -1; - uncomp = dpp_get_pubkey_point(pub, 1); - if (!uncomp) - return -1; - addr[0] = wpabuf_head(uncomp); - len[0] = wpabuf_len(uncomp); - wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", - addr[0], len[0]); - res = sha256_vector(1, addr, len, hash); - wpabuf_free(uncomp); - if (res < 0) - return -1; - if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { - wpa_printf(MSG_DEBUG, - "DPP: Received hash value does not match calculated public key hash value"); - wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", - hash, SHA256_MAC_LEN); - return -1; - } - return 0; -} - - static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_key *csign) { unsigned char *der = NULL; @@ -5076,148 +4193,6 @@ static void dpp_copy_netaccesskey(struct dpp_authentication *auth, crypto_free_buffer(der); } -struct dpp_signed_connector_info { - unsigned char *payload; - size_t payload_len; -}; - -static enum dpp_status_error -dpp_process_signed_connector(struct dpp_signed_connector_info *info, - struct crypto_key *csign_pub, const char *connector) -{ - enum dpp_status_error ret = 255; - const char *pos, *end, *signed_start, *signed_end; - struct wpabuf *kid = NULL; - unsigned char *prot_hdr = NULL, *signature = NULL; - size_t prot_hdr_len = 0, signature_len = 0, signed_len; - struct crypto_bignum *r = NULL, *s = NULL; - const struct dpp_curve_params *curve; - const struct crypto_ec_group *group; - int id, hash_func = -1; - u8 *hash = NULL; - - group = crypto_ec_get_group_from_key(csign_pub); - if (!group) - goto fail; - id = crypto_ec_get_curve_id(group); - curve = dpp_get_curve_group_id(id); - if (!curve) - goto fail; - wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); - os_memset(info, 0, sizeof(*info)); - - signed_start = pos = connector; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); - if (!prot_hdr) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Protected Header"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Protected Header", - (u8 *)prot_hdr, prot_hdr_len); - kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); - if (!kid) { - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - if (wpabuf_len(kid) != SHA256_MAC_LEN) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", - (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - pos = end + 1; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, - "DPP: Missing dot(2) in signedConnector"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - signed_end = end - 1; - info->payload = base64_url_decode(pos, end - pos, &info->payload_len); - if (!info->payload) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector JWS Payload"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump_ascii(MSG_DEBUG, - "DPP: signedConnector - JWS Payload", - (u8 *)info->payload, info->payload_len); - pos = end + 1; - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector signature"); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", - signature, signature_len); - - if (dpp_check_pubkey_match(csign_pub, kid) < 0) { - ret = DPP_STATUS_NO_MATCH; - goto fail; - } - - if (signature_len & 0x01) { - wpa_printf(MSG_DEBUG, - "DPP: Unexpected signedConnector signature length (%d)", - (int) signature_len); - ret = DPP_STATUS_INVALID_CONNECTOR; - goto fail; - } - - /* JWS Signature encodes the signature (r,s) as two octet strings. Need - * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ - r = crypto_bignum_init_set(signature, signature_len / 2); - s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2); - - signed_len = signed_end - signed_start + 1; - hash = os_malloc(curve->hash_len); - if (!hash) { - wpa_printf(MSG_ERROR, "malloc failed"); - goto fail; - } - - if (hash_func == CRYPTO_HASH_ALG_SHA256) { - if ((sha256_vector(1, (const u8 **) &signed_start, &signed_len, hash)) != 0) { - goto fail; - } - } else { - goto fail; - } - - if ((crypto_edcsa_sign_verify((unsigned char *)hash, r, s, - csign_pub, curve->hash_len)) != 0) { - goto fail; - } - - ret = DPP_STATUS_OK; -fail: - if (hash != NULL) { - os_free(hash); - } - os_free(prot_hdr); - wpabuf_free(kid); - os_free(signature); - crypto_bignum_deinit(r, 0); - crypto_bignum_deinit(s, 0); - return ret; -} - - static int dpp_parse_cred_dpp(struct dpp_authentication *auth, struct dpp_config_obj *conf, struct json_token *cred) @@ -5292,7 +4267,6 @@ fail: return ret; } - const char * dpp_akm_str(enum dpp_akm akm) { switch (akm) { @@ -5313,7 +4287,6 @@ const char * dpp_akm_str(enum dpp_akm akm) } } - const char * dpp_akm_selector_str(enum dpp_akm akm) { switch (akm) { @@ -5334,7 +4307,6 @@ const char * dpp_akm_selector_str(enum dpp_akm akm) } } - static enum dpp_akm dpp_akm_from_str(const char *akm) { const char *pos; @@ -5387,7 +4359,6 @@ static enum dpp_akm dpp_akm_from_str(const char *akm) return DPP_AKM_UNKNOWN; } - static int dpp_parse_conf_obj(struct dpp_authentication *auth, const u8 *conf_obj, u16 conf_obj_len) { @@ -5503,7 +4474,6 @@ fail: return ret; } - int dpp_conf_resp_rx(struct dpp_authentication *auth, const uint8_t *resp, uint32_t resp_len) { @@ -5617,7 +4587,6 @@ void dpp_configurator_free(struct dpp_configurator *conf) os_free(conf); } - int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, size_t buflen) { @@ -5637,7 +4606,6 @@ int dpp_configurator_get_key(const struct dpp_configurator *conf, char *buf, return ret; } - struct dpp_configurator * dpp_keygen_configurator(const char *curve, u8 *privkey, size_t privkey_len) @@ -5699,7 +4667,6 @@ fail: goto out; } - int dpp_configurator_own_config(struct dpp_authentication *auth, const char *curve, int ap) { @@ -5746,7 +4713,6 @@ fail: return ret; } - static int dpp_compatible_netrole(const char *role1, const char *role2) { return (os_strcmp(role1, "sta") == 0 && os_strcmp(role2, "ap") == 0) || @@ -5827,74 +4793,39 @@ static int dpp_connector_match_groups(struct json_token *own_root, return 0; } -static int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, - unsigned int hash_len) +struct json_token * dpp_parse_own_connector(const char *own_connector) { - u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; - const char *info = "DPP PMK"; - int res; + unsigned char *own_conn; + size_t own_conn_len; + const char *pos, *end; + struct json_token *own_root; - /* PMK = HKDF(<>, "DPP PMK", N.x) */ + pos = os_strchr(own_connector, '.'); + if (!pos) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the firstdot (.)"); + return NULL; + } + pos++; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Own connector is missing second dot (.)"); + return NULL; + } + own_conn = base64_url_decode(pos, end - pos, &own_conn_len); + if (!own_conn) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode own signedConnectior JWS Payload"); + return NULL; + } - /* HKDF-Extract(<>, N.x) */ - os_memset(salt, 0, hash_len); - if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) - return -1; - wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", - prk, hash_len); + own_root = json_parse((const char *) own_conn, own_conn_len); + os_free(own_conn); + if (!own_root) + wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); - /* HKDF-Expand(PRK, info, L) */ - res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); - forced_memzero(prk, hash_len); - if (res < 0) - return -1; - - wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", - pmk, hash_len); - return 0; + return own_root; } - -static int dpp_derive_pmkid(const struct dpp_curve_params *curve, - struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid) -{ - struct wpabuf *nkx, *pkx; - int ret = -1, res; - const u8 *addr[2]; - size_t len[2]; - u8 hash[SHA256_MAC_LEN]; - - /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ - nkx = dpp_get_pubkey_point(own_key, 0); - pkx = dpp_get_pubkey_point(peer_key, 0); - if (!nkx || !pkx) - goto fail; - addr[0] = wpabuf_head(nkx); - len[0] = wpabuf_len(nkx) / 2; - addr[1] = wpabuf_head(pkx); - len[1] = wpabuf_len(pkx) / 2; - if (len[0] != len[1]) - goto fail; - if (os_memcmp(addr[0], addr[1], len[0]) > 0) { - addr[0] = wpabuf_head(pkx); - addr[1] = wpabuf_head(nkx); - } - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); - res = sha256_vector(2, addr, len, hash); - if (res < 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); - os_memcpy(pmkid, hash, PMKID_LEN); - wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); - ret = 0; -fail: - wpabuf_free(nkx); - wpabuf_free(pkx); - return ret; -} - - enum dpp_status_error dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, const u8 *net_access_key, size_t net_access_key_len, @@ -5909,12 +4840,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, struct wpabuf *own_key_pub = NULL; const struct dpp_curve_params *curve, *own_curve; struct dpp_signed_connector_info info; - const unsigned char *p; - struct crypto_key *csign = NULL; - char *signed_connector = NULL; - const char *pos, *end; - unsigned char *own_conn = NULL; - size_t own_conn_len; size_t Nx_len; u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; @@ -5923,14 +4848,6 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, if (expiry) *expiry = 0; - p = csign_key; - csign = crypto_ec_parse_subpub_key(p, csign_key_len); - if (!csign) { - wpa_printf(MSG_ERROR, - "DPP: Failed to parse local C-sign-key information"); - goto fail; - } - own_key = dpp_set_keypair(&own_curve, net_access_key, net_access_key_len); if (!own_key) { @@ -5938,39 +4855,14 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, goto fail; } - pos = os_strchr(own_connector, '.'); - if (!pos) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the first dot (.)"); - goto fail; - } - pos++; - end = os_strchr(pos, '.'); - if (!end) { - wpa_printf(MSG_DEBUG, "DPP: Own connector is missing the second dot (.)"); - goto fail; - } - own_conn = base64_url_decode(pos, end - pos, &own_conn_len); - if (!own_conn) { - wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode own signedConnector JWS Payload"); - goto fail; - } - - own_root = json_parse((const char *) own_conn, own_conn_len); + own_root = dpp_parse_own_connector(own_connector); if (!own_root) { - wpa_printf(MSG_DEBUG, "DPP: Failed to parse local connector"); goto fail; } - wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", - (u8 *)peer_connector, peer_connector_len); - signed_connector = os_malloc(peer_connector_len + 1); - if (!signed_connector) - goto fail; - os_memcpy(signed_connector, peer_connector, peer_connector_len); - signed_connector[peer_connector_len] = '\0'; - res = dpp_process_signed_connector(&info, csign, signed_connector); + res = dpp_check_signed_connector(&info, csign_key, csign_key_len, + peer_connector, peer_connector_len); if (res != DPP_STATUS_OK) { ret = res; goto fail; @@ -6051,74 +4943,15 @@ fail: if (ret != DPP_STATUS_OK) os_memset(intro, 0, sizeof(*intro)); forced_memzero(Nx, sizeof(Nx)); - os_free(own_conn); - os_free(signed_connector); os_free(info.payload); crypto_ec_free_key(own_key); wpabuf_free(own_key_pub); crypto_ec_free_key(peer_key); - crypto_ec_free_key(csign); json_free(root); json_free(own_root); return ret; } -#ifdef CONFIG_TESTING_OPTIONS -static int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve) -{ - return 0; -} - -char * dpp_corrupt_connector_signature(const char *connector) -{ - char *tmp, *pos, *signed3 = NULL; - unsigned char *signature = NULL; - size_t signature_len = 0, signed3_len; - - tmp = os_zalloc(os_strlen(connector) + 5); - if (!tmp) - goto fail; - os_memcpy(tmp, connector, os_strlen(connector)); - - pos = os_strchr(tmp, '.'); - if (!pos) - goto fail; - - pos = os_strchr(pos + 1, '.'); - if (!pos) - goto fail; - pos++; - - wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", - pos); - signature = base64_url_decode(pos, os_strlen(pos), &signature_len); - if (!signature || signature_len == 0) - goto fail; - wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", - signature, signature_len); - signature[signature_len - 1] ^= 0x01; - wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", - signature, signature_len); - signed3 = base64_url_encode(signature, signature_len, &signed3_len); - if (!signed3) - goto fail; - os_memcpy(pos, signed3, signed3_len); - pos[signed3_len] = '\0'; - wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", - pos); - -out: - os_free(signature); - os_free(signed3); - return tmp; -fail: - os_free(tmp); - tmp = NULL; - goto out; -} -#endif /* CONFIG_TESTING_OPTIONS */ - static unsigned int dpp_next_id(struct dpp_global *dpp) { struct dpp_bootstrap_info *bi; @@ -6153,7 +4986,6 @@ static int dpp_bootstrap_del(struct dpp_global *dpp, unsigned int id) return found ? 0 : -1; } - struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, const char *uri) { @@ -6172,7 +5004,6 @@ struct dpp_bootstrap_info * dpp_add_qr_code(struct dpp_global *dpp, return bi; } - struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, const char *uri) { @@ -6191,7 +5022,6 @@ struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, return bi; } - int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) { char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL; @@ -6202,6 +5032,9 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) int ret = -1; struct dpp_bootstrap_info *bi; + if (!dpp) + return -1; + bi = os_zalloc(sizeof(*bi)); if (!bi) goto fail; @@ -6276,7 +5109,6 @@ fail: return ret; } - struct dpp_bootstrap_info * dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id) { @@ -6292,7 +5124,6 @@ dpp_bootstrap_get_id(struct dpp_global *dpp, unsigned int id) return NULL; } - int dpp_bootstrap_remove(struct dpp_global *dpp, const char *id) { unsigned int id_val; @@ -6343,7 +5174,6 @@ int dpp_get_bootstrap_info(struct dpp_global *dpp, int id, pkhash); } - void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, const u8 *r_bootstrap, struct dpp_bootstrap_info **own_bi, @@ -6379,7 +5209,6 @@ void dpp_bootstrap_find_pair(struct dpp_global *dpp, const u8 *i_bootstrap, } - static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) { struct dpp_configurator *conf; @@ -6393,7 +5222,6 @@ static unsigned int dpp_next_configurator_id(struct dpp_global *dpp) return max_id + 1; } - int dpp_configurator_add(struct dpp_global *dpp, const char *cmd) { char *curve = NULL; @@ -6430,7 +5258,6 @@ fail: return ret; } - static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id) { struct dpp_configurator *conf, *tmp; @@ -6453,7 +5280,6 @@ static int dpp_configurator_del(struct dpp_global *dpp, unsigned int id) return found ? 0 : -1; } - int dpp_configurator_remove(struct dpp_global *dpp, const char *id) { unsigned int id_val; @@ -6469,7 +5295,6 @@ int dpp_configurator_remove(struct dpp_global *dpp, const char *id) return dpp_configurator_del(dpp, id_val); } - int dpp_configurator_get_key_id(struct dpp_global *dpp, unsigned int id, char *buf, size_t buflen) { @@ -6497,7 +5322,6 @@ struct dpp_global * dpp_global_init(struct dpp_global_config *config) return dpp; } - void dpp_global_clear(struct dpp_global *dpp) { if (!dpp) @@ -6507,7 +5331,6 @@ void dpp_global_clear(struct dpp_global *dpp) dpp_configurator_del(dpp, 0); } - void dpp_global_deinit(struct dpp_global *dpp) { dpp_global_clear(dpp); diff --git a/components/wpa_supplicant/src/common/dpp.h b/components/wpa_supplicant/src/common/dpp.h index 61c056c380..da09aba2e8 100644 --- a/components/wpa_supplicant/src/common/dpp.h +++ b/components/wpa_supplicant/src/common/dpp.h @@ -18,6 +18,7 @@ #include "utils/common.h" #include "esp_err.h" #include "esp_dpp.h" +#include "crypto/crypto.h" struct crypto_ecdh; struct hostapd_ip_addr; @@ -594,5 +595,64 @@ void dpp_global_deinit(struct dpp_global *dpp); int dpp_connect(uint8_t *bssid, bool pdr_done); esp_err_t esp_dpp_start_net_intro_protocol(uint8_t *bssid); +/* dpp_crypto.c */ + +struct dpp_signed_connector_info { + unsigned char *payload; + size_t payload_len; +}; + +const struct dpp_curve_params *dpp_get_curve_name(const char *name); +const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name); +const struct dpp_curve_params * dpp_get_curve_group_id(int group_id); +void dpp_debug_print_key(const char *title, struct crypto_key *key); +int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen); +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac); +struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, + const u8 *buf, size_t len); +struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve); +struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len); +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); +char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + u8 *privkey, size_t privkey_len); +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, + unsigned int hash_len); +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, + unsigned int hash_len); +int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer, + u8 *secret, size_t *secret_len); +struct wpabuf *dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func); +int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash); +enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, + struct crypto_key *csign_pub, const char *connector); +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); +int dpp_auth_derive_l_responder(struct dpp_authentication *auth); +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, + unsigned int hash_len); +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid); +int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len); +struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key); +struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix); +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); +int dpp_derive_bk_ke(struct dpp_authentication *auth); +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len); + +/* dpp crypto apis */ + #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/components/wpa_supplicant/src/common/dpp_crypto.c b/components/wpa_supplicant/src/common/dpp_crypto.c new file mode 100644 index 0000000000..c5a4f5b7f9 --- /dev/null +++ b/components/wpa_supplicant/src/common/dpp_crypto.c @@ -0,0 +1,1191 @@ +/* + * DPP functionality shared between hostapd and wpa_supplicant + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include + +#include "utils/common.h" +#include "common/defs.h" +#include "utils/base64.h" +#include "utils/json.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/sha256.h" +#include "dpp.h" +#include "esp_dpp_i.h" + +const struct dpp_curve_params dpp_curves[] = { + /* The mandatory to support and the default NIST P-256 curve needs to + * be the first entry on this list. */ + { "secp256r1", 32, 32, 16, 32, "P-256", 19, "ES256" }, + { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, + { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, + { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, + { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, + { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, + { NULL, 0, 0, 0, 0, NULL, 0, NULL } +}; + +const struct dpp_curve_params *dpp_get_curve_name(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (os_strcmp(name, dpp_curves[i].name) == 0 || + (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) + return &dpp_curves[i]; + } + return NULL; +} + +const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0) + return &dpp_curves[i]; + } + + return NULL; +} + +const struct dpp_curve_params * dpp_get_curve_group_id(int group_id) +{ + unsigned int i; + + if (!group_id) + return NULL; + + for (i = 0; dpp_curves[i].ike_group; i++) { + if (group_id == dpp_curves[i].ike_group) + return &dpp_curves[i]; + } + return NULL; +} + +void dpp_debug_print_key(const char *title, struct crypto_key *key) +{ + crypto_ec_key_debug_print(title, key); +} + +int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + if (curve->hash_len == 32) + return sha256_vector(num_elem, addr, len, mac); +#ifndef ESP_SUPPLICANT + if (curve->hash_len == 48) + return sha384_vector(num_elem, addr, len, mac); + if (curve->hash_len == 64) + return sha512_vector(num_elem, addr, len, mac); +#endif + return -1; +} + +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen) +{ + if (hash_len == 32) + return hmac_sha256_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); +#ifndef ESP_SUPPLICANT + if (hash_len == 48) + return hmac_sha384_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 64) + return hmac_sha512_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); +#endif + return -1; +} + +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256_vector(key, key_len, num_elem, addr, len, + mac); +#ifndef ESP_SUPPLICANT + if (hash_len == 48) + return hmac_sha384_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 64) + return hmac_sha512_vector(key, key_len, num_elem, addr, len, + mac); +#endif + return -1; +} + +int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256(key, key_len, data, data_len, mac); +#ifndef ESP_SUPPLICANT + if (hash_len == 48) + return hmac_sha384(key, key_len, data, data_len, mac); + if (hash_len == 64) + return hmac_sha512(key, key_len, data, data_len, mac); +#endif + return -1; +} + +struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, + const u8 *buf, size_t len) +{ + const struct crypto_ec_group *group; + struct crypto_key *pkey = NULL; + + if (len & 1) + return NULL; + + group = crypto_ec_get_group_from_key(group_key); + if (group) + pkey = crypto_ec_set_pubkey_point(group, buf, + len); + else + wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); + + return pkey; +} + +struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve) +{ + struct crypto_key *key = crypto_ec_key_gen(curve->ike_group); + + wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); + dpp_debug_print_key("Own generated key", key); + + return key; +} + +struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len) +{ + struct crypto_ec_group *group; + struct crypto_key *pkey = crypto_ec_key_parse_priv(privkey, privkey_len); + int id; + + if (!pkey) { + wpa_printf(MSG_ERROR, "%s: failed to get pkey", __func__); + return NULL; + } + group = crypto_ec_get_group_from_key(pkey); + if (!group) { + crypto_ec_free_key(pkey); + return NULL; + } + id = crypto_ec_get_curve_id(group); + *curve = dpp_get_curve_group_id(id); + if (!*curve) { + wpa_printf(MSG_INFO, + "DPP: Unsupported curve (id=%d) in pre-assigned key", + id); + crypto_ec_free_key(pkey); + return NULL; + } + + return pkey; +} + +struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key) +{ + unsigned char *der = NULL; + struct wpabuf *ret = NULL; + int der_len; + + der_len = crypto_ec_write_pub_key(key, &der); + if (!der) { + printf("failed to get der for bootstrapping key\n"); + return NULL; + } + ret = wpabuf_alloc_copy(der, der_len); + + os_free(der); + return ret; +} + +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) +{ + struct wpabuf *der; + int res; + const u8 *addr[1]; + size_t len[1]; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + return -1; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + addr[0] = wpabuf_head(der); + len[0] = wpabuf_len(der); + res = sha256_vector(1, addr, len, bi->pubkey_hash); + if (res < 0) + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + else + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, + SHA256_MAC_LEN); + wpabuf_free(der); + return res; +} + +char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + u8 *privkey, size_t privkey_len) +{ + char *base64 = NULL; + char *pos, *end; + size_t len; + struct wpabuf *der = NULL; + const u8 *addr[1]; + int res; + + if (!curve) { + bi->curve = &dpp_curves[0]; + } else { + bi->curve = dpp_get_curve_name(curve); + if (!bi->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", + curve); + return NULL; + } + } + if (privkey) + bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); + else + bi->pubkey = dpp_gen_keypair(bi->curve); + if (!bi->pubkey) + goto fail; + bi->own = 1; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + addr[0] = wpabuf_head(der); + len = wpabuf_len(der); + res = sha256_vector(1, addr, &len, bi->pubkey_hash); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, + SHA256_MAC_LEN); + + base64 = (char *)base64_encode(wpabuf_head(der), wpabuf_len(der), &len); + wpabuf_free(der); + der = NULL; + if (!base64) + goto fail; + pos = base64; + end = pos + len; + for (;;) { + pos = os_strchr(pos, '\n'); + if (!pos) + break; + os_memmove(pos, pos + 1, end - pos); + } + return base64; +fail: + os_free(base64); + wpabuf_free(der); + return NULL; +} + +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, + unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "first intermediate key"; + int res; + + /* k1 = HKDF(<>, "first intermediate key", M.x) */ + + /* HKDF-Extract(<>, M.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); + forced_memzero(prk, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", + k1, hash_len); + return 0; +} + +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, + unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "second intermediate key"; + int res; + + /* k2 = HKDF(<>, "second intermediate key", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); + forced_memzero(prk, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", + k2, hash_len); + return 0; +} + +int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer, + u8 *secret, size_t *secret_len) +{ + return crypto_ecdh(own, peer, secret, secret_len); +} + +struct wpabuf * +dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func) +{ + struct json_token *root, *token; + struct wpabuf *kid = NULL; + + root = json_parse((const char *) prot_hdr, prot_hdr_len); + if (!root) { + wpa_printf(MSG_DEBUG, + "DPP: JSON parsing failed for JWS Protected Header"); + goto fail; + } + + if (root->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: JWS Protected Header root is not an object"); + goto fail; + } + + token = json_get_member(root, "typ"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", + token->string); + if (os_strcmp(token->string, "dppCon") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header typ=%s", + token->string); + goto fail; + } + + token = json_get_member(root, "alg"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", + token->string); + if (os_strcmp(token->string, curve->jws_alg) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", + token->string, curve->jws_alg); + goto fail; + } + + if (os_strcmp(token->string, "ES256") == 0 || + os_strcmp(token->string, "BS256") == 0) { + *hash_func = CRYPTO_HASH_ALG_SHA256; + } else { + *hash_func = -1; + wpa_printf(MSG_ERROR, "Unsupported JWS Protected Header alg=%s", token->string); + } + + kid = json_get_member_base64url(root, "kid"); + if (!kid) { + wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", + kid); + +fail: + json_free(root); + return kid; +} + +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len) +{ + struct crypto_key *pkey; + const unsigned char *p; + struct crypto_ec_group *group; + int id; + + if (sha256_vector(1, (const u8 **) &data, &data_len, + bi->pubkey_hash) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); + + /* DER encoded ASN.1 SubjectPublicKeyInfo + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * subjectPublicKey = compressed format public key per ANSI X9.63 + * algorithm = ecPublicKey (1.2.840.10045.2.1) + * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., + * prime256v1 (1.2.840.10045.3.1.7) + */ + + p = data; + + pkey = crypto_ec_parse_subpub_key((unsigned char *)p, data_len); + + if (!pkey) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); + return -1; + } + + if (!crypto_is_ec_key(pkey)) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo does not describe an EC key"); + crypto_ec_free_key(pkey); + return -1; + } + + group = crypto_ec_get_group_from_key(pkey); + if (!group) { + return -1; + } + id = crypto_ec_get_curve_id(group); + bi->curve = dpp_get_curve_group_id(id); + if (!bi->curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo curve"); + goto fail; + } + + bi->pubkey = pkey; + return 0; +fail: + crypto_ec_free_key(pkey); + return -1; + +} + +int dpp_derive_bk_ke(struct dpp_authentication *auth) +{ + size_t nonce_len = auth->curve->nonce_len; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + const char *info_ke = "DPP Key"; + u8 prk[DPP_MAX_HASH_LEN]; + int res; + const u8 *addr[3]; + size_t len[3]; + size_t num_elem = 0; + unsigned int hash_len = auth->curve->hash_len; + + if (!auth->Mx_len || !auth->Nx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Mx/Nx not available - cannot derive ke"); + return -1; + } + + /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */ + + /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ + os_memcpy(nonces, auth->i_nonce, nonce_len); + os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); + addr[num_elem] = auth->Mx; + len[num_elem] = auth->Mx_len; + num_elem++; + addr[num_elem] = auth->Nx; + len[num_elem] = auth->Nx_len; + num_elem++; + if (auth->peer_bi && auth->own_bi) { + if (!auth->Lx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Lx not available - cannot derive ke"); + return -1; + } + addr[num_elem] = auth->Lx; + len[num_elem] = auth->secret_len; + num_elem++; + } + res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, + num_elem, addr, len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, auth->ke, hash_len); + forced_memzero(prk, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)", + auth->ke, hash_len); + return 0; +} + +struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix) +{ + int len, res; + struct wpabuf *buf; + unsigned char *pos = NULL; + + len = crypto_ec_get_publickey_buf(pkey, pos, 0); + if (len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to determine public key encoding length"); + return NULL; + } + + buf = wpabuf_alloc(len); + if (!buf) { + return NULL; + } + + pos = wpabuf_put(buf, len); + + res = crypto_ec_get_publickey_buf(pkey, pos, len); + if (res != len) { + wpa_printf(MSG_ERROR, + "DDP: Failed to encode public key (res=%d/%d)", + res, len); + wpabuf_free(buf); + return NULL; + } + + if (!prefix) { + /* Remove 0x04 prefix to match DPP definition */ + pos = wpabuf_mhead(buf); + os_memmove(pos, pos + 1, len - 1); + buf->used--; + } + + return buf; +} + +int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash) +{ + struct wpabuf *uncomp; + int res; + u8 hash[SHA256_MAC_LEN]; + const u8 *addr[1]; + size_t len[1]; + + if (wpabuf_len(r_hash) != SHA256_MAC_LEN) + return -1; + uncomp = dpp_get_pubkey_point(pub, 1); + if (!uncomp) + return -1; + addr[0] = wpabuf_head(uncomp); + len[0] = wpabuf_len(uncomp); + wpa_hexdump(MSG_DEBUG, "DPP: Uncompressed public key", + addr[0], len[0]); + res = sha256_vector(1, addr, len, hash); + wpabuf_free(uncomp); + if (res < 0) + return -1; + if (os_memcmp(hash, wpabuf_head(r_hash), SHA256_MAC_LEN) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Received hash value does not match calculated public key hash value"); + wpa_hexdump(MSG_DEBUG, "DPP: Calculated hash", + hash, SHA256_MAC_LEN); + return -1; + } + return 0; +} + +enum dpp_status_error +dpp_process_signed_connector(struct dpp_signed_connector_info *info, + struct crypto_key *csign_pub, const char *connector) +{ + enum dpp_status_error ret = 255; + const char *pos, *end, *signed_start, *signed_end; + struct wpabuf *kid = NULL; + unsigned char *prot_hdr = NULL, *signature = NULL; + size_t prot_hdr_len = 0, signature_len = 0, signed_len; + struct crypto_bignum *r = NULL, *s = NULL; + const struct dpp_curve_params *curve; + const struct crypto_ec_group *group; + int id, hash_func = -1; + u8 *hash = NULL; + + group = crypto_ec_get_group_from_key(csign_pub); + if (!group) + goto fail; + id = crypto_ec_get_curve_id(group); + curve = dpp_get_curve_group_id(id); + if (!curve) + goto fail; + wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); + os_memset(info, 0, sizeof(*info)); + + signed_start = pos = connector; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, "DPP: Missing dot(1) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + prot_hdr = base64_url_decode(pos, end - pos, &prot_hdr_len); + if (!prot_hdr) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Protected Header"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Protected Header", + (u8 *)prot_hdr, prot_hdr_len); + kid = dpp_parse_jws_prot_hdr(curve, prot_hdr, prot_hdr_len, &hash_func); + if (!kid) { + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + if (wpabuf_len(kid) != SHA256_MAC_LEN) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector JWS Protected Header kid length: %u (expected %u)", + (unsigned int) wpabuf_len(kid), SHA256_MAC_LEN); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + pos = end + 1; + end = os_strchr(pos, '.'); + if (!end) { + wpa_printf(MSG_DEBUG, + "DPP: Missing dot(2) in signedConnector"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + signed_end = end - 1; + info->payload = base64_url_decode(pos, end - pos, &info->payload_len); + if (!info->payload) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector JWS Payload"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: signedConnector - JWS Payload", + (u8 *)info->payload, info->payload_len); + pos = end + 1; + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to base64url decode signedConnector signature"); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector - signature", + signature, signature_len); + + if (dpp_check_pubkey_match(csign_pub, kid) < 0) { + ret = DPP_STATUS_NO_MATCH; + goto fail; + } + + if (signature_len & 0x01) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected signedConnector signature length (%d)", + (int) signature_len); + ret = DPP_STATUS_INVALID_CONNECTOR; + goto fail; + } + + /* JWS Signature encodes the signature (r,s) as two octet strings. Need + * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ + r = crypto_bignum_init_set(signature, signature_len / 2); + s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2); + + signed_len = signed_end - signed_start + 1; + hash = os_malloc(curve->hash_len); + if (!hash) { + wpa_printf(MSG_ERROR, "malloc failed"); + goto fail; + } + + if (hash_func == CRYPTO_HASH_ALG_SHA256) { + if ((sha256_vector(1, (const u8 **) &signed_start, &signed_len, hash)) != 0) { + goto fail; + } + } else { + goto fail; + } + + if ((crypto_edcsa_sign_verify((unsigned char *)hash, r, s, + csign_pub, curve->hash_len)) != 0) { + goto fail; + } + + ret = DPP_STATUS_OK; +fail: + if (hash != NULL) { + os_free(hash); + } + os_free(prot_hdr); + wpabuf_free(kid); + os_free(signature); + crypto_bignum_deinit(r, 0); + crypto_bignum_deinit(s, 0); + return ret; +} + +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len) +{ + struct crypto_key *csign; + char *signed_connector = NULL; + enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; + const unsigned char *p; + + p = csign_key; + csign = crypto_ec_parse_subpub_key(p, csign_key_len); + if (!csign) { + wpa_printf(MSG_ERROR, + "DPP: Failed to parse local C-sign-key information"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Peer signedConnector", + (u8 *)peer_connector, peer_connector_len); + signed_connector = os_malloc(peer_connector_len + 1); + if (!signed_connector) + goto fail; + os_memcpy(signed_connector, peer_connector, peer_connector_len); + signed_connector[peer_connector_len] = '\0'; + + res = dpp_process_signed_connector(info, csign, signed_connector); +fail: + os_free(signed_connector); + crypto_ec_free_key(csign); + return res; + +} + +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) +{ + struct wpabuf *pix, *prx, *bix, *brx; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 zero = 0; + int res = -1; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + addr[num_elem] = &zero; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) +{ + struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 one = 1; + int res = -1; + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + if (!auth->peer_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + if (!auth->own_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = &one; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + +int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len) +{ + if (crypto_bignum_to_bin(bn, pos, len, 0) < 0) + return -1; + + return 0; +} + +int dpp_auth_derive_l_responder(struct dpp_authentication *auth) +{ + struct crypto_ec_group *group; + struct crypto_ec_point *l = NULL; + struct crypto_ec_point *BI_point; + struct crypto_bignum *lx, *sum, *q; + struct crypto_bignum *bR_bn, *pR_bn; + int ret = -1; + + /* L = ((bR + pR) modulo q) * BI */ + + sum = crypto_bignum_init(); + q = crypto_bignum_init(); + lx = crypto_bignum_init(); + if (!sum || !q || !lx) + goto fail; + + BI_point = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); + group = crypto_ec_get_group_from_key(auth->peer_bi->pubkey); + bR_bn = crypto_ec_key_get_private_key(auth->own_bi->pubkey); + pR_bn = crypto_ec_key_get_private_key(auth->own_protocol_key); + + if (!bR_bn || !pR_bn) + goto fail; + + if ((crypto_get_order(group, q) != 0) || + (crypto_bignum_addmod(sum, bR_bn, pR_bn, q) != 0)) + goto fail; + + l = crypto_ec_point_init((struct crypto_ec *)group); + if (!l || (crypto_ec_point_mul((struct crypto_ec *)group, BI_point, sum, l) != 0) || + (crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0)) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", __func__); + goto fail; + } + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + crypto_ec_point_deinit(l, 1); + crypto_bignum_deinit(lx, 0); + crypto_bignum_deinit(sum, 0); + crypto_bignum_deinit(q, 0); + + return ret; +} + +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) +{ + struct crypto_ec_group *group; + struct crypto_ec_point *l = NULL, *sum = NULL; + struct crypto_ec_point *BR_point, *PR_point; + struct crypto_bignum *lx; + struct crypto_bignum *bI_bn; + int ret = -1; + + /* L = bI * (BR + PR) */ + + lx = crypto_bignum_init(); + if (!lx) + goto fail; + BR_point = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); + PR_point = crypto_ec_key_get_public_key(auth->peer_protocol_key); + + group = crypto_ec_get_group_from_key(auth->own_bi->pubkey); + bI_bn = crypto_ec_key_get_private_key(auth->own_bi->pubkey); + if (!group || !bI_bn) + goto fail; + sum = crypto_ec_point_init((struct crypto_ec *)group); + l = crypto_ec_point_init((struct crypto_ec *)group); + if (!sum || !l || + crypto_ec_point_add((struct crypto_ec *)group, BR_point, PR_point, sum) != 0 || + crypto_ec_point_mul((struct crypto_ec *)group, sum, bI_bn, l) != 0 || + crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", __func__); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + crypto_ec_point_deinit(l, 1); + crypto_ec_point_deinit(sum, 1); + crypto_bignum_deinit(lx, 0); + + + return ret; +} + +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, + unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "DPP PMK"; + int res; + + /* PMK = HKDF(<>, "DPP PMK", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, pmk, hash_len); + forced_memzero(prk, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: PMK = HKDF-Expand(PRK, info, L)", + pmk, hash_len); + return 0; +} + +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid) +{ + struct wpabuf *nkx, *pkx; + int ret = -1, res; + const u8 *addr[2]; + size_t len[2]; + u8 hash[SHA256_MAC_LEN]; + + /* PMKID = Truncate-128(H(min(NK.x, PK.x) | max(NK.x, PK.x))) */ + nkx = dpp_get_pubkey_point(own_key, 0); + pkx = dpp_get_pubkey_point(peer_key, 0); + if (!nkx || !pkx) + goto fail; + addr[0] = wpabuf_head(nkx); + len[0] = wpabuf_len(nkx) / 2; + addr[1] = wpabuf_head(pkx); + len[1] = wpabuf_len(pkx) / 2; + if (len[0] != len[1]) + goto fail; + if (os_memcmp(addr[0], addr[1], len[0]) > 0) { + addr[0] = wpabuf_head(pkx); + addr[1] = wpabuf_head(nkx); + } + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 1", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash payload 2", addr[1], len[1]); + res = sha256_vector(2, addr, len, hash); + if (res < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: PMKID hash output", hash, SHA256_MAC_LEN); + os_memcpy(pmkid, hash, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "DPP: PMKID", pmkid, PMKID_LEN); + ret = 0; +fail: + wpabuf_free(nkx); + wpabuf_free(pkx); + return ret; +} + +#ifdef CONFIG_TESTING_OPTIONS +int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve) +{ + return 0; +} + +char * dpp_corrupt_connector_signature(const char *connector) +{ + char *tmp, *pos, *signed3 = NULL; + unsigned char *signature = NULL; + size_t signature_len = 0, signed3_len; + + tmp = os_zalloc(os_strlen(connector) + 5); + if (!tmp) + goto fail; + os_memcpy(tmp, connector, os_strlen(connector)); + + pos = os_strchr(tmp, '.'); + if (!pos) + goto fail; + + pos = os_strchr(pos + 1, '.'); + if (!pos) + goto fail; + pos++; + + wpa_printf(MSG_DEBUG, "DPP: Original base64url encoded signature: %s", + pos); + signature = base64_url_decode(pos, os_strlen(pos), &signature_len); + if (!signature || signature_len == 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Original Connector signature", + signature, signature_len); + signature[signature_len - 1] ^= 0x01; + wpa_hexdump(MSG_DEBUG, "DPP: Corrupted Connector signature", + signature, signature_len); + signed3 = base64_url_encode(signature, signature_len, &signed3_len); + if (!signed3) + goto fail; + os_memcpy(pos, signed3, signed3_len); + pos[signed3_len] = '\0'; + wpa_printf(MSG_DEBUG, "DPP: Corrupted base64url encoded signature: %s", + pos); + +out: + os_free(signature); + os_free(signed3); + return tmp; +fail: + os_free(tmp); + tmp = NULL; + goto out; +} +#endif /* CONFIG_TESTING_OPTIONS */ diff --git a/components/wpa_supplicant/src/crypto/crypto.h b/components/wpa_supplicant/src/crypto/crypto.h index 7d7e458020..1181c4d148 100644 --- a/components/wpa_supplicant/src/crypto/crypto.h +++ b/components/wpa_supplicant/src/crypto/crypto.h @@ -798,7 +798,7 @@ const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e); */ /** - * crypto_ec_get_b - Get 'b' coeffiecient of an EC group's curve + * crypto_ec_get_b - Get 'b' coefficient of an EC group's curve * @e: EC context from crypto_ec_init() * Returns: 'b' coefficient (bignum) of the group */ @@ -949,19 +949,19 @@ int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len); struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key); /** - * crypto_ec_get_private_key - Get EC private key (in bignum format) + * crypto_ec_key_get_private_key - Get EC private key (in bignum format) * @key: crypto key * Returns: Private key */ -struct crypto_bignum *crypto_ec_get_private_key(struct crypto_key *key); +struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_key *key); /** - * crypto_ec_get_key - Read key from character stream + * crypto_ec_key_parse_priv - Read key from character stream * @privkey: Private key * @privkey_len: private key len * Returns: Crypto key */ -struct crypto_key *crypto_ec_get_key(const u8 *privkey, size_t privkey_len); +struct crypto_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len); /** * crypto_ec_get_mbedtls_to_nist_group_id - get nist group from mbedtls internal group @@ -1029,14 +1029,14 @@ struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len int crypto_is_ec_key(struct crypto_key *key); /** - * crypto_ec_gen_keypair: generate crypto ec keypair + * crypto_ec_key_gen: generate crypto ec keypair * @ike_group: grpup * Return: crypto key */ -struct crypto_key * crypto_ec_gen_keypair(u16 ike_group); +struct crypto_key * crypto_ec_key_gen(u16 ike_group); /** - * crypto_ec_write_pub_key: return public key in charater buffer + * crypto_ec_write_pub_key: return public key in character buffer * @key: crypto key * @der_len: buffer len * Return: public key buffer @@ -1047,7 +1047,7 @@ int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf); * crypto_ec_set_pubkey_point: set bignum point on ec curve * @group: ec group * @buf: x,y coordinate - * @len: length of x and y coordiate + * @len: length of x and y coordinate * Return : crypto key */ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, @@ -1058,19 +1058,19 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro */ void crypto_ec_free_key(struct crypto_key *key); /** - * crypto_debug_print_ec_key: print ec key + * crypto_ec_key_debug_print: print ec key * @title: title * @key: crypto key * Return: None */ -void crypto_debug_print_ec_key(const char *title, struct crypto_key *key); +void crypto_ec_key_debug_print(const char *title, struct crypto_key *key); /** - * crypto_ec_get_public_key: Public key from crypto key + * crypto_ec_key_get_public_key: Public key from crypto key * @key: crypto key * Return : Public key */ -struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key); +struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_key *key); /** * crypto_get_order: free crypto key @@ -1079,7 +1079,7 @@ struct crypto_ec_point *crypto_ec_get_public_key(struct crypto_key *key); int crypto_get_order(struct crypto_ec_group *group, struct crypto_bignum *x); /** - * crypto_ec_get_affine_coordinates : get affine corrdinate of ec curve + * crypto_ec_get_affine_coordinates : get affine coordinate of ec curve * @e: ec curve * @pt: point * @x: x coordinate @@ -1105,7 +1105,7 @@ int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2); /* * crypto_write_pubkey_der: get public key in der format * @csign: key - * @key_buf: key buffer in charater format + * @key_buf: key buffer in character format * Return : len of char buffer if success */ int crypto_write_pubkey_der(struct crypto_key *csign, unsigned char **key_buf); @@ -1120,8 +1120,8 @@ void crypto_free_buffer(unsigned char *buf); /** * @crypto_ec_get_priv_key_der: get private key in der format * @key: key structure - * @key_data: key data in charater buffer - * @key_len = key length of charater buffer + * @key_data: key data in character buffer + * @key_len = key length of character buffer * Return : 0 if success */ int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len); From fbde07c95377b39d3fad1b4029405ae402f467a1 Mon Sep 17 00:00:00 2001 From: aditi Date: Tue, 23 Jul 2024 18:27:43 +0530 Subject: [PATCH 2/3] feat(esp_wifi): Replace crypto_key with crypto_ec_key Replaced all occurances of crypto_key with crypto_ec_key struct to make the code more consistent with upstream. --- .../src/crypto/crypto_mbedtls-ec.c | 52 +++++++++---------- components/wpa_supplicant/src/common/dpp.c | 20 +++---- components/wpa_supplicant/src/common/dpp.h | 34 ++++++------ .../wpa_supplicant/src/common/dpp_crypto.c | 30 +++++------ components/wpa_supplicant/src/crypto/crypto.h | 46 ++++++++-------- 5 files changed, 91 insertions(+), 91 deletions(-) diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index 0a86120dd2..18a19f92fc 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -453,7 +453,7 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, (const mbedtls_ecp_point *) b); } -int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2) +int crypto_ec_key_compare(struct crypto_ec_key *key1, struct crypto_ec_key *key2) { int ret = 0; mbedtls_entropy_context entropy; @@ -488,7 +488,7 @@ void crypto_debug_print_point(const char *title, struct crypto_ec *e, wpa_hexdump(MSG_ERROR, "y:", y, 32); } -static struct crypto_key *crypto_alloc_key(void) +static struct crypto_ec_key *crypto_alloc_key(void) { mbedtls_pk_context *key = os_malloc(sizeof(*key)); @@ -498,14 +498,14 @@ static struct crypto_key *crypto_alloc_key(void) } mbedtls_pk_init(key); - return (struct crypto_key *)key; + return (struct crypto_ec_key *)key; } -struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, +struct crypto_ec_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, const u8 *buf, size_t len) { mbedtls_ecp_point *point = NULL; - struct crypto_key *pkey = NULL; + struct crypto_ec_key *pkey = NULL; int ret; mbedtls_pk_context *key = (mbedtls_pk_context *)crypto_alloc_key(); mbedtls_ecp_group *ecp_grp = (mbedtls_ecp_group *)group; @@ -543,7 +543,7 @@ struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *gro mbedtls_ecp_copy(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(Q), point); mbedtls_ecp_group_load(&mbedtls_pk_ec(*key)->MBEDTLS_PRIVATE(grp), ecp_grp->id); - pkey = (struct crypto_key *)key; + pkey = (struct crypto_ec_key *)key; crypto_ec_point_deinit((struct crypto_ec_point *)point, 0); return pkey; fail: @@ -557,21 +557,21 @@ fail: return pkey; } -void crypto_ec_free_key(struct crypto_key *key) +void crypto_ec_free_key(struct crypto_ec_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; mbedtls_pk_free(pkey); os_free(key); } -struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_key *key) +struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_ec_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; return (struct crypto_ec_point *)&mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(Q); } -int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len) +int crypto_ec_get_priv_key_der(struct crypto_ec_key *key, unsigned char **key_data, int *key_len) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; char *der_data = os_malloc(ECP_PRV_DER_MAX_BYTES); @@ -599,7 +599,7 @@ int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, return 0; } -struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key) +struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_ec_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -614,14 +614,14 @@ int crypto_ec_key_group(struct crypto_ec_key *key) return iana_group; } -struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_key *key) +struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_ec_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; return ((struct crypto_bignum *) & (mbedtls_pk_ec(*pkey)->MBEDTLS_PRIVATE(d))); } -int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) +int crypto_ec_get_publickey_buf(struct crypto_ec_key *key, u8 *key_buf, int len) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; unsigned char buf[MBEDTLS_MPI_MAX_SIZE + 10]; /* tag, length + MPI */ @@ -644,7 +644,7 @@ int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len) return pk_len; } -int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) +int crypto_write_pubkey_der(struct crypto_ec_key *key, unsigned char **key_buf) { unsigned char *buf = os_malloc(ECP_PUB_DER_MAX_BYTES); @@ -669,7 +669,7 @@ int crypto_write_pubkey_der(struct crypto_key *key, unsigned char **key_buf) return len; } -struct crypto_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len) +struct crypto_ec_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len) { int ret; mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); @@ -685,7 +685,7 @@ struct crypto_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_le goto fail; } - return (struct crypto_key *)kctx; + return (struct crypto_ec_key *)kctx; fail: mbedtls_pk_free(kctx); @@ -728,7 +728,7 @@ int crypto_ec_get_curve_id(const struct crypto_ec_group *group) return (crypto_ec_get_mbedtls_to_nist_group_id(grp->id)); } -int crypto_ecdh(struct crypto_key *key_own, struct crypto_key *key_peer, +int crypto_ecdh(struct crypto_ec_key *key_own, struct crypto_ec_key *key_peer, u8 *secret, size_t *secret_len) { mbedtls_ecdh_context *ctx = NULL; @@ -795,7 +795,7 @@ fail: } int crypto_ecdsa_get_sign(unsigned char *hash, - const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hash_len) + const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_ec_key *csign, int hash_len) { int ret = -1; mbedtls_pk_context *pkey = (mbedtls_pk_context *)csign; @@ -821,7 +821,7 @@ fail: } int crypto_edcsa_sign_verify(const unsigned char *hash, - const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_key *csign, int hlen) + const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_ec_key *csign, int hlen) { /* (mbedtls_ecdsa_context *) */ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)csign); @@ -841,7 +841,7 @@ int crypto_edcsa_sign_verify(const unsigned char *hash, return ret; } -void crypto_ec_key_debug_print(const char *title, struct crypto_key *key) +void crypto_ec_key_debug_print(const char *title, struct crypto_ec_key *key) { #ifdef DEBUG_PRINT mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -861,7 +861,7 @@ void crypto_ec_key_debug_print(const char *title, struct crypto_key *key) #endif } -struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len) +struct crypto_ec_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len) { int ret; mbedtls_pk_context *pkey = (mbedtls_pk_context *)crypto_alloc_key(); @@ -871,7 +871,7 @@ struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len } ret = mbedtls_pk_parse_subpubkey((unsigned char **)&p, p + len, pkey); if (ret == 0) { - return (struct crypto_key *)pkey; + return (struct crypto_ec_key *)pkey; } mbedtls_pk_free(pkey); @@ -879,13 +879,13 @@ struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len return NULL; } -int crypto_is_ec_key(struct crypto_key *key) +int crypto_is_ec_key(struct crypto_ec_key *key) { int ret = mbedtls_pk_can_do((mbedtls_pk_context *)key, MBEDTLS_PK_ECKEY); return ret; } -struct crypto_key * crypto_ec_key_gen(u16 ike_group) +struct crypto_ec_key * crypto_ec_key_gen(u16 ike_group) { mbedtls_pk_context *kctx = (mbedtls_pk_context *)crypto_alloc_key(); @@ -902,7 +902,7 @@ struct crypto_key * crypto_ec_key_gen(u16 ike_group) mbedtls_ecp_gen_key(MBEDTLS_ECP_DP_SECP256R1, mbedtls_pk_ec(*kctx), //get this from argument crypto_rng_wrapper, NULL); - return (struct crypto_key *)kctx; + return (struct crypto_ec_key *)kctx; fail: mbedtls_pk_free(kctx); os_free(kctx); @@ -1018,7 +1018,7 @@ int crypto_pk_write_formatted_pubkey_der(mbedtls_pk_context *key, unsigned char return ((int) len); } -int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf) +int crypto_ec_write_pub_key(struct crypto_ec_key *key, unsigned char **key_buf) { unsigned char output_buf[1600] = {0}; int len = crypto_pk_write_formatted_pubkey_der((mbedtls_pk_context *)key, output_buf, 1600, 1); @@ -1140,7 +1140,7 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, struct crypto_bignum *bn_x = NULL; struct crypto_ec_point *ec_pt = NULL; uint8_t *px = NULL, *py = NULL, *buf = NULL; - struct crypto_key *pkey = NULL; + struct crypto_ec_key *pkey = NULL; struct wpabuf *sh_secret = NULL; int secret_key = 0; diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index 968c7ff17b..75bf205e13 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -1730,7 +1730,7 @@ dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, unsigned int curr_chan, const u8 *hdr, const u8 *attr_start, size_t attr_len) { - struct crypto_key *pi = NULL; + struct crypto_ec_key *pi = NULL; size_t secret_len; const u8 *addr[2]; size_t len[2]; @@ -2275,7 +2275,7 @@ struct wpabuf * dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, const u8 *attr_start, size_t attr_len) { - struct crypto_key *pr; + struct crypto_ec_key *pr; size_t secret_len; const u8 *addr[2]; size_t len[2]; @@ -3203,7 +3203,7 @@ dpp_build_conf_start(struct dpp_authentication *auth, return buf; } -static int dpp_build_jwk(struct wpabuf *buf, const char *name, struct crypto_key *key, +static int dpp_build_jwk(struct wpabuf *buf, const char *name, struct crypto_ec_key *key, const char *kid, const struct dpp_curve_params *curve) { struct wpabuf *pub; @@ -3907,7 +3907,7 @@ static int dpp_parse_cred_legacy(struct dpp_config_obj *conf, return 0; } -static struct crypto_key * dpp_parse_jwk(struct json_token *jwk, +static struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk, const struct dpp_curve_params **key_curve) { struct json_token *token; @@ -3915,7 +3915,7 @@ static struct crypto_key * dpp_parse_jwk(struct json_token *jwk, struct wpabuf *x = NULL, *y = NULL; unsigned char *a = NULL; struct crypto_ec_group *group; - struct crypto_key *pkey = NULL; + struct crypto_ec_key *pkey = NULL; size_t len; token = json_get_member(jwk, "kty"); @@ -4077,7 +4077,7 @@ static int dpp_parse_connector(struct dpp_authentication *auth, { struct json_token *root, *groups, *netkey, *token; int ret = -1; - struct crypto_key *key = NULL; + struct crypto_ec_key *key = NULL; const struct dpp_curve_params *curve; unsigned int rules = 0; @@ -4144,7 +4144,7 @@ skip_groups: goto fail; dpp_debug_print_key("DPP: Received netAccessKey", key); - if (crypto_key_compare(key, auth->own_protocol_key) != 1) { + if (crypto_ec_key_compare(key, auth->own_protocol_key) != 1) { wpa_printf(MSG_DEBUG, "DPP: netAccessKey in connector does not match own protocol key"); #ifdef CONFIG_TESTING_OPTIONS @@ -4166,7 +4166,7 @@ fail: return ret; } -static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_key *csign) +static void dpp_copy_csign(struct dpp_config_obj *conf, struct crypto_ec_key *csign) { unsigned char *der = NULL; int der_len; @@ -4200,7 +4200,7 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, struct dpp_signed_connector_info info; struct json_token *token, *csign; int ret = -1; - struct crypto_key *csign_pub = NULL; + struct crypto_ec_key *csign_pub = NULL; const struct dpp_curve_params *key_curve = NULL; const char *signed_connector; @@ -4836,7 +4836,7 @@ dpp_peer_intro(struct dpp_introduction *intro, const char *own_connector, struct json_token *root = NULL, *netkey, *token; struct json_token *own_root = NULL; enum dpp_status_error ret = 255, res; - struct crypto_key *own_key = NULL, *peer_key = NULL; + struct crypto_ec_key *own_key = NULL, *peer_key = NULL; struct wpabuf *own_key_pub = NULL; const struct dpp_curve_params *curve, *own_curve; struct dpp_signed_connector_info info; diff --git a/components/wpa_supplicant/src/common/dpp.h b/components/wpa_supplicant/src/common/dpp.h index da09aba2e8..fcf80f2faa 100644 --- a/components/wpa_supplicant/src/common/dpp.h +++ b/components/wpa_supplicant/src/common/dpp.h @@ -164,7 +164,7 @@ struct dpp_bootstrap_info { unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq; int own; - struct crypto_key *pubkey; + struct crypto_ec_key *pubkey; u8 pubkey_hash[SHA256_MAC_LEN]; const struct dpp_curve_params *curve; unsigned int pkex_t; /* number of failures before dpp_pkex @@ -183,12 +183,12 @@ struct dpp_pkex { u8 peer_mac[ETH_ALEN]; char *identifier; char *code; - struct crypto_key *x; - struct crypto_key *y; + struct crypto_ec_key *x; + struct crypto_ec_key *y; u8 Mx[DPP_MAX_SHARED_SECRET_LEN]; u8 Nx[DPP_MAX_SHARED_SECRET_LEN]; u8 z[DPP_MAX_HASH_LEN]; - struct crypto_key *peer_bootstrap_key; + struct crypto_ec_key *peer_bootstrap_key; struct wpabuf *exchange_req; struct wpabuf *exchange_resp; unsigned int t; /* number of failures on code use */ @@ -251,8 +251,8 @@ struct dpp_authentication { u8 e_nonce[DPP_MAX_NONCE_LEN]; u8 i_capab; u8 r_capab; - struct crypto_key *own_protocol_key; - struct crypto_key *peer_protocol_key; + struct crypto_ec_key *own_protocol_key; + struct crypto_ec_key *peer_protocol_key; struct wpabuf *req_msg; struct wpabuf *resp_msg; /* Intersection of possible frequencies for initiating DPP @@ -321,7 +321,7 @@ struct dpp_configurator { struct dl_list list; unsigned int id; int own; - struct crypto_key *csign; + struct crypto_ec_key *csign; char *kid; const struct dpp_curve_params *curve; }; @@ -605,7 +605,7 @@ struct dpp_signed_connector_info { const struct dpp_curve_params *dpp_get_curve_name(const char *name); const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name); const struct dpp_curve_params * dpp_get_curve_group_id(int group_id); -void dpp_debug_print_key(const char *title, struct crypto_key *key); +void dpp_debug_print_key(const char *title, struct crypto_ec_key *key); int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, @@ -615,10 +615,10 @@ int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, const size_t *len, u8 *mac); int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac); -struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, +struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, const u8 *buf, size_t len); -struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve); -struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, +struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve); +struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, const u8 *privkey, size_t privkey_len); int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, @@ -627,13 +627,13 @@ int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len); int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len); -int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer, +int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, u8 *secret, size_t *secret_len); struct wpabuf *dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func); -int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash); +int dpp_check_pubkey_match(struct crypto_ec_key *pub, struct wpabuf *r_hash); enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, - struct crypto_key *csign_pub, const char *connector); + struct crypto_ec_key *csign_pub, const char *connector); int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); int dpp_auth_derive_l_responder(struct dpp_authentication *auth); @@ -641,10 +641,10 @@ int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len); int dpp_derive_pmkid(const struct dpp_curve_params *curve, - struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid); + struct crypto_ec_key *own_key, struct crypto_ec_key *peer_key, u8 *pmkid); int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len); -struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key); -struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix); +struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key); +struct wpabuf * dpp_get_pubkey_point(struct crypto_ec_key *pkey, int prefix); int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); int dpp_derive_bk_ke(struct dpp_authentication *auth); enum dpp_status_error diff --git a/components/wpa_supplicant/src/common/dpp_crypto.c b/components/wpa_supplicant/src/common/dpp_crypto.c index c5a4f5b7f9..67dd44be02 100644 --- a/components/wpa_supplicant/src/common/dpp_crypto.c +++ b/components/wpa_supplicant/src/common/dpp_crypto.c @@ -74,7 +74,7 @@ const struct dpp_curve_params * dpp_get_curve_group_id(int group_id) return NULL; } -void dpp_debug_print_key(const char *title, struct crypto_key *key) +void dpp_debug_print_key(const char *title, struct crypto_ec_key *key) { crypto_ec_key_debug_print(title, key); } @@ -146,11 +146,11 @@ int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, return -1; } -struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, +struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, const u8 *buf, size_t len) { const struct crypto_ec_group *group; - struct crypto_key *pkey = NULL; + struct crypto_ec_key *pkey = NULL; if (len & 1) return NULL; @@ -165,9 +165,9 @@ struct crypto_key * dpp_set_pubkey_point(struct crypto_key *group_key, return pkey; } -struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve) +struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) { - struct crypto_key *key = crypto_ec_key_gen(curve->ike_group); + struct crypto_ec_key *key = crypto_ec_key_gen(curve->ike_group); wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); dpp_debug_print_key("Own generated key", key); @@ -175,11 +175,11 @@ struct crypto_key * dpp_gen_keypair(const struct dpp_curve_params *curve) return key; } -struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, +struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, const u8 *privkey, size_t privkey_len) { struct crypto_ec_group *group; - struct crypto_key *pkey = crypto_ec_key_parse_priv(privkey, privkey_len); + struct crypto_ec_key *pkey = crypto_ec_key_parse_priv(privkey, privkey_len); int id; if (!pkey) { @@ -204,7 +204,7 @@ struct crypto_key * dpp_set_keypair(const struct dpp_curve_params **curve, return pkey; } -struct wpabuf * dpp_bootstrap_key_der(struct crypto_key *key) +struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key) { unsigned char *der = NULL; struct wpabuf *ret = NULL; @@ -365,7 +365,7 @@ int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, return 0; } -int dpp_ecdh(struct crypto_key *own, struct crypto_key *peer, +int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, u8 *secret, size_t *secret_len) { return crypto_ecdh(own, peer, secret, secret_len); @@ -442,7 +442,7 @@ fail: int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len) { - struct crypto_key *pkey; + struct crypto_ec_key *pkey; const unsigned char *p; struct crypto_ec_group *group; int id; @@ -565,7 +565,7 @@ int dpp_derive_bk_ke(struct dpp_authentication *auth) return 0; } -struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix) +struct wpabuf * dpp_get_pubkey_point(struct crypto_ec_key *pkey, int prefix) { int len, res; struct wpabuf *buf; @@ -604,7 +604,7 @@ struct wpabuf * dpp_get_pubkey_point(struct crypto_key *pkey, int prefix) return buf; } -int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash) +int dpp_check_pubkey_match(struct crypto_ec_key *pub, struct wpabuf *r_hash) { struct wpabuf *uncomp; int res; @@ -637,7 +637,7 @@ int dpp_check_pubkey_match(struct crypto_key *pub, struct wpabuf *r_hash) enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, - struct crypto_key *csign_pub, const char *connector) + struct crypto_ec_key *csign_pub, const char *connector) { enum dpp_status_error ret = 255; const char *pos, *end, *signed_start, *signed_end; @@ -776,7 +776,7 @@ dpp_check_signed_connector(struct dpp_signed_connector_info *info, const u8 *csign_key, size_t csign_key_len, const u8 *peer_connector, size_t peer_connector_len) { - struct crypto_key *csign; + struct crypto_ec_key *csign; char *signed_connector = NULL; enum dpp_status_error res = DPP_STATUS_INVALID_CONNECTOR; const unsigned char *p; @@ -1096,7 +1096,7 @@ int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, } int dpp_derive_pmkid(const struct dpp_curve_params *curve, - struct crypto_key *own_key, struct crypto_key *peer_key, u8 *pmkid) + struct crypto_ec_key *own_key, struct crypto_ec_key *peer_key, u8 *pmkid) { struct wpabuf *nkx, *pkx; int ret = -1, res; diff --git a/components/wpa_supplicant/src/crypto/crypto.h b/components/wpa_supplicant/src/crypto/crypto.h index 1181c4d148..f665e21713 100644 --- a/components/wpa_supplicant/src/crypto/crypto.h +++ b/components/wpa_supplicant/src/crypto/crypto.h @@ -932,6 +932,9 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, const struct crypto_ec_point *a, const struct crypto_ec_point *b); + +struct crypto_ec_key; + /** * crypto_ec_get_publickey_buf - Write EC public key to buffer * @key: crypto key @@ -939,21 +942,21 @@ int crypto_ec_point_cmp(const struct crypto_ec *e, * @len: length of buffer * Returns: 0 on success, non-zero otherwise */ -int crypto_ec_get_publickey_buf(struct crypto_key *key, u8 *key_buf, int len); +int crypto_ec_get_publickey_buf(struct crypto_ec_key *key, u8 *key_buf, int len); /** * crypto_ec_get_group_from_key - Write EC group from key * @key: crypto key * Returns: EC group */ -struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_key *key); +struct crypto_ec_group *crypto_ec_get_group_from_key(struct crypto_ec_key *key); /** * crypto_ec_key_get_private_key - Get EC private key (in bignum format) * @key: crypto key * Returns: Private key */ -struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_key *key); +struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_ec_key *key); /** * crypto_ec_key_parse_priv - Read key from character stream @@ -961,7 +964,7 @@ struct crypto_bignum *crypto_ec_key_get_private_key(struct crypto_key *key); * @privkey_len: private key len * Returns: Crypto key */ -struct crypto_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len); +struct crypto_ec_key *crypto_ec_key_parse_priv(const u8 *privkey, size_t privkey_len); /** * crypto_ec_get_mbedtls_to_nist_group_id - get nist group from mbedtls internal group @@ -985,7 +988,7 @@ int crypto_ec_get_curve_id(const struct crypto_ec_group *group); * @secret_len: secret len * Returns: 0 if success else negative value */ -int crypto_ecdh(struct crypto_key *key_own, struct crypto_key *key_peer, +int crypto_ecdh(struct crypto_ec_key *key_own, struct crypto_ec_key *key_peer, u8 *secret, size_t *secret_len); /** @@ -999,7 +1002,7 @@ int crypto_ecdh(struct crypto_key *key_own, struct crypto_key *key_peer, */ int crypto_ecdsa_get_sign(unsigned char *hash, const struct crypto_bignum *r, const struct crypto_bignum *s, - struct crypto_key *csign, int hash_len); + struct crypto_ec_key *csign, int hash_len); /** * crypto_edcsa_sign_verify: verify crypto ecdsa signed hash @@ -1011,29 +1014,29 @@ int crypto_ecdsa_get_sign(unsigned char *hash, * Return: 0 if success else negative value */ int crypto_edcsa_sign_verify(const unsigned char *hash, const struct crypto_bignum *r, - const struct crypto_bignum *s, struct crypto_key *csign, int hlen); + const struct crypto_bignum *s, struct crypto_ec_key *csign, int hlen); /** * crypto_ec_parse_subpub_key: get EC key context from sub public key * @p: data * @len: data len - * Return: crypto_key + * Return: crypto_ec_key */ -struct crypto_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len); +struct crypto_ec_key *crypto_ec_parse_subpub_key(const unsigned char *p, size_t len); /** * crypto_is_ec_key: check whether a key is EC key or not * @key: crypto key * Return: true if key else false */ -int crypto_is_ec_key(struct crypto_key *key); +int crypto_is_ec_key(struct crypto_ec_key *key); /** * crypto_ec_key_gen: generate crypto ec keypair * @ike_group: grpup * Return: crypto key */ -struct crypto_key * crypto_ec_key_gen(u16 ike_group); +struct crypto_ec_key * crypto_ec_key_gen(u16 ike_group); /** * crypto_ec_write_pub_key: return public key in character buffer @@ -1041,7 +1044,7 @@ struct crypto_key * crypto_ec_key_gen(u16 ike_group); * @der_len: buffer len * Return: public key buffer */ -int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf); +int crypto_ec_write_pub_key(struct crypto_ec_key *key, unsigned char **key_buf); /** * crypto_ec_set_pubkey_point: set bignum point on ec curve @@ -1050,27 +1053,27 @@ int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf); * @len: length of x and y coordinate * Return : crypto key */ -struct crypto_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, +struct crypto_ec_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, const u8 *buf, size_t len); /** * crypto_ec_free_key: free crypto key * Return : None */ -void crypto_ec_free_key(struct crypto_key *key); +void crypto_ec_free_key(struct crypto_ec_key *key); /** * crypto_ec_key_debug_print: print ec key * @title: title * @key: crypto key * Return: None */ -void crypto_ec_key_debug_print(const char *title, struct crypto_key *key); +void crypto_ec_key_debug_print(const char *title, struct crypto_ec_key *key); /** * crypto_ec_key_get_public_key: Public key from crypto key * @key: crypto key * Return : Public key */ -struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_key *key); +struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_ec_key *key); /** * crypto_get_order: free crypto key @@ -1097,10 +1100,10 @@ int crypto_ec_get_affine_coordinates(struct crypto_ec *e, struct crypto_ec_point struct crypto_ec_group *crypto_ec_get_group_byname(const char *name); /** - * crypto_key_compare: check whether two keys belong to same + * crypto_ec_key_compare: check whether two keys belong to same * Return : 1 if yes else 0 */ -int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2); +int crypto_ec_key_compare(struct crypto_ec_key *key1, struct crypto_ec_key *key2); /* * crypto_write_pubkey_der: get public key in der format @@ -1108,7 +1111,7 @@ int crypto_key_compare(struct crypto_key *key1, struct crypto_key *key2); * @key_buf: key buffer in character format * Return : len of char buffer if success */ -int crypto_write_pubkey_der(struct crypto_key *csign, unsigned char **key_buf); +int crypto_write_pubkey_der(struct crypto_ec_key *csign, unsigned char **key_buf); /** * crypto_free_buffer: free buffer allocated by crypto API @@ -1124,7 +1127,7 @@ void crypto_free_buffer(unsigned char *buf); * @key_len = key length of character buffer * Return : 0 if success */ -int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data, int *key_len); +int crypto_ec_get_priv_key_der(struct crypto_ec_key *key, unsigned char **key_data, int *key_len); /** * crypto_bignum_to_string: get big number in ascii format @@ -1148,9 +1151,6 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, const u8 *key, size_t len); -struct crypto_ec_key; - - /** * crypto_ec_key_parse_pub - Initialize EC key pair from SubjectPublicKeyInfo ASN.1 * @der: DER encoding of ASN.1 SubjectPublicKeyInfo From beda28452437578de2e7a4b7ebbf3e9c75fa89dc Mon Sep 17 00:00:00 2001 From: aditi Date: Fri, 26 Jul 2024 16:41:56 +0530 Subject: [PATCH 3/3] feat(esp_wifi): Add esp-idf specific changes Added esp-idf implementation specific changes on top of the upstream updates. --- .../src/crypto/crypto_mbedtls-ec.c | 56 ++- .../esp_supplicant/src/esp_dpp_i.h | 3 +- components/wpa_supplicant/src/common/dpp.c | 184 ++++------ components/wpa_supplicant/src/common/dpp.h | 64 +--- .../wpa_supplicant/src/common/dpp_crypto.c | 324 +++++++++--------- components/wpa_supplicant/src/common/dpp_i.h | 79 +++++ components/wpa_supplicant/src/crypto/crypto.h | 36 +- 7 files changed, 358 insertions(+), 388 deletions(-) create mode 100644 components/wpa_supplicant/src/common/dpp_i.h diff --git a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c index 18a19f92fc..5f929284be 100644 --- a/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c +++ b/components/wpa_supplicant/esp_supplicant/src/crypto/crypto_mbedtls-ec.c @@ -501,8 +501,8 @@ static struct crypto_ec_key *crypto_alloc_key(void) return (struct crypto_ec_key *)key; } -struct crypto_ec_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, - const u8 *buf, size_t len) +struct crypto_ec_key * crypto_ec_key_set_pub(const struct crypto_ec_group *group, + const u8 *buf, size_t len) { mbedtls_ecp_point *point = NULL; struct crypto_ec_key *pkey = NULL; @@ -557,13 +557,6 @@ fail: return pkey; } -void crypto_ec_free_key(struct crypto_ec_key *key) -{ - mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; - mbedtls_pk_free(pkey); - os_free(key); -} - struct crypto_ec_point *crypto_ec_key_get_public_key(struct crypto_ec_key *key) { mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; @@ -820,8 +813,10 @@ fail: return ret; } -int crypto_edcsa_sign_verify(const unsigned char *hash, - const struct crypto_bignum *r, const struct crypto_bignum *s, struct crypto_ec_key *csign, int hlen) +int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *csign, + const unsigned char *hash, int hlen, + const u8 *r, size_t r_len, + const u8 *s, size_t s_len) { /* (mbedtls_ecdsa_context *) */ mbedtls_ecp_keypair *ecp_kp = mbedtls_pk_ec(*(mbedtls_pk_context *)csign); @@ -829,35 +824,41 @@ int crypto_edcsa_sign_verify(const unsigned char *hash, return -1; } + struct crypto_bignum *rb = NULL, *sb = NULL; + rb = crypto_bignum_init_set(r, r_len); + sb = crypto_bignum_init_set(s, s_len); + mbedtls_ecp_group *ecp_kp_grp = &ecp_kp->MBEDTLS_PRIVATE(grp); mbedtls_ecp_point *ecp_kp_q = &ecp_kp->MBEDTLS_PRIVATE(Q); int ret = mbedtls_ecdsa_verify(ecp_kp_grp, hash, hlen, - ecp_kp_q, (mbedtls_mpi *)r, (mbedtls_mpi *)s); + ecp_kp_q, (mbedtls_mpi *)rb, (mbedtls_mpi *)sb); if (ret != 0) { wpa_printf(MSG_ERROR, "ecdsa verification failed"); + crypto_bignum_deinit(rb, 0); + crypto_bignum_deinit(sb, 0); return ret; } return ret; } -void crypto_ec_key_debug_print(const char *title, struct crypto_ec_key *key) +void crypto_ec_key_debug_print(struct crypto_ec_key *key, const char *title) { #ifdef DEBUG_PRINT mbedtls_pk_context *pkey = (mbedtls_pk_context *)key; mbedtls_ecp_keypair *ecp = mbedtls_pk_ec(*pkey); u8 x[32], y[32], d[32]; - wpa_printf(MSG_ERROR, "curve: %s", + wpa_printf(MSG_INFO, "curve: %s", mbedtls_ecp_curve_info_from_grp_id(ecp->MBEDTLS_PRIVATE(grp).id)->name); int len = mbedtls_mpi_size((mbedtls_mpi *)crypto_ec_get_prime((struct crypto_ec *)crypto_ec_get_group_from_key(key))); - wpa_printf(MSG_ERROR, "prime len is %d", len); + wpa_printf(MSG_INFO, "prime len is %d", len); crypto_ec_point_to_bin((struct crypto_ec *)crypto_ec_get_group_from_key(key), crypto_ec_key_get_public_key(key), x, y); crypto_bignum_to_bin(crypto_ec_key_get_private_key(key), - d, len, len); + d, len, len); wpa_hexdump(MSG_INFO, "Q_x:", x, 32); wpa_hexdump(MSG_INFO, "Q_y:", y, 32); - wpa_hexdump(MSG_INFO, "d: ", d , 32); + wpa_hexdump(MSG_INFO, "d: ", d, 32); #endif } @@ -1036,6 +1037,23 @@ int crypto_ec_write_pub_key(struct crypto_ec_key *key, unsigned char **key_buf) return len; } +struct wpabuf * crypto_ec_key_get_subject_public_key(struct crypto_ec_key *key) +{ + unsigned char *der = NULL; + struct wpabuf *ret = NULL; + int der_len; + + der_len = crypto_ec_write_pub_key(key, &der); + if (!der) { + wpa_printf(MSG_ERROR, "failed to get der for bootstrapping key\n"); + return NULL; + } + ret = wpabuf_alloc_copy(der, der_len); + + os_free(der); + return ret; +} + int crypto_mbedtls_get_grp_id(int group) { switch (group) { @@ -1188,7 +1206,7 @@ struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y, os_memcpy(buf, px, len); os_memcpy(buf + len, py, len); - pkey = crypto_ec_set_pubkey_point((struct crypto_ec_group*)ACCESS_ECDH(&ctx, grp), buf, len); + pkey = crypto_ec_key_set_pub((struct crypto_ec_group*)ACCESS_ECDH(&ctx, grp), buf, len); if (!pkey) { wpa_printf(MSG_ERROR, "Failed to set point for peer's public key"); goto cleanup; @@ -1228,7 +1246,7 @@ cleanup: os_free(py); os_free(buf); os_free(secret); - crypto_ec_free_key(pkey); + crypto_ec_key_deinit(pkey); crypto_bignum_deinit(bn_x, 1); crypto_ec_point_deinit(ec_pt, 1); mbedtls_ctr_drbg_free(&ctr_drbg); diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h index b8e4c280ef..d3dbc95c37 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_dpp_i.h @@ -59,8 +59,7 @@ int esp_supp_rx_action(uint8_t *hdr, uint8_t *payload, size_t len, uint8_t chann esp_err_t esp_dpp_post_evt(uint32_t evt_id, uint32_t data); #ifdef CONFIG_TESTING_OPTIONS -int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve); +int dpp_test_gen_invalid_key(struct wpabuf *msg, const struct dpp_curve_params *curve); char * dpp_corrupt_connector_signature(const char *connector); #endif /* CONFIG_TESTING_OPTIONS */ diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index 75bf205e13..7fa67d10fa 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -20,6 +20,8 @@ #include "crypto/aes_siv.h" #include "crypto/sha256.h" #include "dpp.h" +#include "dpp_i.h" +#include "esp_dpp_i.h" static const char * dpp_netrole_str(enum dpp_netrole netrole); @@ -30,7 +32,7 @@ size_t dpp_protocol_key_override_len = 0; u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; size_t dpp_nonce_override_len = 0; -static int dpp_test_gen_invalid_key(struct wpabuf *msg, +int dpp_test_gen_invalid_key(struct wpabuf *msg, const struct dpp_curve_params *curve); #endif /* CONFIG_TESTING_OPTIONS */ @@ -73,7 +75,7 @@ void dpp_debug_print_point(const char *title, struct crypto_ec *e, u8 x[64], y[64]; if (crypto_ec_point_to_bin(e, point, x, y) < 0) { - printf("error: failed to get coordinates\n"); + wpa_printf(MSG_ERROR, "Failed to get coordinates"); return; } @@ -198,7 +200,9 @@ void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) return; os_free(info->uri); os_free(info->info); - crypto_ec_free_key(info->pubkey); + os_free(info->chan); + os_free(info->pk); + crypto_ec_key_deinit(info->pubkey); os_free(info); } @@ -349,68 +353,6 @@ static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) res = dpp_get_subject_public_key(bi, data, data_len); os_free(data); return res; -#if 0 - if (sha256_vector(1, (const u8 **) &data, &data_len, - bi->pubkey_hash) < 0) { - wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - os_free(data); - return -1; - } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", - bi->pubkey_hash, SHA256_MAC_LEN); - - /* DER encoded ASN.1 SubjectPublicKeyInfo - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * subjectPublicKey = compressed format public key per ANSI X9.63 - * algorithm = ecPublicKey (1.2.840.10045.2.1) - * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., - * prime256v1 (1.2.840.10045.3.1.7) - */ - - p = data; - - pkey = crypto_ec_parse_subpub_key((unsigned char *)p, data_len); - os_free(data); - - if (!pkey) { - wpa_printf(MSG_DEBUG, - "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); - return -1; - } - - if (!crypto_is_ec_key(pkey)) { - wpa_printf(MSG_DEBUG, - "DPP: SubjectPublicKeyInfo does not describe an EC key"); - crypto_ec_free_key(pkey); - return -1; - } - - group = crypto_ec_get_group_from_key(pkey); - if (!group) { - return -1; - } - id = crypto_ec_get_curve_id(group); - bi->curve = dpp_get_curve_group_id(id); - if (!bi->curve) { - wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo curve"); - goto fail; - } - - bi->pubkey = pkey; - return 0; -fail: - crypto_ec_free_key(pkey); - return -1; -#endif } static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) @@ -1073,11 +1015,40 @@ static int dpp_prepare_channel_list(struct dpp_authentication *auth, return 0; } +int dpp_gen_uri(struct dpp_bootstrap_info *bi) +{ + char macstr[ETH_ALEN * 2 + 10]; + size_t len; + + len = 4; /* "DPP:" */ + if (bi->chan) + len += 3 + os_strlen(bi->chan); /* C:...; */ + if (is_zero_ether_addr(bi->mac_addr)) + macstr[0] = '\0'; + else + os_snprintf(macstr, sizeof(macstr), "M:" MACSTR ";", MAC2STR(bi->mac_addr)); + len += os_strlen(macstr); /* M:...; */ + if (bi->info) + len += 3 + os_strlen(bi->info); /* I:...; */ + len += 4 + os_strlen(bi->pk); /* K:...;; */ + + os_free(bi->uri); + bi->uri = os_malloc(len + 1); + if (!bi->uri) + return -1; + os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%sK:%s;;", + bi->chan ? "C:" : "", bi->chan ? bi->chan : "", + bi->chan ? ";" : "", + macstr, + bi->info ? "I:" : "", bi->info ? bi->info : "", + bi->info ? ";" : "", + bi->pk); + return 0; +} + static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) { struct dpp_bootstrap_info *bi; - char *pk = NULL; - size_t len; if (auth->own_bi) return 0; /* already generated */ @@ -1086,27 +1057,16 @@ static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) if (!bi) return -1; bi->type = DPP_BOOTSTRAP_QR_CODE; - pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0); - if (!pk) + if (dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0) < 0 || + dpp_gen_uri(bi) < 0) goto fail; - - len = 4; /* "DPP:" */ - len += 4 + os_strlen(pk); - bi->uri = os_malloc(len + 1); - if (!bi->uri) - goto fail; - os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk); wpa_printf(MSG_DEBUG, "DPP: Auto-generated own bootstrapping key info: URI %s", bi->uri); - auth->tmp_own_bi = auth->own_bi = bi; - os_free(pk); - return 0; fail: - os_free(pk); dpp_bootstrap_info_free(bi); return -1; } @@ -1517,7 +1477,7 @@ static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) #endif /* CONFIG_TESTING_OPTIONS */ wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); - crypto_ec_free_key(auth->own_protocol_key); + crypto_ec_key_deinit(auth->own_protocol_key); #ifdef CONFIG_TESTING_OPTIONS if (dpp_protocol_key_override_len) { const struct dpp_curve_params *tmp_curve; @@ -1973,7 +1933,7 @@ not_compatible: return auth; fail: bin_clear_free(unwrapped, unwrapped_len); - crypto_ec_free_key(pi); + crypto_ec_key_deinit(pi); dpp_auth_deinit(auth); return NULL; } @@ -2411,7 +2371,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); goto fail; } - crypto_ec_free_key(auth->peer_protocol_key); + crypto_ec_key_deinit(auth->peer_protocol_key); auth->peer_protocol_key = pr; pr = NULL; @@ -2581,7 +2541,7 @@ dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, fail: bin_clear_free(unwrapped, unwrapped_len); bin_clear_free(unwrapped2, unwrapped2_len); - crypto_ec_free_key(pr); + crypto_ec_key_deinit(pr); return NULL; } @@ -3135,8 +3095,8 @@ void dpp_auth_deinit(struct dpp_authentication *auth) dpp_configuration_free(auth->conf2_ap); dpp_configuration_free(auth->conf_sta); dpp_configuration_free(auth->conf2_sta); - crypto_ec_free_key(auth->own_protocol_key); - crypto_ec_free_key(auth->peer_protocol_key); + crypto_ec_key_deinit(auth->own_protocol_key); + crypto_ec_key_deinit(auth->peer_protocol_key); wpabuf_free(auth->req_msg); wpabuf_free(auth->resp_msg); wpabuf_free(auth->conf_req); @@ -3979,7 +3939,7 @@ static struct crypto_ec_key * dpp_parse_jwk(struct json_token *jwk, a = os_zalloc(len); os_memcpy(a, wpabuf_head(x), wpabuf_len(x)); os_memcpy(a + wpabuf_len(x), wpabuf_head(y), wpabuf_len(y)); - pkey = crypto_ec_set_pubkey_point(group, a, len); + pkey = crypto_ec_key_set_pub(group, a, len); crypto_ec_deinit((struct crypto_ec *)group); *key_curve = curve; @@ -4161,7 +4121,7 @@ skip_groups: ret = 0; fail: - crypto_ec_free_key(key); + crypto_ec_key_deinit(key); json_free(root); return ret; } @@ -4262,7 +4222,7 @@ static int dpp_parse_cred_dpp(struct dpp_authentication *auth, ret = 0; fail: - crypto_ec_free_key(csign_pub); + crypto_ec_key_deinit(csign_pub); os_free(info.payload); return ret; } @@ -4582,7 +4542,7 @@ void dpp_configurator_free(struct dpp_configurator *conf) { if (!conf) return; - crypto_ec_free_key(conf->csign); + crypto_ec_key_deinit(conf->csign); os_free(conf->kid); os_free(conf); } @@ -4944,9 +4904,9 @@ fail: os_memset(intro, 0, sizeof(*intro)); forced_memzero(Nx, sizeof(Nx)); os_free(info.payload); - crypto_ec_free_key(own_key); + crypto_ec_key_deinit(own_key); wpabuf_free(own_key_pub); - crypto_ec_free_key(peer_key); + crypto_ec_key_deinit(peer_key); json_free(root); json_free(own_root); return ret; @@ -5024,11 +4984,10 @@ struct dpp_bootstrap_info * dpp_add_nfc_uri(struct dpp_global *dpp, int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) { - char *chan = NULL, *mac = NULL, *info = NULL, *pk = NULL, *curve = NULL; + char *mac = NULL, *info = NULL, *curve = NULL; char *key = NULL; u8 *privkey = NULL; size_t privkey_len = 0; - size_t len; int ret = -1; struct dpp_bootstrap_info *bi; @@ -5048,7 +5007,7 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) else goto fail; - chan = get_param(cmd, " chan="); + bi->chan = get_param(cmd, " chan="); mac = get_param(cmd, " mac="); info = get_param(cmd, " info="); curve = get_param(cmd, " curve="); @@ -5063,44 +5022,19 @@ int dpp_bootstrap_gen(struct dpp_global *dpp, const char *cmd) } wpa_hexdump(MSG_DEBUG, "private key", privkey, privkey_len); - pk = dpp_keygen(bi, curve, privkey, privkey_len); - if (!pk) + if (dpp_keygen(bi, curve, privkey, privkey_len) < 0 || + dpp_parse_uri_chan_list(bi, bi->chan) < 0 || + dpp_parse_uri_mac(bi, mac) < 0 || + dpp_parse_uri_info(bi, info) < 0 || + dpp_gen_uri(bi) < 0) goto fail; - len = 4; /* "DPP:" */ - if (chan) { - if (dpp_parse_uri_chan_list(bi, chan) < 0) - goto fail; - len += 3 + os_strlen(chan); /* C:...; */ - } - if (mac) { - if (dpp_parse_uri_mac(bi, mac) < 0) - goto fail; - len += 3 + os_strlen(mac); /* M:...; */ - } - if (info) { - if (dpp_parse_uri_info(bi, info) < 0) - goto fail; - len += 3 + os_strlen(info); /* I:...; */ - } - len += 4 + os_strlen(pk); - bi->uri = os_malloc(len + 1); - if (!bi->uri) - goto fail; - os_snprintf(bi->uri, len + 1, "DPP:%s%s%s%s%s%s%s%s%sK:%s;;", - chan ? "C:" : "", chan ? chan : "", chan ? ";" : "", - mac ? "M:" : "", mac ? mac : "", mac ? ";" : "", - info ? "I:" : "", info ? info : "", info ? ";" : "", - pk); - bi->id = dpp_next_id(dpp); dl_list_add(&dpp->bootstrap, &bi->list); ret = bi->id; bi = NULL; fail: os_free(curve); - os_free(pk); - os_free(chan); os_free(mac); os_free(info); str_clear_free(key); diff --git a/components/wpa_supplicant/src/common/dpp.h b/components/wpa_supplicant/src/common/dpp.h index fcf80f2faa..84a9416ae9 100644 --- a/components/wpa_supplicant/src/common/dpp.h +++ b/components/wpa_supplicant/src/common/dpp.h @@ -160,7 +160,9 @@ struct dpp_bootstrap_info { enum dpp_bootstrap_type type; char *uri; u8 mac_addr[ETH_ALEN]; + char *chan; char *info; + char *pk; unsigned int freq[DPP_BOOTSTRAP_MAX_FREQ]; unsigned int num_freq; int own; @@ -441,13 +443,10 @@ extern size_t dpp_nonce_override_len; void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info); const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type); -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, const char *chan_list); int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac); int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info); -char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, - u8 *privkey, size_t privkey_len); struct hostapd_hw_modes; struct dpp_authentication * dpp_auth_init(void *msg_ctx, struct dpp_bootstrap_info *peer_bi, @@ -595,64 +594,5 @@ void dpp_global_deinit(struct dpp_global *dpp); int dpp_connect(uint8_t *bssid, bool pdr_done); esp_err_t esp_dpp_start_net_intro_protocol(uint8_t *bssid); -/* dpp_crypto.c */ - -struct dpp_signed_connector_info { - unsigned char *payload; - size_t payload_len; -}; - -const struct dpp_curve_params *dpp_get_curve_name(const char *name); -const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name); -const struct dpp_curve_params * dpp_get_curve_group_id(int group_id); -void dpp_debug_print_key(const char *title, struct crypto_ec_key *key); -int dpp_hash_vector(const struct dpp_curve_params *curve, - size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); -int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, - const char *label, u8 *out, size_t outlen); -int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac); -int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, - const u8 *data, size_t data_len, u8 *mac); -struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, - const u8 *buf, size_t len); -struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve); -struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, - const u8 *privkey, size_t privkey_len); -int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); -char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, - u8 *privkey, size_t privkey_len); -int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, - unsigned int hash_len); -int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, - unsigned int hash_len); -int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, - u8 *secret, size_t *secret_len); -struct wpabuf *dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func); -int dpp_check_pubkey_match(struct crypto_ec_key *pub, struct wpabuf *r_hash); -enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, - struct crypto_ec_key *csign_pub, const char *connector); -int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); -int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); -int dpp_auth_derive_l_responder(struct dpp_authentication *auth); -int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); -int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, - unsigned int hash_len); -int dpp_derive_pmkid(const struct dpp_curve_params *curve, - struct crypto_ec_key *own_key, struct crypto_ec_key *peer_key, u8 *pmkid); -int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len); -struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key); -struct wpabuf * dpp_get_pubkey_point(struct crypto_ec_key *pkey, int prefix); -int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); -int dpp_derive_bk_ke(struct dpp_authentication *auth); -enum dpp_status_error -dpp_check_signed_connector(struct dpp_signed_connector_info *info, - const u8 *csign_key, size_t csign_key_len, - const u8 *peer_connector, size_t peer_connector_len); - -/* dpp crypto apis */ - #endif /* CONFIG_DPP */ #endif /* DPP_H */ diff --git a/components/wpa_supplicant/src/common/dpp_crypto.c b/components/wpa_supplicant/src/common/dpp_crypto.c index 67dd44be02..b95584e8e1 100644 --- a/components/wpa_supplicant/src/common/dpp_crypto.c +++ b/components/wpa_supplicant/src/common/dpp_crypto.c @@ -1,7 +1,7 @@ /* - * DPP functionality shared between hostapd and wpa_supplicant + * DPP crypto functionality shared between hostapd and wpa_supplicant * Copyright (c) 2017, Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation + * Copyright (c) 2018-2024, The Linux Foundation * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -20,24 +20,30 @@ #include "crypto/aes_siv.h" #include "crypto/sha256.h" #include "dpp.h" -#include "esp_dpp_i.h" +#include "dpp_i.h" const struct dpp_curve_params dpp_curves[] = { /* The mandatory to support and the default NIST P-256 curve needs to * be the first entry on this list. */ { "secp256r1", 32, 32, 16, 32, "P-256", 19, "ES256" }, +#ifndef ESP_SUPPLICANT { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, +#endif { NULL, 0, 0, 0, 0, NULL, 0, NULL } }; -const struct dpp_curve_params *dpp_get_curve_name(const char *name) + +const struct dpp_curve_params * dpp_get_curve_name(const char *name) { int i; + if (!name) + return &dpp_curves[0]; + for (i = 0; dpp_curves[i].name; i++) { if (os_strcmp(name, dpp_curves[i].name) == 0 || (dpp_curves[i].jwk_crv && @@ -47,7 +53,8 @@ const struct dpp_curve_params *dpp_get_curve_name(const char *name) return NULL; } -const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name) + +const struct dpp_curve_params * dpp_get_curve_jwk_crv(const char *name) { int i; @@ -56,29 +63,28 @@ const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name) os_strcmp(name, dpp_curves[i].jwk_crv) == 0) return &dpp_curves[i]; } - return NULL; } -const struct dpp_curve_params * dpp_get_curve_group_id(int group_id) + +const struct dpp_curve_params * dpp_get_curve_ike_group(u16 group) { - unsigned int i; + int i; - if (!group_id) - return NULL; - - for (i = 0; dpp_curves[i].ike_group; i++) { - if (group_id == dpp_curves[i].ike_group) + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].ike_group == group) return &dpp_curves[i]; } return NULL; } + void dpp_debug_print_key(const char *title, struct crypto_ec_key *key) { - crypto_ec_key_debug_print(title, key); + crypto_ec_key_debug_print(key, title); } + int dpp_hash_vector(const struct dpp_curve_params *curve, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) @@ -94,8 +100,9 @@ int dpp_hash_vector(const struct dpp_curve_params *curve, return -1; } + int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, - const char *label, u8 *out, size_t outlen) + const char *label, u8 *out, size_t outlen) { if (hash_len == 32) return hmac_sha256_kdf(secret, secret_len, NULL, @@ -114,9 +121,10 @@ int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, return -1; } + int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, - size_t num_elem, const u8 *addr[], - const size_t *len, u8 *mac) + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) { if (hash_len == 32) return hmac_sha256_vector(key, key_len, num_elem, addr, len, @@ -132,6 +140,7 @@ int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, return -1; } + int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, const u8 *data, size_t data_len, u8 *mac) { @@ -147,7 +156,7 @@ int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, } struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, - const u8 *buf, size_t len) + const u8 *buf, size_t len) { const struct crypto_ec_group *group; struct crypto_ec_key *pkey = NULL; @@ -157,115 +166,116 @@ struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, group = crypto_ec_get_group_from_key(group_key); if (group) - pkey = crypto_ec_set_pubkey_point(group, buf, - len); + pkey = crypto_ec_key_set_pub(group, buf, len); else wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); return pkey; } + struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve) { - struct crypto_ec_key *key = crypto_ec_key_gen(curve->ike_group); + struct crypto_ec_key *key; wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); - dpp_debug_print_key("Own generated key", key); + + key = crypto_ec_key_gen(curve->ike_group); + if (key) + dpp_debug_print_key("Own generated key", key); return key; } -struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, - const u8 *privkey, size_t privkey_len) -{ - struct crypto_ec_group *group; - struct crypto_ec_key *pkey = crypto_ec_key_parse_priv(privkey, privkey_len); - int id; +struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len) +{ + struct crypto_ec_key *pkey; + int group; + + pkey = crypto_ec_key_parse_priv(privkey, privkey_len); if (!pkey) { wpa_printf(MSG_ERROR, "%s: failed to get pkey", __func__); return NULL; } - group = crypto_ec_get_group_from_key(pkey); - if (!group) { - crypto_ec_free_key(pkey); + + group = crypto_ec_key_group(pkey); + if (group < 0) { + crypto_ec_key_deinit(pkey); return NULL; } - id = crypto_ec_get_curve_id(group); - *curve = dpp_get_curve_group_id(id); + + *curve = dpp_get_curve_ike_group(group); if (!*curve) { wpa_printf(MSG_INFO, - "DPP: Unsupported curve (id=%d) in pre-assigned key", - id); - crypto_ec_free_key(pkey); + "DPP: Unsupported curve (group=%d) in pre-assigned key", + group); + crypto_ec_key_deinit(pkey); return NULL; } return pkey; } -struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key) +int dpp_bi_pubkey_hash(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) { - unsigned char *der = NULL; - struct wpabuf *ret = NULL; - int der_len; + const u8 *addr[2]; + size_t len[2]; - der_len = crypto_ec_write_pub_key(key, &der); - if (!der) { - printf("failed to get der for bootstrapping key\n"); - return NULL; - } - ret = wpabuf_alloc_copy(der, der_len); - - os_free(der); - return ret; + addr[0] = data; + len[0] = data_len; + if (sha256_vector(1, addr, len, bi->pubkey_hash) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); +#ifndef ESP_SUPPLICANT + addr[0] = (const u8 *) "chirp"; + len[0] = 5; + addr[1] = data; + len[1] = data_len; + if (sha256_vector(2, addr, len, bi->pubkey_hash_chirp) < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash (chirp)", + bi->pubkey_hash_chirp, SHA256_MAC_LEN); +#endif //ESP_SUPPLICANT + return 0; } + int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) { struct wpabuf *der; int res; - const u8 *addr[1]; - size_t len[1]; - 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)", der); - - addr[0] = wpabuf_head(der); - len[0] = wpabuf_len(der); - res = sha256_vector(1, addr, len, bi->pubkey_hash); + res = dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)); if (res < 0) wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); - else - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); wpabuf_free(der); return res; } -char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, u8 *privkey, size_t privkey_len) { char *base64 = NULL; char *pos, *end; size_t len; struct wpabuf *der = NULL; - const u8 *addr[1]; - int res; - if (!curve) { - bi->curve = &dpp_curves[0]; - } else { - bi->curve = dpp_get_curve_name(curve); - if (!bi->curve) { - wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", - curve); - return NULL; - } + bi->curve = dpp_get_curve_name(curve); + if (!bi->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", curve); + return -1; } + if (privkey) bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); else @@ -274,21 +284,16 @@ char * 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)", der); - addr[0] = wpabuf_head(der); - len = wpabuf_len(der); - res = sha256_vector(1, addr, &len, bi->pubkey_hash); - if (res < 0) { + if (dpp_bi_pubkey_hash(bi, wpabuf_head(der), wpabuf_len(der)) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); goto fail; } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, - SHA256_MAC_LEN); base64 = (char *)base64_encode(wpabuf_head(der), wpabuf_len(der), &len); wpabuf_free(der); @@ -303,15 +308,17 @@ char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, break; os_memmove(pos, pos + 1, end - pos); } - return base64; + os_free(bi->pk); + bi->pk = base64; + return 0; fail: os_free(base64); wpabuf_free(der); - return NULL; + return -1; } -int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, - unsigned int hash_len) + +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, unsigned int hash_len) { u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; const char *info = "first intermediate key"; @@ -337,8 +344,8 @@ int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, return 0; } -int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, - unsigned int hash_len) + +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, unsigned int hash_len) { u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; const char *info = "second intermediate key"; @@ -366,14 +373,16 @@ int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, } int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, - u8 *secret, size_t *secret_len) + u8 *secret, size_t *secret_len) { return crypto_ecdh(own, peer, secret, secret_len); } + struct wpabuf * dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, - const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func) + const u8 *prot_hdr, u16 prot_hdr_len, + int *hash_func) { struct json_token *root, *token; struct wpabuf *kid = NULL; @@ -418,13 +427,22 @@ dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, token->string, curve->jws_alg); goto fail; } - if (os_strcmp(token->string, "ES256") == 0 || os_strcmp(token->string, "BS256") == 0) { *hash_func = CRYPTO_HASH_ALG_SHA256; +#ifndef ESP_SUPPLICANT + } else if (os_strcmp(token->string, "ES384") == 0 || + os_strcmp(token->string, "BS384") == 0) { + *hash_func = CRYPTO_HASH_ALG_SHA384; + } else if (os_strcmp(token->string, "ES512") == 0 || + os_strcmp(token->string, "BS512") == 0) { + *hash_func = CRYPTO_HASH_ALG_SHA512; +#endif // ESP_SUPPLICANT } else { *hash_func = -1; - wpa_printf(MSG_ERROR, "Unsupported JWS Protected Header alg=%s", token->string); + wpa_printf(MSG_ERROR, "DPP : Unsupported JWS Protected Header alg=%s", + token->string); + goto fail; } kid = json_get_member_base64url(root, "kid"); @@ -440,41 +458,20 @@ fail: return kid; } -int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len) + +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, + const u8 *data, size_t data_len) { struct crypto_ec_key *pkey; const unsigned char *p; - struct crypto_ec_group *group; - int id; - if (sha256_vector(1, (const u8 **) &data, &data_len, - bi->pubkey_hash) < 0) { + if (dpp_bi_pubkey_hash(bi, data, data_len) < 0) { wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); return -1; } - wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", - bi->pubkey_hash, SHA256_MAC_LEN); - - /* DER encoded ASN.1 SubjectPublicKeyInfo - * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } - * - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters ANY DEFINED BY algorithm OPTIONAL } - * - * subjectPublicKey = compressed format public key per ANSI X9.63 - * algorithm = ecPublicKey (1.2.840.10045.2.1) - * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., - * prime256v1 (1.2.840.10045.3.1.7) - */ p = data; - pkey = crypto_ec_parse_subpub_key((unsigned char *)p, data_len); - if (!pkey) { wpa_printf(MSG_DEBUG, "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); @@ -484,32 +481,29 @@ int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, si if (!crypto_is_ec_key(pkey)) { wpa_printf(MSG_DEBUG, "DPP: SubjectPublicKeyInfo does not describe an EC key"); - crypto_ec_free_key(pkey); + crypto_ec_key_deinit(pkey); return -1; } - group = crypto_ec_get_group_from_key(pkey); - if (!group) { - return -1; - } - id = crypto_ec_get_curve_id(group); - bi->curve = dpp_get_curve_group_id(id); + bi->curve = dpp_get_curve_ike_group(crypto_ec_key_group(pkey)); if (!bi->curve) { wpa_printf(MSG_DEBUG, - "DPP: Unsupported SubjectPublicKeyInfo curve"); + "DPP: Unsupported SubjectPublicKeyInfo curve: group %d", + crypto_ec_key_group(pkey)); goto fail; } bi->pubkey = pkey; return 0; fail: - crypto_ec_free_key(pkey); + crypto_ec_key_deinit(pkey); return -1; } int dpp_derive_bk_ke(struct dpp_authentication *auth) { + unsigned int hash_len = auth->curve->hash_len; size_t nonce_len = auth->curve->nonce_len; u8 nonces[2 * DPP_MAX_NONCE_LEN]; const char *info_ke = "DPP Key"; @@ -518,7 +512,6 @@ int dpp_derive_bk_ke(struct dpp_authentication *auth) const u8 *addr[3]; size_t len[3]; size_t num_elem = 0; - unsigned int hash_len = auth->curve->hash_len; if (!auth->Mx_len || !auth->Nx_len) { wpa_printf(MSG_DEBUG, @@ -637,24 +630,19 @@ int dpp_check_pubkey_match(struct crypto_ec_key *pub, struct wpabuf *r_hash) enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, - struct crypto_ec_key *csign_pub, const char *connector) + struct crypto_ec_key *csign_pub, + const char *connector) { enum dpp_status_error ret = 255; const char *pos, *end, *signed_start, *signed_end; struct wpabuf *kid = NULL; unsigned char *prot_hdr = NULL, *signature = NULL; size_t prot_hdr_len = 0, signature_len = 0, signed_len; - struct crypto_bignum *r = NULL, *s = NULL; const struct dpp_curve_params *curve; - const struct crypto_ec_group *group; - int id, hash_func = -1; + int res, hash_func = -1; u8 *hash = NULL; - group = crypto_ec_get_group_from_key(csign_pub); - if (!group) - goto fail; - id = crypto_ec_get_curve_id(group); - curve = dpp_get_curve_group_id(id); + curve = dpp_get_curve_ike_group(crypto_ec_key_group(csign_pub)); if (!curve) goto fail; wpa_printf(MSG_DEBUG, "DPP: C-sign-key group: %s", curve->jwk_crv); @@ -713,7 +701,7 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, signature = base64_url_decode(pos, os_strlen(pos), &signature_len); if (!signature) { wpa_printf(MSG_DEBUG, - "DPP: Failed to base64url decode signedConnector signature"); + "DPP: Failed to base64url decode signedConnector signature"); ret = DPP_STATUS_INVALID_CONNECTOR; goto fail; } @@ -733,11 +721,6 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, goto fail; } - /* JWS Signature encodes the signature (r,s) as two octet strings. Need - * to convert that to DER encoded ECDSA_SIG for OpenSSL EVP routines. */ - r = crypto_bignum_init_set(signature, signature_len / 2); - s = crypto_bignum_init_set(signature + signature_len / 2, signature_len / 2); - signed_len = signed_end - signed_start + 1; hash = os_malloc(curve->hash_len); if (!hash) { @@ -753,8 +736,16 @@ dpp_process_signed_connector(struct dpp_signed_connector_info *info, goto fail; } - if ((crypto_edcsa_sign_verify((unsigned char *)hash, r, s, - csign_pub, curve->hash_len)) != 0) { + res = crypto_ec_key_verify_signature_r_s(csign_pub, + (unsigned char *)hash, curve->hash_len, + signature, signature_len / 2, + signature + signature_len / 2, + signature_len / 2); + if (res != 0) { + wpa_printf(MSG_DEBUG, + "DPP: signedConnector signature check failed (res=%d)", + res); + ret = DPP_STATUS_INVALID_CONNECTOR; goto fail; } @@ -766,8 +757,6 @@ fail: os_free(prot_hdr); wpabuf_free(kid); os_free(signature); - crypto_bignum_deinit(r, 0); - crypto_bignum_deinit(s, 0); return ret; } @@ -799,11 +788,12 @@ dpp_check_signed_connector(struct dpp_signed_connector_info *info, res = dpp_process_signed_connector(info, csign, signed_connector); fail: os_free(signed_connector); - crypto_ec_free_key(csign); + crypto_ec_key_deinit(csign); return res; } + int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) { struct wpabuf *pix, *prx, *bix, *brx; @@ -882,6 +872,7 @@ fail: return res; } + int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) { struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; @@ -975,10 +966,10 @@ int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len) int dpp_auth_derive_l_responder(struct dpp_authentication *auth) { struct crypto_ec_group *group; - struct crypto_ec_point *l = NULL; - struct crypto_ec_point *BI_point; + struct crypto_ec_point *L = NULL; + struct crypto_ec_point *BI; struct crypto_bignum *lx, *sum, *q; - struct crypto_bignum *bR_bn, *pR_bn; + struct crypto_bignum *bR, *pR; int ret = -1; /* L = ((bR + pR) modulo q) * BI */ @@ -989,21 +980,21 @@ int dpp_auth_derive_l_responder(struct dpp_authentication *auth) if (!sum || !q || !lx) goto fail; - BI_point = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); + BI = crypto_ec_key_get_public_key(auth->peer_bi->pubkey); group = crypto_ec_get_group_from_key(auth->peer_bi->pubkey); - bR_bn = crypto_ec_key_get_private_key(auth->own_bi->pubkey); - pR_bn = crypto_ec_key_get_private_key(auth->own_protocol_key); + bR = crypto_ec_key_get_private_key(auth->own_bi->pubkey); + pR = crypto_ec_key_get_private_key(auth->own_protocol_key); - if (!bR_bn || !pR_bn) + if (!bR || !pR) goto fail; if ((crypto_get_order(group, q) != 0) || - (crypto_bignum_addmod(sum, bR_bn, pR_bn, q) != 0)) + (crypto_bignum_addmod(sum, bR, pR, q) != 0)) goto fail; - l = crypto_ec_point_init((struct crypto_ec *)group); - if (!l || (crypto_ec_point_mul((struct crypto_ec *)group, BI_point, sum, l) != 0) || - (crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0)) { + L = crypto_ec_point_init((struct crypto_ec *)group); + if (!L || (crypto_ec_point_mul((struct crypto_ec *)group, BI, sum, L) != 0) || + (crypto_ec_get_affine_coordinates((struct crypto_ec *)group, L, lx, NULL) != 0)) { wpa_printf(MSG_ERROR, "OpenSSL: failed: %s", __func__); goto fail; @@ -1014,7 +1005,7 @@ int dpp_auth_derive_l_responder(struct dpp_authentication *auth) auth->Lx_len = auth->secret_len; ret = 0; fail: - crypto_ec_point_deinit(l, 1); + crypto_ec_point_deinit(L, 1); crypto_bignum_deinit(lx, 0); crypto_bignum_deinit(sum, 0); crypto_bignum_deinit(q, 0); @@ -1022,10 +1013,11 @@ fail: return ret; } + int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) { struct crypto_ec_group *group; - struct crypto_ec_point *l = NULL, *sum = NULL; + struct crypto_ec_point *L = NULL, *sum = NULL; struct crypto_ec_point *BR_point, *PR_point; struct crypto_bignum *lx; struct crypto_bignum *bI_bn; @@ -1044,11 +1036,11 @@ int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) if (!group || !bI_bn) goto fail; sum = crypto_ec_point_init((struct crypto_ec *)group); - l = crypto_ec_point_init((struct crypto_ec *)group); - if (!sum || !l || + L = crypto_ec_point_init((struct crypto_ec *)group); + if (!sum || !L || crypto_ec_point_add((struct crypto_ec *)group, BR_point, PR_point, sum) != 0 || - crypto_ec_point_mul((struct crypto_ec *)group, sum, bI_bn, l) != 0 || - crypto_ec_get_affine_coordinates((struct crypto_ec *)group, l, lx, NULL) != 0) { + crypto_ec_point_mul((struct crypto_ec *)group, sum, bI_bn, L) != 0 || + crypto_ec_get_affine_coordinates((struct crypto_ec *)group, L, lx, NULL) != 0) { wpa_printf(MSG_ERROR, "OpenSSL: failed: %s", __func__); goto fail; @@ -1060,7 +1052,7 @@ int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) auth->Lx_len = auth->secret_len; ret = 0; fail: - crypto_ec_point_deinit(l, 1); + crypto_ec_point_deinit(L, 1); crypto_ec_point_deinit(sum, 1); crypto_bignum_deinit(lx, 0); @@ -1068,8 +1060,8 @@ fail: return ret; } -int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, - unsigned int hash_len) + +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, unsigned int hash_len) { u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; const char *info = "DPP PMK"; @@ -1095,8 +1087,10 @@ int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, return 0; } + int dpp_derive_pmkid(const struct dpp_curve_params *curve, - struct crypto_ec_key *own_key, struct crypto_ec_key *peer_key, u8 *pmkid) + struct crypto_ec_key *own_key, + struct crypto_ec_key *peer_key, u8 *pmkid) { struct wpabuf *nkx, *pkx; int ret = -1, res; @@ -1136,7 +1130,7 @@ fail: #ifdef CONFIG_TESTING_OPTIONS int dpp_test_gen_invalid_key(struct wpabuf *msg, - const struct dpp_curve_params *curve) + const struct dpp_curve_params *curve) { return 0; } diff --git a/components/wpa_supplicant/src/common/dpp_i.h b/components/wpa_supplicant/src/common/dpp_i.h new file mode 100644 index 0000000000..fc0d4acedb --- /dev/null +++ b/components/wpa_supplicant/src/common/dpp_i.h @@ -0,0 +1,79 @@ +/* + * DPP module internal definitions + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2020, The Linux Foundation + * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ESP_DPP_I_H +#define ESP_DPP_I_H + +#include "esp_err.h" +#include "utils/includes.h" +#include "utils/common.h" +#include "common/dpp.h" +#include "esp_dpp.h" +#include "esp_wifi_driver.h" + +/* dpp_crypto.c */ + +struct dpp_signed_connector_info { + unsigned char *payload; + size_t payload_len; +}; + +const struct dpp_curve_params *dpp_get_curve_name(const char *name); +const struct dpp_curve_params *dpp_get_curve_jwk_crv(const char *name); +void dpp_debug_print_key(const char *title, struct crypto_ec_key *key); +int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); +int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen); +int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac); +struct crypto_ec_key * dpp_set_pubkey_point(struct crypto_ec_key *group_key, + const u8 *buf, size_t len); +struct crypto_ec_key * dpp_gen_keypair(const struct dpp_curve_params *curve); +struct crypto_ec_key * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len); +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi); +int dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + u8 *privkey, size_t privkey_len); +int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, + unsigned int hash_len); +int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, + unsigned int hash_len); +int dpp_ecdh(struct crypto_ec_key *own, struct crypto_ec_key *peer, + u8 *secret, size_t *secret_len); +struct wpabuf *dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, int *hash_func); +int dpp_check_pubkey_match(struct crypto_ec_key *pub, struct wpabuf *r_hash); +enum dpp_status_error dpp_process_signed_connector(struct dpp_signed_connector_info *info, + struct crypto_ec_key *csign_pub, const char *connector); +int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth); +int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth); +int dpp_auth_derive_l_responder(struct dpp_authentication *auth); +int dpp_auth_derive_l_initiator(struct dpp_authentication *auth); +int dpp_derive_pmk(const u8 *Nx, size_t Nx_len, u8 *pmk, + unsigned int hash_len); +int dpp_derive_pmkid(const struct dpp_curve_params *curve, + struct crypto_ec_key *own_key, struct crypto_ec_key *peer_key, u8 *pmkid); +int dpp_bn2bin_pad(const struct crypto_bignum *bn, u8 *pos, size_t len); +struct wpabuf * dpp_bootstrap_key_der(struct crypto_ec_key *key); +struct wpabuf * dpp_get_pubkey_point(struct crypto_ec_key *pkey, int prefix); +int dpp_get_subject_public_key(struct dpp_bootstrap_info *bi, const u8 *data, size_t data_len); +int dpp_derive_bk_ke(struct dpp_authentication *auth); +enum dpp_status_error +dpp_check_signed_connector(struct dpp_signed_connector_info *info, + const u8 *csign_key, size_t csign_key_len, + const u8 *peer_connector, size_t peer_connector_len); + +/* dpp crypto apis */ + +#endif /* ESP_DPP_I_H */ diff --git a/components/wpa_supplicant/src/crypto/crypto.h b/components/wpa_supplicant/src/crypto/crypto.h index f665e21713..183cbf590f 100644 --- a/components/wpa_supplicant/src/crypto/crypto.h +++ b/components/wpa_supplicant/src/crypto/crypto.h @@ -1005,16 +1005,20 @@ int crypto_ecdsa_get_sign(unsigned char *hash, struct crypto_ec_key *csign, int hash_len); /** - * crypto_edcsa_sign_verify: verify crypto ecdsa signed hash + * crypto_ec_key_verify_signature_r_s: verify ec key signature + * @csign: csign * @hash: signed hash + * @hlen: length of hash * @r: ecdsa r * @s: ecdsa s - * @csign: csign - * @hlen: length of hash + * @r_len: Length of @r buffer + * @s_len: Length of @s buffer * Return: 0 if success else negative value */ -int crypto_edcsa_sign_verify(const unsigned char *hash, const struct crypto_bignum *r, - const struct crypto_bignum *s, struct crypto_ec_key *csign, int hlen); +int crypto_ec_key_verify_signature_r_s(struct crypto_ec_key *csign, + const unsigned char *hash, int hlen, + const u8 *r, size_t r_len, + const u8 *s, size_t s_len); /** * crypto_ec_parse_subpub_key: get EC key context from sub public key @@ -1047,26 +1051,28 @@ struct crypto_ec_key * crypto_ec_key_gen(u16 ike_group); int crypto_ec_write_pub_key(struct crypto_ec_key *key, unsigned char **key_buf); /** - * crypto_ec_set_pubkey_point: set bignum point on ec curve + * crypto_ec_key_get_subject_public_key - Get SubjectPublicKeyInfo ASN.1 for an EC key + * @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); + +/** + * crypto_ec_key_set_pub: set bignum point on ec curve * @group: ec group * @buf: x,y coordinate * @len: length of x and y coordinate - * Return : crypto key + * Return : crypto key or NULL on failure */ -struct crypto_ec_key * crypto_ec_set_pubkey_point(const struct crypto_ec_group *group, +struct crypto_ec_key * crypto_ec_key_set_pub(const struct crypto_ec_group *group, const u8 *buf, size_t len); -/** - * crypto_ec_free_key: free crypto key - * Return : None - */ -void crypto_ec_free_key(struct crypto_ec_key *key); /** * crypto_ec_key_debug_print: print ec key - * @title: title * @key: crypto key + * @title: title * Return: None */ -void crypto_ec_key_debug_print(const char *title, struct crypto_ec_key *key); +void crypto_ec_key_debug_print(struct crypto_ec_key *key, const char *title); /** * crypto_ec_key_get_public_key: Public key from crypto key