diff options
Diffstat (limited to 'contrib/hostapd/eap_psk.c')
-rw-r--r-- | contrib/hostapd/eap_psk.c | 108 |
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; +} |