Import of WPA supplicant 0.5.10

This commit is contained in:
Sam Leffler 2008-03-24 19:46:53 +00:00
parent 7700b89cce
commit f2afa83e72
66 changed files with 2634 additions and 530 deletions

View File

@ -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<path> 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

View File

@ -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

View File

@ -1,7 +1,7 @@
WPA Supplicant
==============
Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> and contributors
Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 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<pid file>] [-g<global ctrl>] \
wpa_supplicant [-BddfhKLqqtuvwW] [-P<pid file>] [-g<global ctrl>] \
-i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] [-p<driver_param>] \
[-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] [-D<driver>] \
[-p<driver_param>] [-b<br_ifname>] ...]
@ -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

View File

@ -7,7 +7,7 @@
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
*
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -34,10 +34,11 @@
/**
* aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
* @kek: Key encryption key (KEK)
* @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
* @plain: Plaintext key to be wrapped, n * 64 bit
* @cipher: Wrapped key, (n + 1) * 64 bit
* @kek: 16-octet Key encryption key (KEK)
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @plain: Plaintext key to be wrapped, n * 64 bits
* @cipher: Wrapped key, (n + 1) * 64 bits
* Returns: 0 on success, -1 on failure
*/
int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
@ -93,9 +94,10 @@ int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
/**
* aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
* @kek: Key encryption key (KEK)
* @n: Length of the wrapped key in 64-bit units; e.g., 2 = 128-bit = 16 bytes
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bit
* @plain: Plaintext key, n * 64 bit
* @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
* bytes
* @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
* @plain: Plaintext key, n * 64 bits
* Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
*/
int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
@ -167,28 +169,45 @@ static void gf_mulx(u8 *pad)
/**
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
* omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
* @key: 128-bit key for the hash operation
* @data: Data buffer for which a MAC is determined
* @data: Length of data buffer in bytes
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*/
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
int omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
void *ctx;
u8 cbc[BLOCK_SIZE], pad[BLOCK_SIZE];
const u8 *pos = data;
size_t i, left = data_len;
const u8 *pos, *end;
size_t i, e, left, total_len;
ctx = aes_encrypt_init(key, 16);
if (ctx == NULL)
return -1;
os_memset(cbc, 0, BLOCK_SIZE);
total_len = 0;
for (e = 0; e < num_elem; e++)
total_len += len[e];
left = total_len;
e = 0;
pos = addr[0];
end = pos + len[0];
while (left >= BLOCK_SIZE) {
for (i = 0; i < BLOCK_SIZE; i++)
for (i = 0; i < BLOCK_SIZE; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
e++;
pos = addr[e];
end = pos + len[e];
}
}
if (left > BLOCK_SIZE)
aes_encrypt(ctx, cbc, cbc);
left -= BLOCK_SIZE;
@ -198,9 +217,15 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
aes_encrypt(ctx, pad, pad);
gf_mulx(pad);
if (left || data_len == 0) {
for (i = 0; i < left; i++)
if (left || total_len == 0) {
for (i = 0; i < left; i++) {
cbc[i] ^= *pos++;
if (pos >= end) {
e++;
pos = addr[e];
end = pos + len[e];
}
}
cbc[left] ^= 0x80;
gf_mulx(pad);
}
@ -212,6 +237,24 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
return 0;
}
/**
* omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
* @key: 128-bit key for the hash operation
* @data: Data buffer for which a MAC is determined
* @data_len: Length of data buffer in bytes
* @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
* Returns: 0 on success, -1 on failure
*
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
*/
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
#endif /* CONFIG_NO_AES_OMAC1 */

View File

@ -7,7 +7,7 @@
* - AES-128 EAX mode encryption/decryption
* - AES-128 CBC
*
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -24,6 +24,8 @@
int aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher);
int aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain);
int omac1_aes_128_vector(const u8 *key, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac);
int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac);
int aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out);
int aes_128_ctr_encrypt(const u8 *key, const u8 *nonce,

View File

@ -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;
}

View File

@ -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;

View File

