OWE support for station

This commit is contained in:
Shyamal Khachane 2022-06-14 11:31:52 +05:30
parent 7c7d53813c
commit 6d55761f60
20 changed files with 562 additions and 20 deletions

View File

@ -2082,7 +2082,6 @@ wep_decap = 0x40002028;
dbg_hmac_rxtx_statis_dump = 0x4000202c;
dbg_hmac_statis_dump = 0x40002030;
ieee80211_send_action_vendor_spec = 0x40002034;
ieee80211_send_mgmt = 0x40002038;
ieee80211_deauth_construct = 0x40002040;
ieee80211_disassoc_construct = 0x40002044;
ieee80211_vnd_lora_ie_size = 0x40002048;
@ -2091,7 +2090,6 @@ ieee80211_add_ssid = 0x40002050;
ieee80211_add_rates = 0x40002054;
ieee80211_add_xrates = 0x40002058;
ieee80211_is_ht_cipher = 0x4000205c;
ieee80211_assoc_req_construct = 0x40002060;
ieee80211_assoc_resp_construct = 0x40002064;
ieee80211_setup_lr_rates = 0x40002068;
ieee80211_ht_node_init = 0x4000206c;
@ -2144,10 +2142,8 @@ ieee80211_tx_mgt_cb = 0x4000212c;
ieee80211_getcapinfo = 0x40002130;
sta_rx_csa = 0x40002134;
sta_recv_sa_query_resp = 0x40002144;
ieee80211_parse_beacon = 0x40002148;
ieee80211_set_max_rate = 0x4000214c;
ic_set_sta = 0x40002150;
ieee80211_match_security = 0x40002154;
ieee80211_parse_wpa = 0x40002158;
ieee80211_add_assoc_req_ies = 0x40002160;
ieee80211_add_probe_req_ies = 0x40002164;

View File

@ -250,6 +250,15 @@ menu "Wi-Fi"
PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details.
config ESP32_WIFI_ENABLE_WPA3_OWE_STA
bool "Enable OWE STA"
default y
select WPA_MBEDTLS_CRYPTO
help
Select this option to allow the device to establish OWE connection with eligible AP's.
PMF (Protected Management Frames) is a prerequisite feature for a WPA3 connection, it needs to be
explicitly configured before attempting connection. Please refer to the Wi-Fi Driver API Guide for details.
config ESP_WIFI_SLP_IRAM_OPT
bool "WiFi SLP IRAM speed optimization"
select PM_SLP_DEFAULT_PARAMS_OPT

View File

