diff options
author | sam <sam@FreeBSD.org> | 2007-07-11 15:48:36 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2007-07-11 15:48:36 +0000 |
commit | 35aef052ff21baa52c4cec68b512986c21f70a48 (patch) | |
tree | c3da7f33886a852f7dceb74373fbdeec49a48f77 /contrib/wpa_supplicant/eap_sim.c | |
parent | 840099f34d8de1ca769f02fae379c4d8e5d6688a (diff) | |
download | FreeBSD-src-35aef052ff21baa52c4cec68b512986c21f70a48.zip FreeBSD-src-35aef052ff21baa52c4cec68b512986c21f70a48.tar.gz |
Import of WPA supplicant 0.5.8
Diffstat (limited to 'contrib/wpa_supplicant/eap_sim.c')
-rw-r--r-- | contrib/wpa_supplicant/eap_sim.c | 371 |
1 files changed, 177 insertions, 194 deletions
diff --git a/contrib/wpa_supplicant/eap_sim.c b/contrib/wpa_supplicant/eap_sim.c index ca9d737..545f0ae 100644 --- a/contrib/wpa_supplicant/eap_sim.c +++ b/contrib/wpa_supplicant/eap_sim.c @@ -1,6 +1,6 @@ /* - * WPA Supplicant / EAP-SIM (draft-haverinen-pppext-eap-sim-13.txt) - * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi> + * EAP peer method: EAP-SIM (RFC 4186) + * 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 @@ -12,50 +12,30 @@ * See README and COPYING for more details. */ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> +#include "includes.h" #include "common.h" #include "eap_i.h" -#include "wpa_supplicant.h" #include "config_ssid.h" #include "crypto.h" #include "pcsc_funcs.h" #include "eap_sim_common.h" -#define EAP_SIM_VERSION 1 - -/* EAP-SIM Subtypes */ -#define EAP_SIM_SUBTYPE_START 10 -#define EAP_SIM_SUBTYPE_CHALLENGE 11 -#define EAP_SIM_SUBTYPE_NOTIFICATION 12 -#define EAP_SIM_SUBTYPE_REAUTHENTICATION 13 -#define EAP_SIM_SUBTYPE_CLIENT_ERROR 14 - -/* AT_CLIENT_ERROR_CODE error codes */ -#define EAP_SIM_UNABLE_TO_PROCESS_PACKET 0 -#define EAP_SIM_UNSUPPORTED_VERSION 1 -#define EAP_SIM_INSUFFICIENT_NUM_OF_CHAL 2 -#define EAP_SIM_RAND_NOT_FRESH 3 - -#define KC_LEN 8 -#define SRES_LEN 4 -#define EAP_SIM_MAX_FAST_REAUTHS 1000 struct eap_sim_data { u8 *ver_list; size_t ver_list_len; int selected_version; - int min_num_chal, num_chal; + size_t min_num_chal, num_chal; - u8 kc[3][KC_LEN]; - u8 sres[3][SRES_LEN]; + u8 kc[3][EAP_SIM_KC_LEN]; + u8 sres[3][EAP_SIM_SRES_LEN]; u8 nonce_mt[EAP_SIM_NONCE_MT_LEN], nonce_s[EAP_SIM_NONCE_S_LEN]; u8 mk[EAP_SIM_MK_LEN]; u8 k_aut[EAP_SIM_K_AUT_LEN]; u8 k_encr[EAP_SIM_K_ENCR_LEN]; u8 msk[EAP_SIM_KEYING_DATA_LEN]; + u8 emsk[EAP_EMSK_LEN]; u8 rand[3][GSM_RAND_LEN]; int num_id_req, num_notification; @@ -76,33 +56,33 @@ static void * eap_sim_init(struct eap_sm *sm) struct eap_sim_data *data; struct wpa_ssid *config = eap_get_config(sm); - data = malloc(sizeof(*data)); + data = os_zalloc(sizeof(*data)); if (data == NULL) return NULL; - memset(data, 0, sizeof(*data)); if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " "for NONCE_MT"); - free(data); + os_free(data); return NULL; } data->min_num_chal = 2; if (config && config->phase1) { - char *pos = strstr(config->phase1, "sim_min_num_chal="); + char *pos = os_strstr(config->phase1, "sim_min_num_chal="); if (pos) { data->min_num_chal = atoi(pos + 17); if (data->min_num_chal < 2 || data->min_num_chal > 3) { wpa_printf(MSG_WARNING, "EAP-SIM: Invalid " "sim_min_num_chal configuration " - "(%d, expected 2 or 3)", - data->min_num_chal); - free(data); + "(%lu, expected 2 or 3)", + (unsigned long) data->min_num_chal); + os_free(data); return NULL; } wpa_printf(MSG_DEBUG, "EAP-SIM: Set minimum number of " - "challenges to %d", data->min_num_chal); + "challenges to %lu", + (unsigned long) data->min_num_chal); } } @@ -116,11 +96,11 @@ static void eap_sim_deinit(struct eap_sm *sm, void *priv) { struct eap_sim_data *data = priv; if (data) { - free(data->ver_list); - free(data->pseudonym); - free(data->reauth_id); - free(data->last_eap_identity); - free(data); + os_free(data->ver_list); + os_free(data->pseudonym); + os_free(data->reauth_id); + os_free(data->last_eap_identity); + os_free(data); } } @@ -146,26 +126,26 @@ static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) * concerned, but it is quite useful for cases where the AS is rotating * the order of pre-configured values. */ { - int i; + size_t i; for (i = 0; i < data->num_chal; i++) { if (data->rand[i][0] == 0xaa) { - memcpy(data->kc[i], - "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", - KC_LEN); - memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", - SRES_LEN); + os_memcpy(data->kc[i], + "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7", + EAP_SIM_KC_LEN); + os_memcpy(data->sres[i], "\xd1\xd2\xd3\xd4", + EAP_SIM_SRES_LEN); } else if (data->rand[i][0] == 0xbb) { - memcpy(data->kc[i], - "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", - KC_LEN); - memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", - SRES_LEN); + os_memcpy(data->kc[i], + "\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7", + EAP_SIM_KC_LEN); + os_memcpy(data->sres[i], "\xe1\xe2\xe3\xe4", + EAP_SIM_SRES_LEN); } else { - memcpy(data->kc[i], - "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", - KC_LEN); - memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", - SRES_LEN); + os_memcpy(data->kc[i], + "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7", + EAP_SIM_KC_LEN); + os_memcpy(data->sres[i], "\xf1\xf2\xf3\xf4", + EAP_SIM_SRES_LEN); } } } @@ -174,38 +154,12 @@ static int eap_sim_gsm_auth(struct eap_sm *sm, struct eap_sim_data *data) } -static int eap_sim_supported_ver(struct eap_sim_data *data, int version) +static int eap_sim_supported_ver(int version) { return version == EAP_SIM_VERSION; } -static void eap_sim_derive_mk(struct eap_sim_data *data, - const u8 *identity, size_t identity_len) -{ - u8 sel_ver[2]; - const unsigned char *addr[5]; - size_t len[5]; - - addr[0] = identity; - len[0] = identity_len; - addr[1] = (u8 *) data->kc; - len[1] = data->num_chal * KC_LEN; - addr[2] = data->nonce_mt; - len[2] = EAP_SIM_NONCE_MT_LEN; - addr[3] = data->ver_list; - len[3] = data->ver_list_len; - addr[4] = sel_ver; - len[4] = 2; - - WPA_PUT_BE16(sel_ver, data->selected_version); - - /* MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version) */ - sha1_vector(5, addr, len, data->mk); - wpa_hexdump_key(MSG_DEBUG, "EAP-SIM: MK", data->mk, EAP_SIM_MK_LEN); -} - - #define CLEAR_PSEUDONYM 0x01 #define CLEAR_REAUTH_ID 0x02 #define CLEAR_EAP_ID 0x04 @@ -217,17 +171,17 @@ static void eap_sim_clear_identities(struct eap_sim_data *data, int id) id & CLEAR_REAUTH_ID ? " reauth_id" : "", id & CLEAR_EAP_ID ? " eap_id" : ""); if (id & CLEAR_PSEUDONYM) { - free(data->pseudonym); + os_free(data->pseudonym); data->pseudonym = NULL; data->pseudonym_len = 0; } if (id & CLEAR_REAUTH_ID) { - free(data->reauth_id); + os_free(data->reauth_id); data->reauth_id = NULL; data->reauth_id_len = 0; } if (id & CLEAR_EAP_ID) { - free(data->last_eap_identity); + os_free(data->last_eap_identity); data->last_eap_identity = NULL; data->last_eap_identity_len = 0; } @@ -238,15 +192,15 @@ static int eap_sim_learn_ids(struct eap_sim_data *data, struct eap_sim_attrs *attr) { if (attr->next_pseudonym) { - free(data->pseudonym); - data->pseudonym = malloc(attr->next_pseudonym_len); + os_free(data->pseudonym); + data->pseudonym = os_malloc(attr->next_pseudonym_len); if (data->pseudonym == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " "next pseudonym"); return -1; } - memcpy(data->pseudonym, attr->next_pseudonym, - attr->next_pseudonym_len); + os_memcpy(data->pseudonym, attr->next_pseudonym, + attr->next_pseudonym_len); data->pseudonym_len = attr->next_pseudonym_len; wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: (encr) AT_NEXT_PSEUDONYM", @@ -255,15 +209,15 @@ static int eap_sim_learn_ids(struct eap_sim_data *data, } if (attr->next_reauth_id) { - free(data->reauth_id); - data->reauth_id = malloc(attr->next_reauth_id_len); + os_free(data->reauth_id); + data->reauth_id = os_malloc(attr->next_reauth_id_len); if (data->reauth_id == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) No memory for " "next reauth_id"); return -1; } - memcpy(data->reauth_id, attr->next_reauth_id, - attr->next_reauth_id_len); + os_memcpy(data->reauth_id, attr->next_reauth_id, + attr->next_reauth_id_len); data->reauth_id_len = attr->next_reauth_id_len; wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: (encr) AT_NEXT_REAUTH_ID", @@ -275,7 +229,7 @@ static int eap_sim_learn_ids(struct eap_sim_data *data, } -static u8 * eap_sim_client_error(struct eap_sm *sm, struct eap_sim_data *data, +static u8 * eap_sim_client_error(struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen, int err) { @@ -298,8 +252,7 @@ static u8 * eap_sim_response_start(struct eap_sm *sm, size_t *respDataLen, enum eap_sim_id_req id_req) { - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity = NULL; + const u8 *identity = NULL; size_t identity_len = 0; struct eap_sim_msg *msg; @@ -313,11 +266,12 @@ static u8 * eap_sim_response_start(struct eap_sm *sm, identity = data->pseudonym; identity_len = data->pseudonym_len; eap_sim_clear_identities(data, CLEAR_REAUTH_ID); - } else if (id_req != NO_ID_REQ && config && config->identity) { - identity = config->identity; - identity_len = config->identity_len; - eap_sim_clear_identities(data, - CLEAR_PSEUDONYM | CLEAR_REAUTH_ID); + } else if (id_req != NO_ID_REQ) { + identity = eap_get_config_identity(sm, &identity_len); + if (identity) { + eap_sim_clear_identities(data, CLEAR_PSEUDONYM | + CLEAR_REAUTH_ID); + } } if (id_req != NO_ID_REQ) eap_sim_clear_identities(data, CLEAR_EAP_ID); @@ -346,8 +300,7 @@ static u8 * eap_sim_response_start(struct eap_sm *sm, } -static u8 * eap_sim_response_challenge(struct eap_sm *sm, - struct eap_sim_data *data, +static u8 * eap_sim_response_challenge(struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen) { @@ -361,12 +314,11 @@ static u8 * eap_sim_response_challenge(struct eap_sm *sm, eap_sim_msg_add_mac(msg, EAP_SIM_AT_MAC); return eap_sim_msg_finish(msg, respDataLen, data->k_aut, (u8 *) data->sres, - data->num_chal * SRES_LEN); + data->num_chal * EAP_SIM_SRES_LEN); } -static u8 * eap_sim_response_reauth(struct eap_sm *sm, - struct eap_sim_data *data, +static u8 * eap_sim_response_reauth(struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen, int counter_too_small) { @@ -405,8 +357,7 @@ static u8 * eap_sim_response_reauth(struct eap_sm *sm, } -static u8 * eap_sim_response_notification(struct eap_sm *sm, - struct eap_sim_data *data, +static u8 * eap_sim_response_notification(struct eap_sim_data *data, const struct eap_hdr *req, size_t *respDataLen, u16 notification) @@ -445,36 +396,37 @@ static u8 * eap_sim_response_notification(struct eap_sm *sm, static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, - const struct eap_hdr *req, size_t reqDataLen, + const struct eap_hdr *req, size_t *respDataLen, struct eap_sim_attrs *attr) { - int i, selected_version = -1, id_error; + int selected_version = -1, id_error; + size_t i; u8 *pos; wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Start"); if (attr->version_list == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: No AT_VERSION_LIST in " "SIM/Start"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNSUPPORTED_VERSION); } - free(data->ver_list); - data->ver_list = malloc(attr->version_list_len); + os_free(data->ver_list); + data->ver_list = os_malloc(attr->version_list_len); if (data->ver_list == NULL) { wpa_printf(MSG_DEBUG, "EAP-SIM: Failed to allocate " "memory for version list"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } - memcpy(data->ver_list, attr->version_list, attr->version_list_len); + os_memcpy(data->ver_list, attr->version_list, attr->version_list_len); data->ver_list_len = attr->version_list_len; pos = data->ver_list; for (i = 0; i < data->ver_list_len / 2; i++) { int ver = pos[0] * 256 + pos[1]; pos += 2; - if (eap_sim_supported_ver(data, ver)) { + if (eap_sim_supported_ver(ver)) { selected_version = ver; break; } @@ -482,7 +434,7 @@ static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, if (selected_version < 0) { wpa_printf(MSG_INFO, "EAP-SIM: Could not find a supported " "version"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNSUPPORTED_VERSION); } wpa_printf(MSG_DEBUG, "EAP-SIM: Selected Version %d", @@ -512,7 +464,7 @@ static u8 * eap_sim_process_start(struct eap_sm *sm, struct eap_sim_data *data, if (id_error) { wpa_printf(MSG_INFO, "EAP-SIM: Too many ID requests " "used within one authentication"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -528,8 +480,7 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, size_t *respDataLen, struct eap_sim_attrs *attr) { - struct wpa_ssid *config = eap_get_config(sm); - u8 *identity; + const u8 *identity; size_t identity_len; struct eap_sim_attrs eattr; @@ -540,7 +491,7 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, "did not include%s%s", !attr->mac ? " AT_MAC" : "", !attr->rand ? " AT_RAND" : ""); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -549,36 +500,36 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, if (attr->num_chal < data->min_num_chal) { wpa_printf(MSG_INFO, "EAP-SIM: Insufficient number of " "challenges (%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_INSUFFICIENT_NUM_OF_CHAL); } if (attr->num_chal > 3) { wpa_printf(MSG_INFO, "EAP-SIM: Too many challenges " "(%lu)", (unsigned long) attr->num_chal); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } /* Verify that RANDs are different */ - if (memcmp(attr->rand, attr->rand + GSM_RAND_LEN, + if (os_memcmp(attr->rand, attr->rand + GSM_RAND_LEN, GSM_RAND_LEN) == 0 || (attr->num_chal > 2 && - (memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0 || - memcmp(attr->rand + GSM_RAND_LEN, - attr->rand + 2 * GSM_RAND_LEN, - GSM_RAND_LEN) == 0))) { + (os_memcmp(attr->rand, attr->rand + 2 * GSM_RAND_LEN, + GSM_RAND_LEN) == 0 || + os_memcmp(attr->rand + GSM_RAND_LEN, + attr->rand + 2 * GSM_RAND_LEN, + GSM_RAND_LEN) == 0))) { wpa_printf(MSG_INFO, "EAP-SIM: Same RAND used multiple times"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_RAND_NOT_FRESH); } - memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); + os_memcpy(data->rand, attr->rand, attr->num_chal * GSM_RAND_LEN); data->num_chal = attr->num_chal; if (eap_sim_gsm_auth(sm, data)) { wpa_printf(MSG_WARNING, "EAP-SIM: GSM authentication failed"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (data->last_eap_identity) { @@ -587,20 +538,22 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, } else if (data->pseudonym) { identity = data->pseudonym; identity_len = data->pseudonym_len; - } else { - identity = config->identity; - identity_len = config->identity_len; - } + } else + identity = eap_get_config_identity(sm, &identity_len); wpa_hexdump_ascii(MSG_DEBUG, "EAP-SIM: Selected identity for MK " "derivation", identity, identity_len); - eap_sim_derive_mk(data, identity, identity_len); - eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk); + eap_sim_derive_mk(identity, identity_len, data->nonce_mt, + data->selected_version, data->ver_list, + data->ver_list_len, data->num_chal, + (const u8 *) data->kc, data->mk); + eap_sim_derive_keys(data->mk, data->k_encr, data->k_aut, data->msk, + data->emsk); if (eap_sim_verify_mac(data->k_aut, (const u8 *) req, reqDataLen, attr->mac, data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { wpa_printf(MSG_WARNING, "EAP-SIM: Challenge message " "used invalid AT_MAC"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -617,11 +570,11 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, &eattr, 0); if (decrypted == NULL) { return eap_sim_client_error( - sm, data, req, respDataLen, + data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } eap_sim_learn_ids(data, &eattr); - free(decrypted); + os_free(decrypted); } if (data->state != FAILURE) @@ -629,17 +582,15 @@ static u8 * eap_sim_process_challenge(struct eap_sm *sm, data->num_id_req = 0; data->num_notification = 0; - /* draft-haverinen-pppext-eap-sim-13.txt specifies that counter - * is initialized to one after fullauth, but initializing it to - * zero makes it easier to implement reauth verification. */ + /* RFC 4186 specifies that counter is initialized to one after + * fullauth, but initializing it to zero makes it easier to implement + * reauth verification. */ data->counter = 0; - return eap_sim_response_challenge(sm, data, req, respDataLen); + return eap_sim_response_challenge(data, req, respDataLen); } static int eap_sim_process_notification_reauth(struct eap_sim_data *data, - const struct eap_hdr *req, - size_t reqDataLen, struct eap_sim_attrs *attr) { struct eap_sim_attrs eattr; @@ -660,15 +611,15 @@ static int eap_sim_process_notification_reauth(struct eap_sim_data *data, return -1; } - if (eattr.counter != data->counter) { + if (eattr.counter < 0 || (size_t) eattr.counter != data->counter) { wpa_printf(MSG_WARNING, "EAP-SIM: Counter in notification " "message does not match with counter in reauth " "message"); - free(decrypted); + os_free(decrypted); return -1; } - free(decrypted); + os_free(decrypted); return 0; } @@ -692,7 +643,7 @@ static int eap_sim_process_notification_auth(struct eap_sim_data *data, } if (data->reauth && - eap_sim_process_notification_reauth(data, req, reqDataLen, attr)) { + eap_sim_process_notification_reauth(data, attr)) { wpa_printf(MSG_WARNING, "EAP-SIM: Invalid notification " "message after reauth"); return -1; @@ -713,20 +664,20 @@ static u8 * eap_sim_process_notification(struct eap_sm *sm, if (data->num_notification > 0) { wpa_printf(MSG_INFO, "EAP-SIM: too many notification " "rounds (only one allowed)"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } data->num_notification++; if (attr->notification == -1) { wpa_printf(MSG_INFO, "EAP-SIM: no AT_NOTIFICATION in " "Notification message"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if ((attr->notification & 0x4000) == 0 && eap_sim_process_notification_auth(data, req, reqDataLen, attr)) { - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -734,7 +685,7 @@ static u8 * eap_sim_process_notification(struct eap_sm *sm, if (attr->notification >= 0 && attr->notification < 32768) { data->state = FAILURE; } - return eap_sim_response_notification(sm, data, req, respDataLen, + return eap_sim_response_notification(data, req, respDataLen, attr->notification); } @@ -754,7 +705,7 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, if (data->reauth_id == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: Server is trying " "reauthentication, but no reauth_id available"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -763,14 +714,14 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, attr->mac, (u8 *) "", 0)) { wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " "did not have valid AT_MAC"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } if (attr->encr_data == NULL || attr->iv == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: Reauthentication " "message did not include encrypted data"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -780,7 +731,7 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, if (decrypted == NULL) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to parse encrypted " "data from reauthentication message"); - return eap_sim_client_error(sm, data, req, respDataLen, + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } @@ -788,12 +739,12 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, wpa_printf(MSG_INFO, "EAP-SIM: (encr) No%s%s in reauth packet", !eattr.nonce_s ? " AT_NONCE_S" : "", eattr.counter < 0 ? " AT_COUNTER" : ""); - free(decrypted); - return eap_sim_client_error(sm, data, req, respDataLen, + os_free(decrypted); + return eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); } - if (eattr.counter <= data->counter) { + if (eattr.counter < 0 || (size_t) eattr.counter <= data->counter) { wpa_printf(MSG_INFO, "EAP-SIM: (encr) Invalid counter " "(%d <= %d)", eattr.counter, data->counter); data->counter_too_small = eattr.counter; @@ -802,23 +753,24 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, * However, since it was used in the last EAP-Response-Identity * packet, it has to saved for the following fullauth to be * used in MK derivation. */ - free(data->last_eap_identity); + os_free(data->last_eap_identity); data->last_eap_identity = data->reauth_id; data->last_eap_identity_len = data->reauth_id_len; data->reauth_id = NULL; data->reauth_id_len = 0; - free(decrypted); - return eap_sim_response_reauth(sm, data, req, respDataLen, 1); + os_free(decrypted); + return eap_sim_response_reauth(data, req, respDataLen, 1); } data->counter = eattr.counter; - memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); + os_memcpy(data->nonce_s, eattr.nonce_s, EAP_SIM_NONCE_S_LEN); wpa_hexdump(MSG_DEBUG, "EAP-SIM: (encr) AT_NONCE_S", data->nonce_s, EAP_SIM_NONCE_S_LEN); eap_sim_derive_keys_reauth(data->counter, data->reauth_id, data->reauth_id_len, - data->nonce_s, data->mk, data->msk); + data->nonce_s, data->mk, data->msk, + data->emsk); eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); eap_sim_learn_ids(data, &eattr); @@ -832,8 +784,8 @@ static u8 * eap_sim_process_reauthentication(struct eap_sm *sm, "fast reauths performed - force fullauth"); eap_sim_clear_identities(data, CLEAR_REAUTH_ID | CLEAR_EAP_ID); } - free(decrypted); - return eap_sim_response_reauth(sm, data, req, respDataLen, 0); + os_free(decrypted); + return eap_sim_response_reauth(data, req, respDataLen, 0); } @@ -843,7 +795,6 @@ static u8 * eap_sim_process(struct eap_sm *sm, void *priv, size_t *respDataLen) { struct eap_sim_data *data = priv; - struct wpa_ssid *config = eap_get_config(sm); const struct eap_hdr *req; u8 subtype, *res; const u8 *pos; @@ -851,14 +802,15 @@ static u8 * eap_sim_process(struct eap_sm *sm, void *priv, size_t len; wpa_hexdump(MSG_DEBUG, "EAP-SIM: EAP data", reqData, reqDataLen); - if (config == NULL || config->identity == NULL) { + if (eap_get_config_identity(sm, &len) == NULL) { wpa_printf(MSG_INFO, "EAP-SIM: Identity not configured"); - eap_sm_request_identity(sm, config); + eap_sm_request_identity(sm); ret->ignore = TRUE; return NULL; } - pos = eap_hdr_validate(EAP_TYPE_SIM, reqData, reqDataLen, &len); + pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SIM, + reqData, reqDataLen, &len); if (pos == NULL || len < 1) { ret->ignore = TRUE; return NULL; @@ -876,14 +828,14 @@ static u8 * eap_sim_process(struct eap_sm *sm, void *priv, pos += 2; /* Reserved */ if (eap_sim_parse_attr(pos, reqData + len, &attr, 0, 0)) { - res = eap_sim_client_error(sm, data, req, respDataLen, + res = eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); goto done; } switch (subtype) { case EAP_SIM_SUBTYPE_START: - res = eap_sim_process_start(sm, data, req, len, + res = eap_sim_process_start(sm, data, req, respDataLen, &attr); break; case EAP_SIM_SUBTYPE_CHALLENGE: @@ -900,12 +852,12 @@ static u8 * eap_sim_process(struct eap_sm *sm, void *priv, break; case EAP_SIM_SUBTYPE_CLIENT_ERROR: wpa_printf(MSG_DEBUG, "EAP-SIM: subtype Client-Error"); - res = eap_sim_client_error(sm, data, req, respDataLen, + res = eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); break; default: wpa_printf(MSG_DEBUG, "EAP-SIM: Unknown subtype=%d", subtype); - res = eap_sim_client_error(sm, data, req, respDataLen, + res = eap_sim_client_error(data, req, respDataLen, EAP_SIM_UNABLE_TO_PROCESS_PACKET); break; } @@ -947,7 +899,7 @@ static void * eap_sim_init_for_reauth(struct eap_sm *sm, void *priv) if (hostapd_get_rand(data->nonce_mt, EAP_SIM_NONCE_MT_LEN)) { wpa_printf(MSG_WARNING, "EAP-SIM: Failed to get random data " "for NONCE_MT"); - free(data); + os_free(data); return NULL; } data->num_id_req = 0; @@ -991,28 +943,59 @@ static u8 * eap_sim_getKey(struct eap_sm *sm, void *priv, size_t *len) if (data->state != SUCCESS) return NULL; - key = malloc(EAP_SIM_KEYING_DATA_LEN); + key = os_malloc(EAP_SIM_KEYING_DATA_LEN); if (key == NULL) return NULL; *len = EAP_SIM_KEYING_DATA_LEN; - memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); + os_memcpy(key, data->msk, EAP_SIM_KEYING_DATA_LEN); return key; } -const struct eap_method eap_method_sim = +static u8 * eap_sim_get_emsk(struct eap_sm *sm, void *priv, size_t *len) { - .method = EAP_TYPE_SIM, - .name = "SIM", - .init = eap_sim_init, - .deinit = eap_sim_deinit, - .process = eap_sim_process, - .isKeyAvailable = eap_sim_isKeyAvailable, - .getKey = eap_sim_getKey, - .has_reauth_data = eap_sim_has_reauth_data, - .deinit_for_reauth = eap_sim_deinit_for_reauth, - .init_for_reauth = eap_sim_init_for_reauth, - .get_identity = eap_sim_get_identity, -}; + struct eap_sim_data *data = priv; + u8 *key; + + if (data->state != SUCCESS) + return NULL; + + key = os_malloc(EAP_EMSK_LEN); + if (key == NULL) + return NULL; + + *len = EAP_EMSK_LEN; + os_memcpy(key, data->emsk, EAP_EMSK_LEN); + + return key; +} + + +int eap_peer_sim_register(void) +{ + struct eap_method *eap; + int ret; + + eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, + EAP_VENDOR_IETF, EAP_TYPE_SIM, "SIM"); + if (eap == NULL) + return -1; + + eap->init = eap_sim_init; + eap->deinit = eap_sim_deinit; + eap->process = eap_sim_process; + eap->isKeyAvailable = eap_sim_isKeyAvailable; + eap->getKey = eap_sim_getKey; + eap->has_reauth_data = eap_sim_has_reauth_data; + eap->deinit_for_reauth = eap_sim_deinit_for_reauth; + eap->init_for_reauth = eap_sim_init_for_reauth; + eap->get_identity = eap_sim_get_identity; + eap->get_emsk = eap_sim_get_emsk; + + ret = eap_peer_method_register(eap); + if (ret) + eap_peer_method_free(eap); + return ret; +} |