kopia lustrzana https://github.com/espressif/esp-idf
esp_wifi: Add support for GCMP and GMAC ciphers
rodzic
b86fe0c66c
commit
797c7144bd
|
@ -1567,7 +1567,6 @@ ppEnqueueRxq = 0x400016c8;
|
|||
ppEnqueueTxDone = 0x400016cc;
|
||||
ppGetTxQFirstAvail_Locked = 0x400016d0;
|
||||
ppGetTxframe = 0x400016d4;
|
||||
ppProcTxSecFrame = 0x400016dc;
|
||||
ppProcessRxPktHdr = 0x400016e0;
|
||||
ppProcessTxQ = 0x400016e4;
|
||||
ppRecordBarRRC = 0x400016e8;
|
||||
|
|
|
@ -1873,7 +1873,6 @@ ppEnqueueTxDone = 0x400055a4;
|
|||
ppGetTxQFirstAvail_Locked = 0x400055b0;
|
||||
ppGetTxframe = 0x400055bc;
|
||||
ppMapTxQueue = 0x400055c8;
|
||||
ppProcTxSecFrame = 0x400055d4;
|
||||
ppProcessRxPktHdr = 0x400055e0;
|
||||
ppProcessTxQ = 0x400055ec;
|
||||
ppRecordBarRRC = 0x400055f8;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 049fbb7f22962fc4e2316e732ad08fc95b14149f
|
||||
Subproject commit 0c3f24cc83d595f60e3b785e3eb098c3bc5ce2d3
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Galois/Counter Mode (GCM) and GMAC with AES
|
||||
*
|
||||
* Copyright (c) 2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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);
|
||||
}
|
|
@ -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 = {
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* SHA384-based KDF (IEEE 802.11ac)
|
||||
* Copyright (c) 2003-2017, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* 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;
|
||||
}
|
|
@ -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));
|
||||
|
|
|
@ -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_* */
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Ładowanie…
Reference in New Issue