@ -47,6 +47,8 @@ typedef struct {
wifi_country_policy_t policy; /**< country policy */
} wifi_country_t;
/* Strength of authmodes */
/* OPEN < WEP < WPA_PSK < OWE < WPA2_PSK = WPA_WPA2_PSK < WAPI_PSK < WPA2_ENTERPRISE < WPA3_PSK = WPA2_WPA3_PSK */
typedef enum {
WIFI_AUTH_OPEN = 0, /**< authenticate mode : open */
WIFI_AUTH_WEP, /**< authenticate mode : WEP */
@ -57,6 +59,7 @@ typedef enum {
WIFI_AUTH_WPA3_PSK, /**< authenticate mode : WPA3_PSK */
WIFI_AUTH_WPA2_WPA3_PSK, /**< authenticate mode : WPA2_WPA3_PSK */
WIFI_AUTH_WAPI_PSK, /**< authenticate mode : WAPI_PSK */
WIFI_AUTH_OWE, /**< authenticate mode : OWE */
WIFI_AUTH_MAX
} wifi_auth_mode_t;
@ -250,7 +253,8 @@ typedef struct {
uint32_t btm_enabled:1; /**< Whether BSS Transition Management is enabled for the connection */
uint32_t mbo_enabled:1; /**< Whether MBO is enabled for the connection */
uint32_t ft_enabled:1; /**< Whether FT is enabled for the connection */
uint32_t reserved:28; /**< Reserved for future feature set */
uint32_t owe_enabled:1; /**< Whether OWE is enabled for the connection */
uint32_t reserved:27; /**< Reserved for future feature set */
} wifi_sta_config_t;
/** @brief Configuration data for ESP32 AP or STA.

@ -1 +1 @@
Subproject commit dd7254fb02c05aaa4d0c5f6f805a6e28998f9ab5
Subproject commit bf6e8acaa3625cd6bb84a8f1531f0c39f8f4a6f8

View File

@ -62,7 +62,8 @@ set(esp_srcs "esp_supplicant/src/esp_wpa2.c"
"esp_supplicant/src/esp_wpas_glue.c"
"esp_supplicant/src/esp_common.c"
"esp_supplicant/src/esp_wps.c"
"esp_supplicant/src/esp_wpa3.c")
"esp_supplicant/src/esp_wpa3.c"
"esp_supplicant/src/esp_owe.c")
if(CONFIG_ESP_WIFI_SOFTAP_SUPPORT)
set(esp_srcs ${esp_srcs} "esp_supplicant/src/esp_hostap.c")
endif()
@ -141,6 +142,7 @@ else()
"src/crypto/sha1-pbkdf2.c"
"src/crypto/sha1.c"
"src/crypto/sha256-internal.c"
"src/crypto/sha256.c"
"src/crypto/sha384-internal.c"
"src/crypto/sha512-internal.c"
"src/crypto/sha256.c")
@ -259,4 +261,7 @@ endif()
if(CONFIG_WPA_WPS_SOFTAP_REGISTRAR)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_REGISTRAR)
endif()
if(CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA)
target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_OWE_STA)
endif()
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY LINK_INTERFACE_MULTIPLICITY 3)

View File

@ -3,6 +3,9 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#ifdef ESP_PLATFORM
#include "esp_system.h"
#include "mbedtls/bignum.h"
@ -27,6 +30,12 @@
#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES
#ifdef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT
#define ACCESS_ECDH(S, var) S->var
#else
#define ACCESS_ECDH(S, var) S->ctx.mbed_ecdh.var
#endif
#ifdef CONFIG_ECC
struct crypto_ec {
mbedtls_ecp_group group;
@ -994,4 +1003,192 @@ int crypto_ec_write_pub_key(struct crypto_key *key, unsigned char **key_buf)
return len;
}
int crypto_mbedtls_get_grp_id(int group)
{
switch(group) {
case IANA_SECP256R1:
return MBEDTLS_ECP_DP_SECP256R1;
case IANA_SECP384R1:
return MBEDTLS_ECP_DP_SECP384R1;
case IANA_SECP521R1:
return MBEDTLS_ECP_DP_SECP521R1;
default:
return MBEDTLS_ECP_DP_NONE;
}
}
void crypto_ecdh_deinit(struct crypto_ecdh *ecdh)
{
mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh;
if (!ctx) {
return;
}
mbedtls_ecdh_free(ctx);
os_free(ctx);
ctx = NULL;
}
struct crypto_ecdh * crypto_ecdh_init(int group)
{
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
mbedtls_ecdh_context *ctx;
ctx = os_zalloc(sizeof(*ctx));
if (!ctx) {
wpa_printf(MSG_ERROR, "Memory allocation failed for ecdh context");
goto fail;
}
mbedtls_ecdh_init(ctx);
if ((mbedtls_ecp_group_load(ACCESS_ECDH(&ctx, grp), crypto_mbedtls_get_grp_id(group))) != 0) {
wpa_printf(MSG_ERROR, "Failed to set up ECDH context with group info");
goto fail;
}
/* Initialize CTR_DRBG context */
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
/* Seed and setup CTR_DRBG entropy source for future reseeds */
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) {
wpa_printf(MSG_ERROR, "Seeding entropy source failed");
goto fail;
}
/* Generates ECDH keypair on elliptic curve */
if (mbedtls_ecdh_gen_public(ACCESS_ECDH(&ctx, grp), ACCESS_ECDH(&ctx, d), ACCESS_ECDH(&ctx, Q), mbedtls_ctr_drbg_random, &ctr_drbg)!=0) {
wpa_printf(MSG_ERROR, "ECDH keypair on curve failed");
goto fail;
}
return (struct crypto_ecdh *)ctx;
fail:
return NULL;
}
struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh, int y)
{
struct wpabuf *public_key = NULL;
uint8_t *buf = NULL;
mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh;
size_t prime_len = ACCESS_ECDH(ctx, grp).pbits/8;
buf = os_zalloc(y ? prime_len : 2 * prime_len);
if (!buf) {
wpa_printf(MSG_ERROR, "Memory allocation failed");
return NULL;
}
/* Export an MPI into unsigned big endian binary data of fixed size */
mbedtls_mpi_write_binary(ACCESS_ECDH(&ctx, Q).X, buf, prime_len);
public_key = wpabuf_alloc_copy(buf, 32);
os_free(buf);
return public_key;
}
struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
const u8 *key, size_t len)
{
uint8_t *secret = 0;
size_t olen = 0, len_prime = 0;
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 wpabuf *sh_secret = NULL;
int secret_key = 0;
mbedtls_ecdh_context *ctx = (mbedtls_ecdh_context *)ecdh;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_entropy_context entropy;
/* Initialize CTR_DRBG context */
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
/* Seed and setup CTR_DRBG entropy source for future reseeds */
if (mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) != 0) {
wpa_printf(MSG_ERROR, "Seeding entropy source failed");
goto cleanup;
}
len_prime = ACCESS_ECDH(ctx, grp).pbits/8;
bn_x = crypto_bignum_init_set(key, len);
/* Initialize data for EC point */
ec_pt = crypto_ec_point_init((struct crypto_ec*)ACCESS_ECDH(&ctx, grp));
if (!ec_pt) {
wpa_printf(MSG_ERROR,"Initializing for EC point failed");
goto cleanup;
}
if (crypto_ec_point_solve_y_coord((struct crypto_ec*)ACCESS_ECDH(&ctx, grp), ec_pt, bn_x, inc_y) != 0) {
wpa_printf(MSG_ERROR,"Failed to solve for y coordinate");
goto cleanup;
}
px = os_zalloc(len);
py = os_zalloc(len);
buf = os_zalloc(2*len);
if (!px || !py || !buf) {
wpa_printf(MSG_ERROR, "Memory allocation failed");
goto cleanup;
}
if (crypto_ec_point_to_bin((struct crypto_ec*)ACCESS_ECDH(&ctx, grp), ec_pt, px, py) != 0) {
wpa_printf(MSG_ERROR,"Failed to write EC point value as binary data");
goto cleanup;
}
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);
if (!pkey) {
wpa_printf(MSG_ERROR, "Failed to set point for peer's public key");
goto cleanup;
}
mbedtls_pk_context *peer = (mbedtls_pk_context*)pkey;
/* Setup ECDH context from EC key */
/* Call to mbedtls_ecdh_get_params() will initialize the context when not LEGACY context */
if (ctx != NULL && peer != NULL) {
mbedtls_ecp_copy( ACCESS_ECDH(&ctx, Qp), &(mbedtls_pk_ec(*peer))->Q );
#ifndef CONFIG_MBEDTLS_ECDH_LEGACY_CONTEXT
ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
#endif
} else {
wpa_printf(MSG_ERROR, "Failed to set peer's ECDH context");
goto cleanup;
}
int len_secret = inc_y ? 2*len : len;
secret = os_zalloc(len_secret);
if (!secret) {
wpa_printf(MSG_ERROR, "Allocation failed for secret");
goto cleanup;
}
/* Calculate secret
z = F(DH(x,Y)) */
secret_key = mbedtls_ecdh_calc_secret(ctx, &olen, secret, len_prime, mbedtls_ctr_drbg_random, &ctr_drbg);
if (secret_key != 0) {
wpa_printf(MSG_ERROR, "Calculation of secret failed");
goto cleanup;
}
sh_secret = wpabuf_alloc_copy(secret, len_secret);
cleanup:
os_free(px);
os_free(py);
os_free(buf);
os_free(secret);
crypto_ec_free_key(pkey);
crypto_bignum_deinit(bn_x, 1);
crypto_ec_point_deinit(ec_pt, 1);
return sh_secret;
}
#endif /* CONFIG_ECC */

