From 153f9c1cd9a5b749f57e28682fadb39c781e1e5d Mon Sep 17 00:00:00 2001 From: sam Date: Mon, 24 Mar 2008 19:46:53 +0000 Subject: Import of WPA supplicant 0.5.10 --- contrib/wpa_supplicant/ChangeLog | 41 ++ contrib/wpa_supplicant/Makefile | 25 +- contrib/wpa_supplicant/README | 5 +- contrib/wpa_supplicant/aes_wrap.c | 77 +++- contrib/wpa_supplicant/aes_wrap.h | 4 +- contrib/wpa_supplicant/asn1.c | 6 +- contrib/wpa_supplicant/common.c | 28 +- contrib/wpa_supplicant/common.h | 4 +- contrib/wpa_supplicant/config.c | 13 +- contrib/wpa_supplicant/config_ssid.h | 12 + contrib/wpa_supplicant/ctrl_iface.c | 7 + contrib/wpa_supplicant/ctrl_iface_dbus.c | 25 +- contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c | 126 +++++++ contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h | 6 + contrib/wpa_supplicant/ctrl_iface_unix.c | 39 +- contrib/wpa_supplicant/dbus-wpa_supplicant.conf | 4 - contrib/wpa_supplicant/dbus-wpa_supplicant.service | 4 + contrib/wpa_supplicant/defconfig | 7 +- contrib/wpa_supplicant/doc/ctrl_iface.doxygen | 9 +- .../wpa_supplicant/doc/docbook/wpa_background.8 | 2 +- contrib/wpa_supplicant/doc/docbook/wpa_cli.8 | 4 +- contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml | 2 +- .../wpa_supplicant/doc/docbook/wpa_passphrase.8 | 2 +- .../wpa_supplicant/doc/docbook/wpa_supplicant.8 | 7 +- .../doc/docbook/wpa_supplicant.conf.5 | 2 +- .../wpa_supplicant/doc/docbook/wpa_supplicant.sgml | 10 +- contrib/wpa_supplicant/driver_ndis.c | 2 +- contrib/wpa_supplicant/eap_gpsk.c | 415 +++++++++++++++------ contrib/wpa_supplicant/eap_gpsk_common.c | 304 +++++++-------- contrib/wpa_supplicant/eap_gpsk_common.h | 6 +- contrib/wpa_supplicant/eap_peap.c | 21 +- contrib/wpa_supplicant/eap_sim.c | 18 +- contrib/wpa_supplicant/eap_sim_common.c | 11 +- contrib/wpa_supplicant/eap_tlv.c | 16 +- contrib/wpa_supplicant/eap_tlv.h | 5 +- contrib/wpa_supplicant/eapol_sm.c | 12 +- contrib/wpa_supplicant/eapol_test.c | 6 +- contrib/wpa_supplicant/events.c | 13 +- contrib/wpa_supplicant/main.c | 15 +- contrib/wpa_supplicant/os.h | 3 + contrib/wpa_supplicant/os_unix.c | 21 +- contrib/wpa_supplicant/pcsc_funcs.c | 32 +- contrib/wpa_supplicant/radius.c | 29 +- contrib/wpa_supplicant/radius.h | 1 + contrib/wpa_supplicant/radius_client.c | 17 +- contrib/wpa_supplicant/tests/test_aes.c | 306 +++++++++++++++ contrib/wpa_supplicant/tests/test_eap_sim_common.c | 53 +++ contrib/wpa_supplicant/tests/test_md4.c | 99 +++++ contrib/wpa_supplicant/tests/test_md5.c | 99 +++++ contrib/wpa_supplicant/tests/test_ms_funcs.c | 119 ++++++ contrib/wpa_supplicant/tests/test_sha1.c | 328 ++++++++++++++++ contrib/wpa_supplicant/tests/test_sha256.c | 330 ++++++++++++++++ contrib/wpa_supplicant/tests/test_x509v3.c | 69 ++++ contrib/wpa_supplicant/tls_openssl.c | 16 + contrib/wpa_supplicant/version.h | 2 +- contrib/wpa_supplicant/wpa.c | 4 - contrib/wpa_supplicant/wpa_cli.c | 122 +++--- .../wpa_supplicant/wpa_gui-qt4/networkconfig.cpp | 2 +- contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp | 4 +- contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h | 2 +- .../wpa_gui/setup-mingw-cross-compiling | 6 +- contrib/wpa_supplicant/wpa_gui/wpagui.ui.h | 2 +- contrib/wpa_supplicant/wpa_supplicant.c | 25 +- contrib/wpa_supplicant/wpa_supplicant.conf | 8 + contrib/wpa_supplicant/wpa_supplicant_i.h | 4 +- contrib/wpa_supplicant/x509v3.c | 96 ++++- 66 files changed, 2609 insertions(+), 505 deletions(-) create mode 100644 contrib/wpa_supplicant/dbus-wpa_supplicant.service create mode 100644 contrib/wpa_supplicant/tests/test_aes.c create mode 100644 contrib/wpa_supplicant/tests/test_eap_sim_common.c create mode 100644 contrib/wpa_supplicant/tests/test_md4.c create mode 100644 contrib/wpa_supplicant/tests/test_md5.c create mode 100644 contrib/wpa_supplicant/tests/test_ms_funcs.c create mode 100644 contrib/wpa_supplicant/tests/test_sha1.c create mode 100644 contrib/wpa_supplicant/tests/test_sha256.c create mode 100644 contrib/wpa_supplicant/tests/test_x509v3.c (limited to 'contrib') diff --git a/contrib/wpa_supplicant/ChangeLog b/contrib/wpa_supplicant/ChangeLog index 5bf3660..1ba2e1c 100644 --- a/contrib/wpa_supplicant/ChangeLog +++ b/contrib/wpa_supplicant/ChangeLog @@ -1,5 +1,46 @@ ChangeLog for wpa_supplicant +2008-02-19 - v0.5.10 + * added support for Makefile builds to include debug-log-to-a-file + functionality (CONFIG_DEBUG_FILE=y and -f on command line) + * added network configuration parameter 'frequency' for setting + initial channel for IBSS (adhoc) networks + * fixed EAP-SIM and EAP-AKA message parser to validate attribute + lengths properly to avoid potential crash caused by invalid messages + * added driver_wext workaround for race condition between scanning and + association with drivers that take very long time to scan all + channels (e.g., madwifi with dual-band cards); wpa_supplicant is now + using a longer hardcoded timeout for the scan if the driver supports + notifications for scan completion (SIOCGIWSCAN event); this helps, + e.g., in cases where wpa_supplicant and madwifi driver ended up in + loop where the driver did not even try to associate + * fixed EAP-SIM not to include AT_NONCE_MT and AT_SELECTED_VERSION + attributes in EAP-SIM Start/Response when using fast reauthentication + * fixed problems in getting NDIS events from WMI on Windows 2000 + +2007-12-02 - v0.5.9 + * fixed an integer overflow issue in the ASN.1 parser used by the + (experimental) internal TLS implementation to avoid a potential + buffer read overflow + * fixed a race condition with -W option (wait for a control interface + monitor before starting) that could have caused the first messages to + be lost + * updated EAP Generalized Pre-Shared Key (EAP-GPSK) to use the latest + draft (draft-ietf-emu-eap-gpsk-07.txt) + * added ctrl_iface RECONNECT (wpa_cli reconnect) command + (like reassociate, but only takes effect if already associated) + * fixed a possible race condition between wpa_cli reassociate and + wpa_cli disconnect + * return a non-zero exit code from non-interactive wpa_cli if the + command is not recognized or fails + * fixed 0.5.8 regressions in BSS selection that prevented wildcard SSID + from being used with non-WPA networks and disabled workaround for + ignoring bogus WPA/RSN IE in non-WPA configuration + * fixed OpenSSL TLS wrapper to clear trusted CA list to allow + network blocks to use different trusted CA configurations + * fixed a potential EAP state machine loop when mloving from PSK to EAP + configuration without restarting wpa_supplicant + 2007-05-28 - v0.5.8 * updated driver_wext.c to build with the current wireless-dev.git tree and net/d80211 changes diff --git a/contrib/wpa_supplicant/Makefile b/contrib/wpa_supplicant/Makefile index f29eb69..51114fa 100644 --- a/contrib/wpa_supplicant/Makefile +++ b/contrib/wpa_supplicant/Makefile @@ -654,8 +654,25 @@ endif ifdef CONFIG_CTRL_IFACE_DBUS CFLAGS += -DCONFIG_CTRL_IFACE_DBUS -DDBUS_API_SUBJECT_TO_CHANGE OBJS += ctrl_iface_dbus.o ctrl_iface_dbus_handlers.o dbus_dict_helpers.o -LIBS += `pkg-config --libs dbus-1` -CFLAGS += `pkg-config --cflags dbus-1` +ifndef DBUS_LIBS +DBUS_LIBS := $(shell pkg-config --libs dbus-1) +endif +LIBS += $(DBUS_LIBS) +ifndef DBUS_INCLUDE +DBUS_INCLUDE := $(shell pkg-config --cflags dbus-1) +endif +dbus_version=$(subst ., ,$(shell pkg-config --modversion dbus-1)) +DBUS_VERSION_MAJOR=$(word 1,$(dbus_version)) +DBUS_VERSION_MINOR=$(word 2,$(dbus_version)) +ifeq ($(DBUS_VERSION_MAJOR),) +DBUS_VERSION_MAJOR=0 +endif +ifeq ($(DBUS_VERSION_MINOR),) +DBUS_VERSION_MINOR=0 +endif +DBUS_INCLUDE += -DDBUS_VERSION_MAJOR=$(DBUS_VERSION_MAJOR) +DBUS_INCLUDE += -DDBUS_VERSION_MINOR=$(DBUS_VERSION_MINOR) +CFLAGS += $(DBUS_INCLUDE) endif ifdef CONFIG_READLINE @@ -724,6 +741,10 @@ ifndef CONFIG_MAIN CONFIG_MAIN=main endif +ifdef CONFIG_DEBUG_FILE +CFLAGS += -DCONFIG_DEBUG_FILE +endif + OBJS += wpa_supplicant.o events.o OBJS_t := $(OBJS) eapol_test.o radius.o radius_client.o OBJS_t2 := $(OBJS) preauth_test.o diff --git a/contrib/wpa_supplicant/README b/contrib/wpa_supplicant/README index be07574..0b3c585 100644 --- a/contrib/wpa_supplicant/README +++ b/contrib/wpa_supplicant/README @@ -1,7 +1,7 @@ WPA Supplicant ============== -Copyright (c) 2003-2007, Jouni Malinen and contributors +Copyright (c) 2003-2008, Jouni Malinen and contributors All Rights Reserved. This program is dual-licensed under both the GPL version 2 and BSD @@ -481,7 +481,7 @@ Command line options -------------------- usage: - wpa_supplicant [-BddehLqqvwW] [-P] [-g] \ + wpa_supplicant [-BddfhKLqqtuvwW] [-P] [-g] \ -i -c [-C] [-D] [-p] \ [-b [-N -i -c [-C] [-D] \ [-p] [-b] ...] @@ -494,6 +494,7 @@ options: -i = interface name -d = increase debugging verbosity (-dd even more) -D = driver name + -f = Log output to default log location (normally /tmp) -g = global ctrl_interface -K = include keys (passwords, etc.) in debug output -t = include timestamp in debug messages diff --git a/contrib/wpa_supplicant/aes_wrap.c b/contrib/wpa_supplicant/aes_wrap.c index c52e45a..765b1ca 100644 --- a/contrib/wpa_supplicant/aes_wrap.c +++ b/contrib/wpa_supplicant/aes_wrap.c @@ -7,7 +7,7 @@ * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * - * Copyright (c) 2003-2005, Jouni Malinen + * Copyright (c) 2003-2007, Jouni Malinen * * 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/wpa_supplicant/aes_wrap.h b/contrib/wpa_supplicant/aes_wrap.h index 1bc6971..5eb4342 100644 --- a/contrib/wpa_supplicant/aes_wrap.h +++ b/contrib/wpa_supplicant/aes_wrap.h @@ -7,7 +7,7 @@ * - AES-128 EAX mode encryption/decryption * - AES-128 CBC * - * Copyright (c) 2003-2005, Jouni Malinen + * Copyright (c) 2003-2007, Jouni Malinen * * 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/wpa_supplicant/asn1.c b/contrib/wpa_supplicant/asn1.c index ff3db7d..96bc1ac 100644 --- a/contrib/wpa_supplicant/asn1.c +++ b/contrib/wpa_supplicant/asn1.c @@ -58,6 +58,10 @@ int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) } tmp &= 0x7f; /* number of subsequent octets */ hdr->length = 0; + if (tmp > 4) { + wpa_printf(MSG_DEBUG, "ASN.1: Too long length field"); + return -1; + } while (tmp--) { if (pos >= end) { wpa_printf(MSG_DEBUG, "ASN.1: Length " @@ -71,7 +75,7 @@ int asn1_get_next(const u8 *buf, size_t len, struct asn1_hdr *hdr) hdr->length = tmp; } - if (pos + hdr->length > end) { + if (end < pos || hdr->length > (unsigned int) (end - pos)) { wpa_printf(MSG_DEBUG, "ASN.1: Contents underflow"); return -1; } diff --git a/contrib/wpa_supplicant/common.c b/contrib/wpa_supplicant/common.c index c8d6f13..f226c68 100644 --- a/contrib/wpa_supplicant/common.c +++ b/contrib/wpa_supplicant/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/wpa_supplicant/common.h b/contrib/wpa_supplicant/common.h index b200b58..eda328a 100644 --- a/contrib/wpa_supplicant/common.h +++ b/contrib/wpa_supplicant/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/wpa_supplicant/config.c b/contrib/wpa_supplicant/config.c index 171970d..6ea66de 100644 --- a/contrib/wpa_supplicant/config.c +++ b/contrib/wpa_supplicant/config.c @@ -66,17 +66,19 @@ static char * wpa_config_parse_string(const char *value, size_t *len) return os_strdup(value); } else { u8 *str; - size_t hlen = os_strlen(value); + size_t tlen, hlen = os_strlen(value); if (hlen & 1) return NULL; - *len = hlen / 2; - str = os_malloc(*len); + tlen = hlen / 2; + str = os_malloc(tlen + 1); if (str == NULL) return NULL; - if (hexstr2bin(value, str, *len)) { + if (hexstr2bin(value, str, tlen)) { os_free(str); return NULL; } + str[tlen] = '\0'; + *len = tlen; return (char *) str; } } @@ -1157,7 +1159,8 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(ieee80211w, 0, 2) }, #endif /* CONFIG_IEEE80211W */ { INT_RANGE(peerkey, 0, 1) }, - { INT_RANGE(mixed_cell, 0, 1) } + { INT_RANGE(mixed_cell, 0, 1) }, + { INT_RANGE(frequency, 0, 10000) } }; #undef OFFSET diff --git a/contrib/wpa_supplicant/config_ssid.h b/contrib/wpa_supplicant/config_ssid.h index d4c3654..393f750 100644 --- a/contrib/wpa_supplicant/config_ssid.h +++ b/contrib/wpa_supplicant/config_ssid.h @@ -851,6 +851,18 @@ struct wpa_ssid { IEEE80211W_REQUIRED = 2 } ieee80211w; #endif /* CONFIG_IEEE80211W */ + + /** + * frequency - Channel frequency in megahertz (MHz) for IBSS + * + * This value is used to configure the initial channel for IBSS (adhoc) + * networks, e.g., 2412 = IEEE 802.11b/g channel 1. It is ignored in + * the infrastructure mode. In addition, this value is only used by the + * station that creates the IBSS. If an IBSS network with the + * configured SSID is already present, the frequency of the network + * will be used instead of this configured value. + */ + int frequency; }; int wpa_config_allowed_eap_method(struct wpa_ssid *ssid, int vendor, diff --git a/contrib/wpa_supplicant/ctrl_iface.c b/contrib/wpa_supplicant/ctrl_iface.c index c864c91..c84a9f9 100644 --- a/contrib/wpa_supplicant/ctrl_iface.c +++ b/contrib/wpa_supplicant/ctrl_iface.c @@ -1120,6 +1120,12 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, wpa_s->disconnected = 0; wpa_s->reassociate = 1; wpa_supplicant_req_scan(wpa_s, 0, 0); + } else if (os_strcmp(buf, "RECONNECT") == 0) { + if (wpa_s->disconnected) { + wpa_s->disconnected = 0; + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } } else if (os_strncmp(buf, "PREAUTH ", 8) == 0) { if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8)) reply_len = -1; @@ -1147,6 +1153,7 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, reply_len = wpa_supplicant_ctrl_iface_list_networks( wpa_s, reply, reply_size); } else if (os_strcmp(buf, "DISCONNECT") == 0) { + wpa_s->reassociate = 0; wpa_s->disconnected = 1; wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); } else if (os_strcmp(buf, "SCAN") == 0) { diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus.c b/contrib/wpa_supplicant/ctrl_iface_dbus.c index 1d66c96..ba78516 100644 --- a/contrib/wpa_supplicant/ctrl_iface_dbus.c +++ b/contrib/wpa_supplicant/ctrl_iface_dbus.c @@ -30,6 +30,14 @@ #include "wpa_ctrl.h" #include "eap.h" +#define DBUS_VERSION (DBUS_VERSION_MAJOR << 8 | DBUS_VERSION_MINOR) +#define DBUS_VER(major, minor) ((major) << 8 | (minor)) + +#if DBUS_VERSION < DBUS_VER(1,1) +#define dbus_watch_get_unix_fd dbus_watch_get_fd +#endif + + struct ctrl_iface_dbus_priv { DBusConnection *con; int should_dispatch; @@ -92,7 +100,7 @@ static void connection_setup_add_watch(struct ctrl_iface_dbus_priv *iface, return; flags = dbus_watch_get_flags(watch); - fd = dbus_watch_get_fd(watch); + fd = dbus_watch_get_unix_fd(watch); eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception, iface, watch); @@ -117,7 +125,7 @@ static void connection_setup_remove_watch(struct ctrl_iface_dbus_priv *iface, int fd; flags = dbus_watch_get_flags(watch); - fd = dbus_watch_get_fd(watch); + fd = dbus_watch_get_unix_fd(watch); eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION); @@ -536,6 +544,10 @@ static DBusHandlerResult wpas_iface_message_handler(DBusConnection *connection, reply = wpas_dbus_iface_set_ap_scan(message, wpa_s); else if (!strcmp(method, "state")) reply = wpas_dbus_iface_get_state(message, wpa_s); + else if (!strcmp(method, "setBlobs")) + reply = wpas_dbus_iface_set_blobs(message, wpa_s); + else if (!strcmp(method, "removeBlobs")) + reply = wpas_dbus_iface_remove_blobs(message, wpa_s); } /* If the message was handled, send back the reply */ @@ -645,6 +657,7 @@ void wpa_supplicant_dbus_notify_scan_results(struct wpa_supplicant *wpa_s) return; } dbus_connection_send(iface->con, signal, NULL); + dbus_message_unref(signal); } @@ -662,7 +675,7 @@ void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, wpa_states old_state) { struct ctrl_iface_dbus_priv *iface; - DBusMessage *signal; + DBusMessage *signal = NULL; const char *path; const char *new_state_str, *old_state_str; @@ -707,7 +720,7 @@ void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, wpa_printf(MSG_ERROR, "wpa_supplicant_dbus_notify_state_change[dbus]: " "couldn't convert state strings."); - return; + goto out; } if (!dbus_message_append_args(signal, @@ -720,8 +733,12 @@ void wpa_supplicant_dbus_notify_state_change(struct wpa_supplicant *wpa_s, "wpa_supplicant_dbus_notify_state_change[dbus]: " "not enough memory to construct state change " "signal."); + goto out; } dbus_connection_send(iface->con, signal, NULL); + +out: + dbus_message_unref(signal); } diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c index 5e952ec..19972c0 100644 --- a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c +++ b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.c @@ -1203,3 +1203,129 @@ DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, return reply; } + + +/** + * wpas_dbus_iface_set_blobs - Store named binary blobs (ie, for certificates) + * @message: Pointer to incoming dbus message + * @global: %wpa_supplicant global data structure + * Returns: A dbus message containing a UINT32 indicating success (1) or + * failure (0) + * + * Asks wpa_supplicant to internally store a one or more binary blobs. + */ +DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + DBusMessage *reply = NULL; + struct wpa_dbus_dict_entry entry = { .type = DBUS_TYPE_STRING }; + DBusMessageIter iter, iter_dict; + + dbus_message_iter_init(message, &iter); + + if (!wpa_dbus_dict_open_read(&iter, &iter_dict)) + return wpas_dbus_new_invalid_opts_error(message, NULL); + + while (wpa_dbus_dict_has_dict_entry(&iter_dict)) { + struct wpa_config_blob *blob; + + if (!wpa_dbus_dict_get_entry(&iter_dict, &entry)) { + reply = wpas_dbus_new_invalid_opts_error(message, + NULL); + break; + } + + if (entry.type != DBUS_TYPE_ARRAY || + entry.array_type != DBUS_TYPE_BYTE) { + reply = wpas_dbus_new_invalid_opts_error( + message, "Byte array expected."); + break; + } + + if ((entry.array_len <= 0) || (entry.array_len > 65536) || + !strlen(entry.key)) { + reply = wpas_dbus_new_invalid_opts_error( + message, "Invalid array size."); + break; + } + + blob = os_zalloc(sizeof(*blob)); + if (blob == NULL) { + reply = dbus_message_new_error( + message, WPAS_ERROR_ADD_ERROR, + "Not enough memory to add blob."); + break; + } + blob->data = os_zalloc(entry.array_len); + if (blob->data == NULL) { + reply = dbus_message_new_error( + message, WPAS_ERROR_ADD_ERROR, + "Not enough memory to add blob data."); + os_free(blob); + break; + } + + blob->name = os_strdup(entry.key); + blob->len = entry.array_len; + os_memcpy(blob->data, (u8 *) entry.bytearray_value, + entry.array_len); + if (blob->name == NULL || blob->data == NULL) { + wpa_config_free_blob(blob); + reply = dbus_message_new_error( + message, WPAS_ERROR_ADD_ERROR, + "Error adding blob."); + break; + } + + /* Success */ + wpa_config_remove_blob(wpa_s->conf, blob->name); + wpa_config_set_blob(wpa_s->conf, blob); + wpa_dbus_dict_entry_clear(&entry); + } + wpa_dbus_dict_entry_clear(&entry); + + return reply ? reply : wpas_dbus_new_success_reply(message); +} + + +/** + * wpas_dbus_iface_remove_blob - Remove named binary blobs + * @message: Pointer to incoming dbus message + * @global: %wpa_supplicant global data structure + * Returns: A dbus message containing a UINT32 indicating success (1) or + * failure (0) + * + * Asks wpa_supplicant to remove one or more previously stored binary blobs. + */ +DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + DBusMessageIter iter, array; + char *err_msg = NULL; + + dbus_message_iter_init(message, &iter); + + if ((dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) || + (dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRING)) + return wpas_dbus_new_invalid_opts_error(message, NULL); + + dbus_message_iter_recurse(&iter, &array); + while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRING) { + const char *name; + + dbus_message_iter_get_basic(&array, &name); + if (!strlen(name)) + err_msg = "Invalid blob name."; + + if (wpa_config_remove_blob(wpa_s->conf, name) != 0) + err_msg = "Error removing blob."; + dbus_message_iter_next(&array); + } + + if (err_msg) { + return dbus_message_new_error(message, WPAS_ERROR_REMOVE_ERROR, + err_msg); + } + + return wpas_dbus_new_success_reply(message); +} diff --git a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h index 0fd1d31..0ae94c4 100644 --- a/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h +++ b/contrib/wpa_supplicant/ctrl_iface_dbus_handlers.h @@ -71,6 +71,12 @@ DBusMessage * wpas_dbus_iface_set_ap_scan(DBusMessage *message, DBusMessage * wpas_dbus_iface_get_state(DBusMessage *message, struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_iface_set_blobs(DBusMessage *message, + struct wpa_supplicant *wpa_s); + +DBusMessage * wpas_dbus_iface_remove_blobs(DBusMessage *message, + struct wpa_supplicant *wpa_s); + #endif /* CONFIG_CTRL_IFACE_DBUS */ #endif /* CTRL_IFACE_DBUS_HANDLERS_H */ diff --git a/contrib/wpa_supplicant/ctrl_iface_unix.c b/contrib/wpa_supplicant/ctrl_iface_unix.c index e9bc472..9e4f85f 100644 --- a/contrib/wpa_supplicant/ctrl_iface_unix.c +++ b/contrib/wpa_supplicant/ctrl_iface_unix.c @@ -522,9 +522,42 @@ static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) { - wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor", - priv->wpa_s->ifname); - eloop_wait_for_read_sock(priv->sock); + char buf[256]; + int res; + struct sockaddr_un from; + socklen_t fromlen = sizeof(from); + + for (;;) { + wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor to " + "attach", priv->wpa_s->ifname); + eloop_wait_for_read_sock(priv->sock); + + res = recvfrom(priv->sock, buf, sizeof(buf) - 1, 0, + (struct sockaddr *) &from, &fromlen); + if (res < 0) { + perror("recvfrom(ctrl_iface)"); + continue; + } + buf[res] = '\0'; + + if (os_strcmp(buf, "ATTACH") == 0) { + /* handle ATTACH signal of first monitor interface */ + if (!wpa_supplicant_ctrl_iface_attach(priv, &from, + fromlen)) { + sendto(priv->sock, "OK\n", 3, 0, + (struct sockaddr *) &from, fromlen); + /* OK to continue */ + return; + } else { + sendto(priv->sock, "FAIL\n", 5, 0, + (struct sockaddr *) &from, fromlen); + } + } else { + /* return FAIL for all other signals */ + sendto(priv->sock, "FAIL\n", 5, 0, + (struct sockaddr *) &from, fromlen); + } + } } diff --git a/contrib/wpa_supplicant/dbus-wpa_supplicant.conf b/contrib/wpa_supplicant/dbus-wpa_supplicant.conf index 1622af5..51a29e3 100644 --- a/contrib/wpa_supplicant/dbus-wpa_supplicant.conf +++ b/contrib/wpa_supplicant/dbus-wpa_supplicant.conf @@ -8,10 +8,6 @@ - - - - diff --git a/contrib/wpa_supplicant/dbus-wpa_supplicant.service b/contrib/wpa_supplicant/dbus-wpa_supplicant.service new file mode 100644 index 0000000..a9ce1ec --- /dev/null +++ b/contrib/wpa_supplicant/dbus-wpa_supplicant.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=fi.epitest.hostap.WPASupplicant +Exec=/sbin/wpa_supplicant -u +User=root diff --git a/contrib/wpa_supplicant/defconfig b/contrib/wpa_supplicant/defconfig index d9526ef..5216598 100644 --- a/contrib/wpa_supplicant/defconfig +++ b/contrib/wpa_supplicant/defconfig @@ -209,7 +209,9 @@ CONFIG_CTRL_IFACE=y #CONFIG_NO_AES_EXTRAS=y # Select configuration backend: -# file = text file (e.g., wpa_supplicant.conf) +# file = text file (e.g., wpa_supplicant.conf; note: the configuration file +# path is given on command line, not here; this option is just used to +# select the backend that allows configuration files to be used) # winreg = Windows registry (see win_example.reg for an example) CONFIG_BACKEND=file @@ -316,3 +318,6 @@ CONFIG_PEERKEY=y # wireless-dev.git tree). #WIRELESS_DEV=/usr/src/wireless-dev #CFLAGS += -I$(WIRELESS_DEV)/net/mac80211 + +# Add support for writing debug log to a file (/tmp/wpa_supplicant-log-#.txt) +#CONFIG_DEBUG_FILE=y diff --git a/contrib/wpa_supplicant/doc/ctrl_iface.doxygen b/contrib/wpa_supplicant/doc/ctrl_iface.doxygen index f9e7d0e..d649786 100644 --- a/contrib/wpa_supplicant/doc/ctrl_iface.doxygen +++ b/contrib/wpa_supplicant/doc/ctrl_iface.doxygen @@ -203,6 +203,12 @@ IEEE 802.1X EAPOL state machine logoff. Force reassociation. +\subsection ctrl_iface_RECONNECT RECONNECT + +Connect if disconnected (i.e., like \c REASSOCIATE, but only connect +if in disconnected state). + + \subsection ctrl_iface_PREAUTH PREAUTH Start pre-authentication with the given BSSID. @@ -255,7 +261,8 @@ network id / ssid / bssid / flags \subsection ctrl_iface_DISCONNECT DISCONNECT -Disconnect and wait for \c REASSOCIATE command before connecting. +Disconnect and wait for \c REASSOCIATE or \c RECONNECT command before +connecting. \subsection ctrl_iface_SCAN SCAN diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_background.8 b/contrib/wpa_supplicant/doc/docbook/wpa_background.8 index 7f9d637..6244529 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_background.8 +++ b/contrib/wpa_supplicant/doc/docbook/wpa_background.8 @@ -3,7 +3,7 @@ .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . -.TH "WPA_BACKGROUND" "8" "28 May 2007" "" "" +.TH "WPA_BACKGROUND" "8" "19 February 2008" "" "" .SH NAME wpa_background \- Background information on Wi-Fi Protected Access and IEEE 802.11i diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 b/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 index 6d32260..0865264 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 +++ b/contrib/wpa_supplicant/doc/docbook/wpa_cli.8 @@ -3,7 +3,7 @@ .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . -.TH "WPA_CLI" "8" "28 May 2007" "" "" +.TH "WPA_CLI" "8" "19 February 2008" "" "" .SH NAME wpa_cli \- WPA command line client @@ -112,7 +112,7 @@ Run as a daemon in the background. Run in daemon mode executing the action file based on events from wpa_supplicant. The specified file will be executed with the first argument set to interface name and -second to "CONNECT" or "DISCONNECT" depending on the event. +second to "CONNECTED" or "DISCONNECTED" depending on the event. This can be used to execute networking tools required to configure the interface. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml index 140c365b..8430599 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml +++ b/contrib/wpa_supplicant/doc/docbook/wpa_cli.sgml @@ -140,7 +140,7 @@ CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar Run in daemon mode executing the action file based on events from wpa_supplicant. The specified file will be executed with the first argument set to interface name and - second to "CONNECT" or "DISCONNECT" depending on the event. + second to "CONNECTED" or "DISCONNECTED" depending on the event. This can be used to execute networking tools required to configure the interface. diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 index c883777..a0f5c70 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 +++ b/contrib/wpa_supplicant/doc/docbook/wpa_passphrase.8 @@ -3,7 +3,7 @@ .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . -.TH "WPA_PASSPHRASE" "8" "28 May 2007" "" "" +.TH "WPA_PASSPHRASE" "8" "19 February 2008" "" "" .SH NAME wpa_passphrase \- Generate a WPA PSK from an ASCII passphrase for a SSID diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 index 502000d..1a5697d 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 +++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.8 @@ -3,13 +3,13 @@ .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . -.TH "WPA_SUPPLICANT" "8" "28 May 2007" "" "" +.TH "WPA_SUPPLICANT" "8" "19 February 2008" "" "" .SH NAME wpa_supplicant \- Wi-Fi Protected Access client and IEEE 802.1X supplicant .SH SYNOPSIS -\fBwpa_supplicant\fR [ \fB-BddehLqqvw\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ] [ \fB-P\fIPID_file\fB\fR ] +\fBwpa_supplicant\fR [ \fB-BddfhKLqqtuvwW\fR ] [ \fB-i\fIifname\fB\fR ] [ \fB-c\fIconfig file\fB\fR ] [ \fB-D\fIdriver\fB\fR ] [ \fB-P\fIPID_file\fB\fR ] [ \fB-f\fIoutput file\fB\fR ] .SH "OVERVIEW" .PP @@ -272,6 +272,9 @@ Path to global ctrl_interface socket. \fB-D driver\fR Driver to use. See the available options below. .TP +\fB-f output file\fR +Log output to specified file instead of stdout. +.TP \fB-d\fR Increase debugging verbosity (-dd even more). .TP diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 index c7e4c6f..efe17cc 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 +++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.conf.5 @@ -3,7 +3,7 @@ .\" .\" Please send any bug reports, improvements, comments, patches, .\" etc. to Steve Cheng . -.TH "WPA_SUPPLICANT.CONF" "5" "28 May 2007" "" "" +.TH "WPA_SUPPLICANT.CONF" "5" "19 February 2008" "" "" .SH NAME wpa_supplicant.conf \- configuration file for wpa_supplicant diff --git a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml index d19e546..b46d13c 100644 --- a/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml +++ b/contrib/wpa_supplicant/doc/docbook/wpa_supplicant.sgml @@ -12,11 +12,12 @@ wpa_supplicant - -BddehLqqvw + -BddfhKLqqtuvwW -iifname -cconfig file -Ddriver -PPID_file + -foutput file @@ -376,6 +377,13 @@ + -f output file + + Log output to specified file instead of stdout. + + + + -d Increase debugging verbosity (-dd even more). diff --git a/contrib/wpa_supplicant/driver_ndis.c b/contrib/wpa_supplicant/driver_ndis.c index 16e051e..570b4ca 100644 --- a/contrib/wpa_supplicant/driver_ndis.c +++ b/contrib/wpa_supplicant/driver_ndis.c @@ -725,6 +725,7 @@ static int wpa_driver_ndis_scan(void *priv, const u8 *ssid, size_t ssid_len) } res = ndis_set_oid(drv, OID_802_11_BSSID_LIST_SCAN, " ", 4); + eloop_cancel_timeout(wpa_driver_ndis_scan_timeout, drv, drv->ctx); eloop_register_timeout(7, 0, wpa_driver_ndis_scan_timeout, drv, drv->ctx); return res; @@ -1169,7 +1170,6 @@ static int wpa_driver_ndis_remove_pmkid(void *priv, const u8 *bssid, entry = drv->pmkid; prev = NULL; - drv->pmkid = NULL; while (entry) { if (os_memcmp(entry->bssid, bssid, ETH_ALEN) == 0 && os_memcmp(entry->pmkid, pmkid, 16) == 0) { diff --git a/contrib/wpa_supplicant/eap_gpsk.c b/contrib/wpa_supplicant/eap_gpsk.c index 1366d43..81b03ed 100644 --- a/contrib/wpa_supplicant/eap_gpsk.c +++ b/contrib/wpa_supplicant/eap_gpsk.c @@ -1,5 +1,5 @@ /* - * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-03.txt) + * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) * Copyright (c) 2006-2007, Jouni Malinen * * This program is free software; you can redistribute it and/or modify @@ -22,7 +22,7 @@ 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]; @@ -31,8 +31,8 @@ struct eap_gpsk_data { size_t pk_len; u8 session_id; int session_id_set; - u8 *id_client; - size_t id_client_len; + u8 *id_peer; + size_t id_peer_len; u8 *id_server; size_t id_server_len; int vendor; /* CSuite/Specifier */ @@ -42,6 +42,13 @@ struct eap_gpsk_data { }; +static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, + const u8 *csuite_list, size_t csuite_list_len, + size_t *respDataLen); +static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, + size_t *respDataLen); + + #ifndef CONFIG_NO_STDOUT_DEBUG static const char * eap_gpsk_state_txt(int state) { @@ -94,13 +101,13 @@ static void * eap_gpsk_init(struct eap_sm *sm) data->state = GPSK_1; if (config->nai) { - data->id_client = os_malloc(config->nai_len); - if (data->id_client == NULL) { + data->id_peer = os_malloc(config->nai_len); + if (data->id_peer == NULL) { eap_gpsk_deinit(sm, data); return NULL; } - os_memcpy(data->id_client, config->nai, config->nai_len); - data->id_client_len = config->nai_len; + os_memcpy(data->id_peer, config->nai, config->nai_len); + data->id_peer_len = config->nai_len; } data->psk = os_malloc(config->eappsk_len); @@ -119,38 +126,16 @@ static void eap_gpsk_deinit(struct eap_sm *sm, void *priv) { struct eap_gpsk_data *data = priv; os_free(data->id_server); - os_free(data->id_client); + os_free(data->id_peer); os_free(data->psk); os_free(data); } -static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) +const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, + const u8 *pos, const u8 *end) { - size_t len, csuite_list_len, miclen; - struct eap_hdr *resp; - u8 *rpos, *start; - const u8 *csuite_list, *pos, *end; - const struct eap_hdr *req; - struct eap_gpsk_csuite *csuite; u16 alen; - int i, count; - - if (data->state != GPSK_1) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); - - req = (const struct eap_hdr *) reqData; - pos = payload; - end = payload + payload_len; if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); @@ -174,6 +159,16 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, data->id_server, data->id_server_len); pos += alen; + return pos; +} + + +const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, + const u8 *pos, const u8 *end) +{ + if (pos == NULL) + return NULL; + if (end - pos < EAP_GPSK_RAND_LEN) { wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); return NULL; @@ -183,32 +178,26 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, data->rand_server, EAP_GPSK_RAND_LEN); pos += EAP_GPSK_RAND_LEN; - if (end - pos < 2) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); - return NULL; - } - csuite_list_len = WPA_GET_BE16(pos); - pos += 2; - if (end - pos < (int) csuite_list_len) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); - return NULL; - } - csuite_list = pos; + return pos; +} + + +static int eap_gpsk_select_csuite(struct eap_sm *sm, + struct eap_gpsk_data *data, + const u8 *csuite_list, + size_t csuite_list_len) +{ + struct eap_gpsk_csuite *csuite; + int i, count; - if (csuite_list_len == 0 || - csuite_list_len % sizeof(struct eap_gpsk_csuite)) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d", - csuite_list_len); - return NULL; - } count = csuite_list_len / sizeof(struct eap_gpsk_csuite); data->vendor = EAP_GPSK_VENDOR_IETF; data->specifier = EAP_GPSK_CIPHER_RESERVED; csuite = (struct eap_gpsk_csuite *) csuite_list; for (i = 0; i < count; i++) { int vendor, specifier; - vendor = WPA_GET_BE24(csuite->vendor); - specifier = WPA_GET_BE24(csuite->specifier); + vendor = WPA_GET_BE32(csuite->vendor); + specifier = WPA_GET_BE16(csuite->specifier); wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", i, vendor, specifier); if (data->vendor == EAP_GPSK_VENDOR_IETF && @@ -223,34 +212,122 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, data->specifier == EAP_GPSK_CIPHER_RESERVED) { wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " "ciphersuite found"); - eap_gpsk_state(data, FAILURE); - return NULL; + return -1; } wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", data->vendor, data->specifier); + return 0; +} + + +const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, + struct eap_gpsk_data *data, + const u8 **list, size_t *list_len, + const u8 *pos, const u8 *end) +{ + if (pos == NULL) + return NULL; + + if (end - pos < 2) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); + return NULL; + } + *list_len = WPA_GET_BE16(pos); + pos += 2; + if (end - pos < (int) *list_len) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); + return NULL; + } + if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %d", + *list_len); + return NULL; + } + *list = pos; + pos += *list_len; + + if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) + return NULL; + + return pos; +} + + +static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, + struct eap_gpsk_data *data, + struct eap_method_ret *ret, + const u8 *reqData, size_t reqDataLen, + const u8 *payload, size_t payload_len, + size_t *respDataLen) +{ + size_t csuite_list_len; + const u8 *csuite_list, *pos, *end; + const struct eap_hdr *req; + u8 *resp; + + if (data->state != GPSK_1) { + ret->ignore = TRUE; + return NULL; + } + + wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); + + end = payload + payload_len; + + pos = eap_gpsk_process_id_server(data, payload, end); + pos = eap_gpsk_process_rand_server(data, pos, end); + pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, + &csuite_list_len, pos, end); + if (pos == NULL) { + eap_gpsk_state(data, FAILURE); + return NULL; + } + + req = (const struct eap_hdr *) reqData; + resp = eap_gpsk_send_gpsk_2(data, req->identifier, + csuite_list, csuite_list_len, + respDataLen); + if (resp == NULL) + return NULL; + + eap_gpsk_state(data, GPSK_3); + + return (u8 *) resp; +} + + +static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, + const u8 *csuite_list, size_t csuite_list_len, + size_t *respDataLen) +{ + struct eap_hdr *resp; + size_t len, miclen; + u8 *rpos, *start; + struct eap_gpsk_csuite *csuite; + wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); miclen = eap_gpsk_mic_len(data->vendor, data->specifier); - len = 1 + 2 + data->id_client_len + 2 + data->id_server_len + + len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + sizeof(struct eap_gpsk_csuite) + 2 + miclen; resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len, - EAP_CODE_RESPONSE, req->identifier, &rpos); + EAP_CODE_RESPONSE, identifier, &rpos); if (resp == NULL) return NULL; *rpos++ = EAP_GPSK_OPCODE_GPSK_2; start = rpos; - wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Client", - data->id_client, data->id_client_len); - WPA_PUT_BE16(rpos, data->id_client_len); + wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", + data->id_peer, data->id_peer_len); + WPA_PUT_BE16(rpos, data->id_peer_len); rpos += 2; - if (data->id_client) - os_memcpy(rpos, data->id_client, data->id_client_len); - rpos += data->id_client_len; + if (data->id_peer) + os_memcpy(rpos, data->id_peer, data->id_peer_len); + rpos += data->id_peer_len; WPA_PUT_BE16(rpos, data->id_server_len); rpos += 2; @@ -258,16 +335,16 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, os_memcpy(rpos, data->id_server, data->id_server_len); rpos += data->id_server_len; - if (os_get_random(data->rand_client, EAP_GPSK_RAND_LEN)) { + if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " - "for RAND_Client"); + "for RAND_Peer"); eap_gpsk_state(data, FAILURE); os_free(resp); return NULL; } - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client", - data->rand_client, EAP_GPSK_RAND_LEN); - os_memcpy(rpos, data->rand_client, EAP_GPSK_RAND_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", + data->rand_peer, EAP_GPSK_RAND_LEN); + os_memcpy(rpos, data->rand_peer, EAP_GPSK_RAND_LEN); rpos += EAP_GPSK_RAND_LEN; os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN); @@ -279,14 +356,14 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, rpos += csuite_list_len; csuite = (struct eap_gpsk_csuite *) rpos; - 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); rpos = (u8 *) (csuite + 1); if (eap_gpsk_derive_keys(data->psk, data->psk_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, @@ -309,53 +386,25 @@ static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, return NULL; } - eap_gpsk_state(data, GPSK_3); - return (u8 *) resp; } -static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, - struct eap_gpsk_data *data, - struct eap_method_ret *ret, - const u8 *reqData, size_t reqDataLen, - const u8 *payload, size_t payload_len, - size_t *respDataLen) +const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, const u8 *pos, + const u8 *end) { - size_t len, miclen; - struct eap_hdr *resp; - u8 *rpos, *start; - const struct eap_hdr *req; - const u8 *pos, *end; - u16 alen; - int vendor, specifier; - const struct eap_gpsk_csuite *csuite; - u8 mic[EAP_GPSK_MAX_MIC_LEN]; - - if (data->state != GPSK_3) { - ret->ignore = TRUE; - return NULL; - } - - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); - - req = (const struct eap_hdr *) reqData; - pos = payload; - end = payload + payload_len; - if (end - pos < EAP_GPSK_RAND_LEN) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " - "RAND_Client"); + "RAND_Peer"); return NULL; } - if (os_memcmp(pos, data->rand_client, EAP_GPSK_RAND_LEN) != 0) { - wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2 and " + if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " "GPSK-3 did not match"); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-2", - data->rand_client, EAP_GPSK_RAND_LEN); - wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Client in GPSK-3", + wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", + data->rand_peer, EAP_GPSK_RAND_LEN); + wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", pos, EAP_GPSK_RAND_LEN); - eap_gpsk_state(data, FAILURE); return NULL; } pos += EAP_GPSK_RAND_LEN; @@ -372,32 +421,93 @@ static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, data->rand_server, EAP_GPSK_RAND_LEN); wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", pos, EAP_GPSK_RAND_LEN); - eap_gpsk_state(data, FAILURE); return NULL; } pos += EAP_GPSK_RAND_LEN; + return pos; +} + + +const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, + const u8 *pos, const u8 *end) +{ + size_t len; + + if (pos == NULL) + return NULL; + + if (end - pos < (int) 2) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " + "length(ID_Server)"); + return NULL; + } + + len = WPA_GET_BE16(pos); + pos += 2; + + if (end - pos < (int) len) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " + "ID_Server"); + return NULL; + } + + if (len != data->id_server_len || + os_memcmp(pos, data->id_server, len) != 0) { + wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " + "the one used in GPSK-1"); + wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", + data->id_server, data->id_server_len); + wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", + pos, len); + } + + pos += len; + + return pos; +} + + +const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, const u8 *pos, + const u8 *end) +{ + int vendor, specifier; + const struct eap_gpsk_csuite *csuite; + + if (pos == NULL) + return NULL; + if (end - pos < (int) sizeof(*csuite)) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " "CSuite_Sel"); return NULL; } csuite = (const struct eap_gpsk_csuite *) pos; - vendor = WPA_GET_BE24(csuite->vendor); - specifier = WPA_GET_BE24(csuite->specifier); + vendor = WPA_GET_BE32(csuite->vendor); + specifier = WPA_GET_BE16(csuite->specifier); pos += sizeof(*csuite); if (vendor != data->vendor || specifier != data->specifier) { wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " "match with the one sent in GPSK-2 (%d:%d)", vendor, specifier, data->vendor, data->specifier); - eap_gpsk_state(data, FAILURE); return NULL; } + return pos; +} + + +const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, + const u8 *pos, const u8 *end) +{ + u16 alen; + + if (pos == NULL) + return NULL; + if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " "PD_Payload_2 length"); - eap_gpsk_state(data, FAILURE); return NULL; } alen = WPA_GET_BE16(pos); @@ -405,45 +515,110 @@ static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, if (end - pos < alen) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " "%d-octet PD_Payload_2", alen); - eap_gpsk_state(data, FAILURE); return NULL; } wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); pos += alen; + + return pos; +} + + +const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, + const u8 *payload, + const u8 *pos, const u8 *end) +{ + size_t miclen; + u8 mic[EAP_GPSK_MAX_MIC_LEN]; + + if (pos == NULL) + return NULL; + miclen = eap_gpsk_mic_len(data->vendor, data->specifier); if (end - pos < (int) miclen) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " "(left=%d miclen=%d)", end - pos, miclen); - eap_gpsk_state(data, FAILURE); return NULL; } if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, data->specifier, payload, pos - payload, mic) < 0) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); - eap_gpsk_state(data, FAILURE); return NULL; } if (os_memcmp(mic, pos, miclen) != 0) { wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); - eap_gpsk_state(data, FAILURE); return NULL; } pos += miclen; + return pos; +} + + +static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, + struct eap_gpsk_data *data, + struct eap_method_ret *ret, + const u8 *reqData, size_t reqDataLen, + const u8 *payload, size_t payload_len, + size_t *respDataLen) +{ + u8 *resp; + const struct eap_hdr *req; + const u8 *pos, *end; + + if (data->state != GPSK_3) { + ret->ignore = TRUE; + return NULL; + } + + wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); + + end = payload + payload_len; + + pos = eap_gpsk_validate_rand(data, payload, end); + pos = eap_gpsk_validate_id_server(data, pos, end); + pos = eap_gpsk_validate_csuite(data, pos, end); + pos = eap_gpsk_validate_pd_payload_2(data, pos, end); + pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); + + if (pos == NULL) { + eap_gpsk_state(data, FAILURE); + return NULL; + } if (pos != end) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %d bytes of extra " "data in the end of GPSK-2", end - pos); } + req = (const struct eap_hdr *) reqData; + resp = eap_gpsk_send_gpsk_4(data, req->identifier, respDataLen); + if (resp == NULL) + return NULL; + + eap_gpsk_state(data, SUCCESS); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_UNCOND_SUCC; + + return (u8 *) resp; +} + + +static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, + size_t *respDataLen) +{ + struct eap_hdr *resp; + u8 *rpos, *start; + size_t len; + wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); - len = 1 + 2 + miclen; + len = 1 + 2 + eap_gpsk_mic_len(data->vendor, data->specifier); resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len, - EAP_CODE_RESPONSE, req->identifier, &rpos); + EAP_CODE_RESPONSE, identifier, &rpos); if (resp == NULL) return NULL; @@ -462,10 +637,6 @@ static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, return NULL; } - eap_gpsk_state(data, SUCCESS); - ret->methodState = METHOD_DONE; - ret->decision = DECISION_UNCOND_SUCC; - return (u8 *) resp; } diff --git a/contrib/wpa_supplicant/eap_gpsk_common.c b/contrib/wpa_supplicant/eap_gpsk_common.c index a72b5f3..7422fa6 100644 --- a/contrib/wpa_supplicant/eap_gpsk_common.c +++ b/contrib/wpa_supplicant/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/wpa_supplicant/eap_gpsk_common.h b/contrib/wpa_supplicant/eap_gpsk_common.h index c806b7f..a30ab97 100644 --- a/contrib/wpa_supplicant/eap_gpsk_common.h +++ b/contrib/wpa_supplicant/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/wpa_supplicant/eap_peap.c b/contrib/wpa_supplicant/eap_peap.c index 7f23e5b..12bd8d8 100644 --- a/contrib/wpa_supplicant/eap_peap.c +++ b/contrib/wpa_supplicant/eap_peap.c @@ -41,6 +41,8 @@ struct eap_peap_data { const struct eap_method *phase2_method; void *phase2_priv; int phase2_success; + int phase2_eap_success; + int phase2_eap_started; struct eap_method_type phase2_type; struct eap_method_type *phase2_types; @@ -296,7 +298,9 @@ static int eap_peap_phase2_request(struct eap_sm *sm, break; case EAP_TYPE_TLV: os_memset(&iret, 0, sizeof(iret)); - if (eap_tlv_process(sm, &iret, hdr, resp, resp_len)) { + if (eap_tlv_process(sm, &iret, hdr, resp, resp_len, + data->phase2_eap_started && + !data->phase2_eap_success)) { ret->methodState = METHOD_DONE; ret->decision = DECISION_FAIL; return -1; @@ -354,6 +358,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm, ret->decision = DECISION_FAIL; return -1; } + data->phase2_eap_started = 1; os_memset(&iret, 0, sizeof(iret)); *resp = data->phase2_method->process(sm, data->phase2_priv, &iret, (u8 *) hdr, len, @@ -362,6 +367,7 @@ static int eap_peap_phase2_request(struct eap_sm *sm, iret.methodState == METHOD_MAY_CONT) && (iret.decision == DECISION_UNCOND_SUCC || iret.decision == DECISION_COND_SUCC)) { + data->phase2_eap_success = 1; data->phase2_success = 1; } break; @@ -550,6 +556,17 @@ continue_req: /* EAP-Success within TLS tunnel is used to indicate * shutdown of the TLS channel. The authentication has * been completed. */ + if (data->phase2_eap_started && + !data->phase2_eap_success) { + wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 " + "Success used to indicate success, " + "but Phase 2 EAP was not yet " + "completed successfully"); + ret->methodState = METHOD_DONE; + ret->decision = DECISION_FAIL; + os_free(in_decrypted); + return 0; + } wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - " "EAP-Success within TLS tunnel - " "authentication completed"); @@ -797,6 +814,8 @@ static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv) data->phase2_method->init_for_reauth) data->phase2_method->init_for_reauth(sm, data->phase2_priv); data->phase2_success = 0; + data->phase2_eap_success = 0; + data->phase2_eap_started = 0; data->resuming = 1; sm->peap_done = FALSE; return priv; diff --git a/contrib/wpa_supplicant/eap_sim.c b/contrib/wpa_supplicant/eap_sim.c index 545f0ae..53c1987 100644 --- a/contrib/wpa_supplicant/eap_sim.c +++ b/contrib/wpa_supplicant/eap_sim.c @@ -280,14 +280,16 @@ static u8 * eap_sim_response_start(struct eap_sm *sm, req->identifier); msg = eap_sim_msg_init(EAP_CODE_RESPONSE, req->identifier, EAP_TYPE_SIM, EAP_SIM_SUBTYPE_START); - wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, - data->nonce_mt, EAP_SIM_NONCE_MT_LEN); - wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", - data->selected_version); - eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, - data->selected_version, NULL, 0); + if (!data->reauth) { + wpa_hexdump(MSG_DEBUG, " AT_NONCE_MT", + data->nonce_mt, EAP_SIM_NONCE_MT_LEN); + eap_sim_msg_add(msg, EAP_SIM_AT_NONCE_MT, 0, + data->nonce_mt, EAP_SIM_NONCE_MT_LEN); + wpa_printf(MSG_DEBUG, " AT_SELECTED_VERSION %d", + data->selected_version); + eap_sim_msg_add(msg, EAP_SIM_AT_SELECTED_VERSION, + data->selected_version, NULL, 0); + } if (identity) { wpa_hexdump_ascii(MSG_DEBUG, " AT_IDENTITY", diff --git a/contrib/wpa_supplicant/eap_sim_common.c b/contrib/wpa_supplicant/eap_sim_common.c index dc8b2f6..cc43023 100644 --- a/contrib/wpa_supplicant/eap_sim_common.c +++ b/contrib/wpa_supplicant/eap_sim_common.c @@ -1,6 +1,6 @@ /* * EAP peer: EAP-SIM/AKA shared routines - * Copyright (c) 2004-2006, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * 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/wpa_supplicant/eap_tlv.c b/contrib/wpa_supplicant/eap_tlv.c index df328de..e5f29b6 100644 --- a/contrib/wpa_supplicant/eap_tlv.c +++ b/contrib/wpa_supplicant/eap_tlv.c @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2006, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * 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 @@ -103,7 +103,8 @@ u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len) * Returns: 0 on success, -1 on failure */ int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct eap_hdr *hdr, u8 **resp, size_t *resp_len) + const struct eap_hdr *hdr, u8 **resp, size_t *resp_len, + int force_failure) { size_t left, tlv_len; const u8 *pos; @@ -174,8 +175,15 @@ int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, if (status == EAP_TLV_RESULT_SUCCESS) { wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success " "- EAP-TLV/Phase2 Completed"); - resp_status = EAP_TLV_RESULT_SUCCESS; - ret->decision = DECISION_UNCOND_SUCC; + if (force_failure) { + wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure" + " - force failed Phase 2"); + resp_status = EAP_TLV_RESULT_FAILURE; + ret->decision = DECISION_FAIL; + } else { + resp_status = EAP_TLV_RESULT_SUCCESS; + ret->decision = DECISION_UNCOND_SUCC; + } } else if (status == EAP_TLV_RESULT_FAILURE) { wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure"); resp_status = EAP_TLV_RESULT_FAILURE; diff --git a/contrib/wpa_supplicant/eap_tlv.h b/contrib/wpa_supplicant/eap_tlv.h index 0525a60..789eeaa 100644 --- a/contrib/wpa_supplicant/eap_tlv.h +++ b/contrib/wpa_supplicant/eap_tlv.h @@ -1,6 +1,6 @@ /* * EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt) - * Copyright (c) 2004-2005, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * 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 @@ -90,6 +90,7 @@ struct eap_tlv_pac_ack_tlv { u8 * eap_tlv_build_nak(int id, u16 nak_type, size_t *resp_len); u8 * eap_tlv_build_result(int id, u16 status, size_t *resp_len); int eap_tlv_process(struct eap_sm *sm, struct eap_method_ret *ret, - const struct eap_hdr *hdr, u8 **resp, size_t *resp_len); + const struct eap_hdr *hdr, u8 **resp, size_t *resp_len, + int force_failure); #endif /* EAP_TLV_H */ diff --git a/contrib/wpa_supplicant/eapol_sm.c b/contrib/wpa_supplicant/eapol_sm.c index 899e2ce..b76a75d 100644 --- a/contrib/wpa_supplicant/eapol_sm.c +++ b/contrib/wpa_supplicant/eapol_sm.c @@ -1214,7 +1214,7 @@ int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, * eapol_sm_notify_tx_eapol_key - Notification about transmitted EAPOL packet * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * - * Notify EAPOL station machine about transmitted EAPOL packet from an external + * Notify EAPOL state machine about transmitted EAPOL packet from an external * component, e.g., WPA. This will update the statistics. */ void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) @@ -1229,7 +1229,7 @@ void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @enabled: New portEnabled value * - * Notify EAPOL station machine about new portEnabled value. + * Notify EAPOL state machine about new portEnabled value. */ void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) { @@ -1247,7 +1247,7 @@ void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled) * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @valid: New portValid value * - * Notify EAPOL station machine about new portValid value. + * Notify EAPOL state machine about new portValid value. */ void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) { @@ -1265,7 +1265,7 @@ void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid) * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @success: %TRUE = set success, %FALSE = clear success * - * Notify EAPOL station machine that external event has forced EAP state to + * Notify the EAPOL state machine that external event has forced EAP state to * success (success = %TRUE). This can be cleared by setting success = %FALSE. * * This function is called to update EAP state when WPA-PSK key handshake has @@ -1290,7 +1290,7 @@ void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success) * @sm: Pointer to EAPOL state machine allocated with eapol_sm_init() * @fail: %TRUE = set failure, %FALSE = clear failure * - * Notify EAPOL station machine that external event has forced EAP state to + * Notify EAPOL state machine that external event has forced EAP state to * failure (fail = %TRUE). This can be cleared by setting fail = %FALSE. */ void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) @@ -1311,7 +1311,7 @@ void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) * @config: Pointer to current network configuration * @conf: Pointer to EAPOL configuration data * - * Notify EAPOL station machine that configuration has changed. config will be + * Notify EAPOL state machine that configuration has changed. config will be * stored as a backpointer to network configuration. This can be %NULL to clear * the stored pointed. conf will be copied to local EAPOL/EAP configuration * data. If conf is %NULL, this part of the configuration change will be diff --git a/contrib/wpa_supplicant/eapol_test.c b/contrib/wpa_supplicant/eapol_test.c index ac3213b..52cba36 100644 --- a/contrib/wpa_supplicant/eapol_test.c +++ b/contrib/wpa_supplicant/eapol_test.c @@ -248,7 +248,8 @@ static int eapol_test_eapol_send(void *ctx, int type, const u8 *buf, size_t len) { /* struct wpa_supplicant *wpa_s = ctx; */ - printf("WPA: eapol_test_eapol_send(type=%d len=%d)\n", type, len); + printf("WPA: eapol_test_eapol_send(type=%d len=%lu)\n", + type, (unsigned long) len); if (type == IEEE802_1X_TYPE_EAP_PACKET) { wpa_hexdump(MSG_DEBUG, "TX EAP -> RADIUS", buf, len); ieee802_1x_encapsulate_radius(&eapol_test, buf, len); @@ -1052,6 +1053,9 @@ int main(int argc, char *argv[]) eloop_register_signal_reconfig(eapol_test_terminate, NULL); eloop_run(); + eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL); + eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL); + if (eapol_test_compare_pmk(&eapol_test) == 0 || eapol_test.no_mppe_keys) ret = 0; diff --git a/contrib/wpa_supplicant/events.c b/contrib/wpa_supplicant/events.c index c0f4210..7fa7435 100644 --- a/contrib/wpa_supplicant/events.c +++ b/contrib/wpa_supplicant/events.c @@ -439,9 +439,10 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, wpa_printf(MSG_DEBUG, " skip - disabled"); continue; } - if (bss->ssid_len != ssid->ssid_len || - os_memcmp(bss->ssid, ssid->ssid, - bss->ssid_len) != 0) { + if (ssid->ssid_len != 0 && + (bss->ssid_len != ssid->ssid_len || + os_memcmp(bss->ssid, ssid->ssid, + bss->ssid_len) != 0)) { wpa_printf(MSG_DEBUG, " skip - " "SSID mismatch"); continue; @@ -464,8 +465,8 @@ wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, } if ((ssid->key_mgmt & - (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK)) || - bss->wpa_ie_len != 0 || bss->rsn_ie_len != 0) { + (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK)) && + (bss->wpa_ie_len != 0 || bss->rsn_ie_len != 0)) { wpa_printf(MSG_DEBUG, " skip - " "WPA network"); continue; @@ -515,7 +516,7 @@ static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) wpa_supplicant_dbus_notify_scan_results(wpa_s); - if (wpa_s->conf->ap_scan == 2) + if (wpa_s->conf->ap_scan == 2 || wpa_s->disconnected) return; results = wpa_s->scan_results; num = wpa_s->num_scan_results; diff --git a/contrib/wpa_supplicant/main.c b/contrib/wpa_supplicant/main.c index fdce7c5..f371561 100644 --- a/contrib/wpa_supplicant/main.c +++ b/contrib/wpa_supplicant/main.c @@ -39,11 +39,12 @@ static void usage(void) int i; printf("%s\n\n%s\n" "usage:\n" - " wpa_supplicant [-BddehLqquvwW] [-P] " + " wpa_supplicant [-BddhKLqqtuvwW] [-P] " "[-g] \\\n" " -i -c [-C] [-D] " "[-p] \\\n" - " [-b [-N -i -c [-C] " + " [-b] [-f] \\\n" + " [-N -i -c [-C] " "[-D] \\\n" " [-p] [-b] ...]\n" "\n" @@ -65,6 +66,9 @@ static void usage(void) " -i = interface name\n" " -d = increase debugging verbosity (-dd even more)\n" " -D = driver name\n" +#ifdef CONFIG_DEBUG_FILE + " -f = log output to debug file instead of stdout\n" +#endif /* CONFIG_DEBUG_FILE */ " -g = global ctrl_interface\n" " -K = include keys (passwords, etc.) in debug output\n" " -t = include timestamp in debug messages\n" @@ -143,7 +147,7 @@ int main(int argc, char *argv[]) wpa_supplicant_fd_workaround(); for (;;) { - c = getopt(argc, argv, "b:Bc:C:D:dg:hi:KLNp:P:qtuvwW"); + c = getopt(argc, argv, "b:Bc:C:D:df:g:hi:KLNp:P:qtuvwW"); if (c < 0) break; switch (c) { @@ -172,6 +176,11 @@ int main(int argc, char *argv[]) params.wpa_debug_level--; break; #endif /* CONFIG_NO_STDOUT_DEBUG */ +#ifdef CONFIG_DEBUG_FILE + case 'f': + params.wpa_debug_file_path = optarg; + break; +#endif /* CONFIG_DEBUG_FILE */ case 'g': params.ctrl_interface = optarg; break; diff --git a/contrib/wpa_supplicant/os.h b/contrib/wpa_supplicant/os.h index 4931adb..25570a5 100644 --- a/contrib/wpa_supplicant/os.h +++ b/contrib/wpa_supplicant/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/wpa_supplicant/os_unix.c b/contrib/wpa_supplicant/os_unix.c index fb8149a..69ba25a 100644 --- a/contrib/wpa_supplicant/os_unix.c +++ b/contrib/wpa_supplicant/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/wpa_supplicant/pcsc_funcs.c b/contrib/wpa_supplicant/pcsc_funcs.c index cef8653..cf8e3b0 100644 --- a/contrib/wpa_supplicant/pcsc_funcs.c +++ b/contrib/wpa_supplicant/pcsc_funcs.c @@ -848,7 +848,8 @@ static int scard_read_record(struct scard_data *scard, } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: record read returned unexpected " - "length %d (expected %d)", blen, len + 2); + "length %ld (expected %ld)", + (long) blen, (long) len + 2); os_free(buf); return -3; } @@ -891,7 +892,8 @@ static int scard_read_file(struct scard_data *scard, } if (blen != len + 2) { wpa_printf(MSG_DEBUG, "SCARD: file read returned unexpected " - "length %d (expected %d)", blen, len + 2); + "length %ld (expected %ld)", + (long) blen, (long) len + 2); os_free(buf); return -3; } @@ -969,7 +971,7 @@ int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) return -1; if (blen < 4) { wpa_printf(MSG_WARNING, "SCARD: too short (GSM) EF-IMSI " - "header (len=%d)", blen); + "header (len=%ld)", (long) blen); return -2; } @@ -982,14 +984,14 @@ int scard_get_imsi(struct scard_data *scard, char *imsi, size_t *len) blen = file_size; } if (blen < 2 || blen > sizeof(buf)) { - wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%d", - blen); + wpa_printf(MSG_DEBUG, "SCARD: invalid IMSI file length=%ld", + (long) blen); return -3; } imsilen = (blen - 2) * 2 + 1; - wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%d imsilen=%d", - blen, imsilen); + wpa_printf(MSG_DEBUG, "SCARD: IMSI file length=%ld imsilen=%ld", + (long) blen, (long) imsilen); if (blen < 2 || imsilen > *len) { *len = imsilen; return -4; @@ -1071,8 +1073,8 @@ int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, (scard->sim_type == SCARD_USIM && (len != 2 || resp[0] != 0x61 || resp[1] != 0x0e))) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for GSM " - "auth request (len=%d resp=%02x %02x)", - len, resp[0], resp[1]); + "auth request (len=%ld resp=%02x %02x)", + (long) len, resp[0], resp[1]); return -3; } get_resp[4] = resp[1]; @@ -1085,8 +1087,8 @@ int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, if (scard->sim_type == SCARD_GSM_SIM) { if (len != 4 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for GSM auth (len=%d, expected 14)", - len); + "length for GSM auth (len=%ld, expected 14)", + (long) len); return -5; } os_memcpy(sres, buf, 4); @@ -1094,8 +1096,8 @@ int scard_gsm_auth(struct scard_data *scard, const unsigned char *_rand, } else { if (len != 1 + 4 + 1 + 8 + 2) { wpa_printf(MSG_WARNING, "SCARD: unexpected data " - "length for USIM auth (len=%d, " - "expected 16)", len); + "length for USIM auth (len=%ld, " + "expected 16)", (long) len); return -5; } if (buf[0] != 4 || buf[5] != 8) { @@ -1176,8 +1178,8 @@ int scard_umts_auth(struct scard_data *scard, const unsigned char *_rand, return -1; } else if (len != 2 || resp[0] != 0x61) { wpa_printf(MSG_WARNING, "SCARD: unexpected response for UMTS " - "auth request (len=%d resp=%02x %02x)", - len, resp[0], resp[1]); + "auth request (len=%ld resp=%02x %02x)", + (long) len, resp[0], resp[1]); return -1; } get_resp[4] = resp[1]; diff --git a/contrib/wpa_supplicant/radius.c b/contrib/wpa_supplicant/radius.c index bf39b2f..743f340 100644 --- a/contrib/wpa_supplicant/radius.c +++ b/contrib/wpa_supplicant/radius.c @@ -1,6 +1,6 @@ /* * hostapd / RADIUS message processing - * Copyright (c) 2002-2005, Jouni Malinen + * Copyright (c) 2002-2008, Jouni Malinen * * 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/wpa_supplicant/radius.h b/contrib/wpa_supplicant/radius.h index d1b909d..d437537 100644 --- a/contrib/wpa_supplicant/radius.h +++ b/contrib/wpa_supplicant/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/wpa_supplicant/radius_client.c b/contrib/wpa_supplicant/radius_client.c index 5b00bbe..81cd9c5 100644 --- a/contrib/wpa_supplicant/radius_client.c +++ b/contrib/wpa_supplicant/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/wpa_supplicant/tests/test_aes.c b/contrib/wpa_supplicant/tests/test_aes.c new file mode 100644 index 0000000..09c2d8e --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_aes.c @@ -0,0 +1,306 @@ +/* + * Test program for AES + * Copyright (c) 2003-2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_wrap.h" + +#define BLOCK_SIZE 16 + +static void test_aes_perf(void) +{ +#if 0 /* this did not seem to work with new compiler?! */ +#ifdef __i386__ +#define rdtscll(val) \ + __asm__ __volatile__("rdtsc" : "=A" (val)) + const int num_iters = 10; + int i; + unsigned int start, end; + u8 key[16], pt[16], ct[16]; + void *ctx; + + printf("keySetupEnc:"); + for (i = 0; i < num_iters; i++) { + rdtscll(start); + ctx = aes_encrypt_init(key, 16); + rdtscll(end); + aes_encrypt_deinit(ctx); + printf(" %d", end - start); + } + printf("\n"); + + printf("Encrypt:"); + ctx = aes_encrypt_init(key, 16); + for (i = 0; i < num_iters; i++) { + rdtscll(start); + aes_encrypt(ctx, pt, ct); + rdtscll(end); + printf(" %d", end - start); + } + aes_encrypt_deinit(ctx); + printf("\n"); +#endif /* __i386__ */ +#endif +} + + +static int test_eax(void) +{ + u8 msg[] = { 0xF7, 0xFB }; + u8 key[] = { 0x91, 0x94, 0x5D, 0x3F, 0x4D, 0xCB, 0xEE, 0x0B, + 0xF4, 0x5E, 0xF5, 0x22, 0x55, 0xF0, 0x95, 0xA4 }; + u8 nonce[] = { 0xBE, 0xCA, 0xF0, 0x43, 0xB0, 0xA2, 0x3D, 0x84, + 0x31, 0x94, 0xBA, 0x97, 0x2C, 0x66, 0xDE, 0xBD }; + u8 hdr[] = { 0xFA, 0x3B, 0xFD, 0x48, 0x06, 0xEB, 0x53, 0xFA }; + u8 cipher[] = { 0x19, 0xDD, 0x5C, 0x4C, 0x93, 0x31, 0x04, 0x9D, + 0x0B, 0xDA, 0xB0, 0x27, 0x74, 0x08, 0xF6, 0x79, + 0x67, 0xE5 }; + u8 data[sizeof(msg)], tag[BLOCK_SIZE]; + + memcpy(data, msg, sizeof(msg)); + if (aes_128_eax_encrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), + data, sizeof(data), tag)) { + printf("AES-128 EAX mode encryption failed\n"); + return 1; + } + if (memcmp(data, cipher, sizeof(data)) != 0) { + printf("AES-128 EAX mode encryption returned invalid cipher " + "text\n"); + return 1; + } + if (memcmp(tag, cipher + sizeof(data), BLOCK_SIZE) != 0) { + printf("AES-128 EAX mode encryption returned invalid tag\n"); + return 1; + } + + if (aes_128_eax_decrypt(key, nonce, sizeof(nonce), hdr, sizeof(hdr), + data, sizeof(data), tag)) { + printf("AES-128 EAX mode decryption failed\n"); + return 1; + } + if (memcmp(data, msg, sizeof(data)) != 0) { + printf("AES-128 EAX mode decryption returned invalid plain " + "text\n"); + return 1; + } + + return 0; +} + + +static int test_cbc(void) +{ + struct cbc_test_vector { + u8 key[16]; + u8 iv[16]; + u8 plain[32]; + u8 cipher[32]; + size_t len; + } vectors[] = { + { + { 0x06, 0xa9, 0x21, 0x40, 0x36, 0xb8, 0xa1, 0x5b, + 0x51, 0x2e, 0x03, 0xd5, 0x34, 0x12, 0x00, 0x06 }, + { 0x3d, 0xaf, 0xba, 0x42, 0x9d, 0x9e, 0xb4, 0x30, + 0xb4, 0x22, 0xda, 0x80, 0x2c, 0x9f, 0xac, 0x41 }, + "Single block msg", + { 0xe3, 0x53, 0x77, 0x9c, 0x10, 0x79, 0xae, 0xb8, + 0x27, 0x08, 0x94, 0x2d, 0xbe, 0x77, 0x18, 0x1a }, + 16 + }, + { + { 0xc2, 0x86, 0x69, 0x6d, 0x88, 0x7c, 0x9a, 0xa0, + 0x61, 0x1b, 0xbb, 0x3e, 0x20, 0x25, 0xa4, 0x5a }, + { 0x56, 0x2e, 0x17, 0x99, 0x6d, 0x09, 0x3d, 0x28, + 0xdd, 0xb3, 0xba, 0x69, 0x5a, 0x2e, 0x6f, 0x58 }, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, + { 0xd2, 0x96, 0xcd, 0x94, 0xc2, 0xcc, 0xcf, 0x8a, + 0x3a, 0x86, 0x30, 0x28, 0xb5, 0xe1, 0xdc, 0x0a, + 0x75, 0x86, 0x60, 0x2d, 0x25, 0x3c, 0xff, 0xf9, + 0x1b, 0x82, 0x66, 0xbe, 0xa6, 0xd6, 0x1a, 0xb1 }, + 32 + } + }; + int ret = 0; + u8 *buf; + unsigned int i; + + for (i = 0; i < sizeof(vectors) / sizeof(vectors[0]); i++) { + struct cbc_test_vector *tv = &vectors[i]; + buf = malloc(tv->len); + if (buf == NULL) { + ret++; + break; + } + memcpy(buf, tv->plain, tv->len); + aes_128_cbc_encrypt(tv->key, tv->iv, buf, tv->len); + if (memcmp(buf, tv->cipher, tv->len) != 0) { + printf("AES-CBC encrypt %d failed\n", i); + ret++; + } + memcpy(buf, tv->cipher, tv->len); + aes_128_cbc_decrypt(tv->key, tv->iv, buf, tv->len); + if (memcmp(buf, tv->plain, tv->len) != 0) { + printf("AES-CBC decrypt %d failed\n", i); + ret++; + } + free(buf); + } + + return ret; +} + + +/* OMAC1 AES-128 test vectors from + * http://csrc.nist.gov/CryptoToolkit/modes/proposedmodes/omac/omac-ad.pdf + */ + +struct omac1_test_vector { + u8 k[16]; + u8 msg[64]; + int msg_len; + u8 tag[16]; +}; + +static struct omac1_test_vector test_vectors[] = +{ + { + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { }, + 0, + { 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 } + }, + { + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a}, + 16, + { 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c } + }, + { + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11 }, + 40, + { 0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, + 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27 } + }, + { + { 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c }, + { 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 }, + 64, + { 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe } + }, +}; + + +int main(int argc, char *argv[]) +{ + u8 kek[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f + }; + u8 plain[] = { + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + u8 crypt[] = { + 0x1F, 0xA6, 0x8B, 0x0A, 0x81, 0x12, 0xB4, 0x47, + 0xAE, 0xF3, 0x4B, 0xD8, 0xFB, 0x5A, 0x7B, 0x82, + 0x9D, 0x3E, 0x86, 0x23, 0x71, 0xD2, 0xCF, 0xE5 + }; + u8 result[24]; + int ret = 0; + unsigned int i; + struct omac1_test_vector *tv; + + if (aes_wrap(kek, 2, plain, result)) { + printf("AES-WRAP-128-128 reported failure\n"); + ret++; + } + if (memcmp(result, crypt, 24) != 0) { + printf("AES-WRAP-128-128 failed\n"); + ret++; + } + if (aes_unwrap(kek, 2, crypt, result)) { + printf("AES-UNWRAP-128-128 reported failure\n"); + ret++; + } + if (memcmp(result, plain, 16) != 0) { + int i; + printf("AES-UNWRAP-128-128 failed\n"); + ret++; + for (i = 0; i < 16; i++) + printf(" %02x", result[i]); + printf("\n"); + } + + test_aes_perf(); + + for (i = 0; i < sizeof(test_vectors) / sizeof(test_vectors[0]); i++) { + tv = &test_vectors[i]; + omac1_aes_128(tv->k, tv->msg, tv->msg_len, result); + if (memcmp(result, tv->tag, 16) != 0) { + printf("OMAC1-AES-128 test vector %d failed\n", i); + ret++; + } + + if (tv->msg_len > 1) { + const u8 *addr[2]; + size_t len[2]; + + addr[0] = tv->msg; + len[0] = 1; + addr[1] = tv->msg + 1; + len[1] = tv->msg_len - 1; + + omac1_aes_128_vector(tv->k, 2, addr, len, result); + if (memcmp(result, tv->tag, 16) != 0) { + printf("OMAC1-AES-128(vector) test vector %d " + "failed\n", i); + ret++; + } + } + } + + ret += test_eax(); + + ret += test_cbc(); + + if (ret) + printf("FAILED!\n"); + + return ret; +} diff --git a/contrib/wpa_supplicant/tests/test_eap_sim_common.c b/contrib/wpa_supplicant/tests/test_eap_sim_common.c new file mode 100644 index 0000000..ee3eee4 --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_eap_sim_common.c @@ -0,0 +1,53 @@ +/* + * Test program for EAP-SIM PRF + * Copyright (c) 2004-2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "eap_sim_common.c" + + +static int test_eap_sim_prf(void) +{ + /* http://csrc.nist.gov/encryption/dss/Examples-1024bit.pdf */ + u8 xkey[] = { + 0xbd, 0x02, 0x9b, 0xbe, 0x7f, 0x51, 0x96, 0x0b, + 0xcf, 0x9e, 0xdb, 0x2b, 0x61, 0xf0, 0x6f, 0x0f, + 0xeb, 0x5a, 0x38, 0xb6 + }; + u8 w[] = { + 0x20, 0x70, 0xb3, 0x22, 0x3d, 0xba, 0x37, 0x2f, + 0xde, 0x1c, 0x0f, 0xfc, 0x7b, 0x2e, 0x3b, 0x49, + 0x8b, 0x26, 0x06, 0x14, 0x3c, 0x6c, 0x18, 0xba, + 0xcb, 0x0f, 0x6c, 0x55, 0xba, 0xbb, 0x13, 0x78, + 0x8e, 0x20, 0xd7, 0x37, 0xa3, 0x27, 0x51, 0x16 + }; + u8 buf[40]; + + printf("Testing EAP-SIM PRF (FIPS 186-2 + change notice 1)\n"); + eap_sim_prf(xkey, buf, sizeof(buf)); + if (memcmp(w, buf, sizeof(w) != 0)) { + printf("eap_sim_prf failed\n"); + return 1; + } + + return 0; +} + + +int main(int argc, char *argv[]) +{ + int errors = 0; + + errors += test_eap_sim_prf(); + + return errors; +} diff --git a/contrib/wpa_supplicant/tests/test_md4.c b/contrib/wpa_supplicant/tests/test_md4.c new file mode 100644 index 0000000..e92e9a5 --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_md4.c @@ -0,0 +1,99 @@ +/* + * Test program for MD4 (test vectors from RFC 1320) + * Copyright (c) 2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" + +int main(int argc, char *argv[]) +{ + struct { + char *data; + u8 *hash; + } tests[] = { + { + "", + "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31" + "\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0" + }, + { + "a", + "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46" + "\x24\x5e\x05\xfb\xdb\xd6\xfb\x24" + }, + { + "abc", + "\xa4\x48\x01\x7a\xaf\x21\xd8\x52" + "\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d" + }, + { + "message digest", + "\xd9\x13\x0a\x81\x64\x54\x9f\xe8" + "\x18\x87\x48\x06\xe1\xc7\x01\x4b" + }, + { + "abcdefghijklmnopqrstuvwxyz", + "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd" + "\xee\xa8\xed\x63\xdf\x41\x2d\xa9" + }, + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789", + "\x04\x3f\x85\x82\xf2\x41\xdb\x35" + "\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4" + }, + { + "12345678901234567890123456789012345678901234567890" + "123456789012345678901234567890", + "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19" + "\x9c\x3e\x7b\x16\x4f\xcc\x05\x36" + } + }; + unsigned int i; + u8 hash[16]; + const u8 *addr[2]; + size_t len[2]; + int errors = 0; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + printf("MD4 test case %d:", i); + + addr[0] = tests[i].data; + len[0] = strlen(tests[i].data); + md4_vector(1, addr, len, hash); + if (memcmp(hash, tests[i].hash, 16) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + + if (len[0]) { + addr[0] = tests[i].data; + len[0] = strlen(tests[i].data); + addr[1] = tests[i].data + 1; + len[1] = strlen(tests[i].data) - 1; + md4_vector(1, addr, len, hash); + if (memcmp(hash, tests[i].hash, 16) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + } + + printf("\n"); + } + + return errors; +} diff --git a/contrib/wpa_supplicant/tests/test_md5.c b/contrib/wpa_supplicant/tests/test_md5.c new file mode 100644 index 0000000..d8fb41e --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_md5.c @@ -0,0 +1,99 @@ +/* + * Test program for MD5 (test vectors from RFC 1321) + * Copyright (c) 2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" + +int main(int argc, char *argv[]) +{ + struct { + char *data; + u8 *hash; + } tests[] = { + { + "", + "\xd4\x1d\x8c\xd9\x8f\x00\xb2\x04" + "\xe9\x80\x09\x98\xec\xf8\x42\x7e" + }, + { + "a", + "\x0c\xc1\x75\xb9\xc0\xf1\xb6\xa8" + "\x31\xc3\x99\xe2\x69\x77\x26\x61" + }, + { + "abc", + "\x90\x01\x50\x98\x3c\xd2\x4f\xb0" + "\xd6\x96\x3f\x7d\x28\xe1\x7f\x72" + }, + { + "message digest", + "\xf9\x6b\x69\x7d\x7c\xb7\x93\x8d" + "\x52\x5a\x2f\x31\xaa\xf1\x61\xd0" + }, + { + "abcdefghijklmnopqrstuvwxyz", + "\xc3\xfc\xd3\xd7\x61\x92\xe4\x00" + "\x7d\xfb\x49\x6c\xca\x67\xe1\x3b" + }, + { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789", + "\xd1\x74\xab\x98\xd2\x77\xd9\xf5" + "\xa5\x61\x1c\x2c\x9f\x41\x9d\x9f" + }, + { + "12345678901234567890123456789012345678901234567890" + "123456789012345678901234567890", + "\x57\xed\xf4\xa2\x2b\xe3\xc9\x55" + "\xac\x49\xda\x2e\x21\x07\xb6\x7a" + } + }; + unsigned int i; + u8 hash[16]; + const u8 *addr[2]; + size_t len[2]; + int errors = 0; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + printf("MD5 test case %d:", i); + + addr[0] = tests[i].data; + len[0] = strlen(tests[i].data); + md5_vector(1, addr, len, hash); + if (memcmp(hash, tests[i].hash, 16) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + + if (len[0]) { + addr[0] = tests[i].data; + len[0] = strlen(tests[i].data); + addr[1] = tests[i].data + 1; + len[1] = strlen(tests[i].data) - 1; + md5_vector(1, addr, len, hash); + if (memcmp(hash, tests[i].hash, 16) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + } + + printf("\n"); + } + + return errors; +} diff --git a/contrib/wpa_supplicant/tests/test_ms_funcs.c b/contrib/wpa_supplicant/tests/test_ms_funcs.c new file mode 100644 index 0000000..09b53c4 --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_ms_funcs.c @@ -0,0 +1,119 @@ +/* + * Test program for ms_funcs + * Copyright (c) 2003-2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "ms_funcs.c" + + +int main(int argc, char *argv[]) +{ + /* Test vector from RFC2759 example */ + u8 *username = "User"; + u8 *password = "clientPass"; + u8 auth_challenge[] = { + 0x5B, 0x5D, 0x7C, 0x7D, 0x7B, 0x3F, 0x2F, 0x3E, + 0x3C, 0x2C, 0x60, 0x21, 0x32, 0x26, 0x26, 0x28 + }; + u8 peer_challenge[] = { + 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A, + 0x28, 0x29, 0x5F, 0x2B, 0x3A, 0x33, 0x7C, 0x7E + }; + u8 challenge[] = { 0xD0, 0x2E, 0x43, 0x86, 0xBC, 0xE9, 0x12, 0x26 }; + u8 password_hash[] = { + 0x44, 0xEB, 0xBA, 0x8D, 0x53, 0x12, 0xB8, 0xD6, + 0x11, 0x47, 0x44, 0x11, 0xF5, 0x69, 0x89, 0xAE + }; + u8 nt_response[] = { + 0x82, 0x30, 0x9E, 0xCD, 0x8D, 0x70, 0x8B, 0x5E, + 0xA0, 0x8F, 0xAA, 0x39, 0x81, 0xCD, 0x83, 0x54, + 0x42, 0x33, 0x11, 0x4A, 0x3D, 0x85, 0xD6, 0xDF + }; + u8 password_hash_hash[] = { + 0x41, 0xC0, 0x0C, 0x58, 0x4B, 0xD2, 0xD9, 0x1C, + 0x40, 0x17, 0xA2, 0xA1, 0x2F, 0xA5, 0x9F, 0x3F + }; + u8 authenticator_response[] = { + 0x40, 0x7A, 0x55, 0x89, 0x11, 0x5F, 0xD0, 0xD6, + 0x20, 0x9F, 0x51, 0x0F, 0xE9, 0xC0, 0x45, 0x66, + 0x93, 0x2C, 0xDA, 0x56 + }; + u8 master_key[] = { + 0xFD, 0xEC, 0xE3, 0x71, 0x7A, 0x8C, 0x83, 0x8C, + 0xB3, 0x88, 0xE5, 0x27, 0xAE, 0x3C, 0xDD, 0x31 + }; + u8 send_start_key[] = { + 0x8B, 0x7C, 0xDC, 0x14, 0x9B, 0x99, 0x3A, 0x1B, + 0xA1, 0x18, 0xCB, 0x15, 0x3F, 0x56, 0xDC, 0xCB + }; + u8 buf[32]; + + int errors = 0; + + printf("Testing ms_funcs.c\n"); + + challenge_hash(peer_challenge, auth_challenge, + username, strlen(username), + buf); + if (memcmp(challenge, buf, sizeof(challenge)) != 0) { + printf("challenge_hash failed\n"); + errors++; + } + + nt_password_hash(password, strlen(password), buf); + if (memcmp(password_hash, buf, sizeof(password_hash)) != 0) { + printf("nt_password_hash failed\n"); + errors++; + } + + generate_nt_response(auth_challenge, peer_challenge, + username, strlen(username), + password, strlen(password), + buf); + if (memcmp(nt_response, buf, sizeof(nt_response)) != 0) { + printf("generate_nt_response failed\n"); + errors++; + } + + hash_nt_password_hash(password_hash, buf); + if (memcmp(password_hash_hash, buf, sizeof(password_hash_hash)) != 0) { + printf("hash_nt_password_hash failed\n"); + errors++; + } + + generate_authenticator_response(password, strlen(password), + peer_challenge, auth_challenge, + username, strlen(username), + nt_response, buf); + if (memcmp(authenticator_response, buf, sizeof(authenticator_response)) + != 0) { + printf("generate_authenticator_response failed\n"); + errors++; + } + + get_master_key(password_hash_hash, nt_response, buf); + if (memcmp(master_key, buf, sizeof(master_key)) != 0) { + printf("get_master_key failed\n"); + errors++; + } + + get_asymetric_start_key(master_key, buf, sizeof(send_start_key), 1, 1); + if (memcmp(send_start_key, buf, sizeof(send_start_key)) != 0) { + printf("get_asymetric_start_key failed\n"); + errors++; + } + + if (errors) + printf("FAILED! %d errors\n", errors); + + return errors; +} diff --git a/contrib/wpa_supplicant/tests/test_sha1.c b/contrib/wpa_supplicant/tests/test_sha1.c new file mode 100644 index 0000000..a34e3bf --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_sha1.c @@ -0,0 +1,328 @@ +/* + * Test program for SHA1 and MD5 + * Copyright (c) 2003-2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha1.h" +#include "md5.h" +#include "crypto.h" + + +static int test_eap_fast(void) +{ + /* draft-cam-winget-eap-fast-01.txt */ + const u8 pac_key[] = { + 0x0B, 0x97, 0x39, 0x0F, 0x37, 0x51, 0x78, 0x09, + 0x81, 0x1E, 0xFD, 0x9C, 0x6E, 0x65, 0x94, 0x2B, + 0x63, 0x2C, 0xE9, 0x53, 0x89, 0x38, 0x08, 0xBA, + 0x36, 0x0B, 0x03, 0x7C, 0xD1, 0x85, 0xE4, 0x14 + }; + const u8 seed[] = { + 0x3F, 0xFB, 0x11, 0xC4, 0x6C, 0xBF, 0xA5, 0x7A, + 0x54, 0x40, 0xDA, 0xE8, 0x22, 0xD3, 0x11, 0xD3, + 0xF7, 0x6D, 0xE4, 0x1D, 0xD9, 0x33, 0xE5, 0x93, + 0x70, 0x97, 0xEB, 0xA9, 0xB3, 0x66, 0xF4, 0x2A, + 0x00, 0x00, 0x00, 0x02, 0x6A, 0x66, 0x43, 0x2A, + 0x8D, 0x14, 0x43, 0x2C, 0xEC, 0x58, 0x2D, 0x2F, + 0xC7, 0x9C, 0x33, 0x64, 0xBA, 0x04, 0xAD, 0x3A, + 0x52, 0x54, 0xD6, 0xA5, 0x79, 0xAD, 0x1E, 0x00 + }; + const u8 master_secret[] = { + 0x4A, 0x1A, 0x51, 0x2C, 0x01, 0x60, 0xBC, 0x02, + 0x3C, 0xCF, 0xBC, 0x83, 0x3F, 0x03, 0xBC, 0x64, + 0x88, 0xC1, 0x31, 0x2F, 0x0B, 0xA9, 0xA2, 0x77, + 0x16, 0xA8, 0xD8, 0xE8, 0xBD, 0xC9, 0xD2, 0x29, + 0x38, 0x4B, 0x7A, 0x85, 0xBE, 0x16, 0x4D, 0x27, + 0x33, 0xD5, 0x24, 0x79, 0x87, 0xB1, 0xC5, 0xA2 + }; + const u8 key_block[] = { + 0x59, 0x59, 0xBE, 0x8E, 0x41, 0x3A, 0x77, 0x74, + 0x8B, 0xB2, 0xE5, 0xD3, 0x60, 0xAC, 0x4D, 0x35, + 0xDF, 0xFB, 0xC8, 0x1E, 0x9C, 0x24, 0x9C, 0x8B, + 0x0E, 0xC3, 0x1D, 0x72, 0xC8, 0x84, 0x9D, 0x57, + 0x48, 0x51, 0x2E, 0x45, 0x97, 0x6C, 0x88, 0x70, + 0xBE, 0x5F, 0x01, 0xD3, 0x64, 0xE7, 0x4C, 0xBB, + 0x11, 0x24, 0xE3, 0x49, 0xE2, 0x3B, 0xCD, 0xEF, + 0x7A, 0xB3, 0x05, 0x39, 0x5D, 0x64, 0x8A, 0x44, + 0x11, 0xB6, 0x69, 0x88, 0x34, 0x2E, 0x8E, 0x29, + 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, + 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, + 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, + 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, + 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 + }; + const u8 sks[] = { + 0xD6, 0x4B, 0x7D, 0x72, 0x17, 0x59, 0x28, 0x05, + 0xAF, 0xF9, 0xB7, 0xFF, 0x66, 0x6D, 0xA1, 0x96, + 0x8F, 0x0B, 0x5E, 0x06, 0x46, 0x7A, 0x44, 0x84, + 0x64, 0xC1, 0xC8, 0x0C, 0x96, 0x44, 0x09, 0x98, + 0xFF, 0x92, 0xA8, 0xB4, 0xC6, 0x42, 0x28, 0x71 + }; + const u8 isk[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + const u8 imck[] = { + 0x16, 0x15, 0x3C, 0x3F, 0x21, 0x55, 0xEF, 0xD9, + 0x7F, 0x34, 0xAE, 0xC8, 0x1A, 0x4E, 0x66, 0x80, + 0x4C, 0xC3, 0x76, 0xF2, 0x8A, 0xA9, 0x6F, 0x96, + 0xC2, 0x54, 0x5F, 0x8C, 0xAB, 0x65, 0x02, 0xE1, + 0x18, 0x40, 0x7B, 0x56, 0xBE, 0xEA, 0xA7, 0xC5, + 0x76, 0x5D, 0x8F, 0x0B, 0xC5, 0x07, 0xC6, 0xB9, + 0x04, 0xD0, 0x69, 0x56, 0x72, 0x8B, 0x6B, 0xB8, + 0x15, 0xEC, 0x57, 0x7B + }; + const u8 msk[] = { + 0x4D, 0x83, 0xA9, 0xBE, 0x6F, 0x8A, 0x74, 0xED, + 0x6A, 0x02, 0x66, 0x0A, 0x63, 0x4D, 0x2C, 0x33, + 0xC2, 0xDA, 0x60, 0x15, 0xC6, 0x37, 0x04, 0x51, + 0x90, 0x38, 0x63, 0xDA, 0x54, 0x3E, 0x14, 0xB9, + 0x27, 0x99, 0x18, 0x1E, 0x07, 0xBF, 0x0F, 0x5A, + 0x5E, 0x3C, 0x32, 0x93, 0x80, 0x8C, 0x6C, 0x49, + 0x67, 0xED, 0x24, 0xFE, 0x45, 0x40, 0xA0, 0x59, + 0x5E, 0x37, 0xC2, 0xE9, 0xD0, 0x5D, 0x0A, 0xE3 + }; + u8 tlv[] = { + 0x80, 0x0C, 0x00, 0x38, 0x00, 0x01, 0x01, 0x00, + 0xD8, 0x6A, 0x8C, 0x68, 0x3C, 0x32, 0x31, 0xA8, + 0x56, 0x63, 0xB6, 0x40, 0x21, 0xFE, 0x21, 0x14, + 0x4E, 0xE7, 0x54, 0x20, 0x79, 0x2D, 0x42, 0x62, + 0xC9, 0xBF, 0x53, 0x7F, 0x54, 0xFD, 0xAC, 0x58, + 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, + 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, + 0x05, 0xC5, 0x5B, 0xB7 + }; + const u8 compound_mac[] = { + 0x43, 0x24, 0x6E, 0x30, 0x92, 0x17, 0x6D, 0xCF, + 0xE6, 0xE0, 0x69, 0xEB, 0x33, 0x61, 0x6A, 0xCC, + 0x05, 0xC5, 0x5B, 0xB7 + }; + u8 buf[512]; + const u8 *simck, *cmk; + int errors = 0; + + printf("EAP-FAST test cases\n"); + + printf("- T-PRF (SHA1) test case / master_secret\n"); + sha1_t_prf(pac_key, sizeof(pac_key), "PAC to master secret label hash", + seed, sizeof(seed), buf, sizeof(master_secret)); + if (memcmp(master_secret, buf, sizeof(master_secret)) != 0) { + printf("T-PRF test - FAILED!\n"); + errors++; + } + + printf("- PRF (TLS, SHA1/MD5) test case / key_block\n"); + tls_prf(master_secret, sizeof(master_secret), "key expansion", + seed, sizeof(seed), buf, sizeof(key_block)); + if (memcmp(key_block, buf, sizeof(key_block)) != 0) { + printf("PRF test - FAILED!\n"); + errors++; + } + + printf("- T-PRF (SHA1) test case / IMCK\n"); + sha1_t_prf(sks, sizeof(sks), "Inner Methods Compound Keys", + isk, sizeof(isk), buf, sizeof(imck)); + if (memcmp(imck, buf, sizeof(imck)) != 0) { + printf("T-PRF test - FAILED!\n"); + errors++; + } + + simck = imck; + cmk = imck + 40; + + printf("- T-PRF (SHA1) test case / MSK\n"); + sha1_t_prf(simck, 40, "Session Key Generating Function", + (u8 *) "", 0, buf, sizeof(msk)); + if (memcmp(msk, buf, sizeof(msk)) != 0) { + printf("T-PRF test - FAILED!\n"); + errors++; + } + + printf("- Compound MAC test case\n"); + memset(tlv + sizeof(tlv) - 20, 0, 20); + hmac_sha1(cmk, 20, tlv, sizeof(tlv), tlv + sizeof(tlv) - 20); + if (memcmp(tlv + sizeof(tlv) - 20, compound_mac, sizeof(compound_mac)) + != 0) { + printf("Compound MAC test - FAILED!\n"); + errors++; + } + + return errors; +} + + +static u8 key0[] = +{ + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b +}; +static u8 data0[] = "Hi There"; +static u8 prf0[] = +{ + 0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84, + 0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54, + 0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06, + 0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee, + 0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88, + 0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb, + 0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e, + 0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a +}; + +static u8 key1[] = "Jefe"; +static u8 data1[] = "what do ya want for nothing?"; +static u8 prf1[] = +{ + 0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad, + 0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4, + 0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58, + 0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09, + 0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa, + 0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02, + 0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7, + 0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc +}; + + +static u8 key2[] = +{ + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa +}; +static u8 data2[] = +{ + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd +}; +static u8 prf2[] = +{ + 0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f, + 0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1, + 0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1, + 0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce, + 0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc, + 0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae, + 0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6, + 0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07 +}; + + +struct passphrase_test { + char *passphrase; + char *ssid; + char psk[32]; +}; + +static struct passphrase_test passphrase_tests[] = +{ + { + "password", + "IEEE", + { + 0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef, + 0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90, + 0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2, + 0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e + } + }, + { + "ThisIsAPassword", + "ThisIsASSID", + { + 0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6, + 0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3, + 0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08, + 0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf + } + }, + { + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ", + { + 0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83, + 0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c, + 0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48, + 0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62 + } + }, +}; + +#define NUM_PASSPHRASE_TESTS \ +(sizeof(passphrase_tests) / sizeof(passphrase_tests[0])) + + +int main(int argc, char *argv[]) +{ + u8 res[512]; + int ret = 0; + unsigned int i; + + printf("PRF-SHA1 test cases:\n"); + + sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1, + res, sizeof(prf0)); + if (memcmp(res, prf0, sizeof(prf0)) == 0) + printf("Test case 0 - OK\n"); + else { + printf("Test case 0 - FAILED!\n"); + ret++; + } + + sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1, + res, sizeof(prf1)); + if (memcmp(res, prf1, sizeof(prf1)) == 0) + printf("Test case 1 - OK\n"); + else { + printf("Test case 1 - FAILED!\n"); + ret++; + } + + sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2), + res, sizeof(prf2)); + if (memcmp(res, prf2, sizeof(prf2)) == 0) + printf("Test case 2 - OK\n"); + else { + printf("Test case 2 - FAILED!\n"); + ret++; + } + + ret += test_eap_fast(); + + printf("PBKDF2-SHA1 Passphrase test cases:\n"); + for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) { + u8 psk[32]; + struct passphrase_test *test = &passphrase_tests[i]; + pbkdf2_sha1(test->passphrase, + test->ssid, strlen(test->ssid), + 4096, psk, 32); + if (memcmp(psk, test->psk, 32) == 0) + printf("Test case %d - OK\n", i); + else { + printf("Test case %d - FAILED!\n", i); + ret++; + } + } + + return ret; +} diff --git a/contrib/wpa_supplicant/tests/test_sha256.c b/contrib/wpa_supplicant/tests/test_sha256.c new file mode 100644 index 0000000..161533e --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_sha256.c @@ -0,0 +1,330 @@ +/* + * Test program for SHA256 + * Copyright (c) 2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "sha256.h" +#include "crypto.h" + +struct { + char *data; + u8 hash[32]; +} tests[] = { + { + "abc", + { + 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, + 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, + 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, + 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad + } + }, + { + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + { + 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, + 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, + 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, + 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 + } + } +}; + +struct hmac_test { + u8 key[80]; + size_t key_len; + u8 data[128]; + size_t data_len; + u8 hash[32]; +} hmac_tests[] = { + /* draft-ietf-ipsec-ciph-sha-256-01.txt */ + { + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 + }, + 32, + "abc", 3, + { + 0xa2, 0x1b, 0x1f, 0x5d, 0x4c, 0xf4, 0xf7, 0x3a, + 0x4d, 0xd9, 0x39, 0x75, 0x0f, 0x7a, 0x06, 0x6a, + 0x7f, 0x98, 0xcc, 0x13, 0x1c, 0xb1, 0x6a, 0x66, + 0x92, 0x75, 0x90, 0x21, 0xcf, 0xab, 0x81, 0x81 + } + }, + { + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 + }, + 32, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + 56, + { + 0x10, 0x4f, 0xdc, 0x12, 0x57, 0x32, 0x8f, 0x08, + 0x18, 0x4b, 0xa7, 0x31, 0x31, 0xc5, 0x3c, 0xae, + 0xe6, 0x98, 0xe3, 0x61, 0x19, 0x42, 0x11, 0x49, + 0xea, 0x8c, 0x71, 0x24, 0x56, 0x69, 0x7d, 0x30 + } + }, + { + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20 + }, + 32, + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + 112, + { + 0x47, 0x03, 0x05, 0xfc, 0x7e, 0x40, 0xfe, 0x34, + 0xd3, 0xee, 0xb3, 0xe7, 0x73, 0xd9, 0x5a, 0xab, + 0x73, 0xac, 0xf0, 0xfd, 0x06, 0x04, 0x47, 0xa5, + 0xeb, 0x45, 0x95, 0xbf, 0x33, 0xa9, 0xd1, 0xa3 + } + }, + { + { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b + }, + 32, + "Hi There", + 8, + { + 0x19, 0x8a, 0x60, 0x7e, 0xb4, 0x4b, 0xfb, 0xc6, + 0x99, 0x03, 0xa0, 0xf1, 0xcf, 0x2b, 0xbd, 0xc5, + 0xba, 0x0a, 0xa3, 0xf3, 0xd9, 0xae, 0x3c, 0x1c, + 0x7a, 0x3b, 0x16, 0x96, 0xa0, 0xb6, 0x8c, 0xf7 + } + }, + { + "Jefe", + 4, + "what do ya want for nothing?", + 28, + { + 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, + 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, + 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, + 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 + } + }, + { + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + }, + 32, + { + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, + 0xdd, 0xdd + }, + 50, + { + 0xcd, 0xcb, 0x12, 0x20, 0xd1, 0xec, 0xcc, 0xea, + 0x91, 0xe5, 0x3a, 0xba, 0x30, 0x92, 0xf9, 0x62, + 0xe5, 0x49, 0xfe, 0x6c, 0xe9, 0xed, 0x7f, 0xdc, + 0x43, 0x19, 0x1f, 0xbd, 0xe4, 0x5c, 0x30, 0xb0 + } + }, + { + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, + 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, + 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25 + }, + 37, + { + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, + 0xcd, 0xcd + }, + 50, + { + 0xd4, 0x63, 0x3c, 0x17, 0xf6, 0xfb, 0x8d, 0x74, + 0x4c, 0x66, 0xde, 0xe0, 0xf8, 0xf0, 0x74, 0x55, + 0x6e, 0xc4, 0xaf, 0x55, 0xef, 0x07, 0x99, 0x85, + 0x41, 0x46, 0x8e, 0xb4, 0x9b, 0xd2, 0xe9, 0x17 + } + }, + { + { + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, + 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c + }, + 32, + "Test With Truncation", + 20, + { + 0x75, 0x46, 0xaf, 0x01, 0x84, 0x1f, 0xc0, 0x9b, + 0x1a, 0xb9, 0xc3, 0x74, 0x9a, 0x5f, 0x1c, 0x17, + 0xd4, 0xf5, 0x89, 0x66, 0x8a, 0x58, 0x7b, 0x27, + 0x00, 0xa9, 0xc9, 0x7c, 0x11, 0x93, 0xcf, 0x42 + } + }, + { + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + }, + 80, + "Test Using Larger Than Block-Size Key - Hash Key First", + 54, + { + 0x69, 0x53, 0x02, 0x5e, 0xd9, 0x6f, 0x0c, 0x09, + 0xf8, 0x0a, 0x96, 0xf7, 0x8e, 0x65, 0x38, 0xdb, + 0xe2, 0xe7, 0xb8, 0x20, 0xe3, 0xdd, 0x97, 0x0e, + 0x7d, 0xdd, 0x39, 0x09, 0x1b, 0x32, 0x35, 0x2f + } + }, + { + { + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa + }, + 80, + "Test Using Larger Than Block-Size Key and Larger Than One " + "Block-Size Data", + 73, + { + 0x63, 0x55, 0xac, 0x22, 0xe8, 0x90, 0xd0, 0xa3, + 0xc8, 0x48, 0x1a, 0x5c, 0xa4, 0x82, 0x5b, 0xc8, + 0x84, 0xd3, 0xe7, 0xa1, 0xff, 0x98, 0xa2, 0xfc, + 0x2a, 0xc7, 0xd8, 0xe0, 0x64, 0xc3, 0xb2, 0xe6 + } + } +}; + + +int main(int argc, char *argv[]) +{ + + unsigned int i; + u8 hash[32]; + const u8 *addr[2]; + size_t len[2]; + int errors = 0; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + printf("SHA256 test case %d:", i + 1); + + addr[0] = (u8 *) tests[i].data; + len[0] = strlen(tests[i].data); + sha256_vector(1, addr, len, hash); + if (memcmp(hash, tests[i].hash, 32) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + + if (len[0]) { + addr[0] = (u8 *) tests[i].data; + len[0] = 1; + addr[1] = (u8 *) tests[i].data + 1; + len[1] = strlen(tests[i].data) - 1; + sha256_vector(2, addr, len, hash); + if (memcmp(hash, tests[i].hash, 32) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + } + + printf("\n"); + } + + for (i = 0; i < sizeof(hmac_tests) / sizeof(hmac_tests[0]); i++) { + struct hmac_test *t = &hmac_tests[i]; + printf("HMAC-SHA256 test case %d:", i + 1); + + hmac_sha256(t->key, t->key_len, t->data, t->data_len, hash); + if (memcmp(hash, t->hash, 32) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + + addr[0] = t->data; + len[0] = t->data_len; + hmac_sha256_vector(t->key, t->key_len, 1, addr, len, hash); + if (memcmp(hash, t->hash, 32) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + + if (len[0]) { + addr[0] = t->data; + len[0] = 1; + addr[1] = t->data + 1; + len[1] = t->data_len - 1; + hmac_sha256_vector(t->key, t->key_len, 2, addr, len, + hash); + if (memcmp(hash, t->hash, 32) != 0) { + printf(" FAIL"); + errors++; + } else + printf(" OK"); + } + + printf("\n"); + } + + printf("Test IEEE 802.11r KDF\n"); + sha256_prf("abc", 3, "KDF test", "data", 4, hash, sizeof(hash)); + /* TODO: add proper test case for this */ + + return errors; +} diff --git a/contrib/wpa_supplicant/tests/test_x509v3.c b/contrib/wpa_supplicant/tests/test_x509v3.c new file mode 100644 index 0000000..aa98ece --- /dev/null +++ b/contrib/wpa_supplicant/tests/test_x509v3.c @@ -0,0 +1,69 @@ +/* + * Testing tool for X.509v3 routines + * Copyright (c) 2006, Jouni Malinen + * + * 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 + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of BSD + * license. + * + * See README and COPYING for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "asn1.h" +#include "x509v3.h" + +extern int wpa_debug_level; + + +int main(int argc, char *argv[]) +{ + char *buf; + size_t len; + struct x509_certificate *certs = NULL, *last = NULL, *cert; + int i, reason; + + wpa_debug_level = 0; + + if (argc < 3 || strcmp(argv[1], "-v") != 0) { + printf("usage: test_x509v3 -v ..\n"); + return -1; + } + + for (i = 2; i < argc; i++) { + printf("Reading: %s\n", argv[i]); + buf = os_readfile(argv[i], &len); + if (buf == NULL) { + printf("Failed to read '%s'\n", argv[i]); + return -1; + } + + cert = x509_certificate_parse(buf, len); + if (cert == NULL) { + printf("Failed to parse X.509 certificate\n"); + return -1; + } + + free(buf); + + if (certs == NULL) + certs = cert; + else + last->next = cert; + last = cert; + } + + printf("\n\nValidating certificate chain\n"); + if (x509_certificate_chain_validate(last, certs, &reason) < 0) { + printf("\nCertificate chain validation failed: %d\n", reason); + return -1; + } + printf("\nCertificate chain is valid\n"); + + return 0; +} diff --git a/contrib/wpa_supplicant/tls_openssl.c b/contrib/wpa_supplicant/tls_openssl.c index c8d941f..d5aafaa 100644 --- a/contrib/wpa_supplicant/tls_openssl.c +++ b/contrib/wpa_supplicant/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/wpa_supplicant/version.h b/contrib/wpa_supplicant/version.h index 2eed290..364d8ae 100644 --- a/contrib/wpa_supplicant/version.h +++ b/contrib/wpa_supplicant/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/wpa_supplicant/wpa.c b/contrib/wpa_supplicant/wpa.c index b6dd756..5669e6a 100644 --- a/contrib/wpa_supplicant/wpa.c +++ b/contrib/wpa_supplicant/wpa.c @@ -4161,10 +4161,6 @@ int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, * @wpa_ie: Pointer to buffer for WPA/RSN IE * @wpa_ie_len: Pointer to the length of the wpa_ie buffer * Returns: 0 on success, -1 on failure - * - * Inform WPA state machine about the WPA/RSN IE used in (Re)Association - * Request frame. The IE will be used to override the default value generated - * with wpa_sm_set_assoc_wpa_ie_default(). */ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, size_t *wpa_ie_len) diff --git a/contrib/wpa_supplicant/wpa_cli.c b/contrib/wpa_supplicant/wpa_cli.c index a641249..7176c95 100644 --- a/contrib/wpa_supplicant/wpa_cli.c +++ b/contrib/wpa_supplicant/wpa_cli.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - command line interface for wpa_supplicant daemon - * Copyright (c) 2004-2007, Jouni Malinen + * Copyright (c) 2004-2008, Jouni Malinen * * 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 @@ -31,7 +31,7 @@ static const char *wpa_cli_version = "wpa_cli v" VERSION_STR "\n" -"Copyright (c) 2004-2007, Jouni Malinen and contributors"; +"Copyright (c) 2004-2008, Jouni Malinen and contributors"; static const char *wpa_cli_license = @@ -120,8 +120,10 @@ static const char *commands_help = " list of variables when run without arguments)\n" " get_network = get network variables\n" " save_config = save the current configuration\n" -" disconnect = disconnect and wait for reassociate command before " -"connecting\n" +" disconnect = disconnect and wait for reassociate/reconnect command before\n " +" connecting\n" +" reconnect = like reassociate, but only takes effect if already " +"disconnected\n" " scan = request new BSS scan\n" " scan_results = get latest scan results\n" " get_capability = " @@ -318,13 +320,13 @@ static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc != 2) { printf("Invalid SET command: needs two arguments (variable " "name and value)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long SET command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -358,13 +360,13 @@ static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, if (argc != 1) { printf("Invalid PREAUTH command: needs one argument " "(BSSID)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long PREAUTH command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -378,12 +380,12 @@ static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc != 1) { printf("Invalid AP_SCAN command: needs one argument (ap_scan " "value)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long AP_SCAN command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -398,13 +400,13 @@ static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, if (argc != 1) { printf("Invalid STKSTART command: needs one argument " "(Peer STA MAC address)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long STKSTART command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -418,12 +420,12 @@ static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc != 1) { printf("Invalid LEVEL command: needs one argument (debug " "level)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long LEVEL command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -437,7 +439,7 @@ static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc < 2) { printf("Invalid IDENTITY command: needs two arguments " "(network id and identity)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -446,14 +448,14 @@ static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long IDENTITY command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long IDENTITY command.\n"); - return 0; + return -1; } pos += ret; } @@ -470,7 +472,7 @@ static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc < 2) { printf("Invalid PASSWORD command: needs two arguments " "(network id and password)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -479,14 +481,14 @@ static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long PASSWORD command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long PASSWORD command.\n"); - return 0; + return -1; } pos += ret; } @@ -504,7 +506,7 @@ static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, if (argc < 2) { printf("Invalid NEW_PASSWORD command: needs two arguments " "(network id and password)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -513,14 +515,14 @@ static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long NEW_PASSWORD command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long NEW_PASSWORD command.\n"); - return 0; + return -1; } pos += ret; } @@ -537,7 +539,7 @@ static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc < 2) { printf("Invalid PIN command: needs two arguments " "(network id and pin)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -546,14 +548,14 @@ static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long PIN command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long PIN command.\n"); - return 0; + return -1; } pos += ret; } @@ -569,7 +571,7 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc < 2) { printf("Invalid OTP command: needs two arguments (network " "id and password)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -578,14 +580,14 @@ static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long OTP command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long OTP command.\n"); - return 0; + return -1; } pos += ret; } @@ -603,7 +605,7 @@ static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, if (argc < 2) { printf("Invalid PASSPHRASE command: needs two arguments " "(network id and passphrase)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -612,14 +614,14 @@ static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, argv[0], argv[1]); if (ret < 0 || ret >= end - pos) { printf("Too long PASSPHRASE command.\n"); - return 0; + return -1; } pos += ret; for (i = 2; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long PASSPHRASE command.\n"); - return 0; + return -1; } pos += ret; } @@ -636,7 +638,7 @@ static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) if (argc < 2) { printf("Invalid BSSID command: needs two arguments (network " "id and BSSID)\n"); - return 0; + return -1; } end = cmd + sizeof(cmd); @@ -644,14 +646,14 @@ static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) ret = os_snprintf(pos, end - pos, "BSSID"); if (ret < 0 || ret >= end - pos) { printf("Too long BSSID command.\n"); - return 0; + return -1; } pos += ret; for (i = 0; i < argc; i++) { ret = os_snprintf(pos, end - pos, " %s", argv[i]); if (ret < 0 || ret >= end - pos) { printf("Too long BSSID command.\n"); - return 0; + return -1; } pos += ret; } @@ -675,7 +677,7 @@ static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, if (argc < 1) { printf("Invalid SELECT_NETWORK command: needs one argument " "(network id)\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]); @@ -693,7 +695,7 @@ static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, if (argc < 1) { printf("Invalid ENABLE_NETWORK command: needs one argument " "(network id)\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]); @@ -711,7 +713,7 @@ static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, if (argc < 1) { printf("Invalid DISABLE_NETWORK command: needs one argument " "(network id)\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]); @@ -736,7 +738,7 @@ static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, if (argc < 1) { printf("Invalid REMOVE_NETWORK command: needs one argument " "(network id)\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]); @@ -781,14 +783,14 @@ static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, if (argc != 3) { printf("Invalid SET_NETWORK command: needs three arguments\n" "(network id, variable name, and value)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s", argv[0], argv[1], argv[2]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long SET_NETWORK command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -808,14 +810,14 @@ static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, if (argc != 2) { printf("Invalid GET_NETWORK command: needs two arguments\n" "(network id and variable name)\n"); - return 0; + return -1; } res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s", argv[0], argv[1]); if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { printf("Too long GET_NETWORK command.\n"); - return 0; + return -1; } return wpa_ctrl_command(ctrl, cmd); } @@ -828,6 +830,13 @@ static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, } +static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, + char *argv[]) +{ + return wpa_ctrl_command(ctrl, "RECONNECT"); +} + + static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, char *argv[]) { @@ -856,13 +865,13 @@ static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, if (argc < 1 || argc > 2) { printf("Invalid GET_CAPABILITY command: need either one or " "two arguments\n"); - return 0; + return -1; } if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { printf("Invalid GET_CAPABILITY command: second argument, " "if any, must be 'strict'\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0], @@ -929,9 +938,9 @@ static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, if (argc < 1) { printf("Invalid INTERFACE_ADD command: needs at least one " "argument (interface name)\n" - "All arguments: ifname confname driver ctrl_interface " - "driver_param bridge_name\n"); - return 0; + "All arguments: ifname confname driver ctrl_interface " + "driver_param bridge_name\n"); + return -1; } /* @@ -956,7 +965,7 @@ static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, if (argc != 1) { printf("Invalid INTERFACE_REMOVE command: needs one argument " "(interface name)\n"); - return 0; + return -1; } os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]); @@ -1002,6 +1011,7 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { { "get_network", wpa_cli_cmd_get_network }, { "save_config", wpa_cli_cmd_save_config }, { "disconnect", wpa_cli_cmd_disconnect }, + { "reconnect", wpa_cli_cmd_reconnect }, { "scan", wpa_cli_cmd_scan }, { "scan_results", wpa_cli_cmd_scan_results }, { "get_capability", wpa_cli_cmd_get_capability }, @@ -1015,10 +1025,11 @@ static struct wpa_cli_cmd wpa_cli_commands[] = { }; -static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) +static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) { struct wpa_cli_cmd *cmd, *match = NULL; int count; + int ret = 0; count = 0; cmd = wpa_cli_commands; @@ -1047,11 +1058,15 @@ static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) cmd++; } printf("\n"); + ret = 1; } else if (count == 0) { printf("Unknown command '%s'\n", argv[0]); + ret = 1; } else { - match->handler(ctrl, argc - 1, &argv[1]); + ret = match->handler(ctrl, argc - 1, &argv[1]); } + + return ret; } @@ -1497,6 +1512,7 @@ int main(int argc, char *argv[]) int warning_displayed = 0; int c; int daemonize = 0; + int ret = 0; const char *global = NULL; if (os_program_init()) @@ -1608,12 +1624,12 @@ int main(int argc, char *argv[]) else if (action_file) wpa_cli_action(ctrl_conn); else - wpa_request(ctrl_conn, argc - optind, &argv[optind]); + ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]); os_free(ctrl_ifname); wpa_cli_cleanup(); - return 0; + return ret; } #else /* CONFIG_CTRL_IFACE */ diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp index ca86265..6ea35e0 100644 --- a/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp +++ b/contrib/wpa_supplicant/wpa_gui-qt4/networkconfig.cpp @@ -162,7 +162,7 @@ void NetworkConfig::addNetwork() setNetworkParam(id, "ssid", ssidEdit->text().ascii(), true); - char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; + const char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; switch (auth) { case AUTH_NONE: key_mgmt = "NONE"; diff --git a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp index 1dc7af2..31cb38c 100644 --- a/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp +++ b/contrib/wpa_supplicant/wpa_gui-qt4/wpagui.cpp @@ -1,6 +1,6 @@ /* * wpa_gui - WpaGui class - * Copyright (c) 2005-2006, Jouni Malinen + * Copyright (c) 2005-2008, Jouni Malinen * * 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 @@ -513,7 +513,7 @@ void WpaGui::helpContents() void WpaGui::helpAbout() { QMessageBox::about(this, "wpa_gui for wpa_supplicant", - "Copyright (c) 2003-2006,\n" + "Copyright (c) 2003-2008,\n" "Jouni Malinen \n" "and contributors.\n" "\n" diff --git a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h b/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h index 49bc722..a3cd733 100644 --- a/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h +++ b/contrib/wpa_supplicant/wpa_gui/networkconfig.ui.h @@ -131,7 +131,7 @@ void NetworkConfig::addNetwork() setNetworkParam(id, "ssid", ssidEdit->text().ascii(), true); - char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; + const char *key_mgmt = NULL, *proto = NULL, *pairwise = NULL; switch (auth) { case AUTH_NONE: key_mgmt = "NONE"; diff --git a/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling b/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling index e173b00..07e4a8f 100755 --- a/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling +++ b/contrib/wpa_supplicant/wpa_gui/setup-mingw-cross-compiling @@ -4,8 +4,8 @@ # and I have no idea how to change these. For now, just override the # directories in the Makefile.Release file after qmake run. -qmake -spec /q/jm/qt4-win/4.0.0/mkspecs/win32-g++ wpa_gui.pro -o Makefile +qmake -spec /q/jm/qt4-win/4.3.3/mkspecs/win32-g++ wpa_gui.pro -o Makefile cat Makefile.Release | - sed s%qt4/lib%qt4-win/4.0.0/lib%g | - sed s%qt4/include%qt4-win/4.0.0/include%g > tmp.Makefile.Release && + sed s%/usr/lib/qt4%/q/jm/qt4-win/4.3.3/lib%g | + sed s%/usr/include/qt4%/q/jm/qt4-win/4.3.3/include%g > tmp.Makefile.Release && mv -f tmp.Makefile.Release Makefile.Release diff --git a/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h b/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h index 04e438d..6db8862 100644 --- a/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h +++ b/contrib/wpa_supplicant/wpa_gui/wpagui.ui.h @@ -468,7 +468,7 @@ void WpaGui::helpContents() void WpaGui::helpAbout() { QMessageBox::about(this, "wpa_gui for wpa_supplicant", - "Copyright (c) 2003-2005,\n" + "Copyright (c) 2003-2008,\n" "Jouni Malinen \n" "and contributors.\n" "\n" diff --git a/contrib/wpa_supplicant/wpa_supplicant.c b/contrib/wpa_supplicant/wpa_supplicant.c index f7ac13e..99f1185 100644 --- a/contrib/wpa_supplicant/wpa_supplicant.c +++ b/contrib/wpa_supplicant/wpa_supplicant.c @@ -1,6 +1,6 @@ /* * WPA Supplicant - * Copyright (c) 2003-2007, Jouni Malinen + * Copyright (c) 2003-2008, Jouni Malinen * * 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 @@ -38,7 +38,7 @@ const char *wpa_supplicant_version = "wpa_supplicant v" VERSION_STR "\n" -"Copyright (c) 2003-2007, Jouni Malinen and contributors"; +"Copyright (c) 2003-2008, Jouni Malinen and contributors"; const char *wpa_supplicant_license = "This program is free software. You can distribute it and/or modify it\n" @@ -106,7 +106,6 @@ const char *wpa_supplicant_full_license5 = extern struct wpa_driver_ops *wpa_supplicant_drivers[]; -extern int wpa_debug_use_file; extern int wpa_debug_level; extern int wpa_debug_show_keys; extern int wpa_debug_timestamp; @@ -519,7 +518,7 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) if (os_memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0) bssid = wpa_s->pending_bssid; wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", - MAC2STR(wpa_s->bssid)); + MAC2STR(bssid)); wpa_blacklist_add(wpa_s, bssid); wpa_sm_notify_disassoc(wpa_s->wpa); wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING); @@ -900,6 +899,13 @@ int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) * TODO: should notify EAPOL SM about changes in opensc_engine_path, * pkcs11_engine_path, pkcs11_module_path. */ + if (wpa_s->key_mgmt == WPA_KEY_MGMT_PSK) { + /* + * Clear forced success to clear EAP state for next + * authentication. + */ + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + } eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); wpa_sm_set_config(wpa_s->wpa, NULL); wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); @@ -956,7 +962,7 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) struct wpa_ssid *ssid; int enabled, scan_req = 0, ret; - if (wpa_s->disconnected) + if (wpa_s->disconnected && !wpa_s->scan_req) return; enabled = 0; @@ -1461,6 +1467,8 @@ void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; } + if (ssid->mode == 1 && ssid->frequency > 0 && params.freq == 0) + params.freq = ssid->frequency; /* Initial channel for IBSS */ params.wpa_ie = wpa_ie; params.wpa_ie_len = wpa_ie_len; params.pairwise_suite = cipher_pairwise; @@ -2414,7 +2422,7 @@ struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, * * This function can be used to dynamically remove network interfaces from * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In - * addition, this function is used to remove all remaining interdaces when + * addition, this function is used to remove all remaining interfaces when * %wpa_supplicant is terminated. */ int wpa_supplicant_remove_iface(struct wpa_global *global, @@ -2479,8 +2487,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) if (params == NULL) return NULL; - wpa_debug_use_file = params->wpa_debug_use_file; - wpa_debug_open_file(); + wpa_debug_open_file(params->wpa_debug_file_path); ret = eap_peer_register_methods(); if (ret) { @@ -2509,8 +2516,6 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) params->wpa_debug_show_keys; wpa_debug_timestamp = global->params.wpa_debug_timestamp = params->wpa_debug_timestamp; - wpa_debug_use_file = global->params.wpa_debug_use_file = - params->wpa_debug_use_file; if (eloop_init(global)) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); diff --git a/contrib/wpa_supplicant/wpa_supplicant.conf b/contrib/wpa_supplicant/wpa_supplicant.conf index dce9d87..ec8b0ee 100644 --- a/contrib/wpa_supplicant/wpa_supplicant.conf +++ b/contrib/wpa_supplicant/wpa_supplicant.conf @@ -192,6 +192,13 @@ fast_reauth=1 # proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or CCMP, but not # both), and psk must also be set. # +# frequency: Channel frequency in megahertz (MHz) for IBSS, e.g., +# 2412 = IEEE 802.11b/g channel 1. This value is used to configure the initial +# channel for IBSS (adhoc) networks. It is ignored in the infrastructure mode. +# In addition, this value is only used by the station that creates the IBSS. If +# an IBSS network with the configured SSID is already present, the frequency of +# the network will be used instead of this configured value. +# # proto: list of accepted protocols # WPA = WPA/IEEE 802.11i/D3.0 # RSN = WPA2/IEEE 802.11i (also WPA2 can be used as an alias for RSN) @@ -657,6 +664,7 @@ network={ network={ ssid="test adhoc" mode=1 + frequency=2412 proto=WPA key_mgmt=WPA-NONE pairwise=NONE diff --git a/contrib/wpa_supplicant/wpa_supplicant_i.h b/contrib/wpa_supplicant/wpa_supplicant_i.h index bb80f89..0d6f24a 100644 --- a/contrib/wpa_supplicant/wpa_supplicant_i.h +++ b/contrib/wpa_supplicant/wpa_supplicant_i.h @@ -158,9 +158,9 @@ struct wpa_params { int dbus_ctrl_interface; /** - * wpa_debug_use_file - Write debug to a file (instead of stdout) + * wpa_debug_file_path - Path of debug file or %NULL to use stdout */ - int wpa_debug_use_file; + const char *wpa_debug_file_path; }; /** diff --git a/contrib/wpa_supplicant/x509v3.c b/contrib/wpa_supplicant/x509v3.c index 1283fff..484c54b 100644 --- a/contrib/wpa_supplicant/x509v3.c +++ b/contrib/wpa_supplicant/x509v3.c @@ -1,6 +1,6 @@ /* * X.509v3 certificate parsing and processing (RFC 3280 profile) - * Copyright (c) 2006, Jouni Malinen + * Copyright (c) 2006-2007, Jouni Malinen * * 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 @@ -75,8 +75,39 @@ void x509_certificate_chain_free(struct x509_certificate *cert) } +static int x509_whitespace(char c) +{ + return c == ' ' || c == '\t'; +} + + +static void x509_str_strip_whitespace(char *a) +{ + char *ipos, *opos; + int remove_whitespace = 1; + + ipos = opos = a; + + while (*ipos) { + if (remove_whitespace && x509_whitespace(*ipos)) + ipos++; + else { + remove_whitespace = x509_whitespace(*ipos); + *opos++ = *ipos++; + } + } + + *opos-- = '\0'; + if (opos > a && x509_whitespace(*opos)) + *opos = '\0'; +} + + static int x509_str_compare(const char *a, const char *b) { + char *aa, *bb; + int ret; + if (!a && b) return -1; if (a && !b) @@ -84,14 +115,31 @@ static int x509_str_compare(const char *a, const char *b) if (!a && !b) return 0; - return os_strcmp(a, b); + aa = os_strdup(a); + bb = os_strdup(b); + + if (aa == NULL || bb == NULL) { + os_free(aa); + os_free(bb); + return os_strcasecmp(a, b); + } + + x509_str_strip_whitespace(aa); + x509_str_strip_whitespace(bb); + + ret = os_strcasecmp(aa, bb); + + os_free(aa); + os_free(bb); + + return ret; } /** * x509_name_compare - Compare X.509 certificate names * @a: Certificate name - * @b: Certifiatte name + * @b: Certificate name * Returns: <0, 0, or >0 based on whether a is less than, equal to, or * greater than b */ @@ -553,6 +601,17 @@ static int x509_parse_time(const u8 *buf, size_t len, u8 asn1_tag, if (os_mktime(year, month, day, hour, min, sec, val) < 0) { wpa_hexdump_ascii(MSG_DEBUG, "X509: Failed to convert Time", buf, len); + if (year < 1970) { + /* + * At least some test certificates have been configured + * to use dates prior to 1970. Set the date to + * beginning of 1970 to handle these case. + */ + wpa_printf(MSG_DEBUG, "X509: Year=%d before epoch - " + "assume epoch as the time", year); + *val = 0; + return 0; + } return -1; } @@ -720,7 +779,8 @@ static int x509_parse_ext_basic_constraints(struct x509_certificate *cert, return 0; } - if (asn1_get_next(pos, len, &hdr) < 0 || + if (asn1_get_next(hdr.payload + hdr.length, len - hdr.length, + &hdr) < 0 || hdr.class != ASN1_CLASS_UNIVERSAL) { wpa_printf(MSG_DEBUG, "X509: Failed to parse " "BasicConstraints"); @@ -1443,6 +1503,13 @@ static int x509_valid_issuer(const struct x509_certificate *cert) return -1; } + if (cert->version == X509_CERT_V3 && + !(cert->extensions_present & X509_EXT_BASIC_CONSTRAINTS)) { + wpa_printf(MSG_DEBUG, "X509: v3 CA certificate did not " + "include BasicConstraints extension"); + return -1; + } + if ((cert->extensions_present & X509_EXT_KEY_USAGE) && !(cert->key_usage & X509_KEY_USAGE_KEY_CERT_SIGN)) { wpa_printf(MSG_DEBUG, "X509: Issuer certificate did not have " @@ -1466,7 +1533,8 @@ int x509_certificate_chain_validate(struct x509_certificate *trusted, struct x509_certificate *chain, int *reason) { - int idx, chain_trusted = 0; + long unsigned idx; + int chain_trusted = 0; struct x509_certificate *cert, *trust; char buf[128]; struct os_time now; @@ -1478,12 +1546,15 @@ int x509_certificate_chain_validate(struct x509_certificate *trusted, for (cert = chain, idx = 0; cert; cert = cert->next, idx++) { x509_name_string(&cert->subject, buf, sizeof(buf)); - wpa_printf(MSG_DEBUG, "X509: %d: %s", idx, buf); + wpa_printf(MSG_DEBUG, "X509: %lu: %s", idx, buf); if (chain_trusted) continue; - if (now.sec < cert->not_before || now.sec > cert->not_after) { + if ((unsigned long) now.sec < + (unsigned long) cert->not_before || + (unsigned long) now.sec > + (unsigned long) cert->not_after) { wpa_printf(MSG_INFO, "X509: Certificate not valid " "(now=%lu not_before=%lu not_after=%lu)", now.sec, cert->not_before, cert->not_after); @@ -1505,7 +1576,16 @@ int x509_certificate_chain_validate(struct x509_certificate *trusted, return -1; } - /* TODO: validate pathLenConstraint */ + if ((cert->next->extensions_present & + X509_EXT_PATH_LEN_CONSTRAINT) && + idx > cert->next->path_len_constraint) { + wpa_printf(MSG_DEBUG, "X509: pathLenConstraint" + " not met (idx=%lu issuer " + "pathLenConstraint=%lu)", idx, + cert->next->path_len_constraint); + *reason = X509_VALIDATE_BAD_CERTIFICATE; + return -1; + } if (x509_certificate_check_signature(cert->next, cert) < 0) { -- cgit v1.1