* EAP peer method: EAP-SAKE (RFC 4763)
* Copyright (c) 2006-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
- * 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_sake_common.h"
struct eap_sake_data *data = priv;
os_free(data->serverid);
os_free(data->peerid);
- os_free(data);
+ bin_clear_free(data, sizeof(*data));
}
static struct wpabuf * eap_sake_process_identity(struct eap_sm *sm,
struct eap_sake_data *data,
struct eap_method_ret *ret,
- const struct wpabuf *reqData,
+ u8 id,
const u8 *payload,
size_t payload_len)
{
wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Identity");
- resp = eap_sake_build_msg(data, eap_get_id(reqData),
- 2 + data->peerid_len,
+ resp = eap_sake_build_msg(data, id, 2 + data->peerid_len,
EAP_SAKE_SUBTYPE_IDENTITY);
if (resp == NULL)
return NULL;
static struct wpabuf * eap_sake_process_challenge(struct eap_sm *sm,
struct eap_sake_data *data,
struct eap_method_ret *ret,
- const struct wpabuf *reqData,
+ u8 id,
const u8 *payload,
size_t payload_len)
{
wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)",
data->rand_s, EAP_SAKE_RAND_LEN);
- if (os_get_random(data->rand_p, EAP_SAKE_RAND_LEN)) {
+ if (random_get_bytes(data->rand_p, EAP_SAKE_RAND_LEN)) {
wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data");
return NULL;
}
rlen = 2 + EAP_SAKE_RAND_LEN + 2 + EAP_SAKE_MIC_LEN;
if (data->peerid)
rlen += 2 + data->peerid_len;
- resp = eap_sake_build_msg(data, eap_get_id(reqData), rlen,
- EAP_SAKE_SUBTYPE_CHALLENGE);
+ resp = eap_sake_build_msg(data, id, rlen, EAP_SAKE_SUBTYPE_CHALLENGE);
if (resp == NULL)
return NULL;
static struct wpabuf * eap_sake_process_confirm(struct eap_sm *sm,
struct eap_sake_data *data,
struct eap_method_ret *ret,
+ u8 id,
const struct wpabuf *reqData,
const u8 *payload,
size_t payload_len)
return NULL;
}
- eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
- data->serverid, data->serverid_len,
- data->peerid, data->peerid_len, 0,
- wpabuf_head(reqData), wpabuf_len(reqData),
- attr.mic_s, mic_s);
- if (os_memcmp(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) {
+ if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p,
+ data->serverid, data->serverid_len,
+ data->peerid, data->peerid_len, 0,
+ wpabuf_head(reqData), wpabuf_len(reqData),
+ attr.mic_s, mic_s)) {
+ wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC");
+ eap_sake_state(data, FAILURE);
+ ret->methodState = METHOD_DONE;
+ ret->decision = DECISION_FAIL;
+ ret->allowNotifications = FALSE;
+ wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Auth-Reject");
+ return eap_sake_build_msg(data, id, 0,
+ EAP_SAKE_SUBTYPE_AUTH_REJECT);
+ }
+ if (os_memcmp_const(attr.mic_s, mic_s, EAP_SAKE_MIC_LEN) != 0) {
wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_S");
eap_sake_state(data, FAILURE);
ret->methodState = METHOD_DONE;
ret->allowNotifications = FALSE;
wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending "
"Response/Auth-Reject");
- return eap_sake_build_msg(data, eap_get_id(reqData), 0,
+ return eap_sake_build_msg(data, id, 0,
EAP_SAKE_SUBTYPE_AUTH_REJECT);
}
wpa_printf(MSG_DEBUG, "EAP-SAKE: Sending Response/Confirm");
- resp = eap_sake_build_msg(data, eap_get_id(reqData),
- 2 + EAP_SAKE_MIC_LEN,
+ resp = eap_sake_build_msg(data, id, 2 + EAP_SAKE_MIC_LEN,
EAP_SAKE_SUBTYPE_CONFIRM);
if (resp == NULL)
return NULL;
struct wpabuf *resp;
const u8 *pos, *end;
size_t len;
- u8 subtype, session_id;
+ u8 subtype, session_id, id;
pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, reqData, &len);
if (pos == NULL || len < sizeof(struct eap_sake_hdr)) {
req = (const struct eap_sake_hdr *) pos;
end = pos + len;
+ id = eap_get_id(reqData);
subtype = req->subtype;
session_id = req->session_id;
pos = (const u8 *) (req + 1);
switch (subtype) {
case EAP_SAKE_SUBTYPE_IDENTITY:
- resp = eap_sake_process_identity(sm, data, ret, reqData,
+ resp = eap_sake_process_identity(sm, data, ret, id,
pos, end - pos);
break;
case EAP_SAKE_SUBTYPE_CHALLENGE:
- resp = eap_sake_process_challenge(sm, data, ret, reqData,
+ resp = eap_sake_process_challenge(sm, data, ret, id,
pos, end - pos);
break;
case EAP_SAKE_SUBTYPE_CONFIRM:
- resp = eap_sake_process_confirm(sm, data, ret, reqData,
+ resp = eap_sake_process_confirm(sm, data, ret, id, reqData,
pos, end - pos);
break;
default:
}
+static u8 * eap_sake_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_sake_data *data = priv;
+ u8 *id;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ *len = 1 + 2 * EAP_SAKE_RAND_LEN;
+ id = os_malloc(*len);
+ if (id == NULL)
+ return NULL;
+
+ id[0] = EAP_TYPE_SAKE;
+ os_memcpy(id + 1, data->rand_s, EAP_SAKE_RAND_LEN);
+ os_memcpy(id + 1 + EAP_SAKE_RAND_LEN, data->rand_s, EAP_SAKE_RAND_LEN);
+ wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Derived Session-Id", id, *len);
+
+ return id;
+}
+
+
static u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
{
struct eap_sake_data *data = priv;
int eap_peer_sake_register(void)
{
struct eap_method *eap;
- int ret;
eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE");
eap->process = eap_sake_process;
eap->isKeyAvailable = eap_sake_isKeyAvailable;
eap->getKey = eap_sake_getKey;
+ eap->getSessionId = eap_sake_get_session_id;
eap->get_emsk = eap_sake_get_emsk;
- ret = eap_peer_method_register(eap);
- if (ret)
- eap_peer_method_free(eap);
- return ret;
+ return eap_peer_method_register(eap);
}