View File

@ -0,0 +1,34 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifdef CONFIG_OWE_STA
#include "crypto/crypto.h"
#include "esp_owe_i.h"
#include "rsn_supp/wpa.h"
uint8_t *owe_build_dhie(uint16_t group)
{
struct wpa_sm *sm = NULL;
sm = get_wpa_sm();
return (uint8_t *)(owe_build_assoc_req(sm, group));
}
void owe_deinit(void)
{
struct wpa_sm *sm;
sm = get_wpa_sm();
if (sm->key_mgmt == WPA_KEY_MGMT_OWE) {
crypto_ecdh_deinit(sm->owe_ecdh);
sm->owe_ecdh = NULL;
}
}
void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb)
{
wpa_cb->owe_build_dhie = owe_build_dhie;
wpa_cb->owe_process_assoc_resp = owe_process_assoc_resp;
}
#endif /* CONFIG_OWE_STA */

View File

@ -0,0 +1,23 @@
/*
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_OWE_H
#define ESP_OWE_H
#ifdef CONFIG_OWE_STA
#include "esp_wifi_driver.h"
#define OWE_PMK_LEN 32
#define OWE_PMKID_LEN 16
#define OWE_DH_GRP19 19
#define OWE_PRIME_LEN 32
void owe_deinit(void);
void esp_wifi_register_owe_cb(struct wpa_funcs *wpa_cb);
#endif /* CONFIG_OWE_STA */
#endif /* ESP_OWE_H */

