From 797c7144bd724cd1c8735de553f97aaceab39411 Mon Sep 17 00:00:00 2001 From: Kapil Gupta Date: Sat, 9 Oct 2021 22:04:55 +0530 Subject: [PATCH] esp_wifi: Add support for GCMP and GMAC ciphers --- components/esp_rom/esp32c3/ld/esp32c3.rom.ld | 1 - components/esp_rom/esp32s3/ld/esp32s3.rom.ld | 1 - components/esp_wifi/Kconfig | 13 + .../esp_wifi/include/esp_wifi_crypto_types.h | 34 +- components/esp_wifi/include/esp_wifi_types.h | 4 + components/esp_wifi/lib | 2 +- components/wpa_supplicant/CMakeLists.txt | 14 + components/wpa_supplicant/Kconfig | 9 + components/wpa_supplicant/component.mk | 12 + .../esp_supplicant/src/esp_wifi_driver.h | 9 +- .../esp_supplicant/src/esp_wpa_main.c | 9 +- .../wpa_supplicant/include/utils/wpa_debug.h | 2 +- components/wpa_supplicant/src/ap/wpa_auth.c | 81 +- components/wpa_supplicant/src/ap/wpa_auth_i.h | 2 +- components/wpa_supplicant/src/common/defs.h | 9 +- components/wpa_supplicant/src/common/dpp.c | 4 - .../wpa_supplicant/src/common/wpa_common.c | 304 +++++- .../wpa_supplicant/src/common/wpa_common.h | 89 +- .../wpa_supplicant/src/crypto/aes-gcm.c | 327 +++++++ .../wpa_supplicant/src/crypto/crypto_ops.c | 31 +- .../wpa_supplicant/src/crypto/sha384-prf.c | 108 +++ .../wpa_supplicant/src/rsn_supp/pmksa_cache.c | 6 +- .../wpa_supplicant/src/rsn_supp/pmksa_cache.h | 2 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 888 +++++++++--------- .../wpa_supplicant/src/rsn_supp/wpa_i.h | 2 +- .../wpa_supplicant/src/rsn_supp/wpa_ie.c | 57 +- tools/ci/check_copyright_ignore.txt | 4 +- 27 files changed, 1416 insertions(+), 608 deletions(-) create mode 100644 components/wpa_supplicant/src/crypto/aes-gcm.c create mode 100644 components/wpa_supplicant/src/crypto/sha384-prf.c diff --git a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld index 4b42f866e5..db1a6ac02c 100644 --- a/components/esp_rom/esp32c3/ld/esp32c3.rom.ld +++ b/components/esp_rom/esp32c3/ld/esp32c3.rom.ld @@ -1567,7 +1567,6 @@ ppEnqueueRxq = 0x400016c8; ppEnqueueTxDone = 0x400016cc; ppGetTxQFirstAvail_Locked = 0x400016d0; ppGetTxframe = 0x400016d4; -ppProcTxSecFrame = 0x400016dc; ppProcessRxPktHdr = 0x400016e0; ppProcessTxQ = 0x400016e4; ppRecordBarRRC = 0x400016e8; diff --git a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld index f78625b3b8..954f027f0d 100644 --- a/components/esp_rom/esp32s3/ld/esp32s3.rom.ld +++ b/components/esp_rom/esp32s3/ld/esp32s3.rom.ld @@ -1873,7 +1873,6 @@ ppEnqueueTxDone = 0x400055a4; ppGetTxQFirstAvail_Locked = 0x400055b0; ppGetTxframe = 0x400055bc; ppMapTxQueue = 0x400055c8; -ppProcTxSecFrame = 0x400055d4; ppProcessRxPktHdr = 0x400055e0; ppProcessTxQ = 0x400055ec; ppRecordBarRRC = 0x400055f8; diff --git a/components/esp_wifi/Kconfig b/components/esp_wifi/Kconfig index 7d20d8f451..1a5c5981e2 100644 --- a/components/esp_wifi/Kconfig +++ b/components/esp_wifi/Kconfig @@ -312,4 +312,17 @@ menu "Wi-Fi" This function depends on BT-off because currently we don't support external coex and internal coex simultaneously. + config ESP_WIFI_GCMP_SUPPORT + bool "WiFi GCMP Support(GCMP128 and GCMP256)" + default n + depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) + help + Select this option to enable GCMP support. GCMP support is compulsory for WiFi Suite-B support. + + config ESP_WIFI_GMAC_SUPPORT + bool "WiFi GMAC Support(GMAC128 and GMAC256)" + default n + help + Select this option to enable GMAC support. GMAC support is compulsory for WiFi 192 bit certification. + endmenu # Wi-Fi diff --git a/components/esp_wifi/include/esp_wifi_crypto_types.h b/components/esp_wifi/include/esp_wifi_crypto_types.h index f55d148443..1249d331a6 100644 --- a/components/esp_wifi/include/esp_wifi_crypto_types.h +++ b/components/esp_wifi/include/esp_wifi_crypto_types.h @@ -1,16 +1,8 @@ -// Hardware crypto support Copyright 2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef __ESP_WIFI_CRYPTO_TYPES_H__ @@ -358,6 +350,21 @@ typedef uint8_t * (*esp_ccmp_decrypt_t)(const uint8_t *tk, const uint8_t *ieee80 typedef uint8_t * (*esp_ccmp_encrypt_t)(const uint8_t *tk, uint8_t *frame, size_t len, size_t hdrlen, uint8_t *pn, int keyid, size_t *encrypted_len); +/** + * @brief One-Key GMAC hash with AES for MIC computation + * + * @key: key for the hash operation + * @keylen: key length + * @iv: initialization vector + * @iv_len: initialization vector length + * @aad: aad + * @aad_len: aad length + * @mic: Buffer for MIC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + */ +typedef int (*esp_aes_gmac_t)(const uint8_t *key, size_t keylen, const uint8_t *iv, size_t iv_len, + const uint8_t *aad, size_t aad_len, uint8_t *mic); + /** * @brief The crypto callback function structure used when do station security connect. * The structure can be set as software crypto or the crypto optimized by ESP32 @@ -390,6 +397,7 @@ typedef struct { esp_omac1_aes_128_t omac1_aes_128; esp_ccmp_decrypt_t ccmp_decrypt; esp_ccmp_encrypt_t ccmp_encrypt; + esp_aes_gmac_t aes_gmac; }wpa_crypto_funcs_t; /** diff --git a/components/esp_wifi/include/esp_wifi_types.h b/components/esp_wifi/include/esp_wifi_types.h index cee23f3faf..ae574416b9 100644 --- a/components/esp_wifi/include/esp_wifi_types.h +++ b/components/esp_wifi/include/esp_wifi_types.h @@ -142,6 +142,10 @@ typedef enum { WIFI_CIPHER_TYPE_TKIP_CCMP, /**< the cipher type is TKIP and CCMP */ WIFI_CIPHER_TYPE_AES_CMAC128,/**< the cipher type is AES-CMAC-128 */ WIFI_CIPHER_TYPE_SMS4, /**< the cipher type is SMS4 */ + WIFI_CIPHER_TYPE_GCMP, /**< the cipher type is GCMP */ + WIFI_CIPHER_TYPE_GCMP256, /**< the cipher type is GCMP-256 */ + WIFI_CIPHER_TYPE_AES_GMAC128,/**< the cipher type is AES-GMAC-128 */ + WIFI_CIPHER_TYPE_AES_GMAC256,/**< the cipher type is AES-GMAC-256 */ WIFI_CIPHER_TYPE_UNKNOWN, /**< the cipher type is unknown */ } wifi_cipher_type_t; diff --git a/components/esp_wifi/lib b/components/esp_wifi/lib index 049fbb7f22..0c3f24cc83 160000 --- a/components/esp_wifi/lib +++ b/components/esp_wifi/lib @@ -1 +1 @@ -Subproject commit 049fbb7f22962fc4e2316e732ad08fc95b14149f +Subproject commit 0c3f24cc83d595f60e3b785e3eb098c3bc5ce2d3 diff --git a/components/wpa_supplicant/CMakeLists.txt b/components/wpa_supplicant/CMakeLists.txt index 3abc2bcab0..cd5a4b442a 100644 --- a/components/wpa_supplicant/CMakeLists.txt +++ b/components/wpa_supplicant/CMakeLists.txt @@ -10,6 +10,7 @@ set(srcs "port/os_xtensa.c" "src/crypto/aes-siv.c" "src/crypto/sha256-kdf.c" "src/crypto/ccmp.c" + "src/crypto/aes-gcm.c" "src/crypto/crypto_ops.c" "src/crypto/dh_group5.c" "src/crypto/dh_groups.c" @@ -19,6 +20,7 @@ set(srcs "port/os_xtensa.c" "src/crypto/sha384-tlsprf.c" "src/crypto/sha256-prf.c" "src/crypto/sha1-prf.c" + "src/crypto/sha384-prf.c" "src/crypto/md4-internal.c" "src/eap_peer/chap.c" "src/eap_peer/eap.c" @@ -194,6 +196,18 @@ endif() if(CONFIG_WPA_WPS_STRICT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_WPS_STRICT) endif() +if(CONFIG_WPA_SUITE_B_192) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUITEB192) +endif() +if(CONFIG_WPA_SUITE_B) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_SUITEB) +endif() +if(CONFIG_ESP_WIFI_GCMP_SUPPORT) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_GCMP) +endif() +if(CONFIG_ESP_WIFI_GMAC_SUPPORT) + target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_GMAC) +endif() if(CONFIG_WPA_MBO_SUPPORT) target_compile_definitions(${COMPONENT_LIB} PRIVATE CONFIG_MBO) diff --git a/components/wpa_supplicant/Kconfig b/components/wpa_supplicant/Kconfig index 31c6931e45..8b80df2628 100644 --- a/components/wpa_supplicant/Kconfig +++ b/components/wpa_supplicant/Kconfig @@ -18,6 +18,15 @@ menu "Supplicant" Select this option to enable WAPI-PSK which is a Chinese National Standard Encryption for Wireless LANs (GB 15629.11-2003). + config WPA_SUITE_B_192 + bool "Enable NSA suite B support with 192 bit key" + default n + select ESP_WIFI_GCMP_SUPPORT + select ESP_WIFI_GMAC_SUPPORT + help + Select this option to enable 192 bit NSA suite-B. + This is necessary to support WPA3 192 bit security. + config WPA_DEBUG_PRINT bool "Print debug messages from WPA Supplicant" default n diff --git a/components/wpa_supplicant/component.mk b/components/wpa_supplicant/component.mk index 4f4609b7cc..908eb7d116 100644 --- a/components/wpa_supplicant/component.mk +++ b/components/wpa_supplicant/component.mk @@ -85,3 +85,15 @@ endif ifdef CONFIG_WPA_MBO_SUPPORT CFLAGS += -DCONFIG_MBO endif +ifdef CONFIG_WPA_SUITE_B_192 + CFLAGS += -DCONFIG_SUITEB192 +endif +ifdef CONFIG_WPA_SUITE_B + CFLAGS += -DCONFIG_SUITEB +endif +ifdef CONFIG_ESP_WIFI_GCMP_SUPPORT + CFLAGS += -DCONFIG_GCMP +endif +ifdef CONFIG_ESP_WIFI_GMAC_SUPPORT + CFLAGS += -DCONFIG_GMAC +endif diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h index f4950dfb49..29331c7407 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wifi_driver.h @@ -65,7 +65,8 @@ enum { WPA2_AUTH_ENT_SHA256= 0x0a, WAPI_AUTH_PSK = 0x0b, WAPI_AUTH_CERT = 0x0c, - WPA2_AUTH_INVALID = 0x0d, + WPA2_AUTH_ENT_SHA384_SUITE_B = 0x0d, + WPA2_AUTH_INVALID = 0x0e, }; typedef enum { @@ -109,7 +110,7 @@ typedef struct { struct wpa_funcs { bool (*wpa_sta_init)(void); bool (*wpa_sta_deinit)(void); - void (*wpa_sta_connect)(uint8_t *bssid); + int (*wpa_sta_connect)(uint8_t *bssid); void (*wpa_sta_disconnected_cb)(uint8_t reason_code); int (*wpa_sta_rx_eapol)(u8 *src_addr, u8 *buf, u32 len); bool (*wpa_sta_in_4way_handshake)(void); @@ -172,11 +173,11 @@ typedef struct { uint32_t arg_size; } wifi_ipc_config_t; -#define WPA_IGTK_LEN 16 +#define WPA_IGTK_MAX_LEN 32 typedef struct { uint8_t keyid[2]; uint8_t pn[6]; - uint8_t igtk[WPA_IGTK_LEN]; + uint8_t igtk[WPA_IGTK_MAX_LEN]; } wifi_wpa_igtk_t; typedef struct { diff --git a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c index aedac29583..11681df428 100644 --- a/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c +++ b/components/wpa_supplicant/esp_supplicant/src/esp_wpa_main.c @@ -165,15 +165,20 @@ bool wpa_deattach(void) return true; } -void wpa_sta_connect(uint8_t *bssid) +int wpa_sta_connect(uint8_t *bssid) { /* use this API to set AP specific IEs during connection */ int ret = 0; ret = wpa_config_profile(); if (ret == 0) { ret = wpa_config_bss(bssid); - WPA_ASSERT(ret == 0); + if (ret) { + wpa_printf(MSG_DEBUG, "Rejecting bss, validation failed"); + return ret; + } } + + return 0; } void wpa_config_done(void) diff --git a/components/wpa_supplicant/include/utils/wpa_debug.h b/components/wpa_supplicant/include/utils/wpa_debug.h index 9714617a60..c6ac189c22 100644 --- a/components/wpa_supplicant/include/utils/wpa_debug.h +++ b/components/wpa_supplicant/include/utils/wpa_debug.h @@ -176,7 +176,7 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, * * Note: New line '\n' is added to the end of the text when printing to stdout. */ -void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); +#define wpa_msg(...) do {} while(0) /** * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors diff --git a/components/wpa_supplicant/src/ap/wpa_auth.c b/components/wpa_supplicant/src/ap/wpa_auth.c index c3fb9bb5a2..a63eef876f 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth.c +++ b/components/wpa_supplicant/src/ap/wpa_auth.c @@ -36,7 +36,8 @@ static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); static int wpa_sm_step(struct wpa_state_machine *sm); -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len); +static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, + size_t data_len); static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, struct wpa_group *group); static void wpa_request_new_ptk(struct wpa_state_machine *sm); @@ -642,6 +643,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *s if (sm->pairwise == WPA_CIPHER_CCMP || sm->pairwise == WPA_CIPHER_GCMP) { if (wpa_use_aes_cmac(sm) && + !wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { return; } @@ -655,7 +657,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *s if (key_info & WPA_KEY_INFO_REQUEST) { if (sm->req_replay_counter_used && - memcmp(key->replay_counter, sm->req_replay_counter, + os_memcmp(key->replay_counter, sm->req_replay_counter, WPA_REPLAY_COUNTER_LEN) <= 0) { return; } @@ -809,7 +811,8 @@ continue_processing: sm->MICVerified = FALSE; if (sm->PTK_valid && !sm->update_snonce) { - if (wpa_verify_key_mic(&sm->PTK, data, data_len)) { + if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data, + data_len)) { return; } sm->MICVerified = TRUE; @@ -1065,10 +1068,10 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { if (aes_wrap(sm->PTK.kek, 16, (key_data_len - 8) / 8, buf, - (u8 *) (key + 1))) { - os_free(hdr); - os_free(buf); - return; + (u8 *) (key + 1))) { + os_free(hdr); + os_free(buf); + return; } WPA_PUT_BE16(key->key_data_length, key_data_len); } else { @@ -1090,8 +1093,9 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, os_free(hdr); return; } - wpa_eapol_key_mic(sm->PTK.kck, version, (u8 *) hdr, len, - key->key_mic); + wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_key_mgmt, version, + (u8 *) hdr, len, key->key_mic); } wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, 1); @@ -1112,7 +1116,7 @@ int hostap_eapol_resend_process(void *timeout_ctx) sm->in_step_loop = 0; wpa_sm_step(sm); } else { - wpa_printf( MSG_INFO, "Station left, stop send EAPOL frame"); + wpa_printf( MSG_INFO, "Station left, stop send EAPOL frame"); } return ESP_OK; @@ -1161,16 +1165,15 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, ets_timer_arm(&sm->resend_eapol, 1000, 0); } - -static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) +static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, + size_t data_len) { struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; u16 key_info; int ret = 0; - int mic_ret = 0; - u8 mic[16]; - char debug_log[8]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = 16; if (data_len < sizeof(*hdr) + sizeof(*key)){ wpa_printf( MSG_DEBUG, "invalid data length, len=%u\n", data_len); @@ -1180,23 +1183,16 @@ static int wpa_verify_key_mic(struct wpa_ptk *PTK, u8 *data, size_t data_len) hdr = (struct ieee802_1x_hdr *) data; key = (struct wpa_eapol_key *) (hdr + 1); key_info = WPA_GET_BE16(key->key_info); - memcpy(mic, key->key_mic, 16); - memset(key->key_mic, 0, 16); - - mic_ret = wpa_eapol_key_mic(PTK->kck, key_info & WPA_KEY_INFO_TYPE_MASK, data, data_len, key->key_mic); - if ( mic_ret || memcmp(mic, key->key_mic, 16) != 0) { + os_memcpy(mic, key->key_mic, mic_len); + os_memset(key->key_mic, 0, mic_len); + if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, + key_info & WPA_KEY_INFO_TYPE_MASK, + data, data_len, key->key_mic) || + os_memcmp_const(mic, key->key_mic, mic_len) != 0) ret = -1; - } - os_memset(debug_log, 0, 8); - os_memcpy(debug_log, "you mic", sizeof("you mic")); - wpa_dump_mem(debug_log, mic, 16); - os_memset(debug_log, 0, 8); - os_memcpy(debug_log, "my mic", sizeof("my mic")); - wpa_dump_mem(debug_log, key->key_mic, 16); - - memcpy(key->key_mic, mic, 16); + os_memcpy(key->key_mic, mic, mic_len); return ret; -} + } void wpa_remove_ptk(struct wpa_state_machine *sm) @@ -1505,21 +1501,19 @@ SM_STATE(WPA_PTK, PTKSTART) } -static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk) +static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, + const u8 *pmk, struct wpa_ptk *ptk) { - size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; #ifdef CONFIG_IEEE80211R + size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); #endif /* CONFIG_IEEE80211R */ - wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", - sm->wpa_auth->addr, sm->addr, sm->ANonce, sm->SNonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); - - return 0; + return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", + sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, + ptk, sm->wpa_key_mgmt, sm->pairwise); } @@ -1548,9 +1542,10 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) pmk = sm->PMK; } - wpa_derive_ptk(sm, pmk, &PTK); + wpa_derive_ptk(sm, sm->SNonce, pmk, &PTK); - if (wpa_verify_key_mic(&PTK, sm->last_rx_eapol_key, + if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, + sm->last_rx_eapol_key, sm->last_rx_eapol_key_len) == 0) { wpa_printf( MSG_DEBUG, "mic verify ok, pmk=%p\n", pmk); ok = 1; @@ -1825,7 +1820,7 @@ SM_STATE(WPA_PTK, PTKINITDONE) enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk1, klen)) { + sm->PTK.tk, klen)) { wpa_sta_disconnect(sm->wpa_auth, sm->addr); return; } @@ -2305,7 +2300,7 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, #ifdef CONFIG_IEEE80211W if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION && wpa_auth_set_key(wpa_auth, group->vlan_id, WIFI_WPA_ALG_IGTK, - broadcast_ether_addr, group->GN_igtk, + broadcast_ether_addr, group->GN_igtk, group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN) < 0) ret = -1; diff --git a/components/wpa_supplicant/src/ap/wpa_auth_i.h b/components/wpa_supplicant/src/ap/wpa_auth_i.h index 7dc19dc66d..fba036732e 100644 --- a/components/wpa_supplicant/src/ap/wpa_auth_i.h +++ b/components/wpa_supplicant/src/ap/wpa_auth_i.h @@ -202,7 +202,7 @@ int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, u8 *buf, size_t len, const u8 *subelem, size_t subelem_len); int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, - struct wpa_ptk *ptk, size_t ptk_len); + struct wpa_ptk *ptk); struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); void wpa_ft_install_ptk(struct wpa_state_machine *sm); diff --git a/components/wpa_supplicant/src/common/defs.h b/components/wpa_supplicant/src/common/defs.h index edd4639804..0c33546957 100644 --- a/components/wpa_supplicant/src/common/defs.h +++ b/components/wpa_supplicant/src/common/defs.h @@ -23,8 +23,11 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #define WPA_CIPHER_TKIP BIT(1) #define WPA_CIPHER_CCMP BIT(3) #define WPA_CIPHER_AES_128_CMAC BIT(5) -#define WPA_CIPHER_GCMP BIT(6) #define WPA_CIPHER_SMS4 BIT(10) +#define WPA_CIPHER_GCMP BIT(11) +#define WPA_CIPHER_GCMP_256 BIT(12) +#define WPA_CIPHER_BIP_GMAC_128 BIT(13) +#define WPA_CIPHER_BIP_GMAC_256 BIT(14) #define WPA_KEY_MGMT_IEEE8021X BIT(0) #define WPA_KEY_MGMT_PSK BIT(1) @@ -143,7 +146,9 @@ enum wpa_cipher { CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 + CIPHER_WEP104, + CIPHER_SMS4, + CIPHER_GCMP_256, }; /** diff --git a/components/wpa_supplicant/src/common/dpp.c b/components/wpa_supplicant/src/common/dpp.c index c96869b318..29eb6b1b3d 100644 --- a/components/wpa_supplicant/src/common/dpp.c +++ b/components/wpa_supplicant/src/common/dpp.c @@ -52,10 +52,6 @@ static const struct dpp_curve_params dpp_curves[] = { { NULL, 0, 0, 0, 0, NULL, 0, NULL } }; -void wpa_msg(void *ctx, int level, const char *fmt, ...) -{ -} - static struct wpabuf * gas_build_req(u8 action, u8 dialog_token, size_t size) { diff --git a/components/wpa_supplicant/src/common/wpa_common.c b/components/wpa_supplicant/src/common/wpa_common.c index 9100517576..070ba0887e 100644 --- a/components/wpa_supplicant/src/common/wpa_common.c +++ b/components/wpa_supplicant/src/common/wpa_common.c @@ -21,13 +21,36 @@ #include "rsn_supp/wpa.h" #include "crypto/sha1.h" #include "crypto/sha256.h" +#include "crypto/sha384.h" #include "crypto/md5.h" #include "crypto/aes.h" #include "crypto/aes_wrap.h" #define MD5_MAC_LEN 16 -#ifndef CONFIG_NO_WPA2 +static unsigned int wpa_kck_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 24; + return 16; +} + +static unsigned int wpa_kek_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 32; + return 16; +} + + +unsigned int wpa_mic_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 24; + + return 16; +} + static int rsn_selector_to_bitfield(const u8 *s) { if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) @@ -40,10 +63,23 @@ static int rsn_selector_to_bitfield(const u8 *s) return WPA_CIPHER_CCMP; if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_WEP104) return WPA_CIPHER_WEP104; +#ifdef COFIG_GCMP + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) + return WPA_CIPHER_GCMP; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256) + return WPA_CIPHER_GCMP_256; +#endif #ifdef CONFIG_IEEE80211W if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) return WPA_CIPHER_AES_128_CMAC; +#ifdef COFIG_GMAC + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128) + return WPA_CIPHER_BIP_GMAC_128; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256) + return WPA_CIPHER_BIP_GMAC_256; +#endif #endif /* CONFIG_IEEE80211W */ + return 0; } @@ -69,6 +105,14 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) return WPA_KEY_MGMT_PSK_SHA256; #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SUITEB + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B; +#endif +#ifdef CONFIG_SUITEB192 + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; +#endif return 0; } @@ -97,7 +141,14 @@ static int wpa_key_mgmt_to_bitfield(const u8 *s) return WPA_KEY_MGMT_WPA_NONE; return 0; } -#endif /* CONFIG_NO_WPA2 */ + +int wpa_cipher_valid_mgmt_group(int cipher) +{ + return cipher == WPA_CIPHER_AES_128_CMAC || + cipher == WPA_CIPHER_BIP_GMAC_128 || + cipher == WPA_CIPHER_BIP_GMAC_256; +} + /** * wpa_parse_wpa_ie_rsn - Parse RSN IE * @rsn_ie: Buffer containing RSN IE @@ -108,7 +159,6 @@ static int wpa_key_mgmt_to_bitfield(const u8 *s) int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data) { -#ifndef CONFIG_NO_WPA2 const struct rsn_ie_hdr *hdr; const u8 *pos; int left; @@ -122,8 +172,9 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, data->capabilities = 0; data->pmkid = NULL; data->num_pmkid = 0; - data->mgmt_group_cipher = 0; + data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; + wpa_hexdump(MSG_DEBUG, "rsn_ie", rsn_ie, rsn_ie_len); if (rsn_ie_len == 0) { /* No RSN IE - fail silently */ return -1; @@ -142,7 +193,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, if (hdr->elem_id != WLAN_EID_RSN || hdr->len != rsn_ie_len - 2 || WPA_GET_LE16(hdr->version) != RSN_VERSION) { - #ifdef DEBUG_PRINT + #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", __func__); #endif @@ -240,6 +291,19 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, } } + if (left >= 4) { + data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); + if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { + wpa_printf(MSG_DEBUG, + "%s: Unsupported management group cipher 0x%x (%08x)", + __func__, data->mgmt_group_cipher, + WPA_GET_BE32(pos)); + return -10; + } + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } + if (left > 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "%s: ie has %u trailing bytes - ignored", @@ -248,9 +312,6 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, } return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ } int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, @@ -365,6 +426,8 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, /** * wpa_eapol_key_mic - Calculate EAPOL-Key MIC * @key: EAPOL-Key Key Confirmation Key (KCK) + * @key_len: KCK length in octets + * @akmp: WPA_KEY_MGMT_* used in key derivation * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) * @buf: Pointer to the beginning of the EAPOL header (version field) * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) @@ -380,26 +443,49 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, * happened during final editing of the standard and the correct behavior is * defined in the last draft (IEEE 802.11i/D10). */ -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic) +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic) { - u8 hash[SHA1_MAC_LEN]; + u8 hash[SHA384_MAC_LEN]; switch (ver) { case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: - return hmac_md5(key, 16, buf, len, mic); + return hmac_md5(key, key_len, buf, len, mic); case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: - if (hmac_sha1(key, 16, buf, len, hash)) + if (hmac_sha1(key, key_len, buf, len, hash)) return -1; memcpy(mic, hash, MD5_MAC_LEN); break; -#ifdef CONFIG_IEEE80211W -#ifdef CONFIG_WPA3_SAE - case WPA_KEY_INFO_TYPE_AKM_DEFINED: -#endif /* CONFIG_WPA3_SAE */ case WPA_KEY_INFO_TYPE_AES_128_CMAC: return omac1_aes_128(key, buf, len, mic); +#ifdef CONFIG_IEEE80211W + case WPA_KEY_INFO_TYPE_AKM_DEFINED: + switch (akmp) { +#ifdef CONFIG_WPA3_SAE + case WPA_KEY_MGMT_SAE: + return omac1_aes_128(key, buf, len, mic); +#endif /* CONFIG_WPA3_SAE */ +#ifdef CONFIG_SUITEB + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, MD5_MAC_LEN); + break; +#endif /* CONFIG_SUITEB */ +#ifdef CONFIG_SUITEB192 + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, 24); + break; +#endif /* CONFIG_SUITEB192 */ + #endif /* CONFIG_IEEE80211W */ + default: + return -1; + } + break; + default: return -1; } @@ -443,6 +529,70 @@ int wpa_compare_rsn_ie(int ft_initial_assoc, return -1; } +#ifdef CONFIG_SUITEB +/** + * rsn_pmkid_suite_b - Calculate PMK identifier for Suite B AKM + * @kck: Key confirmation key + * @kck_len: Length of kck in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @pmkid: Buffer for PMKID + * Returns: 0 on success, -1 on failure + * + * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy + * PMKID = Truncate(HMAC-SHA-256(KCK, "PMK Name" || AA || SPA)) + */ +int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, u8 *pmkid) +{ + char *title = "PMK Name"; + const u8 *addr[3]; + const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; + unsigned char hash[SHA256_MAC_LEN]; + + addr[0] = (u8 *) title; + addr[1] = aa; + addr[2] = spa; + + if (hmac_sha256_vector(kck, kck_len, 3, addr, len, hash) < 0) + return -1; + os_memcpy(pmkid, hash, PMKID_LEN); + return 0; +} +#endif /* CONFIG_SUITEB */ + +#ifdef CONFIG_SUITEB192 +/** + * rsn_pmkid_suite_b_192 - Calculate PMK identifier for Suite B AKM + * @kck: Key confirmation key + * @kck_len: Length of kck in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @pmkid: Buffer for PMKID + * Returns: 0 on success, -1 on failure + * + * IEEE Std 802.11ac-2013 - 11.6.1.3 Pairwise key hierarchy + * PMKID = Truncate(HMAC-SHA-384(KCK, "PMK Name" || AA || SPA)) + */ +int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, u8 *pmkid) +{ + char *title = "PMK Name"; + const u8 *addr[3]; + const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; + unsigned char hash[SHA384_MAC_LEN]; + + addr[0] = (u8 *) title; + addr[1] = aa; + addr[2] = spa; + + if (hmac_sha384_vector(kck, kck_len, 3, addr, len, hash) < 0) + return -1; + os_memcpy(pmkid, hash, PMKID_LEN); + return 0; +} +#endif /* CONFIG_SUITEB192 */ + #ifdef DEBUG_PRINT /** * wpa_cipher_txt - Convert cipher suite to a text string @@ -464,6 +614,14 @@ const char * wpa_cipher_txt(int cipher) return "CCMP"; case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: return "CCMP+TKIP"; + case WPA_CIPHER_GCMP: + return "GCMP"; + case WPA_CIPHER_GCMP_256: + return "GCMP-256"; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + return "WPA2-EAP-SUITE-B"; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + return "WPA2-EAP-SUITE-B-192"; default: return "UNKNOWN"; } @@ -480,8 +638,9 @@ const char * wpa_cipher_txt(int cipher) * @nonce1: ANonce or SNonce * @nonce2: SNonce or ANonce * @ptk: Buffer for pairwise transient key - * @ptk_len: Length of PTK - * @use_sha256: Whether to use SHA256-based KDF + * @akmp: Negotiated AKM + * @cipher: Negotiated pairwise cipher + * Returns: 0 on success, -1 on failure * * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy * PTK = PRF-X(PMK, "Pairwise key expansion", @@ -492,12 +651,14 @@ const char * wpa_cipher_txt(int cipher) * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || * Min(INonce, PNonce) || Max(INonce, PNonce)) */ -void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, - const u8 *addr1, const u8 *addr2, - const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len, int use_sha256) +int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, + const u8 *addr1, const u8 *addr2, + const u8 *nonce1, const u8 *nonce2, + struct wpa_ptk *ptk, int akmp, int cipher) { 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; if (memcmp(addr1, addr2, ETH_ALEN) < 0) { memcpy(data, addr1, ETH_ALEN); @@ -517,19 +678,42 @@ void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, WPA_NONCE_LEN); } - if (use_sha256) { + ptk->kck_len = wpa_kck_len(akmp); + ptk->kek_len = wpa_kek_len(akmp); + ptk->tk_len = wpa_cipher_key_len(cipher); + ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; + +#if defined(CONFIG_SUITEB192) + if (wpa_key_mgmt_sha384(akmp)) { + wpa_printf(MSG_DEBUG, "WPA: PTK derivation using PRF(SHA384)"); + if (sha384_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len) < 0) + return -1; + } else +#endif + if (wpa_key_mgmt_sha256(akmp)) sha256_prf(pmk, pmk_len, label, data, sizeof(data), - ptk, ptk_len); - } + tmp, ptk_len); else - { - sha1_prf(pmk, pmk_len, label, data, sizeof(data), ptk, ptk_len); - } + sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); + wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR"\n", MAC2STR(addr1), MAC2STR(addr2)); wpa_hexdump(MSG_MSGDUMP, "WPA: PMK", pmk, pmk_len); - wpa_hexdump(MSG_MSGDUMP, "WPA: PTK", ptk, ptk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); + + os_memcpy(ptk->kck, tmp, ptk->kck_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len); + + os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); + + os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); + + os_memset(tmp, 0, sizeof(tmp)); + return 0; } /** @@ -570,11 +754,23 @@ void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, int wpa_cipher_key_len(int cipher) { switch (cipher) { - case WPA_CIPHER_CCMP: - case WPA_CIPHER_GCMP: - return 16; case WPA_CIPHER_TKIP: +#ifdef CONFIG_GCMP + case WPA_CIPHER_GCMP_256: +#endif +#ifdef CONFIG_GMAC + case WPA_CIPHER_BIP_GMAC_256: +#endif return 32; + case WPA_CIPHER_CCMP: +#ifdef CONFIG_GCMP + case WPA_CIPHER_GCMP: +#endif +#ifdef CONFIG_GMAC + case WPA_CIPHER_BIP_GMAC_128: +#endif + case WPA_CIPHER_AES_128_CMAC: + return 16; case WPA_CIPHER_WEP104: return 13; case WPA_CIPHER_WEP40: @@ -584,18 +780,35 @@ int wpa_cipher_key_len(int cipher) return 0; } +int wpa_cipher_rsc_len(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_GCMP_256: + case WPA_CIPHER_CCMP: + case WPA_CIPHER_GCMP: + case WPA_CIPHER_TKIP: + return 6; + } + + return 0; +} + int wpa_cipher_to_alg(int cipher) { switch (cipher) { case WPA_CIPHER_CCMP: return WIFI_WPA_ALG_CCMP; +#ifdef CONFIG_GCMP + case WPA_CIPHER_GCMP_256: case WPA_CIPHER_GCMP: return WIFI_WPA_ALG_GCMP; +#endif case WPA_CIPHER_TKIP: return WIFI_WPA_ALG_TKIP; case WPA_CIPHER_WEP104: + return WIFI_WPA_ALG_WEP104; case WPA_CIPHER_WEP40: - return WIFI_WPA_ALG_WEP; + return WIFI_WPA_ALG_WEP40; } return WIFI_WPA_ALG_NONE; } @@ -605,8 +818,12 @@ u32 wpa_cipher_to_suite(int proto, int cipher) if (cipher & WPA_CIPHER_CCMP) return (proto == WPA_PROTO_RSN ? RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); +#ifdef CONFIG_GCMP + if (cipher & WPA_CIPHER_GCMP_256) + return RSN_CIPHER_SUITE_GCMP_256; if (cipher & WPA_CIPHER_GCMP) return RSN_CIPHER_SUITE_GCMP; +#endif if (cipher & WPA_CIPHER_TKIP) return (proto == WPA_PROTO_RSN ? RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); @@ -619,6 +836,14 @@ u32 wpa_cipher_to_suite(int proto, int cipher) if (cipher & WPA_CIPHER_NONE) return (proto == WPA_PROTO_RSN ? RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); + if (cipher & WPA_CIPHER_AES_128_CMAC) + return RSN_CIPHER_SUITE_AES_128_CMAC; +#if CONFIG_GMAC + if (cipher & WPA_CIPHER_BIP_GMAC_128) + return RSN_CIPHER_SUITE_BIP_GMAC_128; + if (cipher & WPA_CIPHER_BIP_GMAC_256) + return RSN_CIPHER_SUITE_BIP_GMAC_256; +#endif return 0; } @@ -626,8 +851,9 @@ int rsn_cipher_put_suites(u8 *pos, int ciphers) { int num_suites = 0; - if (ciphers & WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); +#ifdef CONFIG_GCMP + if (ciphers & WPA_CIPHER_GCMP_256) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256); pos += RSN_SELECTOR_LEN; num_suites++; } @@ -636,6 +862,12 @@ int rsn_cipher_put_suites(u8 *pos, int ciphers) pos += RSN_SELECTOR_LEN; num_suites++; } +#endif + if (ciphers & WPA_CIPHER_CCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + pos += RSN_SELECTOR_LEN; + num_suites++; + } if (ciphers & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; diff --git a/components/wpa_supplicant/src/common/wpa_common.h b/components/wpa_supplicant/src/common/wpa_common.h index bb277e9779..da8132e28c 100644 --- a/components/wpa_supplicant/src/common/wpa_common.h +++ b/components/wpa_supplicant/src/common/wpa_common.h @@ -22,6 +22,8 @@ /* IEEE 802.11i */ #define PMKID_LEN 16 #define PMK_LEN 32 +#define PMK_LEN_MAX 64 +#define PMK_LEN_SUITE_B_192 48 #define WPA_REPLAY_COUNTER_LEN 8 #define WPA_NONCE_LEN 32 #define WPA_KEY_RSC_LEN 8 @@ -65,6 +67,10 @@ #define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) #define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) #define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \ +RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) #define RSN_CIPHER_SUITE_WEP40 RSN_SELECTOR(0x00, 0x0f, 0xac, 1) @@ -76,6 +82,11 @@ #endif /* CONFIG_IEEE80211W */ #define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7) #define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#define RSN_CIPHER_SUITE_GCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 9) +#define RSN_CIPHER_SUITE_CCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 10) +#define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13) /* EAPOL-Key Key Data Encapsulation * GroupKey and PeerKey require encryption, otherwise, encryption is optional. @@ -167,22 +178,39 @@ struct wpa_eapol_key { /* followed by key_data_length bytes of key_data */ } STRUCT_PACKED; +struct wpa_eapol_key_192 { + u8 type; + /* Note: key_info, key_length, and key_data_length are unaligned */ + u8 key_info[2]; /* big endian */ + u8 key_length[2]; /* big endian */ + u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; + u8 key_nonce[WPA_NONCE_LEN]; + u8 key_iv[16]; + u8 key_rsc[WPA_KEY_RSC_LEN]; + u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ + u8 key_mic[24]; + u8 key_data_length[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +} STRUCT_PACKED; + +#define WPA_EAPOL_KEY_MIC_MAX_LEN 24 +#define WPA_KCK_MAX_LEN 24 +#define WPA_KEK_MAX_LEN 32 + +#define WPA_TK_MAX_LEN 32 + /** * struct wpa_ptk - WPA Pairwise Transient Key * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy */ struct wpa_ptk { - u8 kck[16]; /* EAPOL-Key Key Confirmation Key (KCK) */ - u8 kek[16]; /* EAPOL-Key Key Encryption Key (KEK) */ - u8 tk1[16]; /* Temporal Key 1 (TK1) */ - union { - u8 tk2[16]; /* Temporal Key 2 (TK2) */ - struct { - u8 tx_mic_key[8]; - u8 rx_mic_key[8]; - } auth; - } u; -} STRUCT_PACKED; + u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */ + u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */ + size_t kck_len; + size_t kek_len; + size_t tk_len; +}; struct wpa_gtk_data { enum wpa_alg alg; @@ -320,6 +348,28 @@ struct rsn_sppamsdu_sup { bool require; }; +#ifdef CONFIG_SUITEB +int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, u8 *pmkid); +#else /* CONFIG_SUITEB */ +static inline int rsn_pmkid_suite_b(const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, u8 *pmkid) +{ + return -1; +} +#endif /* CONFIG_SUITEB */ + +#ifdef CONFIG_SUITEB192 +int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, u8 *pmkid); +#else /* CONFIG_SUITEB192 */ +static inline int rsn_pmkid_suite_b_192(const u8 *kck, size_t kck_len, + const u8 *aa, const u8 *spa, u8 *pmkid) +{ + return -1; +} +#endif /* CONFIG_SUITEB192 */ + const char * wpa_cipher_txt(int cipher); int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, @@ -327,24 +377,24 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data); -int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len, - u8 *mic); int wpa_compare_rsn_ie(int ft_initial_assoc, const u8 *ie1, size_t ie1len, const u8 *ie2, size_t ie2len); -void wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, - const u8 *addr1, const u8 *addr2, - const u8 *nonce1, const u8 *nonce2, - u8 *ptk, size_t ptk_len, int use_sha256); +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic); +int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, + const u8 *addr1, const u8 *addr2, + const u8 *nonce1, const u8 *nonce2, + struct wpa_ptk *ptk, int akmp, int cipher); void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, u8 *pmkid, int use_sha256); int wpa_cipher_key_len(int cipher); - +int wpa_cipher_rsc_len(int cipher); int wpa_cipher_to_alg(int cipher); - +int wpa_cipher_valid_mgmt_group(int cipher); u32 wpa_cipher_to_suite(int proto, int cipher); int wpa_cipher_put_suites(u8 *pos, int ciphers); @@ -353,5 +403,6 @@ int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data); int rsn_cipher_put_suites(u8 *pos, int ciphers); +unsigned int wpa_mic_len(int akmp); #endif /* WPA_COMMON_H */ diff --git a/components/wpa_supplicant/src/crypto/aes-gcm.c b/components/wpa_supplicant/src/crypto/aes-gcm.c new file mode 100644 index 0000000000..84294d2d10 --- /dev/null +++ b/components/wpa_supplicant/src/crypto/aes-gcm.c @@ -0,0 +1,327 @@ +/* + * Galois/Counter Mode (GCM) and GMAC with AES + * + * Copyright (c) 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "aes.h" +#include "aes_wrap.h" + +static void inc32(u8 *block) +{ + u32 val; + val = WPA_GET_BE32(block + AES_BLOCK_SIZE - 4); + val++; + WPA_PUT_BE32(block + AES_BLOCK_SIZE - 4, val); +} + + +static void xor_block(u8 *dst, const u8 *src) +{ + u32 *d = (u32 *) dst; + u32 *s = (u32 *) src; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; + *d++ ^= *s++; +} + + +static void shift_right_block(u8 *v) +{ + u32 val; + + val = WPA_GET_BE32(v + 12); + val >>= 1; + if (v[11] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 12, val); + + val = WPA_GET_BE32(v + 8); + val >>= 1; + if (v[7] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 8, val); + + val = WPA_GET_BE32(v + 4); + val >>= 1; + if (v[3] & 0x01) + val |= 0x80000000; + WPA_PUT_BE32(v + 4, val); + + val = WPA_GET_BE32(v); + val >>= 1; + WPA_PUT_BE32(v, val); +} + + +/* Multiplication in GF(2^128) */ +static void gf_mult(const u8 *x, const u8 *y, u8 *z) +{ + u8 v[16]; + int i, j; + + os_memset(z, 0, 16); /* Z_0 = 0^128 */ + os_memcpy(v, y, 16); /* V_0 = Y */ + + for (i = 0; i < 16; i++) { + for (j = 0; j < 8; j++) { + if (x[i] & BIT(7 - j)) { + /* Z_(i + 1) = Z_i XOR V_i */ + xor_block(z, v); + } else { + /* Z_(i + 1) = Z_i */ + } + + if (v[15] & 0x01) { + /* V_(i + 1) = (V_i >> 1) XOR R */ + shift_right_block(v); + /* R = 11100001 || 0^120 */ + v[0] ^= 0xe1; + } else { + /* V_(i + 1) = V_i >> 1 */ + shift_right_block(v); + } + } + } +} + + +static void ghash_start(u8 *y) +{ + /* Y_0 = 0^128 */ + os_memset(y, 0, 16); +} + + +static void ghash(const u8 *h, const u8 *x, size_t xlen, u8 *y) +{ + size_t m, i; + const u8 *xpos = x; + u8 tmp[16]; + + m = xlen / 16; + + for (i = 0; i < m; i++) { + /* Y_i = (Y^(i-1) XOR X_i) dot H */ + xor_block(y, xpos); + xpos += 16; + + /* dot operation: + * multiplication operation for binary Galois (finite) field of + * 2^128 elements */ + gf_mult(y, h, tmp); + os_memcpy(y, tmp, 16); + } + + if (x + xlen > xpos) { + /* Add zero padded last block */ + size_t last = x + xlen - xpos; + os_memcpy(tmp, xpos, last); + os_memset(tmp + last, 0, sizeof(tmp) - last); + + /* Y_i = (Y^(i-1) XOR X_i) dot H */ + xor_block(y, tmp); + + /* dot operation: + * multiplication operation for binary Galois (finite) field of + * 2^128 elements */ + gf_mult(y, h, tmp); + os_memcpy(y, tmp, 16); + } + + /* Return Y_m */ +} + + +static void aes_gctr(void *aes, const u8 *icb, const u8 *x, size_t xlen, u8 *y) +{ + size_t i, n, last; + u8 cb[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; + const u8 *xpos = x; + u8 *ypos = y; + + if (xlen == 0) + return; + + n = xlen / 16; + + os_memcpy(cb, icb, AES_BLOCK_SIZE); + /* Full blocks */ + for (i = 0; i < n; i++) { + aes_encrypt(aes, cb, ypos); + xor_block(ypos, xpos); + xpos += AES_BLOCK_SIZE; + ypos += AES_BLOCK_SIZE; + inc32(cb); + } + + last = x + xlen - xpos; + if (last) { + /* Last, partial block */ + aes_encrypt(aes, cb, tmp); + for (i = 0; i < last; i++) + *ypos++ = *xpos++ ^ tmp[i]; + } +} + + +static void * aes_gcm_init_hash_subkey(const u8 *key, size_t key_len, u8 *H) +{ + void *aes; + + aes = aes_encrypt_init(key, key_len); + if (aes == NULL) + return NULL; + + /* Generate hash subkey H = AES_K(0^128) */ + os_memset(H, 0, AES_BLOCK_SIZE); + aes_encrypt(aes, H, H); + wpa_hexdump_key(MSG_EXCESSIVE, "Hash subkey H for GHASH", + H, AES_BLOCK_SIZE); + return aes; +} + + +static void aes_gcm_prepare_j0(const u8 *iv, size_t iv_len, const u8 *H, u8 *J0) +{ + u8 len_buf[16]; + + if (iv_len == 12) { + /* Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */ + os_memcpy(J0, iv, iv_len); + os_memset(J0 + iv_len, 0, AES_BLOCK_SIZE - iv_len); + J0[AES_BLOCK_SIZE - 1] = 0x01; + } else { + /* + * s = 128 * ceil(len(IV)/128) - len(IV) + * J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64) + */ + ghash_start(J0); + ghash(H, iv, iv_len, J0); + WPA_PUT_BE64(len_buf, 0); + WPA_PUT_BE64(len_buf + 8, iv_len * 8); + ghash(H, len_buf, sizeof(len_buf), J0); + } +} + + +static void aes_gcm_gctr(void *aes, const u8 *J0, const u8 *in, size_t len, + u8 *out) +{ + u8 J0inc[AES_BLOCK_SIZE]; + + if (len == 0) + return; + + os_memcpy(J0inc, J0, AES_BLOCK_SIZE); + inc32(J0inc); + aes_gctr(aes, J0inc, in, len, out); +} + + +static void aes_gcm_ghash(const u8 *H, const u8 *aad, size_t aad_len, + const u8 *crypt, size_t crypt_len, u8 *S) +{ + u8 len_buf[16]; + + /* + * u = 128 * ceil[len(C)/128] - len(C) + * v = 128 * ceil[len(A)/128] - len(A) + * S = GHASH_H(A || 0^v || C || 0^u || [len(A)]64 || [len(C)]64) + * (i.e., zero padded to block size A || C and lengths of each in bits) + */ + ghash_start(S); + ghash(H, aad, aad_len, S); + ghash(H, crypt, crypt_len, S); + WPA_PUT_BE64(len_buf, aad_len * 8); + WPA_PUT_BE64(len_buf + 8, crypt_len * 8); + ghash(H, len_buf, sizeof(len_buf), S); + + wpa_hexdump_key(MSG_EXCESSIVE, "S = GHASH_H(...)", S, 16); +} + + +/** + * aes_gcm_ae - GCM-AE_K(IV, P, A) + */ +int aes_gcm_ae(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, u8 *crypt, u8 *tag) +{ + u8 H[AES_BLOCK_SIZE]; + u8 J0[AES_BLOCK_SIZE]; + u8 S[16]; + void *aes; + + aes = aes_gcm_init_hash_subkey(key, key_len, H); + if (aes == NULL) + return -1; + + aes_gcm_prepare_j0(iv, iv_len, H, J0); + + /* C = GCTR_K(inc_32(J_0), P) */ + aes_gcm_gctr(aes, J0, plain, plain_len, crypt); + + aes_gcm_ghash(H, aad, aad_len, crypt, plain_len, S); + + /* T = MSB_t(GCTR_K(J_0, S)) */ + aes_gctr(aes, J0, S, sizeof(S), tag); + + /* Return (C, T) */ + + aes_encrypt_deinit(aes); + + return 0; +} + + +/** + * aes_gcm_ad - GCM-AD_K(IV, C, A, T) + */ +int aes_gcm_ad(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *tag, u8 *plain) +{ + u8 H[AES_BLOCK_SIZE]; + u8 J0[AES_BLOCK_SIZE]; + u8 S[16], T[16]; + void *aes; + + aes = aes_gcm_init_hash_subkey(key, key_len, H); + if (aes == NULL) + return -1; + + aes_gcm_prepare_j0(iv, iv_len, H, J0); + + /* P = GCTR_K(inc_32(J_0), C) */ + aes_gcm_gctr(aes, J0, crypt, crypt_len, plain); + + aes_gcm_ghash(H, aad, aad_len, crypt, crypt_len, S); + + /* T' = MSB_t(GCTR_K(J_0, S)) */ + aes_gctr(aes, J0, S, sizeof(S), T); + + aes_encrypt_deinit(aes); + + if (os_memcmp_const(tag, T, 16) != 0) { + wpa_printf(MSG_EXCESSIVE, "GCM: Tag mismatch"); + return -1; + } + + return 0; +} + + +int aes_gmac(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *aad, size_t aad_len, u8 *tag) +{ + return aes_gcm_ae(key, key_len, iv, iv_len, NULL, 0, aad, aad_len, NULL, + tag); +} diff --git a/components/wpa_supplicant/src/crypto/crypto_ops.c b/components/wpa_supplicant/src/crypto/crypto_ops.c index be4d67c504..d4aff08787 100644 --- a/components/wpa_supplicant/src/crypto/crypto_ops.c +++ b/components/wpa_supplicant/src/crypto/crypto_ops.c @@ -1,16 +1,8 @@ -// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "utils/common.h" #include "aes_wrap.h" @@ -44,6 +36,16 @@ static void esp_aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) aes_decrypt(ctx, crypt, plain); } +static int esp_aes_gmac(const u8 *key, size_t key_len, const u8 *iv, size_t iv_len, + const u8 *aad, size_t aad_len, u8 *tag) +{ +#if CONFIG_GMAC + return aes_gmac(key, key_len, iv, iv_len, aad, aad_len, tag); +#else + return 0; +#endif +} + /* * This structure is used to set the cyrpto callback function for station to connect when in security mode. * These functions either call MbedTLS API's if USE_MBEDTLS_CRYPTO flag is set through Kconfig, or native @@ -76,7 +78,8 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = { .aes_128_decrypt = (esp_aes_128_decrypt_t)aes_128_cbc_decrypt, .omac1_aes_128 = (esp_omac1_aes_128_t)omac1_aes_128, .ccmp_decrypt = (esp_ccmp_decrypt_t)ccmp_decrypt, - .ccmp_encrypt = (esp_ccmp_encrypt_t)ccmp_encrypt + .ccmp_encrypt = (esp_ccmp_encrypt_t)ccmp_encrypt, + .aes_gmac = (esp_aes_gmac_t)esp_aes_gmac, }; const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = { diff --git a/components/wpa_supplicant/src/crypto/sha384-prf.c b/components/wpa_supplicant/src/crypto/sha384-prf.c new file mode 100644 index 0000000000..420e78c380 --- /dev/null +++ b/components/wpa_supplicant/src/crypto/sha384-prf.c @@ -0,0 +1,108 @@ +/* + * SHA384-based KDF (IEEE 802.11ac) + * Copyright (c) 2003-2017, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha384.h" +#include "crypto.h" + + +/** + * sha384_prf - SHA384-based Key derivation function (IEEE 802.11ac, 11.6.1.7.2) + * @key: Key for KDF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bytes of key to generate + * Returns: 0 on success, -1 on failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key. + */ +int sha384_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) +{ + return sha384_prf_bits(key, key_len, label, data, data_len, buf, + buf_len * 8); +} + + +/** + * sha384_prf_bits - IEEE Std 802.11ac-2013, 11.6.1.7.2 Key derivation function + * @key: Key for KDF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bits of key to generate + * Returns: 0 on success, -1 on failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key. If the requested buf_len is not divisible by eight, the least + * significant 1-7 bits of the last octet in the output are not part of the + * requested output. + */ +int sha384_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits) +{ + u16 counter = 1; + size_t pos, plen; + u8 hash[SHA384_MAC_LEN]; + const u8 *addr[4]; + size_t len[4]; + u8 counter_le[2], length_le[2]; + size_t buf_len = (buf_len_bits + 7) / 8; + + addr[0] = counter_le; + len[0] = 2; + addr[1] = (u8 *) label; + len[1] = os_strlen(label); + addr[2] = data; + len[2] = data_len; + addr[3] = length_le; + len[3] = sizeof(length_le); + + WPA_PUT_LE16(length_le, buf_len_bits); + pos = 0; + while (pos < buf_len) { + plen = buf_len - pos; + WPA_PUT_LE16(counter_le, counter); + if (plen >= SHA384_MAC_LEN) { + if (hmac_sha384_vector(key, key_len, 4, addr, len, + &buf[pos]) < 0) + return -1; + pos += SHA384_MAC_LEN; + } else { + if (hmac_sha384_vector(key, key_len, 4, addr, len, + hash) < 0) + return -1; + os_memcpy(&buf[pos], hash, plen); + pos += plen; + break; + } + counter++; + } + + /* + * Mask out unused bits in the last octet if it does not use all the + * bits. + */ + if (buf_len_bits % 8) { + u8 mask = 0xff << (8 - buf_len_bits % 8); + buf[pos - 1] &= mask; + } + + forced_memzero(hash, sizeof(hash)); + + return 0; +} diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c index 00c1bad290..165271ef17 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c @@ -109,7 +109,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, struct rsn_pmksa_cache_entry *entry, *pos, *prev; int64_t now_sec = esp_timer_get_time() / 1e6; - if (pmk_len > PMK_LEN) + if (pmk_len > PMK_LEN_MAX) return NULL; if (wpa_key_mgmt_suite_b(akmp) && !kck) @@ -122,6 +122,10 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, entry->pmk_len = pmk_len; if (pmkid) os_memcpy(entry->pmkid, pmkid, PMKID_LEN); + else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); + else if (wpa_key_mgmt_suite_b(akmp)) + rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); else rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, wpa_key_mgmt_sha256(akmp)); diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h index e2c9156a50..040abc0643 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h @@ -15,7 +15,7 @@ struct rsn_pmksa_cache_entry { struct rsn_pmksa_cache_entry *next; u8 pmkid[PMKID_LEN]; - u8 pmk[PMK_LEN]; + u8 pmk[PMK_LEN_MAX]; size_t pmk_len; os_time_t expiration; int akmp; /* WPA_KEY_MGMT_* */ diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 2de58804d9..87a61e8096 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -131,12 +131,28 @@ unsigned cipher_type_map_public_to_supp(wifi_cipher_type_t cipher) case WIFI_CIPHER_TYPE_CCMP: return WPA_CIPHER_CCMP; +#ifdef CONFIG_GCMP + case WIFI_CIPHER_TYPE_GCMP: + return WPA_CIPHER_GCMP; + + case WIFI_CIPHER_TYPE_GCMP256: + return WPA_CIPHER_GCMP_256; +#endif + case WIFI_CIPHER_TYPE_TKIP_CCMP: return WPA_CIPHER_CCMP|WPA_CIPHER_TKIP; case WIFI_CIPHER_TYPE_AES_CMAC128: return WPA_CIPHER_AES_128_CMAC; +#ifdef CONFIG_GMAC + case WIFI_CIPHER_TYPE_AES_GMAC128: + return WPA_CIPHER_BIP_GMAC_128; + + case WIFI_CIPHER_TYPE_AES_GMAC256: + return WPA_CIPHER_BIP_GMAC_256; +#endif + case WIFI_CIPHER_TYPE_SMS4: return WPA_CIPHER_SMS4; @@ -151,9 +167,11 @@ static bool is_wpa2_enterprise_connection(void) if (esp_wifi_sta_prof_is_wpa2_internal()) { authmode = esp_wifi_sta_get_prof_authmode_internal(); - if ((authmode == WPA2_AUTH_ENT) || (authmode == WPA2_AUTH_ENT_SHA256)) { + if ((authmode == WPA2_AUTH_ENT) || + (authmode == WPA2_AUTH_ENT_SHA256) || + (authmode == WPA2_AUTH_ENT_SHA384_SUITE_B)) { return true; - } + } } return false; @@ -185,7 +203,7 @@ static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) * @len: Frame payload length * Returns: >=0 on success, <0 on failure */ -static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 proto, +static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 proto, const u8 *data, size_t data_len) { void *buffer = (void *)(data - sizeof(struct l2_ethhdr)); @@ -203,6 +221,7 @@ static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 pr * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message * @sm: Pointer to WPA state machine data from wpa_sm_init() * @kck: Key Confirmation Key (KCK, part of PTK) + * @kck_len: KCK length in octets * @ver: Version field from Key Info * @dest: Destination address for the frame * @proto: Ethertype (usually ETH_P_EAPOL) @@ -210,7 +229,7 @@ static inline int wpa_sm_ether_send( struct wpa_sm *sm, const u8 *dest, u16 pr * @msg_len: Length of message * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written */ -void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, +void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, int ver, const u8 *dest, u16 proto, u8 *msg, size_t msg_len, u8 *key_mic) { @@ -234,13 +253,17 @@ void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, } } if (key_mic && - wpa_eapol_key_mic(kck, ver, msg, msg_len, key_mic)) { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Failed to generate EAPOL-Key " - "version %d MIC", ver); - #endif + wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len, + key_mic)) { +#ifdef DEBUG_PRINT + wpa_msg(NULL, MSG_ERROR, + "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC", + ver, sm->key_mgmt); +#endif goto out; } + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len); + wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, wpa_mic_len(sm->key_mgmt)); wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); wpa_sm_ether_send(sm, dest, proto, msg, msg_len); out: @@ -257,35 +280,40 @@ out: * used to request rekeying and it is usually called when a local Michael MIC * failure is detected. */ -void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) +static void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) { - size_t rlen; + size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; + struct wpa_eapol_key_192 *reply192; int key_info, ver; - u8 bssid[ETH_ALEN], *rbuf; + u8 bssid[ETH_ALEN], *rbuf, *key_mic; - if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) + if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || wpa_key_mgmt_suite_b(sm->key_mgmt)) + ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; + else if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) + 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) - ver = 0; + ver = 0; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; if (wpa_sm_get_bssid(sm, bssid) < 0) { - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "Failed to read BSSID for EAPOL-Key " "request"); - #endif return; } + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); + hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return; + reply192 = (struct wpa_eapol_key_192 *) reply; + reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info = WPA_KEY_INFO_REQUEST | ver; @@ -295,35 +323,31 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) key_info |= WPA_KEY_INFO_ERROR|WPA_KEY_INFO_SECURE; if (pairwise) key_info |= WPA_KEY_INFO_KEY_TYPE; + WPA_PUT_BE16(reply->key_info, key_info); WPA_PUT_BE16(reply->key_length, 0); - memcpy(reply->replay_counter, sm->request_counter, + + os_memcpy(reply->replay_counter, sm->request_counter, WPA_REPLAY_COUNTER_LEN); inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); + + if (!(key_info & WPA_KEY_INFO_MIC)) + key_mic = NULL; + else + key_mic = reply192->key_mic; /* same offset in reply */ - WPA_PUT_BE16(reply->key_data_length, 0); - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Sending EAPOL-Key Request (error=%d " "pairwise=%d ptk_set=%d len=%lu)", error, pairwise, sm->ptk_set, (unsigned long) rlen); - #endif - wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL, - rbuf, rlen, key_info & WPA_KEY_INFO_MIC ? - reply->key_mic : NULL); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, + ETH_P_EAPOL, rbuf, rlen, key_mic); wpa_sm_free_eapol(rbuf); } -/* -int wpa_supplicant_get_pmk(struct wpa_sm *sm) -{ - if(sm->pmk_len >0) { - return 0; - } else { - return 1; - } -} -*/ - static void wpa_sm_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, void *ctx, enum pmksa_free_reason reason) @@ -405,9 +429,12 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, #endif /* CONFIG_IEEE80211R */ } else if (wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt)) { int res = 0, pmk_len; - pmk_len = PMK_LEN; /* For ESP_SUPPLICANT this is already set using wpa_set_pmk*/ //res = eapol_sm_get_key(sm->eapol, sm->pmk, PMK_LEN); + if (wpa_key_mgmt_sha384(sm->key_mgmt)) + pmk_len = PMK_LEN_SUITE_B_192; + else + pmk_len = PMK_LEN; if(!sm->pmk_len) { res = -1; @@ -425,70 +452,70 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, sa = pmksa_cache_add(sm->pmksa, sm->pmk, pmk_len, NULL, NULL, 0, src_addr, sm->own_addr, sm->network_ctx, sm->key_mgmt); - } - if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) - { - wpa_printf( MSG_DEBUG, - "RSN: the new PMK matches with the " - "PMKID"); - abort_cached = 0; - } else if (sa && !sm->cur_pmksa && pmkid) { - /* - * It looks like the authentication server - * derived mismatching MSK. This should not - * really happen, but bugs happen.. There is not - * much we can do here without knowing what - * exactly caused the server to misbehave. - */ - wpa_printf( MSG_INFO, - "RSN: PMKID mismatch - authentication server may have derived different MSK?!"); - return -1; - } + } + if (!sm->cur_pmksa && pmkid && + pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) + { + wpa_printf( MSG_DEBUG, + "RSN: the new PMK matches with the " + "PMKID"); + abort_cached = 0; + } else if (sa && !sm->cur_pmksa && pmkid) { + /* + * It looks like the authentication server + * derived mismatching MSK. This should not + * really happen, but bugs happen.. There is not + * much we can do here without knowing what + * exactly caused the server to misbehave. + */ + wpa_printf( MSG_INFO, + "RSN: PMKID mismatch - authentication server may have derived different MSK?!"); + return -1; + } - if (!sm->cur_pmksa) - sm->cur_pmksa = sa; - } else { - wpa_printf( MSG_WARNING, - "WPA: Failed to get master session key from " - "EAPOL state machines - key handshake " - "aborted"); - if (sm->cur_pmksa) { - wpa_printf( MSG_DEBUG, - "RSN: Cancelled PMKSA caching " - "attempt"); - sm->cur_pmksa = NULL; - abort_cached = 1; - } else if (!abort_cached) { - return -1; - } - } - } + if (!sm->cur_pmksa) + sm->cur_pmksa = sa; + } else { + wpa_printf( MSG_WARNING, + "WPA: Failed to get master session key from " + "EAPOL state machines - key handshake " + "aborted"); + if (sm->cur_pmksa) { + wpa_printf( MSG_DEBUG, + "RSN: Cancelled PMKSA caching " + "attempt"); + sm->cur_pmksa = NULL; + abort_cached = 1; + } else if (!abort_cached) { + return -1; + } + } + } - if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && - !wpa_key_mgmt_suite_b(sm->key_mgmt) && - !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN) - { - /* Send EAPOL-Start to trigger full EAP authentication. */ - u8 *buf; - size_t buflen; + if (abort_cached && wpa_key_mgmt_wpa_ieee8021x(sm->key_mgmt) && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + !wpa_key_mgmt_ft(sm->key_mgmt) && sm->key_mgmt != WPA_KEY_MGMT_OSEN) + { + /* Send EAPOL-Start to trigger full EAP authentication. */ + u8 *buf; + size_t buflen; - wpa_printf( MSG_DEBUG, - "RSN: no PMKSA entry found - trigger " - "full EAP authentication"); - buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, - NULL, 0, &buflen, NULL); - if (buf) { - wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, - buf, buflen); - os_free(buf); - return -2; - } + wpa_printf( MSG_DEBUG, + "RSN: no PMKSA entry found - trigger " + "full EAP authentication"); + buf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_START, + NULL, 0, &buflen, NULL); + if (buf) { + wpa_sm_ether_send(sm, sm->bssid, ETH_P_EAPOL, + buf, buflen); + os_free(buf); + return -2; + } - return -1; - } + return -1; + } - return 0; + return 0; } @@ -510,9 +537,10 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, const u8 *wpa_ie, size_t wpa_ie_len, struct wpa_ptk *ptk) { - size_t rlen; + size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - u8 *rbuf; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; if (wpa_ie == NULL) { #ifdef DEBUG_PRINT @@ -524,12 +552,15 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, wpa_hexdump(MSG_MSGDUMP, "WPA: WPA IE for msg 2/4\n", wpa_ie, wpa_ie_len); + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, - NULL, sizeof(*reply) + wpa_ie_len, + NULL, hdrlen + wpa_ie_len, &rlen, (void *) &reply); if (rbuf == NULL) { return -1; } + reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; @@ -543,37 +574,40 @@ int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); - memcpy(reply + 1, wpa_ie, wpa_ie_len); + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) { + WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len); + os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len); + } else { + WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); + os_memcpy(reply + 1, wpa_ie, wpa_ie_len); + } memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 2/4\n"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); + wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, + rbuf, rlen, key_mic); wpa_sm_free_eapol(rbuf); return 0; } -int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, - const struct wpa_eapol_key *key, - struct wpa_ptk *ptk) +static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, + const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { - size_t ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; - - wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", - sm->own_addr, sm->bssid, sm->snonce, key->key_nonce, - (u8 *) ptk, ptk_len, - wpa_key_mgmt_sha256(sm->key_mgmt)); - return 0; + return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", + sm->own_addr, sm->bssid, sm->snonce, + key->key_nonce, ptk, sm->key_mgmt, + sm->pairwise_cipher); } -void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, +void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, - u16 ver) + u16 ver, const u8 *key_data, + size_t key_data_len) { struct wpa_eapol_ie_parse ie; struct wpa_ptk *ptk; @@ -585,19 +619,17 @@ void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, memset(&ie, 0, sizeof(ie)); -#ifndef CONFIG_NO_WPA2 if (sm->proto == WPA_PROTO_RSN) { /* RSN: msg 1/4 should contain PMKID for the selected PMK */ - const u8 *_buf = (const u8 *) (key + 1); - size_t len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_MSGDUMP, "RSN: msg 1/4 key data", _buf, len); - wpa_supplicant_parse_ies(_buf, len, &ie); + wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", + key_data, key_data_len); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) + goto failed; if (ie.pmkid) { wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " "Authenticator", ie.pmkid, PMKID_LEN); } } -#endif /* CONFIG_NO_WPA2 */ res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); if (res == -2) { @@ -648,7 +680,7 @@ failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } - void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) +static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) { struct wpa_sm *sm = eloop_ctx; @@ -659,43 +691,27 @@ failed: } -int wpa_supplicant_install_ptk(struct wpa_sm *sm) +static int wpa_supplicant_install_ptk(struct wpa_sm *sm) { int keylen; enum wpa_alg alg; - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Installing PTK to the driver.\n"); - #endif - switch (sm->pairwise_cipher) { - case WPA_CIPHER_CCMP: - alg = WIFI_WPA_ALG_CCMP; - keylen = 16; - break; - case WPA_CIPHER_TKIP: - alg = WIFI_WPA_ALG_TKIP; - keylen = 32; - break; - case WPA_CIPHER_NONE: - #ifdef DEBUG_PRINT + alg = wpa_cipher_to_alg(sm->pairwise_cipher); + keylen = wpa_cipher_key_len(sm->pairwise_cipher); + + if (alg == WIFI_WPA_ALG_NONE) { wpa_printf(MSG_DEBUG, "WPA: Pairwise Cipher Suite: " "NONE - do not use pairwise keys"); - #endif return 0; - default: - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Unsupported pairwise cipher %d", - sm->pairwise_cipher); - #endif - return -1; } - //now only use keyentry 0 for pairwise key sm->key_entry_valid = esp_wifi_get_sta_hw_key_idx_internal(0); //KEY_IDX_STA_PTK + wpa_hexdump(MSG_DEBUG, "WPA: Pairwise Key", sm->ptk.tk, keylen); if (wpa_sm_set_key(&(sm->install_ptk), alg, sm->bssid, 0, 1, (sm->install_ptk).seq, WPA_KEY_RSC_LEN, - (u8 *) sm->ptk.tk1, keylen,sm->key_entry_valid) < 0) { + sm->ptk.tk, keylen, sm->key_entry_valid) < 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Failed to set PTK to the " "driver (alg=%d keylen=%d bssid=" MACSTR ")", @@ -713,63 +729,31 @@ int wpa_supplicant_install_ptk(struct wpa_sm *sm) return 0; } -int wpa_supplicant_check_group_cipher(int group_cipher, +static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, + int group_cipher, int keylen, int maxkeylen, int *key_rsc_len, enum wpa_alg *alg) { - int ret = 0; + int klen; - switch (group_cipher) { - case WPA_CIPHER_CCMP: - if (keylen != 16 || maxkeylen < 16) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WIFI_WPA_ALG_CCMP; - break; - case WPA_CIPHER_TKIP: - if (keylen != 32 || maxkeylen < 32) { - ret = -1; - break; - } - *key_rsc_len = 6; - *alg = WIFI_WPA_ALG_TKIP; - break; - case WPA_CIPHER_WEP104: - if (keylen != 13 || maxkeylen < 13) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WIFI_WPA_ALG_WEP104; - break; - case WPA_CIPHER_WEP40: - if (keylen != 5 || maxkeylen < 5) { - ret = -1; - break; - } - *key_rsc_len = 0; - *alg = WIFI_WPA_ALG_WEP40; - break; - default: - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Unsupported Group Cipher %d", - group_cipher); - #endif - return -1; + *alg = wpa_cipher_to_alg(group_cipher); + if (*alg == WIFI_WPA_ALG_NONE) { + wpa_printf(MSG_WARNING, + "WPA: Unsupported Group Cipher %d", + group_cipher); + return -1; } + *key_rsc_len = 6; - if (ret < 0 ) { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Unsupported %s Group Cipher key " - "length %d (%d).", - wpa_cipher_txt(group_cipher), keylen, maxkeylen); - #endif + klen = wpa_cipher_key_len(group_cipher); + if (keylen != klen || maxkeylen < klen) { + wpa_printf(MSG_WARNING, + "WPA: Unsupported %s Group Cipher key length %d (%d)", + wpa_cipher_txt(group_cipher), keylen, maxkeylen); + return -1; } - - return ret; + return 0; } void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, @@ -805,12 +789,12 @@ void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, } -int wpa_supplicant_install_gtk(struct wpa_sm *sm, +static int wpa_supplicant_install_gtk(struct wpa_sm *sm, struct wpa_gtk_data *gd) { u8 *_gtk = gd->gtk; u8 gtk_buf[32]; - u8 *key_rsc=(sm->install_gtk).seq; + u8 *key_rsc=(sm->install_gtk).seq; wpa_hexdump(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); @@ -821,11 +805,9 @@ int wpa_supplicant_install_gtk(struct wpa_sm *sm, gd->keyidx, gd->tx, gd->gtk_len); return 0; } - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Installing GTK to the driver " "(keyidx=%d tx=%d len=%d).\n", gd->keyidx, gd->tx, gd->gtk_len); - #endif wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); if (sm->group_cipher == WPA_CIPHER_TKIP) { @@ -842,21 +824,17 @@ int wpa_supplicant_install_gtk(struct wpa_sm *sm, sm->bssid, //(u8 *) "\xff\xff\xff\xff\xff\xff", gd->keyidx, 1, key_rsc, gd->key_rsc_len, _gtk, gd->gtk_len,sm->key_entry_valid) < 0) { - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Failed to set " "GTK to the driver (Group only)."); - #endif return -1; } } else if (wpa_sm_set_key(&(sm->install_gtk), gd->alg, sm->bssid, //(u8 *) "\xff\xff\xff\xff\xff\xff", gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, _gtk, gd->gtk_len, sm->key_entry_valid) < 0) { - #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Failed to set GTK to " "the driver (alg=%d keylen=%d keyidx=%d)", gd->alg, gd->gtk_len, gd->keyidx); - #endif return -1; } @@ -889,7 +867,7 @@ static bool wpa_supplicant_gtk_in_use(struct wpa_sm *sm, struct wpa_gtk_data *gd hw_keyidx = esp_wifi_get_sta_hw_key_idx_internal(gd->keyidx); if (wpa_sm_get_key(&ifx, &alg, bssid, &keyidx, gtk_get, gd->gtk_len, hw_keyidx - 2) == 0) { if (ifx == 0 && alg == gd->alg && memcmp(bssid, sm->bssid, ETH_ALEN) == 0 && - memcmp(_gtk, gtk_get, gd->gtk_len) == 0) { + memcmp(_gtk, gtk_get, gd->gtk_len) == 0) { wpa_printf(MSG_DEBUG, "GTK %d is already in use in entry %d, it may be an attack, ignore it.", gd->keyidx, hw_keyidx); return true; } @@ -920,7 +898,6 @@ int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, const u8 *gtk, size_t gtk_len, int key_info) { -#ifndef CONFIG_NO_WPA2 struct wpa_gtk_data *gd=&(sm->gd); /* @@ -947,7 +924,7 @@ int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, memcpy(gd->gtk, gtk, gtk_len); gd->gtk_len = gtk_len; - if (wpa_supplicant_check_group_cipher(sm->group_cipher, + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gtk_len, gtk_len, &(gd->key_rsc_len), &(gd->alg))) { #ifdef DEBUG_PRINT @@ -956,9 +933,6 @@ int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, return -1; } return 0; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ } #ifdef DEBUG_PRINT @@ -1009,56 +983,40 @@ void wpa_report_ie_mismatch(struct wpa_sm *sm, const u8 *src_addr, wpa_sm_disassociate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); } -int ieee80211w_set_keys(struct wpa_sm *sm, +static int ieee80211w_set_keys(struct wpa_sm *sm, struct wpa_eapol_ie_parse *ie) { #ifdef CONFIG_IEEE80211W - if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) { - return -1; - } + size_t len; - if (ie->igtk) { - const wifi_wpa_igtk_t *igtk; - uint16_t keyidx; + if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher)) + return 0; - if (ie->igtk_len != sizeof(*igtk)) { - return -1; - } - igtk = (const wifi_wpa_igtk_t*)ie->igtk; - keyidx = WPA_GET_LE16(igtk->keyid); - if (keyidx > 4095) { - return -1; - } - return esp_wifi_set_igtk_internal(WIFI_IF_STA, igtk); - } - return 0; -#else - return 0; + if (ie->igtk) { + const wifi_wpa_igtk_t *igtk; + uint16_t keyidx; +#define WPA_IGTK_KDE_PREFIX_LEN (2 + 6) + len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len) { + return -1; + } + + igtk = (const wifi_wpa_igtk_t*)ie->igtk; + keyidx = WPA_GET_LE16(igtk->keyid); + if (keyidx > 4095) { + return -1; + } + wpa_printf(MSG_DEBUG, "WPA: Installing IGTK to the driver.\n"); + return esp_wifi_set_igtk_internal(WIFI_IF_STA, igtk); + } #endif + return 0; } - int wpa_supplicant_validate_ie(struct wpa_sm *sm, +static int wpa_supplicant_validate_ie(struct wpa_sm *sm, const unsigned char *src_addr, struct wpa_eapol_ie_parse *ie) { - if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: No WPA/RSN IE for this AP known. " - "Trying to get from scan results\n"); - #endif - if (wpa_sm_get_beacon_ie(sm) < 0) { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Could not find AP from " - "the scan results"); - #endif - } else { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Found the current AP from " - "updated scan results\n"); - #endif - } - } - if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && (sm->ap_wpa_ie || sm->ap_rsn_ie)) { #ifdef DEBUG_PRINT @@ -1121,26 +1079,24 @@ int ieee80211w_set_keys(struct wpa_sm *sm, * @key: Pointer to the EAPOL-Key frame header * @ver: Version bits from EAPOL-Key Key Info * @key_info: Key Info - * @kde: KDEs to include the EAPOL-Key frame - * @kde_len: Length of KDEs * @ptk: PTK to use for keyed hash and encryption * Returns: 0 on success, -1 on failure */ - int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, +static int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, const struct wpa_eapol_key *key, u16 ver, u16 key_info, - const u8 *kde, size_t kde_len, struct wpa_ptk *ptk) { - size_t rlen; + size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - u8 *rbuf; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; - if (kde) - wpa_hexdump(MSG_DEBUG, "WPA: KDE for msg 4/4", kde, kde_len); + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply) + kde_len, + hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return -1; @@ -1148,6 +1104,7 @@ int ieee80211w_set_keys(struct wpa_sm *sm, sm->txcb_flags |= WPA_4_4_HANDSHAKE_BIT; wpa_printf(MSG_DEBUG, "tx 4/4 txcb_flags=%d\n", sm->txcb_flags); + reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_SECURE; @@ -1160,19 +1117,21 @@ int ieee80211w_set_keys(struct wpa_sm *sm, memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(reply->key_data_length, kde_len); - if (kde) - memcpy(reply + 1, kde, kde_len); + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); wpa_printf(MSG_DEBUG, "WPA Send EAPOL-Key 4/4\n"); - wpa_eapol_key_send(sm, ptk->kck, ver, dst, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); + wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, + rbuf, rlen, key_mic); wpa_sm_free_eapol(rbuf); return 0; } - void wpa_sm_set_seq(struct wpa_sm *sm, struct wpa_eapol_key *key, u8 isptk) +static void wpa_sm_set_seq(struct wpa_sm *sm, struct wpa_eapol_key *key, u8 isptk) { u8 *key_rsc, *seq; u8 null_rsc[WPA_KEY_RSC_LEN]; @@ -1190,12 +1149,12 @@ int ieee80211w_set_keys(struct wpa_sm *sm, memcpy(seq, key_rsc, WPA_KEY_RSC_LEN); } - void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, +static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, struct wpa_eapol_key *key, - u16 ver) + u16 ver, const u8 *key_data, + size_t key_data_len) { - u16 key_info, keylen, len; - const u8 *pos; + u16 key_info, keylen; struct wpa_eapol_ie_parse ie; wpa_sm_set_state(WPA_LAST_HALF_4WAY_HANDSHAKE); @@ -1203,10 +1162,11 @@ int ieee80211w_set_keys(struct wpa_sm *sm, key_info = WPA_GET_BE16(key->key_info); - pos = (const u8 *) (key + 1); - len = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", pos, len); - wpa_supplicant_parse_ies(pos, len, &ie); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) + goto failed; + if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) + goto failed; + if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: GTK IE in unencrypted key data"); @@ -1214,9 +1174,7 @@ int ieee80211w_set_keys(struct wpa_sm *sm, goto failed; } - if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) - goto failed; - + wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len); if (memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: ANonce from message 1 of 4-Way " @@ -1280,7 +1238,7 @@ int ieee80211w_set_keys(struct wpa_sm *sm, /*after txover, callback will continue run remain task*/ if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, - NULL, 0, &sm->ptk)) { + &sm->ptk)) { goto failed; } @@ -1290,8 +1248,7 @@ failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } - - int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm) +static int wpa_supplicant_send_4_of_4_txcallback(struct wpa_sm *sm) { u16 key_info=sm->key_info; @@ -1305,19 +1262,18 @@ failed: wpa_sm_set_state(WPA_GROUP_HANDSHAKE); - if((sm->gd).gtk_len) { - if (sm->key_install) { - if (wpa_supplicant_install_gtk(sm, &(sm->gd))) - goto failed; - } - else { - wpa_printf(MSG_DEBUG, "GTK has been installed, it may be an attack, ignor it."); - } + if ((sm->gd).gtk_len) { + if (sm->key_install) { + if (wpa_supplicant_install_gtk(sm, &(sm->gd))) + goto failed; + } + else { + wpa_printf(MSG_DEBUG, "GTK has been installed, it may be an attack, ignor it."); + } wpa_supplicant_key_neg_complete(sm, sm->bssid, key_info & WPA_KEY_INFO_SECURE); } - if (key_info & WPA_KEY_INFO_SECURE) { wpa_sm_mlme_setprotection( sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, @@ -1326,14 +1282,32 @@ failed: sm->key_install = false; +#if defined(CONFIG_SUITEB192) || defined (CONFIG_SUITEB) + /* Add PMKSA cache entry for Suite B AKMs here since PMKID can be + * calculated only after KCK has been derived. Though, do not replace an + * existing PMKSA entry after each 4-way handshake (i.e., new KCK/PMKID) + * to avoid unnecessary changes of PMKID while continuing to use the + * same PMK. */ + if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt) && + !sm->cur_pmksa) { + struct rsn_pmksa_cache_entry *sa; + + sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, NULL, + sm->ptk.kck, sm->ptk.kck_len, + sm->bssid, sm->own_addr, + sm->network_ctx, sm->key_mgmt); + if (!sm->cur_pmksa) + sm->cur_pmksa = sa; + } +#endif + return 0; failed: return WLAN_REASON_UNSPECIFIED; } - - int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, +static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, const u8 *keydata, size_t keydatalen, u16 key_info, @@ -1358,7 +1332,7 @@ failed: } maxkeylen = gd->gtk_len = ie.gtk_len - 2; - if (wpa_supplicant_check_group_cipher(sm->group_cipher, + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gd->gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; @@ -1386,26 +1360,17 @@ failed: return 0; } - int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, +static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, const struct wpa_eapol_key *key, - size_t keydatalen, int key_info, - size_t extra_len, u16 ver, - struct wpa_gtk_data *gd) + const u8 *key_data, + size_t key_data_len, u16 key_info, + u16 ver, struct wpa_gtk_data *gd) { size_t maxkeylen; u8 ek[32]; gd->gtk_len = WPA_GET_BE16(key->key_length); - maxkeylen = keydatalen; - if (keydatalen > extra_len) { - #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Truncated EAPOL-Key packet:" - " key_data_length=%lu > extra_len=%lu", - (unsigned long) keydatalen, - (unsigned long) extra_len); - #endif - return -1; - } + maxkeylen = key_data_len; if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { if (maxkeylen < 8) { #ifdef DEBUG_PRINT @@ -1417,36 +1382,37 @@ failed: maxkeylen -= 8; } - if (wpa_supplicant_check_group_cipher(sm->group_cipher, + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, gd->gtk_len, maxkeylen, &gd->key_rsc_len, &gd->alg)) return -1; gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> WPA_KEY_INFO_KEY_INDEX_SHIFT; - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { - memcpy(ek, key->key_iv, 16); - memcpy(ek + 16, sm->ptk.kek, 16); - if (keydatalen > sizeof(gd->gtk)) { + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); + if (key_data_len > sizeof(gd->gtk)) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: RC4 key data " "too long (%lu)", - (unsigned long) keydatalen); + (unsigned long) key_data_len); #endif return -1; } - memcpy(gd->gtk, key + 1, keydatalen); - if (rc4_skip(ek, 32, 256, gd->gtk, keydatalen)) { + os_memcpy(gd->gtk, key_data, key_data_len); + if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: RC4 failed"); #endif return -1; } } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { - if (keydatalen % 8) { + if (maxkeylen % 8) { #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: Unsupported AES-WRAP " - "len %lu", (unsigned long) keydatalen); + wpa_printf(MSG_DEBUG, + "WPA: Unsupported AES-WRAP len %lu", + (unsigned long) maxkeylen); #endif return -1; } @@ -1454,18 +1420,17 @@ failed: #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: AES-WRAP key data " "too long (keydatalen=%lu maxkeylen=%lu)", - (unsigned long) keydatalen, + (unsigned long) key_data_len, (unsigned long) maxkeylen); #endif return -1; } - if (aes_unwrap(sm->ptk.kek, 16, maxkeylen / 8, - (const u8 *) (key + 1), gd->gtk)) { + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8, key_data, gd->gtk)) { #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: AES unwrap " + wpa_printf(MSG_DEBUG, "WPA: AES unwrap " "failed - could not decrypt GTK"); #endif - return -1; + return -1; } } else { #ifdef DEBUG_PRINT @@ -1476,25 +1441,31 @@ failed: } gd->tx = wpa_supplicant_gtk_tx_bit_workaround( sm, !!(key_info & WPA_KEY_INFO_TXRX)); + return 0; } - int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, +static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, const struct wpa_eapol_key *key, int ver, u16 key_info) { - size_t rlen; + size_t mic_len, hdrlen, rlen; struct wpa_eapol_key *reply; - u8 *rbuf; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; + + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, - sizeof(*reply), &rlen, (void *) &reply); + hdrlen, &rlen, (void *) &reply); if (rbuf == NULL) return -1; sm->txcb_flags |= WPA_GROUP_HANDSHAKE_BIT; wpa_printf(MSG_DEBUG, "2/2 txcb_flags=%d\n", sm->txcb_flags); + reply192 = (struct wpa_eapol_key_192 *) reply; reply->type = sm->proto == WPA_PROTO_RSN ? EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; @@ -1507,23 +1478,28 @@ failed: memcpy(reply->replay_counter, key->replay_counter, WPA_REPLAY_COUNTER_LEN); - WPA_PUT_BE16(reply->key_data_length, 0); + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); wpa_printf(MSG_DEBUG, "WPA Send 2/2 Group key\n"); - wpa_eapol_key_send(sm, sm->ptk.kck, ver, sm->bssid, ETH_P_EAPOL, - rbuf, rlen, reply->key_mic); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid, ETH_P_EAPOL, + rbuf, rlen, key_mic); wpa_sm_free_eapol(rbuf); return 0; } - void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, +static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, const unsigned char *src_addr, struct wpa_eapol_key *key, - int extra_len, u16 ver) + const u8 *key_data, + size_t key_data_len, u16 ver) { - u16 key_info, keydatalen; + u16 key_info; int ret; struct wpa_gtk_data *gd=&(sm->gd); @@ -1532,17 +1508,13 @@ failed: wpa_printf(MSG_DEBUG, "WPA 1/2 Group Key Handshake\n"); key_info = WPA_GET_BE16(key->key_info); - keydatalen = WPA_GET_BE16(key->key_data_length); if (sm->proto == WPA_PROTO_RSN) { - ret = wpa_supplicant_process_1_of_2_rsn(sm, - (const u8 *) (key + 1), - keydatalen, key_info, - gd); + ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data, + key_data_len, key_info, gd); } else { - ret = wpa_supplicant_process_1_of_2_wpa(sm, key, keydatalen, - key_info, extra_len, - ver, gd); + ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data, + key_data_len, key_info, ver, gd); } wpa_sm_set_state(WPA_GROUP_HANDSHAKE); @@ -1563,7 +1535,7 @@ failed: wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } - int wpa_supplicant_send_2_of_2_txcallback(struct wpa_sm *sm) +static int wpa_supplicant_send_2_of_2_txcallback(struct wpa_sm *sm) { u16 key_info=sm->key_info; u16 rekey= (WPA_SM_STATE(sm) == WPA_COMPLETED); @@ -1592,20 +1564,21 @@ failed: return WLAN_REASON_UNSPECIFIED; } - int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, - struct wpa_eapol_key *key, +static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, + struct wpa_eapol_key_192 *key, u16 ver, const u8 *buf, size_t len) { - u8 mic[16]; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; int ok = 0; + size_t mic_len = wpa_mic_len(sm->key_mgmt); - memcpy(mic, key->key_mic, 16); + os_memcpy(mic, key->key_mic, mic_len); if (sm->tptk_set) { - memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->tptk.kck, ver, buf, len, - key->key_mic); - if (memcmp(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Invalid EAPOL-Key MIC " "when using TPTK - ignoring TPTK"); @@ -1619,10 +1592,10 @@ failed: } if (!ok && sm->ptk_set) { - memset(key->key_mic, 0, 16); - wpa_eapol_key_mic(sm->ptk.kck, ver, buf, len, - key->key_mic); - if (memcmp(mic, key->key_mic, 16) != 0) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Invalid EAPOL-Key MIC " "- dropping packet"); @@ -1651,13 +1624,12 @@ failed: /* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ - int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, - struct wpa_eapol_key *key, u16 ver) +static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, + struct wpa_eapol_key *key, u16 ver, + u8 *key_data, size_t *key_data_len) { - u16 keydatalen = WPA_GET_BE16(key->key_data_length); - wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", - (u8 *) (key + 1), keydatalen); + key_data, *key_data_len); if (!sm->ptk_set) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: PTK not available, " @@ -1668,11 +1640,11 @@ failed: /* Decrypt key data here so that this operation does not need * to be implemented separately for each message type. */ - if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4) { + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { u8 ek[32]; - memcpy(ek, key->key_iv, 16); - memcpy(ek + 16, sm->ptk.kek, 16); - if (rc4_skip(ek, 32, 256, (u8 *) (key + 1), keydatalen)) { + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); + if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: RC4 failed"); #endif @@ -1680,17 +1652,19 @@ failed: } } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || 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) { u8 *buf; - if (keydatalen % 8) { + if (*key_data_len < 8 || *key_data_len % 8) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Unsupported " - "AES-WRAP len %d", keydatalen); + "AES-WRAP len %u", (unsigned int) *key_data_len); #endif return -1; } - keydatalen -= 8; /* AES-WRAP adds 8 bytes */ + *key_data_len -= 8; /* AES-WRAP adds 8 bytes */ /*replaced by xxx to remove malloc*/ buf = ((u8 *) (key+1))+ 8; /* @@ -1703,16 +1677,16 @@ failed: return -1; } */ - if (aes_unwrap(sm->ptk.kek, 16, keydatalen / 8, - (u8 *) (key + 1), buf)) { + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8, + key_data, buf)) { #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: AES unwrap failed - " - "could not decrypt EAPOL-Key key data"); + wpa_printf(MSG_DEBUG, "WPA: AES unwrap failed - " + "could not decrypt EAPOL-Key key data"); #endif - return -1; + return -1; } - memcpy(key + 1, buf, keydatalen); - WPA_PUT_BE16(key->key_data_length, keydatalen); + os_memcpy(key_data, buf, *key_data_len); + WPA_PUT_BE16(key->key_data_length, *key_data_len); } else { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Unsupported key_info type %d", @@ -1721,16 +1695,17 @@ failed: return -1; } wpa_hexdump(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", - (u8 *) (key + 1), keydatalen); + key_data, *key_data_len); return 0; } - void wpa_eapol_key_dump(int level, const struct wpa_eapol_key *key) +static void wpa_eapol_key_dump(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + unsigned int key_data_len, + const u8 *mic, unsigned int mic_len) { #ifdef DEBUG_PRINT - if (level < MSG_MSGDUMP) - return; u16 key_info = WPA_GET_BE16(key->key_info); @@ -1750,8 +1725,15 @@ failed: key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); wpa_printf(MSG_DEBUG, " key_length=%u key_data_length=%u\n", - WPA_GET_BE16(key->key_length), - WPA_GET_BE16(key->key_data_length)); + WPA_GET_BE16(key->key_length), key_data_len); + wpa_hexdump(MSG_DEBUG, " replay_counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); + wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); + wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); + wpa_hexdump(MSG_DEBUG, " key_mic", mic, mic_len); + #endif } @@ -1772,30 +1754,43 @@ failed: * successful key handshake. * buf begin from version, so remove mac header ,snap header and ether_type */ -int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) +int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) { struct wpa_sm *sm = &gWpaSm; - u32 plen, data_len, extra_len; + size_t plen, data_len, key_data_len; struct ieee802_1x_hdr *hdr; struct wpa_eapol_key *key; + struct wpa_eapol_key_192 *key192; u16 key_info, ver; u8 *tmp; int ret = -1; + size_t mic_len, keyhdrlen; + u8 *key_data; - if (len < sizeof(*hdr) + sizeof(*key)) { + mic_len = wpa_mic_len(sm->key_mgmt); + keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + + if (len < sizeof(*hdr) + keyhdrlen) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: EAPOL frame too short to be a WPA " - "EAPOL-Key (len %lu, expecting at least %lu)", - (unsigned long) len, - (unsigned long) sizeof(*hdr) + sizeof(*key)); + "EAPOL-Key (len %lu, expecting at least %lu)", + (unsigned long) len, + (unsigned long) sizeof(*hdr) + sizeof(*key)); #endif return 0; } - tmp = buf; + tmp = buf; hdr = (struct ieee802_1x_hdr *) tmp; key = (struct wpa_eapol_key *) (hdr + 1); + key192 = (struct wpa_eapol_key_192 *) + (tmp + sizeof(struct ieee802_1x_hdr)); + if (mic_len == 24) + key_data = (u8 *) (key192 + 1); + else + key_data = (u8 *) (key + 1); + plen = be_to_host16(hdr->length); data_len = plen + sizeof(*hdr); @@ -1815,7 +1810,7 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) ret = 0; goto out; } - if (plen > len - sizeof(*hdr) || plen < sizeof(*key)) { + if (plen > len - sizeof(*hdr) || plen < keyhdrlen) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: EAPOL frame payload size %lu " "invalid (frame size %lu)", @@ -1825,8 +1820,7 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) goto out; } - if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) - { + if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key type (%d) unknown, " "discarded", key->type); @@ -1835,8 +1829,6 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) goto out; } - wpa_eapol_key_dump(MSG_MSGDUMP, key); - wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", tmp, len); if (data_len < len) { @@ -1854,6 +1846,7 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) #ifdef CONFIG_WPA3_SAE sm->key_mgmt != WPA_KEY_MGMT_SAE && #endif + !wpa_key_mgmt_suite_b(sm->key_mgmt) && #endif ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { #ifdef DEBUG_PRINT @@ -1862,21 +1855,31 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) #endif goto out; } + if (wpa_key_mgmt_suite_b(sm->key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { + wpa_msg(NULL, MSG_INFO, + "RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)", + ver); + goto out; + } #ifdef CONFIG_IEEE80211W if (wpa_key_mgmt_sha256(sm->key_mgmt)) { if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && - sm->key_mgmt != WPA_KEY_MGMT_SAE) { + sm->key_mgmt != WPA_KEY_MGMT_OSEN && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + sm->key_mgmt != WPA_KEY_MGMT_SAE) { goto out; } } else #endif 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) { #ifdef DEBUG_PRINT - wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key " + wpa_printf(MSG_DEBUG, "WPA: CCMP is used, but EAPOL-Key " "descriptor version (%d) is not 2.", ver); #endif if (sm->group_cipher != WPA_CIPHER_CCMP && @@ -1894,10 +1897,20 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) goto out; } +#ifdef CONFIG_GCMP + if (sm->pairwise_cipher == WPA_CIPHER_GCMP && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_msg(NULL, MSG_INFO, + "WPA: GCMP is used, but EAPOL-Key " + "descriptor version (%d) is not 2", ver); + goto out; + } +#endif - if ( sm->rx_replay_counter_set && - memcmp(key->replay_counter, sm->rx_replay_counter, - WPA_REPLAY_COUNTER_LEN) <= 0) { + if (sm->rx_replay_counter_set && + os_memcmp(key->replay_counter, sm->rx_replay_counter, + WPA_REPLAY_COUNTER_LEN) <= 0) { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Replay Counter did not" " increase - dropping packet"); @@ -1920,27 +1933,33 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) } if ((key_info & WPA_KEY_INFO_MIC) && - wpa_supplicant_verify_eapol_key_mic(sm, key, ver, tmp, data_len)) + wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len)) goto out; - extra_len = data_len - sizeof(*hdr) - sizeof(*key); - if (WPA_GET_BE16(key->key_data_length) > extra_len) { - #ifdef DEBUG_PRINT + if (mic_len == 24) + key_data_len = WPA_GET_BE16(key192->key_data_length); + else + key_data_len = WPA_GET_BE16(key->key_data_length); + + wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len); + + + if (key_data_len > plen - keyhdrlen) { +#ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: Invalid EAPOL-Key " - "frame - key_data overflow (%d > %lu)", - WPA_GET_BE16(key->key_data_length), - (unsigned long) extra_len); - #endif + "frame - key_data overflow (%d > %lu)", + (unsigned int) key_data_len, + (unsigned int) (plen - keyhdrlen)); +#endif goto out; } - extra_len = WPA_GET_BE16(key->key_data_length); if (sm->proto == WPA_PROTO_RSN && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { - if (wpa_supplicant_decrypt_key_data(sm, key, ver)) + if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, + &key_data_len)) goto out; - extra_len = WPA_GET_BE16(key->key_data_length); } if (key_info & WPA_KEY_INFO_KEY_TYPE) { @@ -1954,7 +1973,8 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) if (key_info & WPA_KEY_INFO_MIC) { /* 3/4 4-Way Handshake */ - wpa_supplicant_process_3_of_4(sm, key, ver); + wpa_supplicant_process_3_of_4(sm, key, ver, key_data, + key_data_len); } else { /* 1/4 4-Way Handshake */ sm->eapol1_count++; @@ -1966,13 +1986,15 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len) goto out; } wpa_supplicant_process_1_of_4(sm, src_addr, key, - ver); + ver, key_data, + key_data_len); } } else { if (key_info & WPA_KEY_INFO_MIC) { /* 1/2 Group Key Handshake */ wpa_supplicant_process_1_of_2(sm, src_addr, key, - extra_len, ver); + key_data, key_data_len, + ver); } else { #ifdef DEBUG_PRINT wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key (Group) " @@ -2017,23 +2039,23 @@ void wpa_sm_set_state(enum wpa_states state) void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *bssid) { - if (sm == NULL) - return; + if (sm == NULL) + return; - sm->pmk_len = pmk_len; - os_memcpy(sm->pmk, pmk, pmk_len); + sm->pmk_len = pmk_len; + os_memcpy(sm->pmk, pmk, pmk_len); #ifdef CONFIG_IEEE80211R - /* Set XXKey to be PSK for FT key derivation */ - sm->xxkey_len = pmk_len; - os_memcpy(sm->xxkey, pmk, pmk_len); + /* Set XXKey to be PSK for FT key derivation */ + sm->xxkey_len = pmk_len; + os_memcpy(sm->xxkey, pmk, pmk_len); #endif /* CONFIG_IEEE80211R */ - if (bssid) { - pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0, + if (bssid) { + pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, NULL, 0, bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt); - } + } } @@ -2046,16 +2068,16 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, */ void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) { - if (sm == NULL) - return; + if (sm == NULL) + return; - if (sm->cur_pmksa) { - sm->pmk_len = sm->cur_pmksa->pmk_len; - os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); - } else { - sm->pmk_len = PMK_LEN; - os_memset(sm->pmk, 0, PMK_LEN); - } + if (sm->cur_pmksa) { + sm->pmk_len = sm->cur_pmksa->pmk_len; + os_memcpy(sm->pmk, sm->cur_pmksa->pmk, sm->pmk_len); + } else { + sm->pmk_len = PMK_LEN_MAX; + os_memset(sm->pmk, 0, PMK_LEN_MAX); + } } @@ -2119,6 +2141,8 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) sm->key_mgmt = WPA_KEY_MGMT_SAE; /* for WPA3 PSK */ } else if (auth_mode == WAPI_AUTH_PSK) { sm->key_mgmt = WPA_KEY_MGMT_WAPI_PSK; /* for WAPI PSK */ + } else if (auth_mode == WPA2_AUTH_ENT_SHA384_SUITE_B) { + sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; } else { sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */ } @@ -2127,9 +2151,15 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode) void wpa_set_pmk(uint8_t *pmk, const u8 *pmkid, bool cache_pmksa) { struct wpa_sm *sm = &gWpaSm; + int pmk_len; - memcpy(sm->pmk, pmk, PMK_LEN); - sm->pmk_len = PMK_LEN; + if (wpa_key_mgmt_sha384(sm->key_mgmt)) + pmk_len = PMK_LEN_SUITE_B_192; + else + pmk_len = PMK_LEN; + + memcpy(sm->pmk, pmk, pmk_len); + sm->pmk_len = pmk_len; if (cache_pmksa) { pmksa_cache_add(sm->pmksa, pmk, PMK_LEN, pmkid, NULL, 0, @@ -2178,6 +2208,10 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher, esp_wifi_get_config(WIFI_IF_STA, &wifi_cfg); sm->pmf_cfg = wifi_cfg.sta.pmf_cfg; sm->mgmt_group_cipher = cipher_type_map_public_to_supp(esp_wifi_sta_get_mgmt_group_cipher()); + if (sm->mgmt_group_cipher == WPA_CIPHER_NONE) { + wpa_printf(MSG_ERROR, "mgmt_cipher %d not supported", mgmt_cipher); + return -1; + } } else { memset(&sm->pmf_cfg, 0, sizeof(sm->pmf_cfg)); sm->mgmt_group_cipher = WPA_CIPHER_NONE; @@ -2403,7 +2437,7 @@ bool wpa_sta_in_4way_handshake(void) struct wpa_sm *sm = &gWpaSm; if ( WPA_SM_STATE(sm) == WPA_MIC_FAILURE || WPA_SM_STATE(sm) == WPA_FIRST_HALF_4WAY_HANDSHAKE || WPA_SM_STATE(sm) == WPA_LAST_HALF_4WAY_HANDSHAKE) { - return true; + return true; } return false; } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_i.h b/components/wpa_supplicant/src/rsn_supp/wpa_i.h index 8e39d7bb22..ba1c84ee8a 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_i.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa_i.h @@ -30,7 +30,7 @@ struct install_key { * struct wpa_sm - Internal WPA state machine data */ struct wpa_sm { - u8 pmk[PMK_LEN]; + u8 pmk[PMK_LEN_MAX]; size_t pmk_len; struct wpa_ptk ptk, tptk; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c index b206d02e19..a456edc9f1 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa_ie.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa_ie.c @@ -115,16 +115,16 @@ static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, } -static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, +static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, int pairwise_cipher, int group_cipher, int key_mgmt, int mgmt_group_cipher, struct wpa_sm *sm) { -#ifndef CONFIG_NO_WPA2 u8 *pos; struct rsn_ie_hdr *hdr; u16 capab; u8 min_len = 0; + u32 suite; if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + @@ -134,11 +134,6 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, return -1; } - /* For WPA2-PSK, if the RSNE in AP beacon/probe response doesn't specify the - * pairwise cipher or AKM suite, the RSNE IE in association request - * should only contain group cihpher suite, otherwise the WPA2 improvements - * certification will fail. - */ if ( (sm->ap_notify_completed_rsne == true) || (key_mgmt == WPA_KEY_MGMT_IEEE8021X) ) { min_len = sizeof(*hdr) + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2; } else { @@ -154,19 +149,13 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, WPA_PUT_LE16(hdr->version, RSN_VERSION); pos = (u8 *) (hdr + 1); - if (group_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (group_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (group_cipher == WPA_CIPHER_WEP104) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP104); - } else if (group_cipher == WPA_CIPHER_WEP40) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_WEP40); - } else { - wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", - group_cipher); - return -1; + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher); + if (suite == 0) { + wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", + group_cipher); + return -1; } + RSN_SELECTOR_PUT(pos, suite); pos += RSN_SELECTOR_LEN; if ( (sm->ap_notify_completed_rsne == false) && (key_mgmt != WPA_KEY_MGMT_IEEE8021X) ) { @@ -176,21 +165,19 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, *pos++ = 1; *pos++ = 0; - if (pairwise_cipher == WPA_CIPHER_CCMP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); - } else if (pairwise_cipher == WPA_CIPHER_TKIP) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); - } else if (pairwise_cipher == WPA_CIPHER_NONE) { - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); - } else { - wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", - pairwise_cipher); - return -1; + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher); + if (suite == 0 || + (pairwise_cipher == WPA_CIPHER_NONE)) { + wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", + pairwise_cipher); + return -1; } + RSN_SELECTOR_PUT(pos, suite); pos += RSN_SELECTOR_LEN; *pos++ = 1; *pos++ = 0; + if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); } else if (key_mgmt == WPA_KEY_MGMT_PSK) { @@ -211,6 +198,10 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); #endif /* CONFIG_WPA3_SAE */ #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); + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); } else { wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", key_mgmt); @@ -250,7 +241,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } #ifdef CONFIG_IEEE80211W - if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) { + if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) { if (!sm->cur_pmksa) { /* 0 PMKID Count */ WPA_PUT_LE16(pos, 0); @@ -258,7 +249,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, } /* Management Group Cipher Suite */ - RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, + mgmt_group_cipher));; pos += RSN_SELECTOR_LEN; } #endif /* CONFIG_IEEE80211W */ @@ -268,9 +260,6 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); return pos - rsn_ie; -#else /* CONFIG_NO_WPA2 */ - return -1; -#endif /* CONFIG_NO_WPA2 */ } diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 303ae6bee5..5f2c289ec1 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -1218,7 +1218,6 @@ components/esp_wifi/include/esp_private/wifi_os_adapter.h components/esp_wifi/include/esp_private/wifi_types.h components/esp_wifi/include/esp_smartconfig.h components/esp_wifi/include/esp_wifi.h -components/esp_wifi/include/esp_wifi_crypto_types.h components/esp_wifi/include/esp_wifi_default.h components/esp_wifi/include/esp_wifi_netif.h components/esp_wifi/include/smartconfig_ack.h @@ -3002,6 +3001,7 @@ components/wpa_supplicant/src/common/wpa_supplicant_i.h components/wpa_supplicant/src/crypto/aes-cbc.c components/wpa_supplicant/src/crypto/aes-ccm.c components/wpa_supplicant/src/crypto/aes-ctr.c +components/wpa_supplicant/src/crypto/aes-gcm.c components/wpa_supplicant/src/crypto/aes-internal-dec.c components/wpa_supplicant/src/crypto/aes-internal-enc.c components/wpa_supplicant/src/crypto/aes-internal.c @@ -3024,7 +3024,6 @@ components/wpa_supplicant/src/crypto/crypto_mbedtls-bignum.c components/wpa_supplicant/src/crypto/crypto_mbedtls-ec.c components/wpa_supplicant/src/crypto/crypto_mbedtls-rsa.c components/wpa_supplicant/src/crypto/crypto_mbedtls.c -components/wpa_supplicant/src/crypto/crypto_ops.c components/wpa_supplicant/src/crypto/des-internal.c components/wpa_supplicant/src/crypto/des_i.h components/wpa_supplicant/src/crypto/dh_group5.c @@ -3056,6 +3055,7 @@ components/wpa_supplicant/src/crypto/sha256.c components/wpa_supplicant/src/crypto/sha256.h components/wpa_supplicant/src/crypto/sha256_i.h components/wpa_supplicant/src/crypto/sha384-internal.c +components/wpa_supplicant/src/crypto/sha384-prf.c components/wpa_supplicant/src/crypto/sha384-tlsprf.c components/wpa_supplicant/src/crypto/sha384.h components/wpa_supplicant/src/crypto/sha384_i.h