* hostapd / EAP-GPSK (RFC 5433) server
* 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
- * 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_server/eap_i.h"
#include "eap_common/eap_gpsk_common.h"
size_t sk_len;
u8 pk[EAP_GPSK_MAX_PK_LEN];
size_t pk_len;
+ u8 session_id[128];
+ size_t id_len;
u8 *id_peer;
size_t id_peer_len;
- u8 *id_server;
- size_t id_server_len;
#define MAX_NUM_CSUITES 2
struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES];
size_t csuite_count;
return NULL;
data->state = GPSK_1;
- /* TODO: add support for configuring ID_Server */
- data->id_server = (u8 *) os_strdup("hostapd");
- if (data->id_server)
- data->id_server_len = os_strlen((char *) data->id_server);
-
data->csuite_count = 0;
if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF,
EAP_GPSK_CIPHER_AES)) {
static void eap_gpsk_reset(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);
+ bin_clear_free(data, sizeof(*data));
}
wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1");
- if (os_get_random(data->rand_server, EAP_GPSK_RAND_LEN)) {
+ if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) {
wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data");
eap_gpsk_state(data, FAILURE);
return NULL;
wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server",
data->rand_server, EAP_GPSK_RAND_LEN);
- len = 1 + 2 + data->id_server_len + EAP_GPSK_RAND_LEN + 2 +
+ len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 +
data->csuite_count * sizeof(struct eap_gpsk_csuite);
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
EAP_CODE_REQUEST, id);
}
wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1);
- wpabuf_put_be16(req, data->id_server_len);
- wpabuf_put_data(req, data->id_server, data->id_server_len);
+ wpabuf_put_be16(req, sm->server_id_len);
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
wpabuf_put_be16(req,
data->csuite_count * sizeof(struct eap_gpsk_csuite));
wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3");
miclen = eap_gpsk_mic_len(data->vendor, data->specifier);
- len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len +
+ len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len +
sizeof(struct eap_gpsk_csuite) + 2 + miclen;
req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len,
EAP_CODE_REQUEST, id);
wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN);
wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN);
- wpabuf_put_be16(req, data->id_server_len);
- wpabuf_put_data(req, data->id_server, data->id_server_len);
+ wpabuf_put_be16(req, sm->server_id_len);
+ wpabuf_put_data(req, sm->server_id, sm->server_id_len);
csuite = wpabuf_put(req, sizeof(*csuite));
WPA_PUT_BE32(csuite->vendor, data->vendor);
WPA_PUT_BE16(csuite->specifier, data->specifier);
eap_gpsk_state(data, FAILURE);
return;
}
- if (alen != data->id_server_len ||
- os_memcmp(pos, data->id_server, alen) != 0) {
+ if (alen != sm->server_id_len ||
+ os_memcmp(pos, sm->server_id, alen) != 0) {
wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and "
"GPSK-2 did not match");
eap_gpsk_state(data, FAILURE);
data->vendor, data->specifier,
data->rand_peer, data->rand_server,
data->id_peer, data->id_peer_len,
- data->id_server, data->id_server_len,
+ sm->server_id, sm->server_id_len,
data->msk, data->emsk,
data->sk, &data->sk_len,
data->pk, &data->pk_len) < 0) {
return;
}
+ if (eap_gpsk_derive_session_id(sm->user->password,
+ sm->user->password_len,
+ data->vendor, data->specifier,
+ data->rand_peer, data->rand_server,
+ data->id_peer, data->id_peer_len,
+ sm->server_id, sm->server_id_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);
+ return;
+ }
+ wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Derived Session-Id",
+ data->session_id, data->id_len);
+
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 "
eap_gpsk_state(data, FAILURE);
return;
}
- 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-2");
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;
}
- 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-4");
wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen);
wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen);
}
+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_server_gpsk_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK");
eap->getKey = eap_gpsk_getKey;
eap->isSuccess = eap_gpsk_isSuccess;
eap->get_emsk = eap_gpsk_get_emsk;
+ eap->getSessionId = eap_gpsk_get_session_id;
- ret = eap_server_method_register(eap);
- if (ret)
- eap_server_method_free(eap);
- return ret;
+ return eap_server_method_register(eap);
}