View File

@ -71,6 +71,7 @@ enum {
WAPI_AUTH_CERT = 0x0c,
WPA2_AUTH_ENT_SHA384_SUITE_B = 0x0d,
WPA2_AUTH_FT_PSK = 0x0e,
WPA3_AUTH_OWE = 0x0f,
WPA2_AUTH_INVALID
};
@ -134,6 +135,8 @@ struct wpa_funcs {
int (*wpa3_parse_sae_msg)(uint8_t *buf, size_t len, uint32_t type, uint16_t status);
int (*wpa_sta_rx_mgmt)(u8 type, u8 *frame, size_t len, u8 *sender, u32 rssi, u8 channel, u64 current_tsf);
void (*wpa_config_done)(void);
uint8_t *(*owe_build_dhie)(uint16_t group);
int (*owe_process_assoc_resp)(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len);
};
struct wpa2_funcs {
@ -239,7 +242,7 @@ int esp_wifi_ipc_internal(wifi_ipc_config_t *cfg, bool sync);
int esp_wifi_register_wpa2_cb_internal(struct wpa2_funcs *cb);
int esp_wifi_unregister_wpa2_cb_internal(void);
bool esp_wifi_sta_prof_is_wpa2_internal(void);
bool esp_wifi_sta_prof_is_wpa3_internal(void);
bool esp_wifi_sta_prof_is_rsn_internal(void);
bool esp_wifi_sta_prof_is_wapi_internal(void);
esp_err_t esp_wifi_sta_wpa2_ent_disable_internal(wifi_wpa2_param_t *param);
esp_err_t esp_wifi_sta_wpa2_ent_enable_internal(wifi_wpa2_param_t *param);

View File

@ -30,6 +30,7 @@
#include "esp_wpa3_i.h"
#include "esp_wpa2.h"
#include "esp_common_i.h"
#include "esp_owe_i.h"
#include "esp_wps.h"
#include "eap_server/eap.h"
@ -83,7 +84,7 @@ int wpa_config_profile(uint8_t *bssid)
if (esp_wifi_sta_prof_is_wpa_internal()) {
wpa_set_profile(WPA_PROTO_WPA, esp_wifi_sta_get_prof_authmode_internal());
} else if (esp_wifi_sta_prof_is_wpa2_internal() || esp_wifi_sta_prof_is_wpa3_internal()) {
} else if (esp_wifi_sta_prof_is_rsn_internal()) {
wpa_set_profile(WPA_PROTO_RSN, esp_wifi_sta_get_prof_authmode_internal());
} else if (esp_wifi_sta_prof_is_wapi_internal()) {
wpa_set_profile(WPA_PROTO_WAPI, esp_wifi_sta_get_prof_authmode_internal());
@ -242,6 +243,9 @@ static void wpa_sta_disconnected_cb(uint8_t reason_code)
default:
break;
}
#ifdef CONFIG_OWE_STA
owe_deinit();
#endif /* CONFIG_OWE_STA */
}
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
@ -339,6 +343,9 @@ int esp_supplicant_init(void)
wpa_cb->wpa_config_done = wpa_config_done;
esp_wifi_register_wpa3_cb(wpa_cb);
#ifdef CONFIG_OWE_STA
esp_wifi_register_owe_cb(wpa_cb);
#endif /* CONFIG_OWE_STA */
eloop_init();
ret = esp_supplicant_common_init(wpa_cb);

View File

