summaryrefslogtreecommitdiffstats
path: root/contrib/hostapd/eap_psk.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/hostapd/eap_psk.c')
-rw-r--r--contrib/hostapd/eap_psk.c108
1 files changed, 72 insertions, 36 deletions
diff --git a/contrib/hostapd/eap_psk.c b/contrib/hostapd/eap_psk.c
index 2f92d05..7408a52 100644
--- a/contrib/hostapd/eap_psk.c
+++ b/contrib/hostapd/eap_psk.c
@@ -1,6 +1,6 @@
/*
- * hostapd / EAP-PSK (draft-bersani-eap-psk-09.txt) server
- * Copyright (c) 2005, Jouni Malinen <jkmaline@cc.hut.fi>
+ * hostapd / EAP-PSK (RFC 4764) server
+ * Copyright (c) 2005-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
@@ -15,10 +15,7 @@
* different from WPA-PSK. This file is not needed for WPA-PSK functionality.
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <netinet/in.h>
+#include "includes.h"
#include "hostapd.h"
#include "common.h"
@@ -34,7 +31,8 @@ struct eap_psk_data {
u8 *id_p, *id_s;
size_t id_p_len, id_s_len;
u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
- u8 msk[EAP_PSK_MSK_LEN];
+ u8 msk[EAP_MSK_LEN];
+ u8 emsk[EAP_EMSK_LEN];
};
@@ -42,12 +40,11 @@ static void * eap_psk_init(struct eap_sm *sm)
{
struct eap_psk_data *data;
- data = malloc(sizeof(*data));
+ data = wpa_zalloc(sizeof(*data));
if (data == NULL)
- return data;
- memset(data, 0, sizeof(*data));
+ return NULL;
data->state = PSK_1;
- data->id_s = "hostapd";
+ data->id_s = (u8 *) "hostapd";
data->id_s_len = 7;
return data;
@@ -90,7 +87,7 @@ static u8 * eap_psk_build_1(struct eap_sm *sm, struct eap_psk_data *data,
req->identifier = id;
req->length = htons(*reqDataLen);
req->type = EAP_TYPE_PSK;
- req->flags = 0; /* T=0 */
+ req->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */
memcpy(req->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
memcpy((u8 *) (req + 1), data->id_s, data->id_s_len);
@@ -120,13 +117,14 @@ static u8 * eap_psk_build_3(struct eap_sm *sm, struct eap_psk_data *data,
req->identifier = id;
req->length = htons(*reqDataLen);
req->type = EAP_TYPE_PSK;
- req->flags = 2; /* T=2 */
+ req->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */
memcpy(req->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
/* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
buflen = data->id_s_len + EAP_PSK_RAND_LEN;
buf = malloc(buflen);
if (buf == NULL) {
+ free(req);
data->state = FAILURE;
return NULL;
}
@@ -135,9 +133,11 @@ static u8 * eap_psk_build_3(struct eap_sm *sm, struct eap_psk_data *data,
omac1_aes_128(data->ak, buf, buflen, req->mac_s);
free(buf);
- eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk);
+ eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
+ data->emsk);
wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
- wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_PSK_MSK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
+ wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
memset(nonce, 0, sizeof(nonce));
pchannel = (u8 *) (req + 1);
@@ -189,7 +189,7 @@ static Boolean eap_psk_check(struct eap_sm *sm, void *priv,
wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame");
return TRUE;
}
- t = resp->flags & 0x03;
+ t = EAP_PSK_FLAGS_GET_T(resp->flags);
wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t);
@@ -254,13 +254,18 @@ static void eap_psk_process_2(struct eap_sm *sm,
}
for (i = 0;
- i < EAP_MAX_METHODS && sm->user->methods[i] != EAP_TYPE_NONE;
+ i < EAP_MAX_METHODS &&
+ (sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
+ sm->user->methods[i].method != EAP_TYPE_NONE);
i++) {
- if (sm->user->methods[i] == EAP_TYPE_PSK)
+ if (sm->user->methods[i].vendor == EAP_VENDOR_IETF &&
+ sm->user->methods[i].method == EAP_TYPE_PSK)
break;
}
- if (sm->user->methods[i] != EAP_TYPE_PSK) {
+ if (i >= EAP_MAX_METHODS ||
+ sm->user->methods[i].vendor != EAP_VENDOR_IETF ||
+ sm->user->methods[i].method != EAP_TYPE_PSK) {
wpa_hexdump_ascii(MSG_DEBUG,
"EAP-PSK: EAP-PSK not enabled for ID_P",
data->id_p, data->id_p_len);
@@ -393,14 +398,15 @@ static void eap_psk_process(struct eap_sm *sm, void *priv,
struct eap_psk_hdr *resp;
if (sm->user == NULL || sm->user->password == NULL) {
- wpa_printf(MSG_INFO, "EAP-MSCHAPV2: Password not configured");
+ wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not "
+ "configured");
data->state = FAILURE;
return;
}
resp = (struct eap_psk_hdr *) respData;
- switch (resp->flags & 0x03) {
+ switch (EAP_PSK_FLAGS_GET_T(resp->flags)) {
case 1:
eap_psk_process_2(sm, data, respData, respDataLen);
break;
@@ -426,11 +432,29 @@ static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
if (data->state != SUCCESS)
return NULL;
- key = malloc(EAP_PSK_MSK_LEN);
+ key = malloc(EAP_MSK_LEN);
if (key == NULL)
return NULL;
- memcpy(key, data->msk, EAP_PSK_MSK_LEN);
- *len = EAP_PSK_MSK_LEN;
+ memcpy(key, data->msk, EAP_MSK_LEN);
+ *len = EAP_MSK_LEN;
+
+ return key;
+}
+
+
+static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
+{
+ struct eap_psk_data *data = priv;
+ u8 *key;
+
+ if (data->state != SUCCESS)
+ return NULL;
+
+ key = malloc(EAP_EMSK_LEN);
+ if (key == NULL)
+ return NULL;
+ memcpy(key, data->emsk, EAP_EMSK_LEN);
+ *len = EAP_EMSK_LEN;
return key;
}
@@ -443,16 +467,28 @@ static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv)
}
-const struct eap_method eap_method_psk =
+int eap_server_psk_register(void)
{
- .method = EAP_TYPE_PSK,
- .name = "PSK",
- .init = eap_psk_init,
- .reset = eap_psk_reset,
- .buildReq = eap_psk_buildReq,
- .check = eap_psk_check,
- .process = eap_psk_process,
- .isDone = eap_psk_isDone,
- .getKey = eap_psk_getKey,
- .isSuccess = eap_psk_isSuccess,
-};
+ struct eap_method *eap;
+ int ret;
+
+ eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
+ EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
+ if (eap == NULL)
+ return -1;
+
+ eap->init = eap_psk_init;
+ eap->reset = eap_psk_reset;
+ eap->buildReq = eap_psk_buildReq;
+ eap->check = eap_psk_check;
+ eap->process = eap_psk_process;
+ eap->isDone = eap_psk_isDone;
+ eap->getKey = eap_psk_getKey;
+ eap->isSuccess = eap_psk_isSuccess;
+ eap->get_emsk = eap_psk_get_emsk;
+
+ ret = eap_server_method_register(eap);
+ if (ret)
+ eap_server_method_free(eap);
+ return ret;
+}
OpenPOWER on IntegriCloud