18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / EAP-PAX (RFC 4746) server 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/random.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_server/eap_i.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_common/eap_pax_common.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: only PAX_STD subprotocol is currently supported 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: Add support with PAX_SEC with the mandatory to implement ciphersuite 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * (HMAC_SHA1_128, IANA DH Group 14 (2048 bits), RSA-PKCS1-V1_5) and 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * recommended ciphersuite (HMAC_SHA256_128, IANA DH Group 15 (3072 bits), 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSAES-OAEP). 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct eap_pax_data { 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum { PAX_STD_1, PAX_STD_3, SUCCESS, FAILURE } state; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_id; 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt union { 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 e[2 * EAP_PAX_RAND_LEN]; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct { 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 x[EAP_PAX_RAND_LEN]; /* server rand */ 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 y[EAP_PAX_RAND_LEN]; /* client rand */ 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } r; 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } rand; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ak[EAP_PAX_AK_LEN]; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_PAX_MK_LEN]; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ck[EAP_PAX_CK_LEN]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ick[EAP_PAX_ICK_LEN]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int keys_set; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *cid; 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t cid_len; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_pax_init(struct eap_sm *sm) 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data; 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PAX_STD_1; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: make this configurable once EAP_PAX_HMAC_SHA256_128 is 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * supported 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mac_id = EAP_PAX_MAC_HMAC_SHA1_128; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_reset(struct eap_sm *sm, void *priv) 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->cid); 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_build_std_1(struct eap_sm *sm, 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data, u8 id) 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *pax; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (sending)"); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand.r.x, EAP_PAX_RAND_LEN)) { 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*pax) + 2 + EAP_PAX_RAND_LEN + 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax = wpabuf_put(req, sizeof(*pax)); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->op_code = EAP_PAX_OP_STD_1; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->flags = 0; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->mac_id = data->mac_id; 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(req, EAP_PAX_RAND_LEN); 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(req, data->rand.r.x, EAP_PAX_RAND_LEN); 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: A = X (server rand)", 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.x, EAP_PAX_RAND_LEN); 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_put(req, EAP_PAX_MAC_LEN); 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, (u8 *) "", 0, 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, NULL, 0, pos); 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_build_std_3(struct eap_sm *sm, 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data, u8 id) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *req; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *pax; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (sending)"); 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*pax) + 2 + EAP_PAX_MAC_LEN + 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PAX_ICV_LEN, EAP_CODE_REQUEST, id); 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req == NULL) { 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PAX: Failed to allocate memory " 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "request"); 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax = wpabuf_put(req, sizeof(*pax)); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->op_code = EAP_PAX_OP_STD_3; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->flags = 0; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->mac_id = data->mac_id; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->dh_group_id = EAP_PAX_DH_GROUP_NONE; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->public_key_id = EAP_PAX_PUBLIC_KEY_NONE; 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(req, EAP_PAX_MAC_LEN); 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_put(req, EAP_PAX_MAC_LEN); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN, 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len, NULL, 0, pos); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_PAX_MAC_LEN); 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_MAC_LEN; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optional ADE could be added here, if needed */ 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpabuf_put(req, EAP_PAX_MAC_LEN); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_mhead(req), wpabuf_len(req) - EAP_PAX_ICV_LEN, 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, NULL, 0, pos); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return req; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_buildReq(struct eap_sm *sm, void *priv, u8 id) 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (data->state) { 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAX_STD_1: 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_pax_build_std_1(sm, data, id); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case PAX_STD_3: 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return eap_pax_build_std_3(sm, data, id); 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown state %d in buildReq", 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state); 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_pax_check(struct eap_sm *sm, void *priv, 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *resp; 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, mlen; 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 icvbuf[EAP_PAX_ICV_LEN], *icv; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < sizeof(*resp)) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid frame"); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen = sizeof(struct eap_hdr) + 1 + len; 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (struct eap_pax_hdr *) pos; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flags 0x%x mac_id 0x%x dh_group_id 0x%x " 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "public_key_id 0x%x", 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->op_code, resp->flags, resp->mac_id, resp->dh_group_id, 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->public_key_id); 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) (resp + 1), len - sizeof(*resp) - EAP_PAX_ICV_LEN); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PAX_STD_1 && 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->op_code != EAP_PAX_OP_STD_2) { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX_STD-2 - " 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore op %d", resp->op_code); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state == PAX_STD_3 && 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->op_code != EAP_PAX_OP_ACK) { 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Expected PAX-ACK - " 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignore op %d", resp->op_code); 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp->op_code != EAP_PAX_OP_STD_2 && 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->op_code != EAP_PAX_OP_ACK) { 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Unknown op_code 0x%x", 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->op_code); 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->mac_id != resp->mac_id) { 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Expected MAC ID 0x%x, " 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received 0x%x", data->mac_id, resp->mac_id); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp->dh_group_id != EAP_PAX_DH_GROUP_NONE) { 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Expected DH Group ID 0x%x, " 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received 0x%x", EAP_PAX_DH_GROUP_NONE, 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->dh_group_id); 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Expected Public Key ID 0x%x, " 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received 0x%x", EAP_PAX_PUBLIC_KEY_NONE, 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp->public_key_id); 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp->flags & EAP_PAX_FLAGS_MF) { 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for reassembling fragments */ 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported"); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp->flags & EAP_PAX_FLAGS_CE) { 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Unexpected CE flag"); 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->keys_set) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len - sizeof(*resp) < EAP_PAX_ICV_LEN) { 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: No ICV in the packet"); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv = wpabuf_mhead_u8(respData) + mlen - EAP_PAX_ICV_LEN; 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_mhead(respData), 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(respData) - EAP_PAX_ICV_LEN, 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, NULL, 0, icvbuf); 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(icvbuf, icv, EAP_PAX_ICV_LEN) != 0) { 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV"); 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf, EAP_PAX_ICV_LEN); 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return TRUE; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return FALSE; 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_process_std_2(struct eap_sm *sm, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *resp; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac[EAP_PAX_MAC_LEN], icvbuf[EAP_PAX_ICV_LEN]; 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len, left; 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i; 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_STD_1) 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX_STD-2"); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < sizeof(*resp) + EAP_PAX_ICV_LEN) 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (struct eap_pax_hdr *) pos; 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (resp + 1); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = len - sizeof(*resp); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 2 + EAP_PAX_RAND_LEN || 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (B)"); 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand.r.y, pos, EAP_PAX_RAND_LEN); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN); 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_RAND_LEN; 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= EAP_PAX_RAND_LEN; 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 2 || (size_t) 2 + WPA_GET_BE16(pos) > left) { 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (CID)"); 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cid_len = WPA_GET_BE16(pos); 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->cid); 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cid = os_malloc(data->cid_len); 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->cid == NULL) { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Failed to allocate memory for " 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "CID"); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->cid, pos + 2, data->cid_len); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + data->cid_len; 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2 + data->cid_len; 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len); 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 2 + EAP_PAX_MAC_LEN || 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Too short PAX_STD-2 (MAC_CK)"); 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_PAX_MAC_LEN); 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_user_get(sm, (u8 *) data->cid, data->cid_len, 0) < 0) { 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: unknown CID", 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len); 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i < EAP_MAX_METHODS && 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_NONE); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++) { 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method == EAP_TYPE_PAX) 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (i >= EAP_MAX_METHODS || 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].vendor != EAP_VENDOR_IETF || 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->methods[i].method != EAP_TYPE_PAX) { 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "EAP-PAX: EAP-PAX not enabled for CID", 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user->password == NULL || 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->user->password_len != EAP_PAX_AK_LEN) { 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_DEBUG, "EAP-PAX: invalid password in " 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "user database for CID", 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->ak, sm->user->password, EAP_PAX_AK_LEN); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_pax_initial_key_derivation(data->mac_id, data->ak, 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.e, data->mk, data->ck, 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->ick) < 0) { 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Failed to complete initial " 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "key derivation"); 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->keys_set = 1; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.x, EAP_PAX_RAND_LEN, 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN, 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len, mac); 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mac, pos, EAP_PAX_MAC_LEN) != 0) { 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(A, B, CID) in " 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PAX_STD-2"); 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected MAC_CK(A, B, CID)", 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, EAP_PAX_MAC_LEN); 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_MAC_LEN; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= EAP_PAX_MAC_LEN; 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < EAP_PAX_ICV_LEN) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Too short ICV (%lu) in " 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PAX_STD-2", (unsigned long) left); 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", pos, EAP_PAX_ICV_LEN); 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(respData), 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_len(respData) - EAP_PAX_ICV_LEN, NULL, 0, NULL, 0, 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(icvbuf, pos, EAP_PAX_ICV_LEN) != 0) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid ICV in PAX_STD-2"); 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Expected ICV", 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf, EAP_PAX_ICV_LEN); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_ICV_LEN; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= EAP_PAX_ICV_LEN; 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, left); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PAX_STD_3; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_process_ack(struct eap_sm *sm, 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data, 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_STD_3) 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: Received PAX-ACK - authentication " 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "completed successfully"); 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = SUCCESS; 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_process(struct eap_sm *sm, void *priv, 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *respData) 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *resp; 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->user == NULL || sm->user->password == NULL) { 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Plaintext password not " 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "configured"); 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = FAILURE; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, respData, &len); 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos == NULL || len < sizeof(*resp)) 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = (struct eap_pax_hdr *) pos; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (resp->op_code) { 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PAX_OP_STD_2: 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_process_std_2(sm, data, respData); 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PAX_OP_ACK: 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_process_ack(sm, data, respData); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_pax_isDone(struct eap_sm *sm, void *priv) 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS || data->state == FAILURE; 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Master Session Key", data->rand.e, 2 * EAP_PAX_RAND_LEN, 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_MSK_LEN, key); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != SUCCESS) 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Extended Master Session Key", 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.e, 2 * EAP_PAX_RAND_LEN, 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_EMSK_LEN, key); 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_pax_isSuccess(struct eap_sm *sm, void *priv) 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == SUCCESS; 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_server_pax_register(void) 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_pax_init; 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->reset = eap_pax_reset; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->buildReq = eap_pax_buildReq; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->check = eap_pax_check; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_pax_process; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isDone = eap_pax_isDone; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_pax_getKey; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isSuccess = eap_pax_isSuccess; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_pax_get_emsk; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = eap_server_method_register(eap); 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_server_method_free(eap); 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 565