@ -47,6 +47,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
#define WPA_KEY_MGMT_OSEN BIT(15)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16)
#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17)
#define WPA_KEY_MGMT_OWE BIT(22)
static inline int wpa_key_mgmt_wpa_ieee8021x(int akm)
{
@ -87,7 +88,8 @@ static inline int wpa_key_mgmt_sha256(int akm)
WPA_KEY_MGMT_IEEE8021X_SHA256 |
WPA_KEY_MGMT_OSEN |
WPA_KEY_MGMT_SAE |
WPA_KEY_MGMT_IEEE8021X_SUITE_B));
WPA_KEY_MGMT_IEEE8021X_SUITE_B |
WPA_KEY_MGMT_OWE));
}
static inline int wpa_key_mgmt_sha384(int akm)
@ -101,11 +103,17 @@ static inline int wpa_key_mgmt_suite_b(int akm)
WPA_KEY_MGMT_IEEE8021X_SUITE_B_192));
}
static inline int wpa_key_mgmt_owe(int akm)
{
return akm == WPA_KEY_MGMT_OWE;
}
static inline int wpa_key_mgmt_wpa(int akm)
{
return wpa_key_mgmt_wpa_ieee8021x(akm) ||
wpa_key_mgmt_wpa_psk(akm) ||
wpa_key_mgmt_sae(akm);
wpa_key_mgmt_sae(akm) ||
wpa_key_mgmt_owe(akm);
}
static inline int wpa_key_mgmt_wpa_any(int akm)

View File

@ -324,6 +324,11 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE)
return WPA_KEY_MGMT_SAE;
#endif /* CONFIG_WPA3_SAE */
#ifdef CONFIG_OWE_STA
if(RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OWE)
return WPA_KEY_MGMT_OWE;
#endif /* CONFIG_OWE_STA */
return 0;
}
@ -853,7 +858,7 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES:
if (hmac_sha1(key, key_len, buf, len, hash))
return -1;
memcpy(mic, hash, MD5_MAC_LEN);
os_memcpy(mic, hash, MD5_MAC_LEN);
break;
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
return omac1_aes_128(key, buf, len, mic);
@ -878,7 +883,23 @@ int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver,
os_memcpy(mic, hash, 24);
break;
#endif /* CONFIG_SUITEB192 */
#ifdef CONFIG_OWE_STA
case WPA_KEY_MGMT_OWE:
wpa_printf(MSG_DEBUG,
"WPA: EAPOL-Key MIC using HMAC-SHA%u (AKM-defined - OWE)",
(unsigned int) key_len * 8 * 2);
if (key_len == 128 / 8) {
if (hmac_sha256(key, key_len, buf, len, hash))
return -1;
} else {
wpa_printf(MSG_INFO,"OWE: Unsupported KCK length: %u",
(unsigned int) key_len);
return -1;
}
os_memcpy(mic, hash, key_len);
break;
#endif /* CONFIG_OWE_STA */
#endif /* CONFIG_IEEE80211W */
default:
return -1;
@ -1051,6 +1072,10 @@ int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label,
const u8 *nonce1, const u8 *nonce2,
struct wpa_ptk *ptk, int akmp, int cipher)
{
if (pmk_len == 0) {
wpa_printf(MSG_ERROR, "WPA: No PMK set for PTK derivation");
return -1;
}
u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN];
u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
size_t ptk_len;

View File

@ -66,6 +66,8 @@
#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \
RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
#define RSN_AUTH_KEY_MGMT_OWE RSN_SELECTOR(0x00, 0x0f, 0xac, 18)
#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0)
#define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1)
#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2)

View File

@ -20,6 +20,7 @@
#ifndef CRYPTO_H
#define CRYPTO_H
#include "utils/common.h"
/**
* md4_vector - MD4 hash for data vector
@ -1081,4 +1082,15 @@ int crypto_ec_get_priv_key_der(struct crypto_key *key, unsigned char **key_data,
*/
int crypto_bignum_to_string(const struct crypto_bignum *a,
u8 *buf, size_t buflen, size_t padlen);
struct crypto_ecdh;
void crypto_ecdh_deinit(struct crypto_ecdh *ecdh);
struct crypto_ecdh * crypto_ecdh_init(int group);
struct wpabuf * crypto_ecdh_get_pubkey(struct crypto_ecdh *ecdh,int y);
struct wpabuf * crypto_ecdh_set_peerkey(struct crypto_ecdh *ecdh, int inc_y,
const u8 *key, size_t len);
#endif /* CRYPTO_H */

View File

