Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / src / eap_server / eap_server_psk.c
index 4c30346..12b5d25 100644 (file)
@@ -2,14 +2,8 @@
  * 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
- * 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.
  *
  * Note: EAP-PSK is an EAP authentication method and as such, completely
  * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
@@ -19,6 +13,7 @@
 
 #include "common.h"
 #include "crypto/aes_wrap.h"
+#include "crypto/random.h"
 #include "eap_common/eap_psk_common.h"
 #include "eap_server/eap_i.h"
 
@@ -27,8 +22,8 @@ struct eap_psk_data {
        enum { PSK_1, PSK_3, SUCCESS, FAILURE } state;
        u8 rand_s[EAP_PSK_RAND_LEN];
        u8 rand_p[EAP_PSK_RAND_LEN];
-       u8 *id_p, *id_s;
-       size_t id_p_len, id_s_len;
+       u8 *id_p;
+       size_t id_p_len;
        u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
        u8 msk[EAP_MSK_LEN];
        u8 emsk[EAP_EMSK_LEN];
@@ -43,8 +38,6 @@ static void * eap_psk_init(struct eap_sm *sm)
        if (data == NULL)
                return NULL;
        data->state = PSK_1;
-       data->id_s = (u8 *) "hostapd";
-       data->id_s_len = 7;
 
        return data;
 }
@@ -54,7 +47,7 @@ static void eap_psk_reset(struct eap_sm *sm, void *priv)
 {
        struct eap_psk_data *data = priv;
        os_free(data->id_p);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -66,7 +59,7 @@ static struct wpabuf * eap_psk_build_1(struct eap_sm *sm,
 
        wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)");
 
-       if (os_get_random(data->rand_s, EAP_PSK_RAND_LEN)) {
+       if (random_get_bytes(data->rand_s, EAP_PSK_RAND_LEN)) {
                wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
                data->state = FAILURE;
                return NULL;
@@ -75,7 +68,7 @@ static struct wpabuf * eap_psk_build_1(struct eap_sm *sm,
                    data->rand_s, EAP_PSK_RAND_LEN);
 
        req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
-                           sizeof(*psk) + data->id_s_len,
+                           sizeof(*psk) + sm->server_id_len,
                            EAP_CODE_REQUEST, id);
        if (req == NULL) {
                wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory "
@@ -87,7 +80,7 @@ static struct wpabuf * eap_psk_build_1(struct eap_sm *sm,
        psk = wpabuf_put(req, sizeof(*psk));
        psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */
        os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN);
-       wpabuf_put_data(req, data->id_s, data->id_s_len);
+       wpabuf_put_data(req, sm->server_id, sm->server_id_len);
 
        return req;
 }
@@ -117,15 +110,17 @@ static struct wpabuf * eap_psk_build_3(struct eap_sm *sm,
        os_memcpy(psk->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;
+       buflen = sm->server_id_len + EAP_PSK_RAND_LEN;
        buf = os_malloc(buflen);
        if (buf == NULL)
                goto fail;
 
-       os_memcpy(buf, data->id_s, data->id_s_len);
-       os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
-       if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s))
+       os_memcpy(buf, sm->server_id, sm->server_id_len);
+       os_memcpy(buf + sm->server_id_len, data->rand_p, EAP_PSK_RAND_LEN);
+       if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) {
+               os_free(buf);
                goto fail;
+       }
        os_free(buf);
 
        if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk,
@@ -299,7 +294,7 @@ static void eap_psk_process_2(struct eap_sm *sm,
        os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN);
 
        /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
-       buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
+       buflen = data->id_p_len + sm->server_id_len + 2 * EAP_PSK_RAND_LEN;
        buf = os_malloc(buflen);
        if (buf == NULL) {
                data->state = FAILURE;
@@ -307,8 +302,8 @@ static void eap_psk_process_2(struct eap_sm *sm,
        }
        os_memcpy(buf, data->id_p, data->id_p_len);
        pos = buf + data->id_p_len;
-       os_memcpy(pos, data->id_s, data->id_s_len);
-       pos += data->id_s_len;
+       os_memcpy(pos, sm->server_id, sm->server_id_len);
+       pos += sm->server_id_len;
        os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN);
        pos += EAP_PSK_RAND_LEN;
        os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
@@ -319,7 +314,7 @@ static void eap_psk_process_2(struct eap_sm *sm,
        }
        os_free(buf);
        wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN);
-       if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
+       if (os_memcmp_const(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) {
                wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P");
                wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P",
                            mac, EAP_PSK_MAC_LEN);
@@ -490,6 +485,28 @@ static Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv)
 }
 
 
+static u8 * eap_psk_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+       struct eap_psk_data *data = priv;
+       u8 *id;
+
+       if (data->state != SUCCESS)
+               return NULL;
+
+       *len = 1 + 2 * EAP_PSK_RAND_LEN;
+       id = os_malloc(*len);
+       if (id == NULL)
+               return NULL;
+
+       id[0] = EAP_TYPE_PSK;
+       os_memcpy(id + 1, data->rand_p, EAP_PSK_RAND_LEN);
+       os_memcpy(id + 1 + EAP_PSK_RAND_LEN, data->rand_s, EAP_PSK_RAND_LEN);
+       wpa_hexdump(MSG_DEBUG, "EAP-PSK: Derived Session-Id", id, *len);
+
+       return id;
+}
+
+
 int eap_server_psk_register(void)
 {
        struct eap_method *eap;
@@ -509,6 +526,7 @@ int eap_server_psk_register(void)
        eap->getKey = eap_psk_getKey;
        eap->isSuccess = eap_psk_isSuccess;
        eap->get_emsk = eap_psk_get_emsk;
+       eap->getSessionId = eap_psk_get_session_id;
 
        ret = eap_server_method_register(eap);
        if (ret)