@ -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);
/**

View File

@ -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

View File

@ -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,

View File

@ -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) {

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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);
}
}
}

View File

@ -8,10 +8,6 @@
<allow send_destination="fi.epitest.hostap.WPASupplicant"/>
<allow send_interface="fi.epitest.hostap.WPASupplicant"/>
</policy>
<policy at_console="true">
<allow send_destination="fi.epitest.hostap.WPASupplicant"/>
<allow send_interface="fi.epitest.hostap.WPASupplicant"/>
</policy>
<policy context="default">
<deny own="fi.epitest.hostap.WPASupplicant"/>
<deny send_destination="fi.epitest.hostap.WPASupplicant"/>

View File

@ -0,0 +1,4 @@
[D-BUS Service]
Name=fi.epitest.hostap.WPASupplicant
Exec=/sbin/wpa_supplicant -u
User=root

View File

@ -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

View File

@ -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 <BSSID>
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

View File

@ -3,7 +3,7 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.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

View File

@ -3,7 +3,7 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.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.

View File

@ -140,7 +140,7 @@ CTRL-REQ-OTP-2:Challenge 1235663 needed for SSID foobar
<listitem><para>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.</para>

View File

@ -3,7 +3,7 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.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

View File

@ -3,13 +3,13 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.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

View File

@ -3,7 +3,7 @@
.\" <http://shell.ipoline.com/~elmert/comp/docbook2X/>
.\" Please send any bug reports, improvements, comments, patches,
.\" etc. to Steve Cheng <steve@ggi-project.org>.
.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

View File

@ -12,11 +12,12 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>wpa_supplicant</command>
<arg>-BddehLqqvw</arg>
<arg>-BddfhKLqqtuvwW</arg>
<arg>-i<replaceable>ifname</replaceable></arg>
<arg>-c<replaceable>config file</replaceable></arg>
<arg>-D<replaceable>driver</replaceable></arg>
<arg>-P<replaceable>PID_file</replaceable></arg>
<arg>-f<replaceable>output file</replaceable></arg>
</cmdsynopsis>
</refsynopsisdiv>
<refsect1>
@ -375,6 +376,13 @@
</listitem>
</varlistentry>
<varlistentry>
<term>-f output file</term>
<listitem>
<para>Log output to specified file instead of stdout.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-d</term>
<listitem>

View File

@ -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) {

View File

@ -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 <j@w1.fi>
*
* 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;
}

View File

@ -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,6 +77,122 @@ static int eap_gpsk_gkdf(const u8 *psk /* Y */, size_t psk_len,
}
#ifdef EAP_GPSK_SHA256
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[2];
size_t vlen[2];
hashlen = SHA256_MAC_LEN;
/* M_i = MAC_Y (i || Z); (MAC = HMAC-SHA256) */
addr[0] = ibuf;
vlen[0] = sizeof(ibuf);
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);
hmac_sha256_vector(psk, 32, 2, addr, vlen, hash);
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
left -= clen;
}
return 0;
}
#endif /* EAP_GPSK_SHA256 */
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 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);
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;
}
if (psk_len < mk_len)
return -1;
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_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",
data, data_len);
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, mk_len);
if (gkdf(mk, seed, seed_len, kdf_out, kdf_out_len) < 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, sk_len);
os_memcpy(sk, pos, sk_len);
pos += sk_len;
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,
@ -85,223 +200,93 @@ static int eap_gpsk_derive_keys_aes(const u8 *psk, size_t psk_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
* inputString = RAND_Peer || ID_Peer || RAND_Server || ID_Server
* (= seed)
* KS = 16, PL = psk_len, CSuite_Sel = 0x000000 0x000001
* MK = GKDF-32 (0x00, PL || PSK || CSuite_Sel || inputString)
* 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]
* MID = GKDF-16(0x00, "Method ID" || EAP_Method_Type || CSuite_Sel ||
* inputString)
* Hash-Function = SHA-1 (see [RFC3174])
* hashlen = 20 octets (160 bits)
* zero = 0x00 || 0x00 || ... || 0x00 (16 times)
* Method-ID = GKDF-16 (zero, "Method ID" || EAP_Method_Type ||
* CSuite_Sel || inputString)
*/
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;
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_gkdf_sha256(const u8 *psk /* Y */, size_t psk_len,
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];
hashlen = SHA256_MAC_LEN;
/* M_i = Hash-Function (i || Y || Z); */
addr[0] = ibuf;
vlen[0] = sizeof(ibuf);
addr[1] = psk;
vlen[1] = psk_len;
addr[2] = data;
vlen[2] = 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);
clen = left > hashlen ? hashlen : left;
os_memcpy(opos, hash, clen);
opos += clen;
left -= clen;
}
return 0;
}
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,
u8 *pk, size_t *pk_len)
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 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;
/*
* inputString = RAND_Client || ID_Client || RAND_Server || ID_Server
* inputString = RAND_Peer || ID_Peer || 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)
* 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)
*/
os_memset(zero_string, 0, sizeof(zero_string));
*sk_len = EAP_GPSK_SK_LEN_SHA256;
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_SHA256); /* CSuite/Specifier */
pos += 3;
os_memcpy(pos, seed, seed_len); /* inputString */
wpa_hexdump_key(MSG_DEBUG, "EAP-GPSK: Data to MK derivation (SHA256)",
data, data_len);
if (eap_gpsk_gkdf_sha256(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_sha256(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_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: PK",
pos, EAP_GPSK_PK_LEN_SHA256);
os_memcpy(pk, pos, EAP_GPSK_PK_LEN_SHA256);
*pk_len = EAP_GPSK_PK_LEN_SHA256;
return 0;
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:

View File

@ -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

View File

@ -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 @@ static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
/* 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;

View File

@ -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",

View File

@ -1,6 +1,6 @@
/*
* EAP peer: EAP-SIM/AKA shared routines
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -118,6 +118,11 @@ int eap_sim_derive_keys_reauth(u16 _counter,
const u8 *addr[4];
size_t len[4];
while (identity_len > 0 && identity[identity_len - 1] == 0) {
wpa_printf(MSG_DEBUG, "EAP-SIM: Workaround - drop null "
"character from the end of identity");
identity_len--;
}
addr[0] = identity;
len[0] = identity_len;
addr[1] = counter;
@ -250,6 +255,10 @@ int eap_sim_parse_attr(const u8 *start, const u8 *end,
pos, pos[1] * 4, end);
return -1;
}
if (pos[1] == 0) {
wpa_printf(MSG_INFO, "EAP-SIM: Attribute underflow");
return -1;
}
apos = pos + 2;
alen = pos[1] * 4 - 2;
wpa_hexdump(MSG_MSGDUMP, "EAP-SIM: Attribute data",

View File

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -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;

View File

@ -1,6 +1,6 @@
/*
* EAP peer method: EAP-TLV (draft-josefsson-pppext-eap-tls-eap-07.txt)
* Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -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 */

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -39,11 +39,12 @@ static void usage(void)
int i;
printf("%s\n\n%s\n"
"usage:\n"
" wpa_supplicant [-BddehLqquvwW] [-P<pid file>] "
" wpa_supplicant [-BddhKLqqtuvwW] [-P<pid file>] "
"[-g<global ctrl>] \\\n"
" -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
"[-p<driver_param>] \\\n"
" [-b<br_ifname> [-N -i<ifname> -c<conf> [-C<ctrl>] "
" [-b<br_ifname>] [-f<debug file>] \\\n"
" [-N -i<ifname> -c<conf> [-C<ctrl>] "
"[-D<driver>] \\\n"
" [-p<driver_param>] [-b<br_ifname>] ...]\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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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];

View File

@ -1,6 +1,6 @@
/*
* hostapd / RADIUS message processing
* Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
* Copyright (c) 2002-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -138,6 +138,7 @@ static struct radius_attr_type radius_attrs[] =
{ RADIUS_ATTR_CALLING_STATION_ID, "Calling-Station-Id",
RADIUS_ATTR_TEXT },
{ RADIUS_ATTR_NAS_IDENTIFIER, "NAS-Identifier", RADIUS_ATTR_TEXT },
{ RADIUS_ATTR_PROXY_STATE, "Proxy-State", RADIUS_ATTR_UNDIST },
{ RADIUS_ATTR_ACCT_STATUS_TYPE, "Acct-Status-Type",
RADIUS_ATTR_INT32 },
{ RADIUS_ATTR_ACCT_DELAY_TIME, "Acct-Delay-Time", RADIUS_ATTR_INT32 },
@ -230,8 +231,9 @@ static void radius_msg_dump_attr(struct radius_attr_hdr *hdr)
case RADIUS_ATTR_IP:
if (len == 4) {
struct in_addr *addr = (struct in_addr *) pos;
printf(" Value: %s\n", inet_ntoa(*addr));
struct in_addr addr;
os_memcpy(&addr, pos, 4);
printf(" Value: %s\n", inet_ntoa(addr));
} else
printf(" Invalid IP address length %d\n", len);
break;
@ -664,24 +666,21 @@ int radius_msg_verify(struct radius_msg *msg, const u8 *secret,
int radius_msg_copy_attr(struct radius_msg *dst, struct radius_msg *src,
u8 type)
{
struct radius_attr_hdr *attr = NULL;
struct radius_attr_hdr *attr;
size_t i;
int count = 0;
for (i = 0; i < src->attr_used; i++) {
if (src->attrs[i]->type == type) {
attr = src->attrs[i];
break;
attr = src->attrs[i];
if (attr->type == type) {
if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1),
attr->length - sizeof(*attr)))
return -1;
count++;
}
}
if (attr == NULL)
return 0;
if (!radius_msg_add_attr(dst, type, (u8 *) (attr + 1),
attr->length - sizeof(*attr)))
return -1;
return 1;
return count;
}

View File

@ -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,

View File

@ -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);

View File

@ -0,0 +1,306 @@
/*
* Test program for AES
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,53 @@
/*
* Test program for EAP-SIM PRF
* Copyright (c) 2004-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,99 @@
/*
* Test program for MD4 (test vectors from RFC 1320)
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,99 @@
/*
* Test program for MD5 (test vectors from RFC 1321)
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,119 @@
/*
* Test program for ms_funcs
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,328 @@
/*
* Test program for SHA1 and MD5
* Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,330 @@
/*
* Test program for SHA256
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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;
}

View File

@ -0,0 +1,69 @@
/*
* Testing tool for X.509v3 routines
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* 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 <cert1.der> <cert2.der> ..\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;
}

View File

@ -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) +

View File

@ -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 */

View File

@ -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)

View File

@ -1,6 +1,6 @@
/*
* WPA Supplicant - command line interface for wpa_supplicant daemon
* Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -31,7 +31,7 @@
static const char *wpa_cli_version =
"wpa_cli v" VERSION_STR "\n"
"Copyright (c) 2004-2007, Jouni Malinen <j@w1.fi> and contributors";
"Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> 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 <network id> <variable> = 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 <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
@ -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 */

View File

@ -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";

View File

@ -1,6 +1,6 @@
/*
* wpa_gui - WpaGui class
* Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
* Copyright (c) 2005-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -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 <j@w1.fi>\n"
"and contributors.\n"
"\n"

View File

@ -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";

View File

@ -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

View File

@ -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 <j@w1.fi>\n"
"and contributors.\n"
"\n"

View File

@ -1,6 +1,6 @@
/*
* WPA Supplicant
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
* Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -38,7 +38,7 @@
const char *wpa_supplicant_version =
"wpa_supplicant v" VERSION_STR "\n"
"Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> and contributors";
"Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi> 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");

View File

@ -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

View File

@ -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;
};
/**

View File

@ -1,6 +1,6 @@
/*
* X.509v3 certificate parsing and processing (RFC 3280 profile)
* Copyright (c) 2006, Jouni Malinen <j@w1.fi>
* Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@ -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) {