mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 11:17:20 +02:00
Merge branch 'feature/support_pmf' into 'master'
Feature/support pmf See merge request espressif/esp-idf!5708
This commit is contained in:
@ -315,6 +315,47 @@ typedef void * (*esp_aes_decrypt_init_t)(const unsigned char *key, unsigned int
|
||||
*/
|
||||
typedef void (*esp_aes_decrypt_deinit_t)(void *ctx);
|
||||
|
||||
/**
|
||||
* @brief One-Key CBC MAC (OMAC1) hash with AES-128 for MIC computation
|
||||
*
|
||||
* @key: 128-bit key for the hash operation
|
||||
* @data: Data buffer for which a MIC is computed
|
||||
* @data_len: Length of data buffer in bytes
|
||||
* @mic: Buffer for MIC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
typedef int (*esp_omac1_aes_128_t)(const uint8_t *key, const uint8_t *data, size_t data_len,
|
||||
uint8_t *mic);
|
||||
|
||||
/**
|
||||
* @brief Decrypt data using CCMP (Counter Mode CBC-MAC Protocol OR
|
||||
* Counter Mode Cipher Block Chaining Message Authentication
|
||||
* Code Protocol) which is used in IEEE 802.11i RSN standard.
|
||||
* @tk: 128-bit Temporal Key for obtained during 4-way handshake
|
||||
* @hdr: Pointer to IEEE802.11 frame headeri needed for AAD
|
||||
* @data: Pointer to encrypted data buffer
|
||||
* @data_len: Encrypted data length in bytes
|
||||
* @decrypted_len: Length of decrypted data
|
||||
* Returns: Pointer to decrypted data on success, NULL on failure
|
||||
*/
|
||||
typedef uint8_t * (*esp_ccmp_decrypt_t)(const uint8_t *tk, const uint8_t *ieee80211_hdr,
|
||||
const uint8_t *data, size_t data_len, size_t *decrypted_len);
|
||||
|
||||
/**
|
||||
* @brief Encrypt data using CCMP (Counter Mode CBC-MAC Protocol OR
|
||||
* Counter Mode Cipher Block Chaining Message Authentication
|
||||
* Code Protocol) which is used in IEEE 802.11i RSN standard.
|
||||
* @tk: 128-bit Temporal Key for obtained during 4-way handshake
|
||||
* @frame: Pointer to IEEE802.11 frame including header
|
||||
* @len: Length of the frame including header
|
||||
* @hdrlen: Length of the header
|
||||
* @pn: Packet Number counter
|
||||
* @keyid: Key ID to be mentioned in CCMP Vector
|
||||
* @encrypted_len: Length of the encrypted frame including header
|
||||
*/
|
||||
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 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
|
||||
@ -342,6 +383,9 @@ typedef struct {
|
||||
esp_aes_decrypt_t aes_decrypt;
|
||||
esp_aes_decrypt_init_t aes_decrypt_init;
|
||||
esp_aes_decrypt_deinit_t aes_decrypt_deinit;
|
||||
esp_omac1_aes_128_t omac1_aes_128;
|
||||
esp_ccmp_decrypt_t ccmp_decrypt;
|
||||
esp_ccmp_encrypt_t ccmp_encrypt;
|
||||
}wpa_crypto_funcs_t;
|
||||
|
||||
/**
|
||||
|
@ -134,6 +134,7 @@ typedef enum {
|
||||
WIFI_CIPHER_TYPE_TKIP, /**< the cipher type is TKIP */
|
||||
WIFI_CIPHER_TYPE_CCMP, /**< the cipher type is CCMP */
|
||||
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_UNKNOWN, /**< the cipher type is unknown */
|
||||
} wifi_cipher_type_t;
|
||||
|
||||
@ -199,6 +200,12 @@ typedef enum {
|
||||
WIFI_BW_HT40, /* Bandwidth is HT40 */
|
||||
} wifi_bandwidth_t;
|
||||
|
||||
/** Configuration structure for Protected Management Frame */
|
||||
typedef struct {
|
||||
bool capable; /**< Advertizes support for Protected Management Frame. Device will prefer to connect in PMF mode if other device also advertizes PMF capability. */
|
||||
bool required; /**< Advertizes that Protected Management Frame is required. Device will not associate to non-PMF capable devices. */
|
||||
} wifi_pmf_config_t;
|
||||
|
||||
/** @brief Soft-AP configuration settings for the ESP32 */
|
||||
typedef struct {
|
||||
uint8_t ssid[32]; /**< SSID of ESP32 soft-AP. If ssid_len field is 0, this must be a Null terminated string. Otherwise, length is set according to ssid_len. */
|
||||
@ -222,6 +229,7 @@ typedef struct {
|
||||
uint16_t listen_interval; /**< Listen interval for ESP32 station to receive beacon when WIFI_PS_MAX_MODEM is set. Units: AP beacon intervals. Defaults to 3 if set to 0. */
|
||||
wifi_sort_method_t sort_method; /**< sort the connect AP in the list by rssi or security mode */
|
||||
wifi_scan_threshold_t threshold; /**< When sort_method is set, only APs which have an auth mode that is more secure than the selected auth mode and a signal stronger than the minimum RSSI will be used. */
|
||||
wifi_pmf_config_t pmf_cfg; /**< Configuration for Protected Management Frame. Will be advertized in RSN Capabilities in RSN IE. */
|
||||
} wifi_sta_config_t;
|
||||
|
||||
/** @brief Configuration data for ESP32 AP or STA.
|
||||
|
Submodule components/esp_wifi/lib updated: f3c39df1c4...d88a262fbd
@ -5,12 +5,15 @@ set(srcs "port/os_xtensa.c"
|
||||
"src/ap/wpa_auth_ie.c"
|
||||
"src/common/wpa_common.c"
|
||||
"src/crypto/aes-cbc.c"
|
||||
"src/crypto/aes-ccm.c"
|
||||
"src/crypto/aes-internal-dec.c"
|
||||
"src/crypto/aes-internal-enc.c"
|
||||
"src/crypto/aes-internal.c"
|
||||
"src/crypto/aes-unwrap.c"
|
||||
"src/crypto/aes-wrap.c"
|
||||
"src/crypto/aes-omac1.c"
|
||||
"src/crypto/bignum.c"
|
||||
"src/crypto/ccmp.c"
|
||||
"src/crypto/crypto_mbedtls.c"
|
||||
"src/crypto/crypto_ops.c"
|
||||
"src/crypto/crypto_internal-cipher.c"
|
||||
@ -103,4 +106,5 @@ target_compile_definitions(${COMPONENT_LIB} PRIVATE
|
||||
ESPRESSIF_USE
|
||||
ESP32_WORKAROUND
|
||||
CONFIG_ECC
|
||||
CONFIG_IEEE80211W
|
||||
)
|
||||
|
@ -2,4 +2,4 @@ COMPONENT_ADD_INCLUDEDIRS := include port/include include/esp_supplicant
|
||||
COMPONENT_PRIV_INCLUDEDIRS := src
|
||||
COMPONENT_SRCDIRS := port src/ap src/common src/crypto src/eap_peer src/rsn_supp src/tls src/utils src/esp_supplicant src/wps
|
||||
|
||||
CFLAGS += -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
CFLAGS += -DCONFIG_IEEE80211W -DESP_SUPPLICANT -DIEEE8021X_EAPOL -DEAP_PEER_METHOD -DEAP_TLS -DEAP_TTLS -DEAP_PEAP -DEAP_MSCHAPv2 -DUSE_WPA2_TASK -DCONFIG_WPS2 -DCONFIG_WPS_PIN -DUSE_WPS_TASK -DESPRESSIF_USE -DESP32_WORKAROUND -DCONFIG_ECC -D__ets__ -Wno-strict-aliasing
|
||||
|
@ -22,7 +22,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean;
|
||||
#define WPA_CIPHER_WEP104 BIT(8)
|
||||
#define WPA_CIPHER_TKIP BIT(1)
|
||||
#define WPA_CIPHER_CCMP BIT(3)
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(2)
|
||||
#define WPA_CIPHER_AES_128_CMAC BIT(5)
|
||||
#define WPA_CIPHER_GCMP BIT(6)
|
||||
|
||||
#define WPA_KEY_MGMT_IEEE8021X BIT(0)
|
||||
@ -304,7 +304,6 @@ enum wpa_states {
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0
|
||||
#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1
|
||||
|
||||
|
||||
/**
|
||||
* enum mfp_options - Management frame protection (IEEE 802.11w) options
|
||||
*/
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/sha256.h"
|
||||
#include "crypto/md5.h"
|
||||
#include "crypto/aes.h"
|
||||
|
||||
#define MD5_MAC_LEN 16
|
||||
|
||||
@ -388,6 +389,10 @@ int wpa_eapol_key_mic(const u8 *key, int ver, const u8 *buf, size_t len,
|
||||
return -1;
|
||||
memcpy(mic, hash, MD5_MAC_LEN);
|
||||
break;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
case WPA_KEY_INFO_TYPE_AES_128_CMAC:
|
||||
return omac1_aes_128(key, buf, len, mic);
|
||||
#endif
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
215
components/wpa_supplicant/src/crypto/aes-ccm.c
Normal file
215
components/wpa_supplicant/src/crypto/aes-ccm.c
Normal file
@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Counter with CBC-MAC (CCM) with AES
|
||||
*
|
||||
* Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
|
||||
static void xor_aes_block(u8 *dst, const u8 *src)
|
||||
{
|
||||
u32 *d = (u32 *) dst;
|
||||
u32 *s = (u32 *) src;
|
||||
*d++ ^= *s++;
|
||||
*d++ ^= *s++;
|
||||
*d++ ^= *s++;
|
||||
*d++ ^= *s++;
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_auth_start(void *aes, size_t M, size_t L, const u8 *nonce,
|
||||
const u8 *aad, size_t aad_len, size_t plain_len,
|
||||
u8 *x)
|
||||
{
|
||||
u8 aad_buf[2 * AES_BLOCK_SIZE];
|
||||
u8 b[AES_BLOCK_SIZE];
|
||||
|
||||
/* Authentication */
|
||||
/* B_0: Flags | Nonce N | l(m) */
|
||||
b[0] = aad_len ? 0x40 : 0 /* Adata */;
|
||||
b[0] |= (((M - 2) / 2) /* M' */ << 3);
|
||||
b[0] |= (L - 1) /* L' */;
|
||||
os_memcpy(&b[1], nonce, 15 - L);
|
||||
WPA_PUT_BE16(&b[AES_BLOCK_SIZE - L], plain_len);
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "CCM B_0", b, AES_BLOCK_SIZE);
|
||||
aes_encrypt(aes, b, x); /* X_1 = E(K, B_0) */
|
||||
|
||||
if (!aad_len)
|
||||
return;
|
||||
|
||||
WPA_PUT_BE16(aad_buf, aad_len);
|
||||
os_memcpy(aad_buf + 2, aad, aad_len);
|
||||
os_memset(aad_buf + 2 + aad_len, 0, sizeof(aad_buf) - 2 - aad_len);
|
||||
|
||||
xor_aes_block(aad_buf, x);
|
||||
aes_encrypt(aes, aad_buf, x); /* X_2 = E(K, X_1 XOR B_1) */
|
||||
|
||||
if (aad_len > AES_BLOCK_SIZE - 2) {
|
||||
xor_aes_block(&aad_buf[AES_BLOCK_SIZE], x);
|
||||
/* X_3 = E(K, X_2 XOR B_2) */
|
||||
aes_encrypt(aes, &aad_buf[AES_BLOCK_SIZE], x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_auth(void *aes, const u8 *data, size_t len, u8 *x)
|
||||
{
|
||||
size_t last = len % AES_BLOCK_SIZE;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len / AES_BLOCK_SIZE; i++) {
|
||||
/* X_i+1 = E(K, X_i XOR B_i) */
|
||||
xor_aes_block(x, data);
|
||||
data += AES_BLOCK_SIZE;
|
||||
aes_encrypt(aes, x, x);
|
||||
}
|
||||
if (last) {
|
||||
/* XOR zero-padded last block */
|
||||
for (i = 0; i < last; i++)
|
||||
x[i] ^= *data++;
|
||||
aes_encrypt(aes, x, x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_encr_start(size_t L, const u8 *nonce, u8 *a)
|
||||
{
|
||||
/* A_i = Flags | Nonce N | Counter i */
|
||||
a[0] = L - 1; /* Flags = L' */
|
||||
os_memcpy(&a[1], nonce, 15 - L);
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_encr(void *aes, size_t L, const u8 *in, size_t len, u8 *out,
|
||||
u8 *a)
|
||||
{
|
||||
size_t last = len % AES_BLOCK_SIZE;
|
||||
size_t i;
|
||||
|
||||
/* crypt = msg XOR (S_1 | S_2 | ... | S_n) */
|
||||
for (i = 1; i <= len / AES_BLOCK_SIZE; i++) {
|
||||
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
|
||||
/* S_i = E(K, A_i) */
|
||||
aes_encrypt(aes, a, out);
|
||||
xor_aes_block(out, in);
|
||||
out += AES_BLOCK_SIZE;
|
||||
in += AES_BLOCK_SIZE;
|
||||
}
|
||||
if (last) {
|
||||
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], i);
|
||||
aes_encrypt(aes, a, out);
|
||||
/* XOR zero-padded last block */
|
||||
for (i = 0; i < last; i++)
|
||||
*out++ ^= *in++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_encr_auth(void *aes, size_t M, u8 *x, u8 *a, u8 *auth)
|
||||
{
|
||||
size_t i;
|
||||
u8 tmp[AES_BLOCK_SIZE];
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "CCM T", x, M);
|
||||
/* U = T XOR S_0; S_0 = E(K, A_0) */
|
||||
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
|
||||
aes_encrypt(aes, a, tmp);
|
||||
for (i = 0; i < M; i++)
|
||||
auth[i] = x[i] ^ tmp[i];
|
||||
wpa_hexdump_key(MSG_DEBUG, "CCM U", auth, M);
|
||||
}
|
||||
|
||||
|
||||
static void aes_ccm_decr_auth(void *aes, size_t M, u8 *a, const u8 *auth, u8 *t)
|
||||
{
|
||||
size_t i;
|
||||
u8 tmp[AES_BLOCK_SIZE];
|
||||
|
||||
wpa_hexdump_key(MSG_DEBUG, "CCM U", auth, M);
|
||||
/* U = T XOR S_0; S_0 = E(K, A_0) */
|
||||
WPA_PUT_BE16(&a[AES_BLOCK_SIZE - 2], 0);
|
||||
aes_encrypt(aes, a, tmp);
|
||||
for (i = 0; i < M; i++)
|
||||
t[i] = auth[i] ^ tmp[i];
|
||||
wpa_hexdump_key(MSG_DEBUG, "CCM T", t, M);
|
||||
}
|
||||
|
||||
|
||||
/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
|
||||
int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
size_t M, const u8 *plain, size_t plain_len,
|
||||
const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth)
|
||||
{
|
||||
const size_t L = 2;
|
||||
void *aes;
|
||||
u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
|
||||
|
||||
if (aad_len > 30 || M > AES_BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
aes = aes_encrypt_init(key, key_len);
|
||||
if (aes == NULL)
|
||||
return -1;
|
||||
|
||||
aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, plain_len, x);
|
||||
aes_ccm_auth(aes, plain, plain_len, x);
|
||||
|
||||
/* Encryption */
|
||||
aes_ccm_encr_start(L, nonce, a);
|
||||
aes_ccm_encr(aes, L, plain, plain_len, crypt, a);
|
||||
aes_ccm_encr_auth(aes, M, x, a, auth);
|
||||
|
||||
aes_encrypt_deinit(aes);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* AES-CCM with fixed L=2 and aad_len <= 30 assumption */
|
||||
int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
size_t M, const u8 *crypt, size_t crypt_len,
|
||||
const u8 *aad, size_t aad_len, const u8 *auth, u8 *plain)
|
||||
{
|
||||
const size_t L = 2;
|
||||
void *aes;
|
||||
u8 x[AES_BLOCK_SIZE], a[AES_BLOCK_SIZE];
|
||||
u8 t[AES_BLOCK_SIZE];
|
||||
|
||||
if (aad_len > 30 || M > AES_BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
aes = aes_encrypt_init(key, key_len);
|
||||
if (aes == NULL)
|
||||
return -1;
|
||||
|
||||
/* Decryption */
|
||||
aes_ccm_encr_start(L, nonce, a);
|
||||
aes_ccm_decr_auth(aes, M, a, auth, t);
|
||||
|
||||
/* plaintext = msg XOR (S_1 | S_2 | ... | S_n) */
|
||||
aes_ccm_encr(aes, L, crypt, crypt_len, plain, a);
|
||||
|
||||
aes_ccm_auth_start(aes, M, L, nonce, aad, aad_len, crypt_len, x);
|
||||
aes_ccm_auth(aes, plain, crypt_len, x);
|
||||
|
||||
aes_encrypt_deinit(aes);
|
||||
|
||||
if (os_memcmp(x, t, M) != 0) {
|
||||
wpa_printf(MSG_DEBUG, "CCM: Auth mismatch");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
169
components/wpa_supplicant/src/crypto/aes-omac1.c
Normal file
169
components/wpa_supplicant/src/crypto/aes-omac1.c
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* One-key CBC MAC (OMAC1) hash with AES
|
||||
*
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "crypto/aes.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
|
||||
static void gf_mulx(u8 *pad)
|
||||
{
|
||||
int i, carry;
|
||||
|
||||
carry = pad[0] & 0x80;
|
||||
for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
|
||||
pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
|
||||
pad[AES_BLOCK_SIZE - 1] <<= 1;
|
||||
if (carry)
|
||||
pad[AES_BLOCK_SIZE - 1] ^= 0x87;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
|
||||
* @key: Key for the hash operation
|
||||
* @key_len: Key length in octets
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
void *ctx;
|
||||
u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
|
||||
const u8 *pos, *end;
|
||||
size_t i, e, left, total_len;
|
||||
|
||||
ctx = aes_encrypt_init(key, key_len);
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
os_memset(cbc, 0, AES_BLOCK_SIZE);
|
||||
|
||||
total_len = 0;
|
||||
for (e = 0; e < num_elem; e++)
|
||||
total_len += len[e];
|
||||
left = total_len;
|
||||
|
||||
e = 0;
|
||||
pos = addr[0];
|
||||
end = pos + len[0];
|
||||
|
||||
while (left >= AES_BLOCK_SIZE) {
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
||||
cbc[i] ^= *pos++;
|
||||
if (pos >= end) {
|
||||
/*
|
||||
* Stop if there are no more bytes to process
|
||||
* since there are no more entries in the array.
|
||||
*/
|
||||
if (i + 1 == AES_BLOCK_SIZE &&
|
||||
left == AES_BLOCK_SIZE)
|
||||
break;
|
||||
e++;
|
||||
pos = addr[e];
|
||||
end = pos + len[e];
|
||||
}
|
||||
}
|
||||
if (left > AES_BLOCK_SIZE)
|
||||
aes_encrypt(ctx, cbc, cbc);
|
||||
left -= AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
os_memset(pad, 0, AES_BLOCK_SIZE);
|
||||
aes_encrypt(ctx, pad, pad);
|
||||
gf_mulx(pad);
|
||||
|
||||
if (left || total_len == 0) {
|
||||
for (i = 0; i < left; i++) {
|
||||
cbc[i] ^= *pos++;
|
||||
if (pos >= end) {
|
||||
/*
|
||||
* Stop if there are no more bytes to process
|
||||
* since there are no more entries in the array.
|
||||
*/
|
||||
if (i + 1 == left)
|
||||
break;
|
||||
e++;
|
||||
pos = addr[e];
|
||||
end = pos + len[e];
|
||||
}
|
||||
}
|
||||
cbc[left] ^= 0x80;
|
||||
gf_mulx(pad);
|
||||
}
|
||||
|
||||
for (i = 0; i < AES_BLOCK_SIZE; i++)
|
||||
pad[i] ^= cbc[i];
|
||||
aes_encrypt(ctx, pad, mac);
|
||||
aes_encrypt_deinit(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
|
||||
* @key: 128-bit key for the hash operation
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_128_vector(const u8 *key, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
|
||||
* @key: 128-bit key for the hash operation
|
||||
* @data: Data buffer for which a MAC is determined
|
||||
* @data_len: Length of data buffer in bytes
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
||||
{
|
||||
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
|
||||
* @key: 256-bit key for the hash operation
|
||||
* @data: Data buffer for which a MAC is determined
|
||||
* @data_len: Length of data buffer in bytes
|
||||
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This is a mode for using block cipher (AES in this case) for authentication.
|
||||
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
|
||||
* (SP) 800-38B.
|
||||
*/
|
||||
int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
|
||||
{
|
||||
return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
|
||||
}
|
@ -24,4 +24,13 @@ void * aes_decrypt_init(const u8 *key, size_t len);
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
|
||||
void aes_decrypt_deinit(void *ctx);
|
||||
|
||||
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
|
||||
|
||||
int aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
size_t M, const u8 *plain, size_t plain_len,
|
||||
const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth);
|
||||
int aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce,
|
||||
size_t M, const u8 *crypt, size_t crypt_len,
|
||||
const u8 *aad, size_t aad_len, const u8 *auth,
|
||||
u8 *plain);
|
||||
#endif /* AES_H */
|
||||
|
354
components/wpa_supplicant/src/crypto/ccmp.c
Normal file
354
components/wpa_supplicant/src/crypto/ccmp.c
Normal file
@ -0,0 +1,354 @@
|
||||
/*
|
||||
* CTR with CBC-MAC Protocol (CCMP)
|
||||
* Copyright (c) 2010-2012, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
|
||||
#include "utils/includes.h"
|
||||
|
||||
#include "utils/common.h"
|
||||
#include "common/ieee802_11_defs.h"
|
||||
#include "aes.h"
|
||||
#include "aes_wrap.h"
|
||||
|
||||
static void ccmp_aad_nonce(const struct ieee80211_hdr *hdr, const u8 *data,
|
||||
u8 *aad, size_t *aad_len, u8 *nonce)
|
||||
{
|
||||
u16 fc, stype, seq;
|
||||
int qos = 0, addr4 = 0;
|
||||
u8 *pos;
|
||||
|
||||
nonce[0] = 0;
|
||||
|
||||
fc = le_to_host16(hdr->frame_control);
|
||||
stype = WLAN_FC_GET_STYPE(fc);
|
||||
if ((fc & (WLAN_FC_TODS | WLAN_FC_FROMDS)) ==
|
||||
(WLAN_FC_TODS | WLAN_FC_FROMDS))
|
||||
addr4 = 1;
|
||||
|
||||
if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_DATA) {
|
||||
fc &= ~0x0070; /* Mask subtype bits */
|
||||
if (stype & 0x08) {
|
||||
const u8 *qc;
|
||||
qos = 1;
|
||||
fc &= ~WLAN_FC_ORDER;
|
||||
qc = (const u8 *) (hdr + 1);
|
||||
if (addr4)
|
||||
qc += ETH_ALEN;
|
||||
nonce[0] = qc[0] & 0x0f;
|
||||
}
|
||||
} else if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT)
|
||||
nonce[0] |= 0x10; /* Management */
|
||||
|
||||
fc &= ~(WLAN_FC_RETRY | WLAN_FC_PWRMGT | WLAN_FC_MOREDATA);
|
||||
fc |= WLAN_FC_ISWEP;
|
||||
WPA_PUT_LE16(aad, fc);
|
||||
pos = aad + 2;
|
||||
os_memcpy(pos, hdr->addr1, 3 * ETH_ALEN);
|
||||
pos += 3 * ETH_ALEN;
|
||||
seq = le_to_host16(hdr->seq_ctrl);
|
||||
seq &= ~0xfff0; /* Mask Seq#; do not modify Frag# */
|
||||
WPA_PUT_LE16(pos, seq);
|
||||
pos += 2;
|
||||
|
||||
os_memcpy(pos, hdr + 1, addr4 * ETH_ALEN + qos * 2);
|
||||
pos += addr4 * ETH_ALEN;
|
||||
if (qos) {
|
||||
pos[0] &= ~0x70;
|
||||
if (1 /* FIX: either device has SPP A-MSDU Capab = 0 */)
|
||||
pos[0] &= ~0x80;
|
||||
pos++;
|
||||
*pos++ = 0x00;
|
||||
}
|
||||
|
||||
*aad_len = pos - aad;
|
||||
|
||||
os_memcpy(nonce + 1, hdr->addr2, ETH_ALEN);
|
||||
nonce[7] = data[7]; /* PN5 */
|
||||
nonce[8] = data[6]; /* PN4 */
|
||||
nonce[9] = data[5]; /* PN3 */
|
||||
nonce[10] = data[4]; /* PN2 */
|
||||
nonce[11] = data[1]; /* PN1 */
|
||||
nonce[12] = data[0]; /* PN0 */
|
||||
}
|
||||
|
||||
|
||||
static void ccmp_aad_nonce_pv1(const u8 *hdr, const u8 *a1, const u8 *a2,
|
||||
const u8 *a3, const u8 *pn,
|
||||
u8 *aad, size_t *aad_len, u8 *nonce)
|
||||
{
|
||||
u16 fc, type;
|
||||
u8 *pos;
|
||||
|
||||
nonce[0] = BIT(5); /* PV1 */
|
||||
/* TODO: Priority for QMF; 0 is used for Data frames */
|
||||
|
||||
fc = WPA_GET_LE16(hdr);
|
||||
type = (fc & (BIT(2) | BIT(3) | BIT(4))) >> 2;
|
||||
|
||||
if (type == 1)
|
||||
nonce[0] |= 0x10; /* Management */
|
||||
|
||||
fc &= ~(BIT(10) | BIT(11) | BIT(13) | BIT(14) | BIT(15));
|
||||
fc |= BIT(12);
|
||||
WPA_PUT_LE16(aad, fc);
|
||||
pos = aad + 2;
|
||||
if (type == 0 || type == 3) {
|
||||
const u8 *sc;
|
||||
|
||||
os_memcpy(pos, a1, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
os_memcpy(pos, a2, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
|
||||
if (type == 0) {
|
||||
/* Either A1 or A2 contains SID */
|
||||
sc = hdr + 2 + 2 + ETH_ALEN;
|
||||
} else {
|
||||
/* Both A1 and A2 contain full addresses */
|
||||
sc = hdr + 2 + 2 * ETH_ALEN;
|
||||
}
|
||||
/* SC with Sequence Number subfield (bits 4-15 of the Sequence
|
||||
* Control field) masked to 0. */
|
||||
*pos++ = *sc & 0x0f;
|
||||
*pos++ = 0;
|
||||
|
||||
if (a3) {
|
||||
os_memcpy(pos, a3, ETH_ALEN);
|
||||
pos += ETH_ALEN;
|
||||
}
|
||||
}
|
||||
|
||||
*aad_len = pos - aad;
|
||||
|
||||
os_memcpy(nonce + 1, a2, ETH_ALEN);
|
||||
nonce[7] = pn[5]; /* PN5 */
|
||||
nonce[8] = pn[4]; /* PN4 */
|
||||
nonce[9] = pn[3]; /* PN3 */
|
||||
nonce[10] = pn[2]; /* PN2 */
|
||||
nonce[11] = pn[1]; /* PN1 */
|
||||
nonce[12] = pn[0]; /* PN0 */
|
||||
}
|
||||
|
||||
|
||||
u8 * ccmp_decrypt(const u8 *tk, const u8 *hdr, const u8 *data,
|
||||
size_t data_len, size_t *decrypted_len)
|
||||
{
|
||||
u8 aad[30], nonce[13];
|
||||
size_t aad_len;
|
||||
size_t mlen;
|
||||
u8 *plain;
|
||||
|
||||
if (data_len < 8 + 8)
|
||||
return NULL;
|
||||
|
||||
plain = os_malloc(data_len + AES_BLOCK_SIZE);
|
||||
if (plain == NULL)
|
||||
return NULL;
|
||||
|
||||
mlen = data_len - 8 - 8;
|
||||
|
||||
os_memset(aad, 0, sizeof(aad));
|
||||
ccmp_aad_nonce((const struct ieee80211_hdr *)hdr, data, aad, &aad_len, nonce);
|
||||
//wpa_hexdump(MSG_DEBUG, "CCMP AAD", aad, aad_len);
|
||||
//wpa_hexdump(MSG_DEBUG, "CCMP nonce", nonce, 13);
|
||||
|
||||
if (aes_ccm_ad(tk, 16, nonce, 8, data + 8, mlen, aad, aad_len,
|
||||
data + 8 + mlen, plain) < 0) {
|
||||
os_free(plain);
|
||||
return NULL;
|
||||
}
|
||||
//wpa_hexdump(MSG_DEBUG, "CCMP decrypted", plain, mlen);
|
||||
|
||||
*decrypted_len = mlen;
|
||||
return plain;
|
||||
}
|
||||
|
||||
|
||||
void ccmp_get_pn(u8 *pn, const u8 *data)
|
||||
{
|
||||
pn[0] = data[7]; /* PN5 */
|
||||
pn[1] = data[6]; /* PN4 */
|
||||
pn[2] = data[5]; /* PN3 */
|
||||
pn[3] = data[4]; /* PN2 */
|
||||
pn[4] = data[1]; /* PN1 */
|
||||
pn[5] = data[0]; /* PN0 */
|
||||
}
|
||||
|
||||
|
||||
u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
|
||||
u8 *pn, int keyid, size_t *encrypted_len)
|
||||
{
|
||||
u8 aad[30], nonce[13];
|
||||
size_t aad_len, plen;
|
||||
u8 *crypt, *pos;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
if (len < hdrlen || hdrlen < 24)
|
||||
return NULL;
|
||||
plen = len - hdrlen;
|
||||
|
||||
crypt = os_malloc(hdrlen + 8 + plen + 8 + AES_BLOCK_SIZE);
|
||||
if (crypt == NULL)
|
||||
return NULL;
|
||||
|
||||
os_memcpy(crypt, frame, hdrlen);
|
||||
hdr = (struct ieee80211_hdr *) crypt;
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
pos = crypt + hdrlen;
|
||||
*pos++ = pn[5]; /* PN0 */
|
||||
*pos++ = pn[4]; /* PN1 */
|
||||
*pos++ = 0x00; /* Rsvd */
|
||||
*pos++ = 0x20 | (keyid << 6);
|
||||
*pos++ = pn[3]; /* PN2 */
|
||||
*pos++ = pn[2]; /* PN3 */
|
||||
*pos++ = pn[1]; /* PN4 */
|
||||
*pos++ = pn[0]; /* PN5 */
|
||||
|
||||
os_memset(aad, 0, sizeof(aad));
|
||||
ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP AAD", aad, aad_len);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP nonce", nonce, 13);
|
||||
|
||||
if (aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, plen, aad, aad_len,
|
||||
pos, pos + plen) < 0) {
|
||||
os_free(crypt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP encrypted", crypt + hdrlen + 8, plen);
|
||||
|
||||
*encrypted_len = hdrlen + 8 + plen + 8;
|
||||
|
||||
return crypt;
|
||||
}
|
||||
|
||||
|
||||
u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
|
||||
const u8 *frame, size_t len,
|
||||
size_t hdrlen, const u8 *pn, int keyid,
|
||||
size_t *encrypted_len)
|
||||
{
|
||||
u8 aad[24], nonce[13];
|
||||
size_t aad_len, plen;
|
||||
u8 *crypt, *pos;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
if (len < hdrlen || hdrlen < 12)
|
||||
return NULL;
|
||||
plen = len - hdrlen;
|
||||
|
||||
crypt = os_malloc(hdrlen + plen + 8 + AES_BLOCK_SIZE);
|
||||
if (crypt == NULL)
|
||||
return NULL;
|
||||
|
||||
os_memcpy(crypt, frame, hdrlen);
|
||||
hdr = (struct ieee80211_hdr *) crypt;
|
||||
hdr->frame_control |= host_to_le16(BIT(12)); /* Protected Frame */
|
||||
pos = crypt + hdrlen;
|
||||
|
||||
os_memset(aad, 0, sizeof(aad));
|
||||
ccmp_aad_nonce_pv1(crypt, a1, a2, a3, pn, aad, &aad_len, nonce);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP AAD", aad, aad_len);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP nonce", nonce, sizeof(nonce));
|
||||
|
||||
if (aes_ccm_ae(tk, 16, nonce, 8, frame + hdrlen, plen, aad, aad_len,
|
||||
pos, pos + plen) < 0) {
|
||||
os_free(crypt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP encrypted", crypt + hdrlen, plen);
|
||||
|
||||
*encrypted_len = hdrlen + plen + 8;
|
||||
|
||||
return crypt;
|
||||
}
|
||||
|
||||
|
||||
u8 * ccmp_256_decrypt(const u8 *tk, const u8 *hdr, const u8 *data,
|
||||
size_t data_len, size_t *decrypted_len)
|
||||
{
|
||||
u8 aad[30], nonce[13];
|
||||
size_t aad_len;
|
||||
size_t mlen;
|
||||
u8 *plain;
|
||||
|
||||
if (data_len < 8 + 16)
|
||||
return NULL;
|
||||
|
||||
plain = os_malloc(data_len + AES_BLOCK_SIZE);
|
||||
if (plain == NULL)
|
||||
return NULL;
|
||||
|
||||
mlen = data_len - 8 - 16;
|
||||
|
||||
os_memset(aad, 0, sizeof(aad));
|
||||
ccmp_aad_nonce((const struct ieee80211_hdr *)hdr, data, aad, &aad_len, nonce);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 AAD", aad, aad_len);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 nonce", nonce, 13);
|
||||
|
||||
if (aes_ccm_ad(tk, 32, nonce, 16, data + 8, mlen, aad, aad_len,
|
||||
data + 8 + mlen, plain) < 0) {
|
||||
os_free(plain);
|
||||
return NULL;
|
||||
}
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 decrypted", plain, mlen);
|
||||
|
||||
*decrypted_len = mlen;
|
||||
return plain;
|
||||
}
|
||||
|
||||
|
||||
u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
|
||||
u8 *pn, int keyid, size_t *encrypted_len)
|
||||
{
|
||||
u8 aad[30], nonce[13];
|
||||
size_t aad_len, plen;
|
||||
u8 *crypt, *pos;
|
||||
struct ieee80211_hdr *hdr;
|
||||
|
||||
if (len < hdrlen || hdrlen < 24)
|
||||
return NULL;
|
||||
plen = len - hdrlen;
|
||||
|
||||
crypt = os_malloc(hdrlen + 8 + plen + 16 + AES_BLOCK_SIZE);
|
||||
if (crypt == NULL)
|
||||
return NULL;
|
||||
|
||||
os_memcpy(crypt, frame, hdrlen);
|
||||
hdr = (struct ieee80211_hdr *) crypt;
|
||||
hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
|
||||
pos = crypt + hdrlen;
|
||||
*pos++ = pn[5]; /* PN0 */
|
||||
*pos++ = pn[4]; /* PN1 */
|
||||
*pos++ = 0x00; /* Rsvd */
|
||||
*pos++ = 0x20 | (keyid << 6);
|
||||
*pos++ = pn[3]; /* PN2 */
|
||||
*pos++ = pn[2]; /* PN3 */
|
||||
*pos++ = pn[1]; /* PN4 */
|
||||
*pos++ = pn[0]; /* PN5 */
|
||||
|
||||
os_memset(aad, 0, sizeof(aad));
|
||||
ccmp_aad_nonce(hdr, crypt + hdrlen, aad, &aad_len, nonce);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 AAD", aad, aad_len);
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 nonce", nonce, 13);
|
||||
|
||||
if (aes_ccm_ae(tk, 32, nonce, 16, frame + hdrlen, plen, aad, aad_len,
|
||||
pos, pos + plen) < 0) {
|
||||
os_free(crypt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG, "CCMP-256 encrypted", crypt + hdrlen + 8,
|
||||
plen);
|
||||
|
||||
*encrypted_len = hdrlen + 8 + plen + 16;
|
||||
|
||||
return crypt;
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
28
components/wpa_supplicant/src/crypto/ccmp.h
Normal file
28
components/wpa_supplicant/src/crypto/ccmp.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* wlantest - IEEE 802.11 protocol monitoring and testing tool
|
||||
* Copyright (c) 2010-2013, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This software may be distributed under the terms of the BSD license.
|
||||
* See README for more details.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
#ifndef CCMP_H
|
||||
#define CCMP_H
|
||||
|
||||
u8 * ccmp_decrypt(const u8 *tk, const u8 *hdr, const u8 *data,
|
||||
size_t data_len, size_t *decrypted_len);
|
||||
u8 * ccmp_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
|
||||
u8 *pn, int keyid, size_t *encrypted_len);
|
||||
u8 * ccmp_encrypt_pv1(const u8 *tk, const u8 *a1, const u8 *a2, const u8 *a3,
|
||||
const u8 *frame, size_t len,
|
||||
size_t hdrlen, const u8 *pn, int keyid,
|
||||
size_t *encrypted_len);
|
||||
void ccmp_get_pn(u8 *pn, const u8 *data);
|
||||
u8 * ccmp_256_decrypt(const u8 *tk, const u8 *hdr, const u8 *data,
|
||||
size_t data_len, size_t *decrypted_len);
|
||||
u8 * ccmp_256_encrypt(const u8 *tk, u8 *frame, size_t len, size_t hdrlen,
|
||||
u8 *pn, int keyid, size_t *encrypted_len);
|
||||
|
||||
#endif /* CCMP_H */
|
||||
#endif /* CONFIG_IEEE80211W */
|
@ -20,6 +20,7 @@
|
||||
#include "sha1.h"
|
||||
#include "aes.h"
|
||||
#include "esp_wpa.h"
|
||||
#include "ccmp.h"
|
||||
|
||||
/*
|
||||
* This structure is used to set the cyrpto callback function for station to connect when in security mode.
|
||||
@ -48,7 +49,10 @@ const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
|
||||
.aes_encrypt_deinit = (esp_aes_encrypt_deinit_t)aes_encrypt_deinit,
|
||||
.aes_decrypt = (esp_aes_decrypt_t)aes_decrypt,
|
||||
.aes_decrypt_init = (esp_aes_decrypt_init_t)aes_decrypt_init,
|
||||
.aes_decrypt_deinit = (esp_aes_decrypt_deinit_t)aes_decrypt_deinit
|
||||
.aes_decrypt_deinit = (esp_aes_decrypt_deinit_t)aes_decrypt_deinit,
|
||||
.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
|
||||
};
|
||||
|
||||
const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {
|
||||
|
@ -63,7 +63,8 @@ enum {
|
||||
WPA2_AUTH_PSK = 0x05,
|
||||
WPA_AUTH_CCKM = 0x06,
|
||||
WPA2_AUTH_CCKM = 0x07,
|
||||
WPA2_AUTH_INVALID = 0x08,
|
||||
WPA2_AUTH_PSK_SHA256= 0x08,
|
||||
WPA2_AUTH_INVALID = 0x09,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
@ -163,6 +164,13 @@ typedef struct {
|
||||
uint32_t arg_size;
|
||||
} wifi_ipc_config_t;
|
||||
|
||||
#define WPA_IGTK_LEN 16
|
||||
typedef struct {
|
||||
uint8_t keyid[2];
|
||||
uint8_t pn[6];
|
||||
uint8_t igtk[WPA_IGTK_LEN];
|
||||
} wifi_wpa_igtk_t;
|
||||
|
||||
uint8_t *esp_wifi_ap_get_prof_pmk_internal(void);
|
||||
struct wifi_ssid *esp_wifi_ap_get_prof_ap_ssid_internal(void);
|
||||
uint8_t esp_wifi_ap_get_prof_authmode_internal(void);
|
||||
@ -217,5 +225,8 @@ esp_err_t esp_wifi_internal_supplicant_header_md5_check(const char *md5);
|
||||
int esp_wifi_sta_update_ap_info_internal(void);
|
||||
uint8_t *esp_wifi_sta_get_ap_info_prof_pmk_internal(void);
|
||||
esp_err_t esp_wifi_set_wps_start_flag_internal(bool start);
|
||||
uint16_t esp_wifi_sta_pmf_enabled(void);
|
||||
wifi_cipher_type_t esp_wifi_sta_get_mgmt_group_cipher(void);
|
||||
int esp_wifi_set_igtk_internal(uint8_t if_index, const wifi_wpa_igtk_t *igtk);
|
||||
|
||||
#endif /* _ESP_WIFI_DRIVER_H_ */
|
||||
|
@ -158,32 +158,6 @@ void wpa_sta_connect(uint8_t *bssid)
|
||||
WPA_ASSERT(ret == 0);
|
||||
}
|
||||
|
||||
int cipher_type_map(int wpa_cipher)
|
||||
{
|
||||
switch (wpa_cipher) {
|
||||
case WPA_CIPHER_NONE:
|
||||
return WIFI_CIPHER_TYPE_NONE;
|
||||
|
||||
case WPA_CIPHER_WEP40:
|
||||
return WIFI_CIPHER_TYPE_WEP40;
|
||||
|
||||
case WPA_CIPHER_WEP104:
|
||||
return WIFI_CIPHER_TYPE_WEP104;
|
||||
|
||||
case WPA_CIPHER_TKIP:
|
||||
return WIFI_CIPHER_TYPE_TKIP;
|
||||
|
||||
case WPA_CIPHER_CCMP:
|
||||
return WIFI_CIPHER_TYPE_CCMP;
|
||||
|
||||
case WPA_CIPHER_CCMP|WPA_CIPHER_TKIP:
|
||||
return WIFI_CIPHER_TYPE_TKIP_CCMP;
|
||||
|
||||
default:
|
||||
return WIFI_CIPHER_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t *data)
|
||||
{
|
||||
struct wpa_ie_data ie;
|
||||
@ -191,12 +165,12 @@ int wpa_parse_wpa_ie_wrapper(const u8 *wpa_ie, size_t wpa_ie_len, wifi_wpa_ie_t
|
||||
|
||||
ret = wpa_parse_wpa_ie(wpa_ie, wpa_ie_len, &ie);
|
||||
data->proto = ie.proto;
|
||||
data->pairwise_cipher = cipher_type_map(ie.pairwise_cipher);
|
||||
data->group_cipher = cipher_type_map(ie.group_cipher);
|
||||
data->pairwise_cipher = cipher_type_map_supp_to_public(ie.pairwise_cipher);
|
||||
data->group_cipher = cipher_type_map_supp_to_public(ie.group_cipher);
|
||||
data->key_mgmt = ie.key_mgmt;
|
||||
data->capabilities = ie.capabilities;
|
||||
data->pmkid = ie.pmkid;
|
||||
data->mgmt_group_cipher = cipher_type_map(ie.mgmt_group_cipher);
|
||||
data->mgmt_group_cipher = cipher_type_map_supp_to_public(ie.mgmt_group_cipher);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/sha1.h"
|
||||
#include "crypto/aes_wrap.h"
|
||||
#include "crypto/ccmp.h"
|
||||
|
||||
/**
|
||||
* eapol_sm_notify_eap_success - Notification of external EAP success trigger
|
||||
@ -46,7 +47,7 @@
|
||||
/* fix buf for tx for now */
|
||||
#define WPA_TX_MSG_BUFF_MAXLEN 200
|
||||
|
||||
#define ASSOC_IE_LEN 24 + 2 + PMKID_LEN
|
||||
#define ASSOC_IE_LEN 24 + 2 + PMKID_LEN + RSN_SELECTOR_LEN
|
||||
u8 assoc_ie_buf[ASSOC_IE_LEN+2];
|
||||
|
||||
void set_assoc_ie(u8 * assoc_buf);
|
||||
@ -76,6 +77,65 @@ void eapol_sm_notify_eap_success(Boolean success)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher)
|
||||
{
|
||||
switch (wpa_cipher) {
|
||||
case WPA_CIPHER_NONE:
|
||||
return WIFI_CIPHER_TYPE_NONE;
|
||||
|
||||
case WPA_CIPHER_WEP40:
|
||||
return WIFI_CIPHER_TYPE_WEP40;
|
||||
|
||||
case WPA_CIPHER_WEP104:
|
||||
return WIFI_CIPHER_TYPE_WEP104;
|
||||
|
||||
case WPA_CIPHER_TKIP:
|
||||
return WIFI_CIPHER_TYPE_TKIP;
|
||||
|
||||
case WPA_CIPHER_CCMP:
|
||||
return WIFI_CIPHER_TYPE_CCMP;
|
||||
|
||||
case WPA_CIPHER_CCMP|WPA_CIPHER_TKIP:
|
||||
return WIFI_CIPHER_TYPE_TKIP_CCMP;
|
||||
|
||||
case WPA_CIPHER_AES_128_CMAC:
|
||||
return WIFI_CIPHER_TYPE_AES_CMAC128;
|
||||
|
||||
default:
|
||||
return WIFI_CIPHER_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t cipher_type_map_public_to_supp(wifi_cipher_type_t cipher)
|
||||
{
|
||||
switch (cipher) {
|
||||
case WIFI_CIPHER_TYPE_NONE:
|
||||
return WPA_CIPHER_NONE;
|
||||
|
||||
case WIFI_CIPHER_TYPE_WEP40:
|
||||
return WPA_CIPHER_WEP40;
|
||||
|
||||
case WIFI_CIPHER_TYPE_WEP104:
|
||||
return WPA_CIPHER_WEP104;
|
||||
|
||||
case WIFI_CIPHER_TYPE_TKIP:
|
||||
return WPA_CIPHER_TKIP;
|
||||
|
||||
case WIFI_CIPHER_TYPE_CCMP:
|
||||
return WPA_CIPHER_CCMP;
|
||||
|
||||
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;
|
||||
|
||||
default:
|
||||
return WPA_CIPHER_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get_bssid - Get the current BSSID
|
||||
* @priv: private driver interface data
|
||||
@ -622,7 +682,7 @@ int wpa_supplicant_install_ptk(struct wpa_sm *sm)
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (sm->wpa_ptk_rekey) {
|
||||
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
|
||||
eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk,
|
||||
@ -932,7 +992,29 @@ void wpa_report_ie_mismatch(struct wpa_sm *sm, const u8 *src_addr,
|
||||
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;
|
||||
}
|
||||
|
||||
if (ie->igtk) {
|
||||
const wifi_wpa_igtk_t *igtk;
|
||||
uint16_t keyidx;
|
||||
|
||||
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(ESP_IF_WIFI_STA, igtk);
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int wpa_supplicant_validate_ie(struct wpa_sm *sm,
|
||||
@ -1169,7 +1251,7 @@ int ieee80211w_set_keys(struct wpa_sm *sm,
|
||||
}
|
||||
}
|
||||
|
||||
if (ieee80211w_set_keys(sm, &ie) < 0) {
|
||||
if (sm->pmf_cfg.capable && ieee80211w_set_keys(sm, &ie) < 0) {
|
||||
#ifdef DEBUG_PRINT
|
||||
wpa_printf(MSG_DEBUG, "RSN: Failed to configure IGTK");
|
||||
#endif
|
||||
@ -1746,7 +1828,11 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
|
||||
}
|
||||
key_info = WPA_GET_BE16(key->key_info);
|
||||
ver = key_info & WPA_KEY_INFO_TYPE_MASK;
|
||||
|
||||
if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 &&
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
ver != WPA_KEY_INFO_TYPE_AES_128_CMAC &&
|
||||
#endif
|
||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||
#ifdef DEBUG_PRINT
|
||||
wpa_printf(MSG_DEBUG, "WPA: Unsupported EAPOL-Key descriptor "
|
||||
@ -1755,6 +1841,14 @@ int wpa_sm_rx_eapol(u8 *src_addr, u8 *buf, u32 len)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (wpa_key_mgmt_sha256(sm->key_mgmt)) {
|
||||
if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) {
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
|
||||
if (sm->pairwise_cipher == WPA_CIPHER_CCMP &&
|
||||
ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) {
|
||||
#ifdef DEBUG_PRINT
|
||||
@ -1977,10 +2071,13 @@ void wpa_set_profile(u32 wpa_proto, u8 auth_mode)
|
||||
struct wpa_sm *sm = &gWpaSm;
|
||||
|
||||
sm->proto = wpa_proto;
|
||||
if (auth_mode == WPA2_AUTH_ENT)
|
||||
if (auth_mode == WPA2_AUTH_ENT) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_IEEE8021X; /* for wpa2 enterprise */
|
||||
else
|
||||
} else if (auth_mode == WPA2_AUTH_PSK) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_PSK; /* fixed to PSK for now */
|
||||
} else if (auth_mode == WPA2_AUTH_PSK_SHA256) {
|
||||
sm->key_mgmt = WPA_KEY_MGMT_PSK_SHA256;
|
||||
}
|
||||
}
|
||||
|
||||
void wpa_set_pmk(uint8_t *pmk)
|
||||
@ -2011,6 +2108,16 @@ int wpa_set_bss(char *macddr, char * bssid, u8 pairwise_cipher, u8 group_cipher,
|
||||
pmksa_cache_set_current(sm, NULL, (const u8*) bssid, 0, 0);
|
||||
wpa_sm_set_pmk_from_pmksa(sm);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (esp_wifi_sta_pmf_enabled()) {
|
||||
wifi_config_t wifi_cfg;
|
||||
|
||||
esp_wifi_get_config(ESP_IF_WIFI_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());
|
||||
}
|
||||
#endif
|
||||
set_assoc_ie(assoc_ie_buf); /* use static buffer */
|
||||
res = wpa_gen_wpa_ie(sm, sm->assoc_wpa_ie, sm->assoc_wpa_ie_len);
|
||||
if (res < 0)
|
||||
@ -2234,10 +2341,10 @@ bool wpa_sta_in_4way_handshake(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool wpa_sta_is_cur_pmksa_set(void) {
|
||||
struct wpa_sm *sm = &gWpaSm;
|
||||
return (pmksa_cache_get_current(sm) != NULL);
|
||||
}
|
||||
|
||||
#endif // ESP_SUPPLICANT
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "utils/common.h"
|
||||
#include "common/defs.h"
|
||||
#include "common/wpa_common.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "esp_wifi_crypto_types.h"
|
||||
#include "wpa_i.h"
|
||||
|
||||
@ -128,5 +129,9 @@ char * dup_binstr(const void *src, size_t len);
|
||||
|
||||
int wpa_michael_mic_failure(u16 isunicast);
|
||||
|
||||
wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher);
|
||||
|
||||
uint32_t cipher_type_map_supp_to_public(wifi_cipher_type_t cipher);
|
||||
|
||||
#endif /* WPA_H */
|
||||
|
||||
|
@ -89,6 +89,7 @@ struct wpa_sm {
|
||||
u16 key_info; //used for txcallback param
|
||||
u16 txcb_flags;
|
||||
bool ap_notify_completed_rsne;
|
||||
wifi_pmf_config_t pmf_cfg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -214,10 +214,12 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
|
||||
/* RSN Capabilities */
|
||||
capab = 0;
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (sm->mfp)
|
||||
if (sm->pmf_cfg.capable) {
|
||||
capab |= WPA_CAPABILITY_MFPC;
|
||||
if (sm->mfp == 2)
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
if (sm->pmf_cfg.required) {
|
||||
capab |= WPA_CAPABILITY_MFPR;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_IEEE80211W */
|
||||
WPA_PUT_LE16(pos, capab);
|
||||
pos += 2;
|
||||
@ -234,7 +236,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 (!sm->cur_pmksa) {
|
||||
/* PMKID Count */
|
||||
/* 0 PMKID Count */
|
||||
WPA_PUT_LE16(pos, 0);
|
||||
pos += 2;
|
||||
}
|
||||
@ -329,6 +331,16 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end,
|
||||
pos, pos[1] + 2);
|
||||
return 0;
|
||||
}
|
||||
#ifdef CONFIG_IEEE80211W
|
||||
if (pos[1] > RSN_SELECTOR_LEN + 2 &&
|
||||
RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) {
|
||||
ie->igtk = pos + 2 + RSN_SELECTOR_LEN;
|
||||
ie->igtk_len = pos[1] - RSN_SELECTOR_LEN;
|
||||
wpa_hexdump(MSG_DEBUG, "WPA: IGTK in EAPOL-Key",
|
||||
pos, pos[1] + 2);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user