@ -29,9 +29,11 @@
#include "crypto/sha1.h"
#include "crypto/aes_wrap.h"
#include "crypto/ccmp.h"
#include "crypto/sha256.h"
#include "esp_rom_sys.h"
#include "common/bss.h"
#include "esp_common_i.h"
#include "esp_owe_i.h"
/**
* eapol_sm_notify_eap_success - Notification of external EAP success trigger
@ -284,7 +286,7 @@ static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise)
ver = WPA_KEY_INFO_TYPE_AES_128_CMAC;
else if (sm->pairwise_cipher != WPA_CIPHER_TKIP)
ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
else if (sm->key_mgmt == WPA_KEY_MGMT_SAE)
else if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE)
ver = 0;
else
ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
@ -807,7 +809,7 @@ void wpa_supplicant_key_neg_complete(struct wpa_sm *sm,
sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX,
MLME_SETPROTECTION_KEY_TYPE_PAIRWISE);
if (wpa_key_mgmt_wpa_psk(sm->key_mgmt))
if (wpa_key_mgmt_wpa_psk(sm->key_mgmt) || sm->key_mgmt == WPA_KEY_MGMT_OWE)
eapol_sm_notify_eap_success(TRUE);
/*
* Start preauthentication after a short wait to avoid a
@ -1719,7 +1721,8 @@ static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm,
ver == WPA_KEY_INFO_TYPE_AES_128_CMAC ||
sm->key_mgmt == WPA_KEY_MGMT_OSEN ||
wpa_key_mgmt_suite_b(sm->key_mgmt) ||
sm->key_mgmt == WPA_KEY_MGMT_SAE) {
sm->key_mgmt == WPA_KEY_MGMT_SAE ||
sm->key_mgmt == WPA_KEY_MGMT_OWE) {
u8 *buf;
if (*key_data_len < 8 || *key_data_len % 8) {
#ifdef DEBUG_PRINT
@ -1912,6 +1915,9 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
sm->key_mgmt != WPA_KEY_MGMT_SAE &&
#endif
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
#ifdef CONFIG_OWE_STA
sm->key_mgmt != WPA_KEY_MGMT_OWE &&
#endif /* CONFIG_OWE_STA */
#endif
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
#ifdef DEBUG_PRINT
@ -1933,7 +1939,8 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
sm->key_mgmt != WPA_KEY_MGMT_OSEN &&
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
sm->key_mgmt != WPA_KEY_MGMT_SAE &&
sm->key_mgmt != WPA_KEY_MGMT_OWE) {
goto out;
}
} else
@ -1942,7 +1949,8 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
!wpa_key_mgmt_suite_b(sm->key_mgmt) &&
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES &&
sm->key_mgmt != WPA_KEY_MGMT_SAE) {
sm->key_mgmt != WPA_KEY_MGMT_SAE &&
sm->key_mgmt != WPA_KEY_MGMT_OWE) {
#ifdef DEBUG_PRINT
wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key "
"descriptor version (%d) is not 2.", ver);
@ -2223,6 +2231,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192;
} else if (auth_mode == WPA2_AUTH_FT_PSK) {
sm->key_mgmt = WPA_KEY_MGMT_FT_PSK;
} else if (auth_mode == WPA3_AUTH_OWE) {
sm->key_mgmt = WPA_KEY_MGMT_OWE;
} else {
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
}
@ -2274,6 +2284,7 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
sm->ap_notify_completed_rsne = esp_wifi_sta_is_ap_notify_completed_rsne_internal();
if (sm->key_mgmt == WPA_KEY_MGMT_SAE ||
sm->key_mgmt == WPA_KEY_MGMT_OWE ||
is_wpa2_enterprise_connection()) {
if (!esp_wifi_skip_supp_pmkcaching() && use_pmk_cache) {
pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, 0);
@ -2374,7 +2385,7 @@ wpa_set_passphrase(char * passphrase, u8 *ssid, size_t ssid_len)
* Here only handle passphrase string. Need extra step to handle 32B, 64Hex raw
* PMK.
*/
if (sm->key_mgmt == WPA_KEY_MGMT_SAE)
if (sm->key_mgmt == WPA_KEY_MGMT_SAE || sm->key_mgmt == WPA_KEY_MGMT_OWE)
return;
/* This is really SLOW, so just re cacl while reset param */
@ -2595,4 +2606,190 @@ void wpa_sta_clear_curr_pmksa(void) {
pmksa_cache_clear_current(sm);
}
struct wpa_sm * get_wpa_sm(void)
{
return &gWpaSm;
}
#ifdef CONFIG_OWE_STA
struct wpabuf *owe_build_assoc_req(struct wpa_sm *sm, u16 group)
{
struct wpabuf *owe_ie = NULL, *pub = NULL;
size_t prime_len;
if (group == OWE_DH_GRP19) {
prime_len = OWE_PRIME_LEN;
} else {
wpa_printf(MSG_ERROR, "OWE: Unsupported Diffie-Hellman group");
return NULL;
}
sm->owe_ecdh = crypto_ecdh_init(group);
if (!sm->owe_ecdh) {
wpa_printf(MSG_ERROR, "Initialization of ecdh failed");
return NULL;
}
sm->owe_group = group;
/* Get own public key */
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
pub = wpabuf_zeropad(pub, prime_len);
if (!pub) {
wpa_printf(MSG_ERROR, "Own public key is NULL");
goto fail;
}
wpa_hexdump_buf(MSG_DEBUG, "Own public key", pub);
owe_ie = wpabuf_alloc(5 + wpabuf_len(pub));
if (!owe_ie) {
wpa_printf(MSG_ERROR, "OWE IE allocation failed");
goto fail;
}
/* Constructing the DH IE */
wpabuf_put_u8(owe_ie, WLAN_EID_EXTENSION);
wpabuf_put_u8(owe_ie, 1 + 2 + wpabuf_len(pub));
wpabuf_put_u8(owe_ie, WLAN_EID_EXT_OWE_DH_PARAM);
wpabuf_put_le16(owe_ie, group);
wpabuf_put_buf(owe_ie, pub);
wpabuf_free(pub);
wpa_hexdump_buf(MSG_DEBUG, "OWE: Diffie-Hellman Parameter element", owe_ie);
return (struct wpabuf *)wpabuf_head(owe_ie);
fail:
wpabuf_free(pub);
crypto_ecdh_deinit(sm->owe_ecdh);
return NULL;
}
int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len)
{
size_t prime_len=0,hash_len=0;
struct wpabuf * sh_secret = NULL, *pub = NULL, *hkey = NULL;
int res;
const char *info = "OWE Key Generation";
u8 pmkid[SHA256_MAC_LEN], prk[SHA256_MAC_LEN], pmk[SHA256_MAC_LEN];
const u8 *addr[2];
size_t len[2];
u16 group;
struct wpa_sm *sm;
sm = get_wpa_sm();
(void)res;
struct wpa_ie_data *parsed_rsn_data;
parsed_rsn_data = os_zalloc(sizeof(struct wpa_ie_data));
if (!parsed_rsn_data) {
wpa_printf(MSG_ERROR, "Memory allocation failed");
goto fail;
}
if (rsn_ie && rsn_len && wpa_parse_wpa_ie_rsn(rsn_ie, rsn_len + 2, parsed_rsn_data) != 0) {
goto fail;
}
if (!dh_ie && !dh_len && parsed_rsn_data->num_pmkid == 0) {
wpa_printf(MSG_ERROR, "OWE: No diffie hellman parameter in response");
goto fail;
}
if (!sm->cur_pmksa) { /* No PMK caching */
dh_len += 2;
dh_ie += 3;
dh_len -=3;
group = WPA_GET_LE16(dh_ie);
/* Only group 19 is supported */
if ((group != sm->owe_group) || (group != OWE_DH_GRP19)) {
wpa_printf(MSG_ERROR, "OWE: Unexpected Diffie-Hellman group in response");
goto fail;
}
prime_len = OWE_PRIME_LEN;
/* Set peer's public key point and calculate shared secret */
sh_secret = crypto_ecdh_set_peerkey(sm->owe_ecdh, 0, dh_ie+2, dh_len-2);
sh_secret = wpabuf_zeropad(sh_secret, prime_len);
if (!sh_secret) {
wpa_printf(MSG_ERROR, "OWE: Invalid peer DH public key");
goto fail;
}
wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", sh_secret);
pub = crypto_ecdh_get_pubkey(sm->owe_ecdh, 0);
if (!pub) {
wpa_printf(MSG_ERROR, "No own public key");
wpabuf_free(sh_secret);
goto fail;
}
/* PMKID = Truncate-128(Hash(C | A)) */
addr[0] = wpabuf_head(pub);
len[0] = wpabuf_len(pub);
addr[1] = dh_ie + 2;
len[1] = dh_len - 2;
res = sha256_vector(2, addr, len, pmkid);
hash_len = SHA256_MAC_LEN;
pub = wpabuf_zeropad(pub, prime_len);
/* prk = HKDF-extract(C | A | group, z) */
hkey = wpabuf_alloc(wpabuf_len(pub) + dh_len - 2 + 2);
wpabuf_put_buf(hkey, pub); /* C */
wpabuf_free(pub);
wpabuf_put_data(hkey, dh_ie + 2, dh_len - 2); /* A */
wpabuf_put_le16(hkey, sm->owe_group); /* group */
res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), wpabuf_head(sh_secret), wpabuf_len(sh_secret), prk);
hash_len = SHA256_MAC_LEN;
wpabuf_free(hkey);
wpabuf_free(sh_secret);
wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len);
/* PMK = HKDF-expand(prk, "OWE Key Generation", n) */
res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *)info,
os_strlen(info), pmk, hash_len);
forced_memzero(prk, SHA256_MAC_LEN);
wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, OWE_PMKID_LEN);
os_memcpy(sm->pmk,pmk,hash_len);
sm->pmk_len = hash_len;
wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len);
pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0,
sm->bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt);
goto done;
} else { /* PMK caching */
if (parsed_rsn_data && sm->cur_pmksa) {
if (parsed_rsn_data->num_pmkid == 1 && parsed_rsn_data->pmkid) {
if (os_memcmp(parsed_rsn_data->pmkid, sm->cur_pmksa->pmkid, OWE_PMKID_LEN) == 0) {
wpa_printf(MSG_DEBUG, "OWE: Using PMK caching");
wpa_sm_set_pmk_from_pmksa(sm);
goto done;
} else {
wpa_printf(MSG_DEBUG, "OWE : Invalid PMKID in response");
goto fail;
}
}
}
}
done:
os_free(parsed_rsn_data);
return 0;
fail:
os_free(parsed_rsn_data);
return -1;
}
#endif // CONFIG_OWE_STA
#endif // ESP_SUPPLICANT

