diff options
author | Sam Leffler <sam@FreeBSD.org> | 2008-03-24 21:06:16 +0000 |
---|---|---|
committer | Sam Leffler <sam@FreeBSD.org> | 2008-03-24 21:06:16 +0000 |
commit | 6ff97d4b9c8eb4cbb0bc35fbb6386ba0b5f114b6 (patch) | |
tree | 78bf17cbe16912111a6c13e5b474634183b11be0 /contrib | |
parent | 75cbf10273fddabf1de109ac241e64defd66eb38 (diff) | |
download | src-6ff97d4b9c8eb4cbb0bc35fbb6386ba0b5f114b6.tar.gz src-6ff97d4b9c8eb4cbb0bc35fbb6386ba0b5f114b6.zip |
Import of hostapd 0.5.10
Notes
Notes:
svn path=/vendor/hostapd/dist/; revision=177576
Diffstat (limited to 'contrib')
29 files changed, 490 insertions, 323 deletions
diff --git a/contrib/hostapd/ChangeLog b/contrib/hostapd/ChangeLog index 73c63a86522d..ab28973f9bba 100644 --- a/contrib/hostapd/ChangeLog +++ b/contrib/hostapd/ChangeLog @@ -1,5 +1,25 @@ ChangeLog for hostapd +2008-02-19 - v0.5.10 + * fixed EAP-SIM and EAP-AKA message parser to validate attribute + lengths properly to avoid potential crash caused by invalid messages + * fixed Reassociation Response callback processing when using internal + MLME (driver_{hostap,devicescape,test}.c) + * fixed EAP-SIM/AKA realm processing to allow decorated usernames to + be used + * added a workaround for EAP-SIM/AKA peers that include incorrect null + termination in the username + * fixed EAP-SIM Start response processing for fast reauthentication + case + * copy optional Proxy-State attributes into RADIUS response when acting + as a RADIUS authentication server + +2007-12-02 - v0.5.9 + * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest + draft (draft-ietf-emu-eap-gpsk-07.txt) + * fixed debugging code not to use potentially unaligned read to fetch + IPv4 addresses + 2007-05-28 - v0.5.8 * updated driver_devicescape.c to build with the current wireless-dev.git tree and net/d80211 changes diff --git a/contrib/hostapd/README b/contrib/hostapd/README index 541fac428515..dd242042d406 100644 --- a/contrib/hostapd/README +++ b/contrib/hostapd/README @@ -2,7 +2,7 @@ hostapd - user space IEEE 802.11 AP and IEEE 802.1X/WPA/WPA2/EAP Authenticator and RADIUS authentication server ================================================================ -Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> and contributors +Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> and contributors All Rights Reserved. This program is dual-licensed under both the GPL version 2 and BSD diff --git a/contrib/hostapd/aes_wrap.c b/contrib/hostapd/aes_wrap.c index c52e45af27c5..765b1ca871ad 100644 --- a/contrib/hostapd/aes_wrap.c +++ b/contrib/hostapd/aes_wrap.c @@ -7,7 +7,7 @@ * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,10 +34,11 @@ /** * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) - * @kek: Key encryption key (KEK) - * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes - * @plain: Plaintext key to be wrapped, n * 64 bit - * @cipher: Wrapped key, (n + 1) * 64 bit + * @kek: 16-octet Key encryption key (KEK) + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @plain: Plaintext key to be wrapped, n * 64 bits + * @cipher: Wrapped key, (n + 1) * 64 bits * Returns: 0 on success, -1 on failure */ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) @@ -93,9 +94,10 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher) /** * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394) * @kek: Key encryption key (KEK) - * @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes - * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit - * @plain: Plaintext key, n * 64 bit + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits + * @plain: Plaintext key, n * 64 bits * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) */ int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain) @@ -167,28 +169,45 @@ static void gf_mulx(u8 *pad) /** - * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) + * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 * @key: 128-bit key for the hash operation - * @data: Data buffer for which a MAC is determined - * @data: Length of data buffer in bytes + * @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 */ -int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) { void *ctx; u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE]; - const u8 *pos = data; - size_t i, left = data_len; + const u8 *pos, *end; + size_t i, e, left, total_len; ctx = aes_encrypt_init(key, 16); if (ctx == NULL) return -1; os_memset(cbc, 0, 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 >= BLOCK_SIZE) { - for (i = 0; i < BLOCK_SIZE; i++) + for (i = 0; i < BLOCK_SIZE; i++) { cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } if (left > BLOCK_SIZE) aes_encrypt(ctx, cbc, cbc); left -= BLOCK_SIZE; @@ -198,9 +217,15 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) aes_encrypt(ctx, pad, pad); gf_mulx(pad); - if (left || data_len == 0) { - for (i = 0; i < left; i++) + if (left || total_len == 0) { + for (i = 0; i < left; i++) { cbc[i] ^= *pos++; + if (pos >= end) { + e++; + pos = addr[e]; + end = pos + len[e]; + } + } cbc[left] ^= 0x80; gf_mulx(pad); } @@ -212,6 +237,24 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) return 0; } + +/** + * 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); +} + #endif /* CONFIG_NO_AES_OMAC1 */ diff --git a/contrib/hostapd/aes_wrap.h b/contrib/hostapd/aes_wrap.h index 1bc6971eff8e..5eb4342a5bf9 100644 --- a/contrib/hostapd/aes_wrap.h +++ b/contrib/hostapd/aes_wrap.h @@ -7,7 +7,7 @@ * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * - * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi> + * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -24,6 +24,8 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher); int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain); +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, diff --git a/contrib/hostapd/common.c b/contrib/hostapd/common.c index c8d6f130a960..f226c68631b8 100644 --- a/contrib/hostapd/common.c +++ b/contrib/hostapd/common.c @@ -20,7 +20,6 @@ #ifdef CONFIG_DEBUG_FILE static FILE *out_file = NULL; #endif /* CONFIG_DEBUG_FILE */ -int wpa_debug_use_file = 0; int wpa_debug_level = MSG_INFO; int wpa_debug_show_keys = 0; int wpa_debug_timestamp = 0; @@ -344,32 +343,29 @@ void wpa_hexdump_ascii_key(int level, const char *title, const u8 *buf, } -int wpa_debug_open_file(void) +int wpa_debug_open_file(const char *path) { #ifdef CONFIG_DEBUG_FILE - static int count = 0; - char fname[64]; - if (!wpa_debug_use_file) + if (!path) return 0; -#ifdef _WIN32 - os_snprintf(fname, sizeof(fname), "\\Temp\\wpa_supplicant-log-%d.txt", - count++); -#else /* _WIN32 */ - os_snprintf(fname, sizeof(fname), "/tmp/wpa_supplicant-log-%d.txt", - count++); + out_file = fopen(path, "a"); + if (out_file == NULL) { + wpa_printf(MSG_ERROR, "wpa_debug_open_file: Failed to open " + "output file, using standard output"); + return -1; + } +#ifndef _WIN32 + setvbuf(out_file, NULL, _IOLBF, 0); #endif /* _WIN32 */ - out_file = fopen(fname, "w"); - return out_file == NULL ? -1 : 0; -#else /* CONFIG_DEBUG_FILE */ - return 0; #endif /* CONFIG_DEBUG_FILE */ + return 0; } void wpa_debug_close_file(void) { #ifdef CONFIG_DEBUG_FILE - if (!wpa_debug_use_file) + if (!out_file) return; fclose(out_file); out_file = NULL; diff --git a/contrib/hostapd/common.h b/contrib/hostapd/common.h index b200b580d5df..eda328af345d 100644 --- a/contrib/hostapd/common.h +++ b/contrib/hostapd/common.h @@ -264,12 +264,12 @@ enum { MSG_MSGDUMP, MSG_DEBUG, MSG_INFO, MSG_WARNING, MSG_ERROR }; #define wpa_hexdump_key(l,t,b,le) do { } while (0) #define wpa_hexdump_ascii(l,t,b,le) do { } while (0) #define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) -#define wpa_debug_open_file() do { } while (0) +#define wpa_debug_open_file(p) do { } while (0) #define wpa_debug_close_file() do { } while (0) #else /* CONFIG_NO_STDOUT_DEBUG */ -int wpa_debug_open_file(void); +int wpa_debug_open_file(const char *path); void wpa_debug_close_file(void); /** diff --git a/contrib/hostapd/driver_test.c b/contrib/hostapd/driver_test.c index d0b90d1c9e5f..368d76b06103 100644 --- a/contrib/hostapd/driver_test.c +++ b/contrib/hostapd/driver_test.c @@ -170,9 +170,10 @@ static int test_driver_send_mgmt_frame(void *priv, const void *buf, u16 fc; if (drv->test_socket < 0 || len < 10 || drv->socket_dir == NULL) { - wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%d " - "socket_dir=%p)", - __func__, drv->test_socket, len, drv->socket_dir); + wpa_printf(MSG_DEBUG, "%s: invalid parameters (sock=%d len=%lu" + " socket_dir=%p)", + __func__, drv->test_socket, (unsigned long) len, + drv->socket_dir); return -1; } diff --git a/contrib/hostapd/eap_aka.c b/contrib/hostapd/eap_aka.c index 5db4cd3f7260..9b10c8e1eb01 100644 --- a/contrib/hostapd/eap_aka.c +++ b/contrib/hostapd/eap_aka.c @@ -1,6 +1,6 @@ /* * hostapd / EAP-AKA (RFC 4187) - * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -124,6 +124,14 @@ static u8 * eap_aka_build_identity(struct eap_sm *sm, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); + } else { + /* + * RFC 4187, Chap. 4.1.4 recommends that identity from EAP is + * ignored and the AKA/Identity is used to request the + * identity. + */ + wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); + eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } return eap_sim_msg_finish(msg, reqDataLen, NULL, NULL, 0); } @@ -445,10 +453,16 @@ static void eap_aka_determine_identity(struct eap_sm *sm, sm->method_pending = METHOD_PENDING_NONE; } + identity_len = sm->identity_len; + while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { + wpa_printf(MSG_DEBUG, "EAP-AKA: Workaround - drop last null " + "character from identity"); + identity_len--; + } wpa_hexdump_ascii(MSG_DEBUG, "EAP-AKA: Identity for MK derivation", - sm->identity, sm->identity_len); + sm->identity, identity_len); - eap_aka_derive_mk(sm->identity, sm->identity_len, data->ik, data->ck, + eap_aka_derive_mk(sm->identity, identity_len, data->ik, data->ck, data->mk); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, data->emsk); diff --git a/contrib/hostapd/eap_gpsk.c b/contrib/hostapd/eap_gpsk.c index 8ab70a1ac3f3..3fecefe1ad18 100644 --- a/contrib/hostapd/eap_gpsk.c +++ b/contrib/hostapd/eap_gpsk.c @@ -1,5 +1,5 @@ /* - * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-03.txt) server + * hostapd / EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) server * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify @@ -23,15 +23,15 @@ struct eap_gpsk_data { enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; u8 rand_server[EAP_GPSK_RAND_LEN]; - u8 rand_client[EAP_GPSK_RAND_LEN]; + u8 rand_peer[EAP_GPSK_RAND_LEN]; u8 msk[EAP_MSK_LEN]; u8 emsk[EAP_EMSK_LEN]; u8 sk[EAP_GPSK_MAX_SK_LEN]; size_t sk_len; u8 pk[EAP_GPSK_MAX_PK_LEN]; size_t pk_len; - u8 *id_client; - size_t id_client_len; + u8 *id_peer; + size_t id_peer_len; u8 *id_server; size_t id_server_len; #define MAX_NUM_CSUITES 2 @@ -85,17 +85,17 @@ static void * eap_gpsk_init(struct eap_sm *sm) data->csuite_count = 0; if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_AES)) { - WPA_PUT_BE24(data->csuite_list[data->csuite_count].vendor, + WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE24(data->csuite_list[data->csuite_count].specifier, + WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_AES); data->csuite_count++; } if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, EAP_GPSK_CIPHER_SHA256)) { - WPA_PUT_BE24(data->csuite_list[data->csuite_count].vendor, + WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, EAP_GPSK_VENDOR_IETF); - WPA_PUT_BE24(data->csuite_list[data->csuite_count].specifier, + WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, EAP_GPSK_CIPHER_SHA256); data->csuite_count++; } @@ -108,7 +108,7 @@ static void eap_gpsk_reset(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; free(data->id_server); - free(data->id_client); + free(data->id_peer); free(data); } @@ -174,8 +174,8 @@ static u8 * eap_gpsk_build_gpsk_3(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3"); miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 * EAP_GPSK_RAND_LEN + sizeof(struct eap_gpsk_csuite) + 2 + - miclen; + len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len + + sizeof(struct eap_gpsk_csuite) + 2 + miclen; req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqDataLen, len, EAP_CODE_REQUEST, id, &pos); if (req == NULL) { @@ -188,13 +188,18 @@ static u8 * eap_gpsk_build_gpsk_3(struct eap_sm *sm, *pos++ = EAP_GPSK_OPCODE_GPSK_3; start = pos; - memcpy(pos, data->rand_client, EAP_GPSK_RAND_LEN); + memcpy(pos, data->rand_peer, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; memcpy(pos, data->rand_server, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; + WPA_PUT_BE16(pos, data->id_server_len); + pos += 2; + if (data->id_server) + memcpy(pos, data->id_server, data->id_server_len); + pos += data->id_server_len; csuite = (struct eap_gpsk_csuite *) pos; - WPA_PUT_BE24(csuite->vendor, data->vendor); - WPA_PUT_BE24(csuite->specifier, data->specifier); + WPA_PUT_BE32(csuite->vendor, data->vendor); + WPA_PUT_BE16(csuite->specifier, data->specifier); pos += sizeof(*csuite); /* no PD_Payload_2 */ @@ -282,7 +287,7 @@ static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Client length"); + "ID_Peer length"); eap_gpsk_state(data, FAILURE); return; } @@ -290,21 +295,21 @@ static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, pos += 2; if (end - pos < alen) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "ID_Client"); + "ID_Peer"); eap_gpsk_state(data, FAILURE); return; } - free(data->id_client); - data->id_client = malloc(alen); - if (data->id_client == NULL) { + free(data->id_peer); + data->id_peer = malloc(alen); + if (data->id_peer == NULL) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " - "%d-octet ID_Client", alen); + "%d-octet ID_Peer", alen); return; } - memcpy(data->id_client, pos, alen); - data->id_client_len = alen; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Client", - data->id_client, data->id_client_len); + memcpy(data->id_peer, pos, alen); + data->id_peer_len = alen; + wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", + data->id_peer, data->id_peer_len); pos += alen; if (end - pos < 2) { @@ -332,13 +337,13 @@ static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, if (end - pos < EAP_GPSK_RAND_LEN) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " - "RAND_Client"); + "RAND_Peer"); eap_gpsk_state(data, FAILURE); return; } - memcpy(data->rand_client, pos, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client", - data->rand_client, EAP_GPSK_RAND_LEN); + memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", + data->rand_peer, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; if (end - pos < EAP_GPSK_RAND_LEN) { @@ -397,13 +402,13 @@ static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, if (i == data->csuite_count) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " "ciphersuite %d:%d", - WPA_GET_BE24(csuite->vendor), - WPA_GET_BE24(csuite->specifier)); + WPA_GET_BE32(csuite->vendor), + WPA_GET_BE16(csuite->specifier)); eap_gpsk_state(data, FAILURE); return; } - data->vendor = WPA_GET_BE24(csuite->vendor); - data->specifier = WPA_GET_BE24(csuite->specifier); + data->vendor = WPA_GET_BE32(csuite->vendor); + data->specifier = WPA_GET_BE16(csuite->specifier); wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", data->vendor, data->specifier); pos += sizeof(*csuite); @@ -434,8 +439,8 @@ static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, data->vendor, data->specifier, - data->rand_client, data->rand_server, - data->id_client, data->id_client_len, + data->rand_peer, data->rand_server, + data->id_peer, data->id_peer_len, data->id_server, data->id_server_len, data->msk, data->emsk, data->sk, &data->sk_len, diff --git a/contrib/hostapd/eap_gpsk_common.c b/contrib/hostapd/eap_gpsk_common.c index a72b5f3da15f..7422fa6c48f9 100644 --- a/contrib/hostapd/eap_gpsk_common.c +++ b/contrib/hostapd/eap_gpsk_common.c @@ -18,8 +18,9 @@ #include "eap_defs.h" #include "aes_wrap.h" #include "crypto.h" -#include "sha1.h" +#ifdef EAP_GPSK_SHA256 #include "sha256.h" +#endif /* EAP_GPSK_SHA256 */ #include "eap_gpsk_common.h" @@ -43,31 +44,29 @@ int eap_gpsk_supported_ciphersuite(int vendor, int specifier) } -static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len, - const u8 *data /* Z */, size_t data_len, - u8 *buf, size_t len /* X */) +static int eap_gpsk_gkdf_cmac(const u8 *psk /* Y */, + const u8 *data /* Z */, size_t data_len, + u8 *buf, size_t len /* X */) { u8 *opos; size_t i, n, hashlen, left, clen; - u8 ibuf[2], hash[SHA1_MAC_LEN]; - const u8 *addr[3]; - size_t vlen[3]; + u8 ibuf[2], hash[16]; + const u8 *addr[2]; + size_t vlen[2]; - hashlen = SHA1_MAC_LEN; - /* M_i = Hash-Function (i || Y || Z); */ + hashlen = sizeof(hash); + /* M_i = MAC_Y (i || Z); (MAC = AES-CMAC-128) */ addr[0] = ibuf; vlen[0] = sizeof(ibuf); - addr[1] = psk; - vlen[1] = psk_len; - addr[2] = data; - vlen[2] = data_len; + addr[1] = data; + vlen[1] = data_len; opos = buf; left = len; n = (len + hashlen - 1) / hashlen; for (i = 1; i <= n; i++) { WPA_PUT_BE16(ibuf, i); - sha1_vector(3, addr, vlen, hash); + omac1_aes_128_vector(psk, 2, addr, vlen, hash); clen = left > hashlen ? hashlen : left; os_memcpy(opos, hash, clen); opos += clen; @@ -78,112 +77,30 @@ static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len, } -static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len, - const u8 *seed, size_t seed_len, - u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) -{ -#define EAP_GPSK_SK_LEN_AES 16 -#define EAP_GPSK_PK_LEN_AES 16 - u8 zero_string[1], mk[32], *pos, *data; - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES + - EAP_GPSK_PK_LEN_AES]; - size_t data_len; - - /* - * inputString = RAND_Client || ID_Client || RAND_Server || ID_Server - * (= seed) - * KS = 16, PL = psk_len, CSuite_Sel = 0x000000 0x000001 - * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-160 (MK, inputString)[0..63] - * EMSK = GKDF-160 (MK, inputString)[64..127] - * SK = GKDF-160 (MK, inputString)[128..143] - * PK = GKDF-160 (MK, inputString)[144..159] - * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel || - * inputString) - * Hash-Function = SHA-1 (see [RFC3174]) - * hashlen = 20 octets (160 bits) - */ - - os_memset(zero_string, 0, sizeof(zero_string)); - - data_len = 2 + psk_len + 6 + seed_len; - data = os_malloc(data_len); - if (data == NULL) - return -1; - pos = data; - WPA_PUT_BE16(pos, psk_len); - pos += 2; - os_memcpy(pos, psk, psk_len); - pos += psk_len; - WPA_PUT_BE24(pos, 0); /* CSuite/Vendor = IETF */ - pos += 3; - WPA_PUT_BE24(pos, EAP_GPSK_CIPHER_AES); /* CSuite/Specifier */ - pos += 3; - os_memcpy(pos, seed, seed_len); /* inputString */ - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation (AES)", - data, data_len); - - if (eap_gpsk_gkdf(zero_string, sizeof(zero_string), data, data_len, - mk, sizeof(mk)) < 0) { - os_free(data); - return -1; - } - os_free(data); - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, sizeof(mk)); - - if (eap_gpsk_gkdf(mk, sizeof(mk), seed, seed_len, - kdf_out, sizeof(kdf_out)) < 0) - return -1; - - pos = kdf_out; - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MSK", pos, EAP_MSK_LEN); - os_memcpy(msk, pos, EAP_MSK_LEN); - pos += EAP_MSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: EMSK", pos, EAP_EMSK_LEN); - os_memcpy(emsk, pos, EAP_EMSK_LEN); - pos += EAP_EMSK_LEN; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, EAP_GPSK_SK_LEN_AES); - os_memcpy(sk, pos, EAP_GPSK_SK_LEN_AES); - *sk_len = EAP_GPSK_SK_LEN_AES; - pos += EAP_GPSK_SK_LEN_AES; - - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, EAP_GPSK_PK_LEN_AES); - os_memcpy(pk, pos, EAP_GPSK_PK_LEN_AES); - *pk_len = EAP_GPSK_PK_LEN_AES; - - return 0; -} - - #ifdef EAP_GPSK_SHA256 -static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, size_t psk_len, +static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, const u8 *data /* Z */, size_t data_len, u8 *buf, size_t len /* X */) { u8 *opos; size_t i, n, hashlen, left, clen; u8 ibuf[2], hash[SHA256_MAC_LEN]; - const u8 *addr[3]; - size_t vlen[3]; + const u8 *addr[2]; + size_t vlen[2]; hashlen = SHA256_MAC_LEN; - /* M_i = Hash-Function (i || Y || Z); */ + /* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */ addr[0] = ibuf; vlen[0] = sizeof(ibuf); - addr[1] = psk; - vlen[1] = psk_len; - addr[2] = data; - vlen[2] = data_len; + addr[1] = data; + vlen[1] = data_len; opos = buf; left = len; n = (len + hashlen - 1) / hashlen; for (i = 1; i <= n; i++) { WPA_PUT_BE16(ibuf, i); - sha256_vector(3, addr, vlen, hash); + hmac_sha256_vector(psk, 32, 2, addr, vlen, hash); clen = left > hashlen ? hashlen : left; os_memcpy(opos, hash, clen); opos += clen; @@ -192,37 +109,40 @@ static int eap_gpsk_gkdf_sha256(const u8 *psk /* Y */, size_t psk_len, return 0; } +#endif /* EAP_GPSK_SHA256 */ -static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, +static int eap_gpsk_derive_keys_helper(u32 csuite_specifier, + u8 *kdf_out, size_t kdf_out_len, + const u8 *psk, size_t psk_len, const u8 *seed, size_t seed_len, u8 *msk, u8 *emsk, - u8 *sk, size_t *sk_len, - u8 *pk, size_t *pk_len) + u8 *sk, size_t sk_len, + u8 *pk, size_t pk_len) { -#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN -#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN - u8 mk[SHA256_MAC_LEN], zero_string[1], *pos, *data; - u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 + - EAP_GPSK_PK_LEN_SHA256]; - size_t data_len; + u8 mk[32], *pos, *data; + size_t data_len, mk_len; + int (*gkdf)(const u8 *psk, const u8 *data, size_t data_len, + u8 *buf, size_t len); - /* - * inputString = RAND_Client || ID_Client || RAND_Server || ID_Server - * (= seed) - * KS = 32, PL = psk_len, CSuite_Sel = 0x000000 0x000002 - * MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString) - * MSK = GKDF-192 (MK, inputString)[0..63] - * EMSK = GKDF-192 (MK, inputString)[64..127] - * SK = GKDF-192 (MK, inputString)[128..159] - * PK = GKDF-192 (MK, inputString)[160..191] - * MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel || - * inputString) - * Hash-Function = SHA256 (see [RFC4634]) - * hashlen = 32 octets (256 bits) - */ + gkdf = NULL; + switch (csuite_specifier) { + case EAP_GPSK_CIPHER_AES: + gkdf = eap_gpsk_gkdf_cmac; + mk_len = 16; + break; +#ifdef EAP_GPSK_SHA256 + case EAP_GPSK_CIPHER_SHA256: + gkdf = eap_gpsk_gkdf_sha256; + mk_len = SHA256_MAC_LEN; + break; +#endif /* EAP_GPSK_SHA256 */ + default: + return -1; + } - os_memset(zero_string, 0, sizeof(zero_string)); + if (psk_len < mk_len) + return -1; data_len = 2 + psk_len + 6 + seed_len; data = os_malloc(data_len); @@ -233,24 +153,22 @@ static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, pos += 2; os_memcpy(pos, psk, psk_len); pos += psk_len; - WPA_PUT_BE24(pos, 0); /* CSuite/Vendor = IETF */ - pos += 3; - WPA_PUT_BE24(pos, EAP_GPSK_CIPHER_SHA256); /* CSuite/Specifier */ - pos += 3; + WPA_PUT_BE32(pos, EAP_GPSK_VENDOR_IETF); /* CSuite/Vendor = IETF */ + pos += 4; + WPA_PUT_BE16(pos, csuite_specifier); /* CSuite/Specifier */ + pos += 2; os_memcpy(pos, seed, seed_len); /* inputString */ - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation (SHA256)", + wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation", data, data_len); - if (eap_gpsk_gkdf_sha256(zero_string, sizeof(zero_string), - data, data_len, mk, sizeof(mk)) < 0) { + if (gkdf(psk, data, data_len, mk, mk_len) < 0) { os_free(data); return -1; } os_free(data); - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, sizeof(mk)); + wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: MK", mk, mk_len); - if (eap_gpsk_gkdf_sha256(mk, sizeof(mk), seed, seed_len, - kdf_out, sizeof(kdf_out)) < 0) + if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 0) return -1; pos = kdf_out; @@ -262,46 +180,113 @@ static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, os_memcpy(emsk, pos, EAP_EMSK_LEN); pos += EAP_EMSK_LEN; - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", - pos, EAP_GPSK_SK_LEN_SHA256); - os_memcpy(sk, pos, EAP_GPSK_SK_LEN_SHA256); - *sk_len = EAP_GPSK_SK_LEN_AES; - pos += EAP_GPSK_SK_LEN_AES; + wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: SK", pos, sk_len); + os_memcpy(sk, pos, sk_len); + pos += sk_len; - wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", - pos, EAP_GPSK_PK_LEN_SHA256); - os_memcpy(pk, pos, EAP_GPSK_PK_LEN_SHA256); - *pk_len = EAP_GPSK_PK_LEN_SHA256; + if (pk) { + wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PK", pos, pk_len); + os_memcpy(pk, pos, pk_len); + } return 0; } + + +static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_len, + const u8 *seed, size_t seed_len, + u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, + u8 *pk, size_t *pk_len) +{ +#define EAP_GPSK_SK_LEN_AES 16 +#define EAP_GPSK_PK_LEN_AES 16 + u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_AES + + EAP_GPSK_PK_LEN_AES]; + + /* + * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server + * (= seed) + * KS = 16, PL = psk_len, CSuite_Sel = 0x00000000 0x0001 + * MK = GKDF-16 (PSK[0..15], PL || PSK || CSuite_Sel || inputString) + * MSK = GKDF-160 (MK, inputString)[0..63] + * EMSK = GKDF-160 (MK, inputString)[64..127] + * SK = GKDF-160 (MK, inputString)[128..143] + * PK = GKDF-160 (MK, inputString)[144..159] + * zero = 0x00 || 0x00 || ... || 0x00 (16 times) + * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || + * CSuite_Sel || inputString) + */ + + *sk_len = EAP_GPSK_SK_LEN_AES; + *pk_len = EAP_GPSK_PK_LEN_AES; + + return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_AES, + kdf_out, sizeof(kdf_out), + psk, psk_len, seed, seed_len, + msk, emsk, sk, *sk_len, + pk, *pk_len); +} + + +#ifdef EAP_GPSK_SHA256 +static int eap_gpsk_derive_keys_sha256(const u8 *psk, size_t psk_len, + const u8 *seed, size_t seed_len, + u8 *msk, u8 *emsk, + u8 *sk, size_t *sk_len) +{ +#define EAP_GPSK_SK_LEN_SHA256 SHA256_MAC_LEN +#define EAP_GPSK_PK_LEN_SHA256 SHA256_MAC_LEN + u8 kdf_out[EAP_MSK_LEN + EAP_EMSK_LEN + EAP_GPSK_SK_LEN_SHA256 + + EAP_GPSK_PK_LEN_SHA256]; + + /* + * inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server + * (= seed) + * KS = 32, PL = psk_len, CSuite_Sel = 0x00000000 0x0002 + * MK = GKDF-32 (PSK[0..31], PL || PSK || CSuite_Sel || inputString) + * MSK = GKDF-160 (MK, inputString)[0..63] + * EMSK = GKDF-160 (MK, inputString)[64..127] + * SK = GKDF-160 (MK, inputString)[128..159] + * zero = 0x00 || 0x00 || ... || 0x00 (32 times) + * Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type || + * CSuite_Sel || inputString) + */ + + *sk_len = EAP_GPSK_SK_LEN_SHA256; + + return eap_gpsk_derive_keys_helper(EAP_GPSK_CIPHER_SHA256, + kdf_out, sizeof(kdf_out), + psk, psk_len, seed, seed_len, + msk, emsk, sk, *sk_len, + NULL, 0); +} #endif /* EAP_GPSK_SHA256 */ /** * eap_gpsk_derive_keys - Derive EAP-GPSK keys - * @psk: Pre-shared key (at least 16 bytes if AES is used) + * @psk: Pre-shared key * @psk_len: Length of psk in bytes * @vendor: CSuite/Vendor * @specifier: CSuite/Specifier - * @rand_client: 32-byte RAND_Client + * @rand_peer: 32-byte RAND_Peer * @rand_server: 32-byte RAND_Server - * @id_client: ID_Client - * @id_client_len: Length of ID_Client + * @id_peer: ID_Peer + * @id_peer_len: Length of ID_Peer * @id_server: ID_Server * @id_server_len: Length of ID_Server * @msk: Buffer for 64-byte MSK * @emsk: Buffer for 64-byte EMSK * @sk: Buffer for SK (at least EAP_GPSK_MAX_SK_LEN bytes) * @sk_len: Buffer for returning length of SK - * @pk: Buffer for SK (at least EAP_GPSK_MAX_PK_LEN bytes) + * @pk: Buffer for PK (at least EAP_GPSK_MAX_PK_LEN bytes) * @pk_len: Buffer for returning length of PK * Returns: 0 on success, -1 on failure */ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, int specifier, - const u8 *rand_client, const u8 *rand_server, - const u8 *id_client, size_t id_client_len, + const u8 *rand_peer, const u8 *rand_server, + const u8 *id_peer, size_t id_peer_len, const u8 *id_server, size_t id_server_len, u8 *msk, u8 *emsk, u8 *sk, size_t *sk_len, u8 *pk, size_t *pk_len) @@ -318,8 +303,8 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: PSK", psk, psk_len); - /* Seed = RAND_Client || ID_Client || RAND_Server || ID_Server */ - seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_client_len; + /* Seed = RAND_Peer || ID_Peer || RAND_Server || ID_Server */ + seed_len = 2 * EAP_GPSK_RAND_LEN + id_server_len + id_peer_len; seed = os_malloc(seed_len); if (seed == NULL) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to allocate memory " @@ -328,10 +313,10 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, } pos = seed; - os_memcpy(pos, rand_client, EAP_GPSK_RAND_LEN); + os_memcpy(pos, rand_peer, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; - os_memcpy(pos, id_client, id_client_len); - pos += id_client_len; + os_memcpy(pos, id_peer, id_peer_len); + pos += id_peer_len; os_memcpy(pos, rand_server, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; os_memcpy(pos, id_server, id_server_len); @@ -347,8 +332,7 @@ int eap_gpsk_derive_keys(const u8 *psk, size_t psk_len, int vendor, #ifdef EAP_GPSK_SHA256 case EAP_GPSK_CIPHER_SHA256: ret = eap_gpsk_derive_keys_sha256(psk, psk_len, seed, seed_len, - msk, emsk, sk, sk_len, - pk, pk_len); + msk, emsk, sk, sk_len); break; #endif /* EAP_GPSK_SHA256 */ default: diff --git a/contrib/hostapd/eap_gpsk_common.h b/contrib/hostapd/eap_gpsk_common.h index c806b7f85217..a30ab97ffa07 100644 --- a/contrib/hostapd/eap_gpsk_common.h +++ b/contrib/hostapd/eap_gpsk_common.h @@ -32,7 +32,7 @@ #define EAP_GPSK_MAX_PK_LEN 32 #define EAP_GPSK_MAX_MIC_LEN 32 -#define EAP_GPSK_VENDOR_IETF 0x000000 +#define EAP_GPSK_VENDOR_IETF 0x00000000 #define EAP_GPSK_CIPHER_RESERVED 0x000000 #define EAP_GPSK_CIPHER_AES 0x000001 #define EAP_GPSK_CIPHER_SHA256 0x000002 @@ -43,8 +43,8 @@ #endif /* _MSC_VER */ struct eap_gpsk_csuite { - u8 vendor[3]; - u8 specifier[3]; + u8 vendor[4]; + u8 specifier[2]; } STRUCT_PACKED; #ifdef _MSC_VER diff --git a/contrib/hostapd/eap_sim.c b/contrib/hostapd/eap_sim.c index 8c3c82870036..3db24923d43f 100644 --- a/contrib/hostapd/eap_sim.c +++ b/contrib/hostapd/eap_sim.c @@ -1,6 +1,6 @@ /* * hostapd / EAP-SIM (RFC 4186) - * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -110,6 +110,13 @@ static u8 * eap_sim_build_start(struct eap_sm *sm, struct eap_sim_data *data, sm->identity_len)) { wpa_printf(MSG_DEBUG, " AT_PERMANENT_ID_REQ"); eap_sim_msg_add(msg, EAP_SIM_AT_PERMANENT_ID_REQ, 0, NULL, 0); + } else { + /* + * RFC 4186, Chap. 4.2.4 recommends that identity from EAP is + * ignored and the SIM/Start is used to request the identity. + */ + wpa_printf(MSG_DEBUG, " AT_ANY_ID_REQ"); + eap_sim_msg_add(msg, EAP_SIM_AT_ANY_ID_REQ, 0, NULL, 0); } wpa_printf(MSG_DEBUG, " AT_VERSION_LIST"); ver[0] = 0; @@ -331,20 +338,6 @@ static void eap_sim_process_start(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-SIM: Receive start response"); - if (attr->nonce_mt == NULL || attr->selected_version < 0) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " - "required attributes"); - eap_sim_state(data, FAILURE); - return; - } - - if (!eap_sim_supported_ver(data, attr->selected_version)) { - wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " - "version %d", attr->selected_version); - eap_sim_state(data, FAILURE); - return; - } - if (attr->identity) { free(sm->identity); sm->identity = malloc(attr->identity_len); @@ -398,6 +391,20 @@ static void eap_sim_process_start(struct eap_sm *sm, return; } + if (attr->nonce_mt == NULL || attr->selected_version < 0) { + wpa_printf(MSG_DEBUG, "EAP-SIM: Start/Response missing " + "required attributes"); + eap_sim_state(data, FAILURE); + return; + } + + if (!eap_sim_supported_ver(data, attr->selected_version)) { + wpa_printf(MSG_DEBUG, "EAP-SIM: Peer selected unsupported " + "version %d", attr->selected_version); + eap_sim_state(data, FAILURE); + return; + } + data->counter = 0; /* reset re-auth counter since this is full auth */ data->reauth = NULL; @@ -418,12 +425,18 @@ static void eap_sim_process_start(struct eap_sm *sm, return; } + identity_len = sm->identity_len; + while (identity_len > 0 && sm->identity[identity_len - 1] == '\0') { + wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop last null " + "character from identity"); + identity_len--; + } wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Identity for MK derivation", - sm->identity, sm->identity_len); + sm->identity, identity_len); memcpy(data->nonce_mt, attr->nonce_mt, EAP_SIM_NONCE_MT_LEN); WPA_PUT_BE16(ver_list, EAP_SIM_VERSION); - eap_sim_derive_mk(sm->identity, sm->identity_len, attr->nonce_mt, + eap_sim_derive_mk(sm->identity, identity_len, attr->nonce_mt, attr->selected_version, ver_list, sizeof(ver_list), data->num_chal, (const u8 *) data->kc, data->mk); eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, diff --git a/contrib/hostapd/eap_sim_common.c b/contrib/hostapd/eap_sim_common.c index dc8b2f6f4b10..cc430239ab97 100644 --- a/contrib/hostapd/eap_sim_common.c +++ b/contrib/hostapd/eap_sim_common.c @@ -1,6 +1,6 @@ /* * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -118,6 +118,11 @@ int eap_sim_derive_keys_reauth(u16 _counter, const u8 *addr[4]; size_t len[4]; + while (identity_len > 0 && identity[identity_len - 1] == 0) { + wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null " + "character from the end of identity"); + identity_len--; + } addr[0] = identity; len[0] = identity_len; addr[1] = counter; @@ -250,6 +255,10 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end, pos, pos[1] * 4, end); return -1; } + if (pos[1] == 0) { + wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow"); + return -1; + } apos = pos + 2; alen = pos[1] * 4 - 2; wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data", diff --git a/contrib/hostapd/eap_sim_db.c b/contrib/hostapd/eap_sim_db.c index 93ade144fa4f..59c11ac15142 100644 --- a/contrib/hostapd/eap_sim_db.c +++ b/contrib/hostapd/eap_sim_db.c @@ -554,8 +554,7 @@ int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, size_t i; char msg[40]; - if (identity_len < 2 || identity[0] != EAP_SIM_PERMANENT_PREFIX || - identity_len + 1 > sizeof(entry->imsi)) { + if (identity_len < 2 || identity[0] != EAP_SIM_PERMANENT_PREFIX) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", identity, identity_len); return EAP_SIM_DB_FAILURE; @@ -568,6 +567,11 @@ int eap_sim_db_get_gsm_triplets(void *priv, const u8 *identity, break; } } + if (identity_len + 1 > sizeof(entry->imsi)) { + wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", + identity, identity_len); + return EAP_SIM_DB_FAILURE; + } wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get GSM triplets for IMSI", identity, identity_len); @@ -1117,8 +1121,7 @@ int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, char msg[40]; if (identity_len < 2 || identity == NULL || - identity[0] != EAP_AKA_PERMANENT_PREFIX || - identity_len + 1 > sizeof(entry->imsi)) { + identity[0] != EAP_AKA_PERMANENT_PREFIX) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", identity, identity_len); return EAP_SIM_DB_FAILURE; @@ -1131,6 +1134,11 @@ int eap_sim_db_get_aka_auth(void *priv, const u8 *identity, break; } } + if (identity_len + 1 > sizeof(entry->imsi)) { + wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", + identity, identity_len); + return EAP_SIM_DB_FAILURE; + } wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: Get AKA auth for IMSI", identity, identity_len); @@ -1213,9 +1221,23 @@ int eap_sim_db_resynchronize(void *priv, const u8 *identity, const u8 *_rand) { struct eap_sim_db_data *data = priv; + size_t i; - if (identity_len < 2 || identity[0] != EAP_AKA_PERMANENT_PREFIX || - identity_len > 20) { + if (identity_len < 2 || identity == NULL || + identity[0] != EAP_AKA_PERMANENT_PREFIX) { + wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", + identity, identity_len); + return -1; + } + identity++; + identity_len--; + for (i = 0; i < identity_len; i++) { + if (identity[i] == '@') { + identity_len = i; + break; + } + } + if (identity_len > 20) { wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM DB: unexpected identity", identity, identity_len); return -1; @@ -1226,10 +1248,10 @@ int eap_sim_db_resynchronize(void *priv, const u8 *identity, int len, ret; len = snprintf(msg, sizeof(msg), "AKA-AUTS "); - if (len < 0 || len + identity_len - 1 >= sizeof(msg)) + if (len < 0 || len + identity_len >= sizeof(msg)) return -1; - memcpy(msg + len, identity + 1, identity_len - 1); - len += identity_len - 1; + memcpy(msg + len, identity, identity_len); + len += identity_len; ret = snprintf(msg + len, sizeof(msg) - len, " "); if (ret < 0 || (size_t) ret >= sizeof(msg) - len) @@ -1244,7 +1266,7 @@ int eap_sim_db_resynchronize(void *priv, const u8 *identity, len += wpa_snprintf_hex(msg + len, sizeof(msg) - len, _rand, EAP_AKA_RAND_LEN); wpa_hexdump(MSG_DEBUG, "EAP-SIM DB: reporting AKA AUTS for " - "IMSI", identity + 1, identity_len - 1); + "IMSI", identity, identity_len); if (eap_sim_db_send(data, msg, len) < 0) return -1; } diff --git a/contrib/hostapd/eap_tls_common.c b/contrib/hostapd/eap_tls_common.c index 2a089d4d26a0..ce61729bc944 100644 --- a/contrib/hostapd/eap_tls_common.c +++ b/contrib/hostapd/eap_tls_common.c @@ -113,6 +113,11 @@ int eap_tls_data_reassemble(struct eap_sm *sm, struct eap_ssl_data *data, u8 *buf; if (data->tls_in_left > *in_len || data->tls_in) { + if (*in_len == 0) { + wpa_printf(MSG_INFO, "SSL: Empty fragment when trying " + "to reassemble"); + return -1; + } if (data->tls_in_len + *in_len > 65536) { /* Limit length to avoid rogue peers from causing large * memory allocations. */ diff --git a/contrib/hostapd/hostapd.c b/contrib/hostapd/hostapd.c index d4cd488eb5c0..87a552379646 100644 --- a/contrib/hostapd/hostapd.c +++ b/contrib/hostapd/hostapd.c @@ -1,6 +1,6 @@ /* * hostapd / Initialization and configuration - * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -1576,7 +1576,7 @@ static void show_version(void) "hostapd v" VERSION_STR "\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" - "Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi> " + "Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> " "and contributors\n"); } diff --git a/contrib/hostapd/hostapd.conf b/contrib/hostapd/hostapd.conf index 986ca26c0597..d8ebe164f927 100644 --- a/contrib/hostapd/hostapd.conf +++ b/contrib/hostapd/hostapd.conf @@ -388,7 +388,7 @@ wme_ac_vo_acm=0 # Optional displayable message sent with EAP Request-Identity. The first \0 # in this string will be converted to ASCII-0 (nul). This can be used to # separate network info (comma separated list of attribute=value pairs); see, -# e.g., draft-adrangi-eap-network-discovery-07.txt. +# e.g., RFC 4284. #eap_message=hello #eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com diff --git a/contrib/hostapd/ieee802_11.c b/contrib/hostapd/ieee802_11.c index 6dec28918320..817c30e2ae84 100644 --- a/contrib/hostapd/ieee802_11.c +++ b/contrib/hostapd/ieee802_11.c @@ -1436,8 +1436,8 @@ static void handle_assoc_cb(struct hostapd_data *hapd, return; } - if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : - sizeof(mgmt->u.assoc_req))) { + if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) : + sizeof(mgmt->u.assoc_resp))) { printf("handle_assoc_cb(reassoc=%d) - too short payload " "(len=%lu)\n", reassoc, (unsigned long) len); return; diff --git a/contrib/hostapd/ieee802_1x.c b/contrib/hostapd/ieee802_1x.c index a7c726409658..bbd1c1e65bca 100644 --- a/contrib/hostapd/ieee802_1x.c +++ b/contrib/hostapd/ieee802_1x.c @@ -1676,6 +1676,8 @@ int ieee802_1x_init(struct hostapd_data *hapd) void ieee802_1x_deinit(struct hostapd_data *hapd) { + eloop_cancel_timeout(ieee802_1x_rekey, hapd, NULL); + if (hapd->driver != NULL && (hapd->conf->ieee802_1x || hapd->conf->wpa)) hostapd_set_ieee8021x(hapd->conf->iface, hapd, 0); diff --git a/contrib/hostapd/madwifi.conf b/contrib/hostapd/madwifi.conf index a9bf539d236b..ed3704fcb634 100644 --- a/contrib/hostapd/madwifi.conf +++ b/contrib/hostapd/madwifi.conf @@ -59,7 +59,7 @@ ssid=wpa-test # Optional displayable message sent with EAP Request-Identity. The first \0 # in this string will be converted to ASCII-0 (nul). This can be used to # separate network info (comma separated list of attribute=value pairs); see, -# e.g., draft-adrangi-eap-network-discovery-07.txt. +# e.g., RFC 4284. #eap_message=hello #eap_message=hello\0networkid=netw,nasid=foo,portid=0,NAIRealms=example.com diff --git a/contrib/hostapd/os.h b/contrib/hostapd/os.h index 4931adb2b8c2..25570a5e171a 100644 --- a/contrib/hostapd/os.h +++ b/contrib/hostapd/os.h @@ -63,6 +63,9 @@ int os_get_time(struct os_time *t); * @t: Buffer for returning calendar time representation (seconds since * 1970-01-01 00:00:00) * Returns: 0 on success, -1 on failure + * + * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time + * which is used by POSIX mktime(). */ int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t); diff --git a/contrib/hostapd/os_unix.c b/contrib/hostapd/os_unix.c index fb8149a7f3b9..69ba25a3e856 100644 --- a/contrib/hostapd/os_unix.c +++ b/contrib/hostapd/os_unix.c @@ -39,7 +39,9 @@ int os_get_time(struct os_time *t) int os_mktime(int year, int month, int day, int hour, int min, int sec, os_time_t *t) { - struct tm tm; + struct tm tm, *tm1; + time_t t_local, t1, t2; + os_time_t tz_offset; if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || @@ -54,7 +56,22 @@ int os_mktime(int year, int month, int day, int hour, int min, int sec, tm.tm_min = min; tm.tm_sec = sec; - *t = (os_time_t) mktime(&tm); + t_local = mktime(&tm); + + /* figure out offset to UTC */ + tm1 = localtime(&t_local); + if (tm1) { + t1 = mktime(tm1); + tm1 = gmtime(&t_local); + if (tm1) { + t2 = mktime(tm1); + tz_offset = t2 - t1; + } else + tz_offset = 0; + } else + tz_offset = 0; + + *t = (os_time_t) t_local - tz_offset; return 0; } diff --git a/contrib/hostapd/radius.c b/contrib/hostapd/radius.c index bf39b2fc42e8..743f3400f1de 100644 --- a/contrib/hostapd/radius.c +++ b/contrib/hostapd/radius.c @@ -1,6 +1,6 @@ /* * hostapd / RADIUS message processing - * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi> + * Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -138,6 +138,7 @@ static struct radius_attr_type radius_attrs[] = { RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id", RADIUS_ATTR_TEXT }, { RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT }, + { RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST }, { RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type", RADIUS_ATTR_INT32 }, { RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 }, @@ -230,8 +231,9 @@ static void radius_msg_dump_attr(struct radius_attr_hdr *hdr) case RADIUS_ATTR_IP: if (len == 4) { - struct in_addr *addr = (struct in_addr *) pos; - printf(" Value: %s\n", inet_ntoa(*addr)); + struct in_addr addr; + os_memcpy(&addr, pos, 4); + printf(" Value: %s\n", inet_ntoa(addr)); } else printf(" Invalid IP address length %d\n", len); break; @@ -664,24 +666,21 @@ int radius_msg_verify(struct radius_msg *msg, const u8 *secret, int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src, u8 type) { - struct radius_attr_hdr *attr = NULL; + struct radius_attr_hdr *attr; size_t i; + int count = 0; for (i = 0; i < src->attr_used; i++) { - if (src->attrs[i]->type == type) { - attr = src->attrs[i]; - break; + attr = src->attrs[i]; + if (attr->type == type) { + if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1), + attr->length - sizeof(*attr))) + return -1; + count++; } } - if (attr == NULL) - return 0; - - if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1), - attr->length - sizeof(*attr))) - return -1; - - return 1; + return count; } diff --git a/contrib/hostapd/radius.h b/contrib/hostapd/radius.h index d1b909da98bf..d4375376a94f 100644 --- a/contrib/hostapd/radius.h +++ b/contrib/hostapd/radius.h @@ -62,6 +62,7 @@ enum { RADIUS_ATTR_USER_NAME = 1, RADIUS_ATTR_CALLED_STATION_ID = 30, RADIUS_ATTR_CALLING_STATION_ID = 31, RADIUS_ATTR_NAS_IDENTIFIER = 32, + RADIUS_ATTR_PROXY_STATE = 33, RADIUS_ATTR_ACCT_STATUS_TYPE = 40, RADIUS_ATTR_ACCT_DELAY_TIME = 41, RADIUS_ATTR_ACCT_INPUT_OCTETS = 42, diff --git a/contrib/hostapd/radius_client.c b/contrib/hostapd/radius_client.c index 5b00bbeb8577..81cd9c58b16b 100644 --- a/contrib/hostapd/radius_client.c +++ b/contrib/hostapd/radius_client.c @@ -142,7 +142,8 @@ static void radius_client_handle_send_error(struct radius_client_data *radius, #ifndef CONFIG_NATIVE_WINDOWS int _errno = errno; perror("send[RADIUS]"); - if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL) { + if (_errno == ENOTCONN || _errno == EDESTADDRREQ || _errno == EINVAL || + _errno == EBADF) { hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "Send failed - maybe interface status changed -" @@ -451,6 +452,13 @@ int radius_client_send(struct radius_client_data *radius, } if (msg_type == RADIUS_ACCT || msg_type == RADIUS_ACCT_INTERIM) { + if (conf->acct_server == NULL) { + hostapd_logger(radius->ctx, NULL, + HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, + "No accounting server configured"); + return -1; + } shared_secret = conf->acct_server->shared_secret; shared_secret_len = conf->acct_server->shared_secret_len; radius_msg_finish_acct(msg, shared_secret, shared_secret_len); @@ -458,6 +466,13 @@ int radius_client_send(struct radius_client_data *radius, s = radius->acct_sock; conf->acct_server->requests++; } else { + if (conf->auth_server == NULL) { + hostapd_logger(radius->ctx, NULL, + HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, + "No authentication server configured"); + return -1; + } shared_secret = conf->auth_server->shared_secret; shared_secret_len = conf->auth_server->shared_secret_len; radius_msg_finish(msg, shared_secret, shared_secret_len); diff --git a/contrib/hostapd/radius_server.c b/contrib/hostapd/radius_server.c index bb78f751640c..409d537f42ab 100644 --- a/contrib/hostapd/radius_server.c +++ b/contrib/hostapd/radius_server.c @@ -1,6 +1,6 @@ /* * hostapd / RADIUS authentication server - * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi> + * Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -376,6 +376,13 @@ radius_server_encapsulate_eap(struct radius_server_data *data, } } + if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { + RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); + radius_msg_free(msg); + os_free(msg); + return NULL; + } + if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, request->hdr->authenticator) < 0) { @@ -414,6 +421,12 @@ static int radius_server_reject(struct radius_server_data *data, RADIUS_DEBUG("Failed to add EAP-Message attribute"); } + if (radius_msg_copy_attr(msg, request, RADIUS_ATTR_PROXY_STATE) < 0) { + RADIUS_DEBUG("Failed to copy Proxy-State attribute(s)"); + radius_msg_free(msg); + os_free(msg); + return -1; + } if (radius_msg_finish_srv(msg, (u8 *) client->shared_secret, client->shared_secret_len, diff --git a/contrib/hostapd/tls_openssl.c b/contrib/hostapd/tls_openssl.c index c8d941f7a113..d5aafaaa89d4 100644 --- a/contrib/hostapd/tls_openssl.c +++ b/contrib/hostapd/tls_openssl.c @@ -1095,6 +1095,18 @@ static int tls_connection_ca_cert(void *_ssl_ctx, struct tls_connection *conn, { SSL_CTX *ssl_ctx = _ssl_ctx; + /* + * Remove previously configured trusted CA certificates before adding + * new ones. + */ + X509_STORE_free(ssl_ctx->cert_store); + ssl_ctx->cert_store = X509_STORE_new(); + if (ssl_ctx->cert_store == NULL) { + wpa_printf(MSG_DEBUG, "OpenSSL: %s - failed to allocate new " + "certificate store", __func__); + return -1; + } + if (ca_cert_blob) { X509 *cert = d2i_X509(NULL, (OPENSSL_d2i_TYPE) &ca_cert_blob, ca_cert_blob_len); @@ -2272,7 +2284,11 @@ int tls_connection_get_keyblock_size(void *tls_ctx, return -1; c = conn->ssl->enc_read_ctx->cipher; +#if OPENSSL_VERSION_NUMBER >= 0x00909000L + h = EVP_MD_CTX_md(conn->ssl->read_hash); +#else h = conn->ssl->read_hash; +#endif return 2 * (EVP_CIPHER_key_length(c) + EVP_MD_size(h) + diff --git a/contrib/hostapd/version.h b/contrib/hostapd/version.h index 2eed290d1b92..364d8aea9657 100644 --- a/contrib/hostapd/version.h +++ b/contrib/hostapd/version.h @@ -1,6 +1,6 @@ #ifndef VERSION_H #define VERSION_H -#define VERSION_STR "0.5.8" +#define VERSION_STR "0.5.10" #endif /* VERSION_H */ diff --git a/contrib/hostapd/wpa.c b/contrib/hostapd/wpa.c index 1f66a3e5644a..b92cb2fbac63 100644 --- a/contrib/hostapd/wpa.c +++ b/contrib/hostapd/wpa.c @@ -1,6 +1,6 @@ /* * hostapd - IEEE 802.11i-2004 / WPA Authenticator - * Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> + * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -105,7 +105,6 @@ struct wpa_state_machine { unsigned int in_step_loop:1; unsigned int pending_deinit:1; unsigned int started:1; - unsigned int sta_counted:1; unsigned int mgmt_frame_prot:1; u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; @@ -134,7 +133,6 @@ struct wpa_group { int vlan_id; Boolean GInit; - int GNoStations; int GKeyDoneStations; Boolean GTKReKey; int GTK_len; @@ -2685,14 +2683,6 @@ SM_STATE(WPA_PTK, DISCONNECT) SM_STATE(WPA_PTK, DISCONNECTED) { SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); - if (sm->sta_counted) { - sm->group->GNoStations--; - sm->sta_counted = 0; - } else { - wpa_printf(MSG_DEBUG, "WPA: WPA_PTK::DISCONNECTED - did not " - "decrease GNoStations (STA " MACSTR ")", - MAC2STR(sm->addr)); - } sm->DeauthenticationRequest = FALSE; } @@ -2700,14 +2690,6 @@ SM_STATE(WPA_PTK, DISCONNECTED) SM_STATE(WPA_PTK, AUTHENTICATION) { SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); - if (!sm->sta_counted) { - sm->group->GNoStations++; - sm->sta_counted = 1; - } else { - wpa_printf(MSG_DEBUG, "WPA: WPA_PTK::DISCONNECTED - did not " - "increase GNoStations (STA " MACSTR ")", - MAC2STR(sm->addr)); - } memset(&sm->PTK, 0, sizeof(sm->PTK)); sm->PTK_valid = FALSE; wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, @@ -3219,8 +3201,9 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) { SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); sm->EAPOLKeyReceived = FALSE; + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; - sm->group->GKeyDoneStations--; sm->GTimeoutCtr = 0; /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, @@ -3233,7 +3216,8 @@ SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) SM_STATE(WPA_PTK_GROUP, KEYERROR) { SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); - sm->group->GKeyDoneStations--; + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; sm->Disconnect = TRUE; } @@ -3309,6 +3293,12 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) { + if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "Not in PTKINITDONE; skip Group Key update"); + return 0; + } + sm->group->GKeyDoneStations++; sm->GUpdateStationKeys = TRUE; wpa_sm_step(sm); return 0; @@ -3328,10 +3318,14 @@ static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, tmp = group->GM; group->GM = group->GN; group->GN = tmp; - group->GKeyDoneStations = group->GNoStations; + /* "GKeyDoneStations = GNoStations" is done in more robust way by + * counting the STAs that are marked with GUpdateStationKeys instead of + * including all STAs that could be in not-yet-completed state. */ wpa_gtk_update(wpa_auth, group); wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, NULL); + wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", + group->GKeyDoneStations); } @@ -3780,13 +3774,6 @@ int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); - if (sm->group && sm->group != group && sm->sta_counted) { - sm->group->GNoStations--; - sm->sta_counted = 0; - wpa_printf(MSG_DEBUG, "WLA: Decreased GNoStations for the " - "previously used group state machine"); - } - sm->group = group; return 0; } |