X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=libeap%2Fsrc%2Feap_peer%2Feap_gpsk.c;fp=libeap%2Fsrc%2Feap_peer%2Feap_gpsk.c;h=902b4ba26d6e46b6a10019bd8c958e4deb7fc985;hb=4f319dde67a76fe0aaf33f6d2788968012584ada;hp=f6a1955baff1a84adad479aeb5d7b0488a048ad4;hpb=ed09b5e64dd485851310307979d5eed14678087b;p=mech_eap.git diff --git a/libeap/src/eap_peer/eap_gpsk.c b/libeap/src/eap_peer/eap_gpsk.c index f6a1955..902b4ba 100644 --- a/libeap/src/eap_peer/eap_gpsk.c +++ b/libeap/src/eap_peer/eap_gpsk.c @@ -1,20 +1,15 @@ /* * EAP peer method: EAP-GPSK (RFC 5433) - * Copyright (c) 2006-2008, Jouni Malinen + * Copyright (c) 2006-2014, Jouni Malinen * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" #include "common.h" +#include "crypto/random.h" #include "eap_peer/eap_i.h" #include "eap_common/eap_gpsk_common.h" @@ -28,8 +23,8 @@ struct eap_gpsk_data { size_t sk_len; u8 pk[EAP_GPSK_MAX_PK_LEN]; size_t pk_len; - u8 session_id; - int session_id_set; + u8 session_id[128]; + size_t id_len; u8 *id_peer; size_t id_peer_len; u8 *id_server; @@ -38,6 +33,7 @@ struct eap_gpsk_data { int specifier; /* CSuite/Specifier */ u8 *psk; size_t psk_len; + u16 forced_cipher; /* force cipher or 0 to allow all supported */ }; @@ -85,6 +81,7 @@ static void * eap_gpsk_init(struct eap_sm *sm) struct eap_gpsk_data *data; const u8 *identity, *password; size_t identity_len, password_len; + const char *phase1; password = eap_get_config_password(sm, &password_len); if (password == NULL) { @@ -108,6 +105,18 @@ static void * eap_gpsk_init(struct eap_sm *sm) data->id_peer_len = identity_len; } + phase1 = eap_get_config_phase1(sm); + if (phase1) { + const char *pos; + + pos = os_strstr(phase1, "cipher="); + if (pos) { + data->forced_cipher = atoi(pos + 7); + wpa_printf(MSG_DEBUG, "EAP-GPSK: Forced cipher %u", + data->forced_cipher); + } + } + data->psk = os_malloc(password_len); if (data->psk == NULL) { eap_gpsk_deinit(sm, data); @@ -125,8 +134,11 @@ 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_peer); - os_free(data->psk); - os_free(data); + if (data->psk) { + os_memset(data->psk, 0, data->psk_len); + os_free(data->psk); + } + bin_clear_free(data, sizeof(*data)); } @@ -200,7 +212,9 @@ static int eap_gpsk_select_csuite(struct eap_sm *sm, i, vendor, specifier); if (data->vendor == EAP_GPSK_VENDOR_IETF && data->specifier == EAP_GPSK_CIPHER_RESERVED && - eap_gpsk_supported_ciphersuite(vendor, specifier)) { + eap_gpsk_supported_ciphersuite(vendor, specifier) && + (!data->forced_cipher || data->forced_cipher == specifier)) + { data->vendor = vendor; data->specifier = specifier; } @@ -225,6 +239,8 @@ static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, size_t *list_len, const u8 *pos, const u8 *end) { + size_t len; + if (pos == NULL) return NULL; @@ -232,23 +248,25 @@ static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); return NULL; } - *list_len = WPA_GET_BE16(pos); + len = WPA_GET_BE16(pos); pos += 2; - if (end - pos < (int) *list_len) { + if (len > (size_t) (end - pos)) { wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); return NULL; } - if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { + if (len == 0 || (len % sizeof(struct eap_gpsk_csuite))) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", - (unsigned long) *list_len); + (unsigned long) len); return NULL; } - *list = pos; - pos += *list_len; - if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) + if (eap_gpsk_select_csuite(sm, data, pos, len) < 0) return NULL; + *list = pos; + *list_len = len; + pos += len; + return pos; } @@ -256,7 +274,7 @@ static const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, struct eap_gpsk_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 identifier, const u8 *payload, size_t payload_len) { @@ -278,11 +296,12 @@ static struct wpabuf * eap_gpsk_process_gpsk_1(struct eap_sm *sm, pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, &csuite_list_len, pos, end); if (pos == NULL) { + ret->methodState = METHOD_DONE; eap_gpsk_state(data, FAILURE); return NULL; } - resp = eap_gpsk_send_gpsk_2(data, eap_get_id(reqData), + resp = eap_gpsk_send_gpsk_2(data, identifier, csuite_list, csuite_list_len); if (resp == NULL) return NULL; @@ -326,7 +345,7 @@ static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, wpabuf_put_be16(resp, data->id_server_len); wpabuf_put_data(resp, data->id_server, data->id_server_len); - if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) { + if (random_get_bytes(data->rand_peer, EAP_GPSK_RAND_LEN)) { wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " "for RAND_Peer"); eap_gpsk_state(data, FAILURE); @@ -359,6 +378,21 @@ static struct wpabuf * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, return NULL; } + if (eap_gpsk_derive_session_id(data->psk, data->psk_len, + data->vendor, data->specifier, + data->rand_peer, data->rand_server, + data->id_peer, data->id_peer_len, + data->id_server, data->id_server_len, + EAP_TYPE_GPSK, + data->session_id, &data->id_len) < 0) { + wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive Session-Id"); + eap_gpsk_state(data, FAILURE); + wpabuf_free(resp); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id", + data->session_id, data->id_len); + /* No PD_Payload_1 */ wpabuf_put_be16(resp, 0); @@ -534,7 +568,7 @@ static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); return NULL; } - if (os_memcmp(mic, pos, miclen) != 0) { + if (os_memcmp_const(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); @@ -549,7 +583,7 @@ static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, struct eap_gpsk_data *data, struct eap_method_ret *ret, - const struct wpabuf *reqData, + u8 identifier, const u8 *payload, size_t payload_len) { @@ -581,7 +615,7 @@ static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, (unsigned long) (end - pos)); } - resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); + resp = eap_gpsk_send_gpsk_4(data, identifier); if (resp == NULL) return NULL; @@ -636,6 +670,7 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, struct wpabuf *resp; const u8 *pos; size_t len; + u8 opcode, id; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); if (pos == NULL || len < 1) { @@ -643,25 +678,27 @@ static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, return NULL; } - wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); + id = eap_get_id(reqData); + opcode = *pos++; + len--; + wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", opcode); ret->ignore = FALSE; ret->methodState = METHOD_MAY_CONT; ret->decision = DECISION_FAIL; ret->allowNotifications = FALSE; - switch (*pos) { + switch (opcode) { case EAP_GPSK_OPCODE_GPSK_1: - resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, - pos + 1, len - 1); + resp = eap_gpsk_process_gpsk_1(sm, data, ret, id, pos, len); break; case EAP_GPSK_OPCODE_GPSK_3: - resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, - pos + 1, len - 1); + resp = eap_gpsk_process_gpsk_3(sm, data, ret, id, pos, len); break; default: - wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " - "unknown opcode %d", *pos); + wpa_printf(MSG_DEBUG, + "EAP-GPSK: Ignoring message with unknown opcode %d", + opcode); ret->ignore = TRUE; return NULL; } @@ -713,6 +750,24 @@ static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) } +static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) +{ + struct eap_gpsk_data *data = priv; + u8 *sid; + + if (data->state != SUCCESS) + return NULL; + + sid = os_malloc(data->id_len); + if (sid == NULL) + return NULL; + os_memcpy(sid, data->session_id, data->id_len); + *len = data->id_len; + + return sid; +} + + int eap_peer_gpsk_register(void) { struct eap_method *eap; @@ -729,6 +784,7 @@ int eap_peer_gpsk_register(void) eap->isKeyAvailable = eap_gpsk_isKeyAvailable; eap->getKey = eap_gpsk_getKey; eap->get_emsk = eap_gpsk_get_emsk; + eap->getSessionId = eap_gpsk_get_session_id; ret = eap_peer_method_register(eap); if (ret)