View File

@ -115,4 +115,12 @@ wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len,
}
#endif /* CONFIG_IEEE80211R */
struct wpa_sm * get_wpa_sm(void);
void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
int owe_process_assoc_resp(const u8 *rsn_ie, size_t rsn_len, const uint8_t *dh_ie, size_t dh_len);
struct wpabuf *owe_build_assoc_req(struct wpa_sm *sm, u16 group);
#endif /* WPA_H */

View File

@ -109,6 +109,10 @@ struct wpa_sm {
u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */
size_t assoc_resp_ies_len;
#endif /* CONFIG_IEEE80211R */
#ifdef CONFIG_OWE_STA
struct crypto_ecdh *owe_ecdh;
u16 owe_group;
#endif /* CONFIG_OWE_STA */
};
/**

View File

@ -197,6 +197,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
} else if (key_mgmt == WPA_KEY_MGMT_SAE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE);
#endif /* CONFIG_WPA3_SAE */
#ifdef CONFIG_OWE_STA
} else if (key_mgmt == WPA_KEY_MGMT_OWE) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE);
#endif /* CONFIG_OWE_STA */
#endif /* CONFIG_IEEE80211W */
} else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) {
RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192);
@ -214,7 +218,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
#ifdef CONFIG_IEEE80211W
if (sm->pmf_cfg.capable) {
capab |= WPA_CAPABILITY_MFPC;
if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE) {
if (sm->pmf_cfg.required || key_mgmt == WPA_KEY_MGMT_SAE || key_mgmt == WPA_KEY_MGMT_OWE) {
capab |= WPA_CAPABILITY_MFPR;
}
}

View File

@ -474,5 +474,6 @@ void * __hide_aliasing_typecast(void *foo);
#endif /* CONFIG_VALGRIND */
#define IANA_SECP256R1 19
#define IANA_SECP384R1 20
#define IANA_SECP521R1 21
#endif /* COMMON_H */

View File

@ -28,6 +28,9 @@ static void print_auth_mode(int authmode)
case WIFI_AUTH_OPEN:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OPEN");
break;
case WIFI_AUTH_OWE:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_OWE");
break;
case WIFI_AUTH_WEP:
ESP_LOGI(TAG, "Authmode \tWIFI_AUTH_WEP");
break;