Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / src / eap_server / eap_server_pax.c
index 1dc023b..0e6b4a0 100644 (file)
@@ -2,19 +2,14 @@
  * hostapd / EAP-PAX (RFC 4746) 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.
  */
 
 #include "includes.h"
 
 #include "common.h"
+#include "crypto/random.h"
 #include "eap_server/eap_i.h"
 #include "eap_common/eap_pax_common.h"
 
@@ -41,6 +36,7 @@ struct eap_pax_data {
        u8 mk[EAP_PAX_MK_LEN];
        u8 ck[EAP_PAX_CK_LEN];
        u8 ick[EAP_PAX_ICK_LEN];
+       u8 mid[EAP_PAX_MID_LEN];
        int keys_set;
        char *cid;
        size_t cid_len;
@@ -69,7 +65,7 @@ static void eap_pax_reset(struct eap_sm *sm, void *priv)
 {
        struct eap_pax_data *data = priv;
        os_free(data->cid);
-       os_free(data);
+       bin_clear_free(data, sizeof(*data));
 }
 
 
@@ -82,7 +78,7 @@ static struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm,
 
        wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)");
 
-       if (os_get_random(data->rand.r.x, EAP_PAX_RAND_LEN)) {
+       if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) {
                wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data");
                data->state = FAILURE;
                return NULL;
@@ -153,7 +149,6 @@ static struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm,
                    (u8 *) data->cid, data->cid_len, NULL, 0, pos);
        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)",
                    pos, EAP_PAX_MAC_LEN);
-       pos += EAP_PAX_MAC_LEN;
 
        /* Optional ADE could be added here, if needed */
 
@@ -273,7 +268,7 @@ static Boolean eap_pax_check(struct eap_sm *sm, void *priv,
                            wpabuf_mhead(respData),
                            wpabuf_len(respData) - EAP_PAX_ICV_LEN,
                            NULL, 0, NULL, 0, icvbuf);
-               if (os_memcmp(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
+               if (os_memcmp_const(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) {
                        wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV");
                        wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
                                    icvbuf, EAP_PAX_ICV_LEN);
@@ -292,7 +287,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
        struct eap_pax_hdr *resp;
        u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN];
        const u8 *pos;
-       size_t len, left;
+       size_t len, left, cid_len;
        int i;
 
        if (data->state != PAX_STD_1)
@@ -325,7 +320,12 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
                wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)");
                return;
        }
-       data->cid_len = WPA_GET_BE16(pos);
+       cid_len = WPA_GET_BE16(pos);
+       if (cid_len > 1500) {
+               wpa_printf(MSG_INFO, "EAP-PAX: Too long CID");
+               return;
+       }
+       data->cid_len = cid_len;
        os_free(data->cid);
        data->cid = os_malloc(data->cid_len);
        if (data->cid == NULL) {
@@ -388,7 +388,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
 
        if (eap_pax_initial_key_derivation(data->mac_id, data->ak,
                                           data->rand.e, data->mk, data->ck,
-                                          data->ick) < 0) {
+                                          data->ick, data->mid) < 0) {
                wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial "
                           "key derivation");
                data->state = FAILURE;
@@ -400,7 +400,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
                    data->rand.r.x, EAP_PAX_RAND_LEN,
                    data->rand.r.y, EAP_PAX_RAND_LEN,
                    (u8 *) data->cid, data->cid_len, mac);
-       if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) {
+       if (os_memcmp_const(mac, pos, EAP_PAX_MAC_LEN) != 0) {
                wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in "
                           "PAX_STD-2");
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)",
@@ -422,7 +422,7 @@ static void eap_pax_process_std_2(struct eap_sm *sm,
                    wpabuf_head(respData),
                    wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0,
                    icvbuf);
-       if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
+       if (os_memcmp_const(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) {
                wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2");
                wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV",
                            icvbuf, EAP_PAX_ICV_LEN);
@@ -542,6 +542,26 @@ static Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv)
 }
 
 
+static u8 * eap_pax_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
+{
+       struct eap_pax_data *data = priv;
+       u8 *sid;
+
+       if (data->state != SUCCESS)
+               return NULL;
+
+       sid = os_malloc(1 + EAP_PAX_MID_LEN);
+       if (sid == NULL)
+               return NULL;
+
+       *len = 1 + EAP_PAX_MID_LEN;
+       sid[0] = EAP_TYPE_PAX;
+       os_memcpy(sid + 1, data->mid, EAP_PAX_MID_LEN);
+
+       return sid;
+}
+
+
 int eap_server_pax_register(void)
 {
        struct eap_method *eap;
@@ -561,6 +581,7 @@ int eap_server_pax_register(void)
        eap->getKey = eap_pax_getKey;
        eap->isSuccess = eap_pax_isSuccess;
        eap->get_emsk = eap_pax_get_emsk;
+       eap->getSessionId = eap_pax_get_session_id;
 
        ret = eap_server_method_register(eap);
        if (ret)