18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * EAP peer method: EAP-PAX (RFC 4746) 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2005-2008, 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_common/eap_pax_common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eap_i.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_INIT, PAX_STD_2_SENT, PAX_DONE } state; 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mac_id, dh_group_id, public_key_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 char *cid; 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t cid_len; 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ak[EAP_PAX_AK_LEN]; 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mk[EAP_PAX_MK_LEN]; 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ck[EAP_PAX_CK_LEN]; 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ick[EAP_PAX_ICK_LEN]; 41fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt u8 mid[EAP_PAX_MID_LEN]; 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_deinit(struct eap_sm *sm, void *priv); 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void * eap_pax_init(struct eap_sm *sm) 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data; 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *identity, *password; 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t identity_len, password_len; 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt identity = eap_get_config_identity(sm, &identity_len); 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt password = eap_get_config_password(sm, &password_len); 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!identity || !password) { 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: CID (nai) or key (password) " 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not configured"); 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (password_len != EAP_PAX_AK_LEN) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid PSK length"); 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data = os_zalloc(sizeof(*data)); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data == NULL) 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PAX_INIT; 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cid = os_malloc(identity_len); 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->cid == NULL) { 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_deinit(sm, data); 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->cid, identity, identity_len); 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->cid_len = identity_len; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->ak, password, EAP_PAX_AK_LEN); 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data; 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void eap_pax_deinit(struct eap_sm *sm, void *priv) 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(data->cid); 90c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt bin_clear_free(data, sizeof(*data)); 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_alloc_resp(const struct eap_pax_hdr *req, 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 id, u8 op_code, size_t plen) 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_hdr *pax; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PAX, 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(*pax) + plen, EAP_CODE_RESPONSE, id); 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax = wpabuf_put(resp, sizeof(*pax)); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->op_code = op_code; 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->flags = 0; 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->mac_id = req->mac_id; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->dh_group_id = req->dh_group_id; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pax->public_key_id = req->public_key_id; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_process_std_1(struct eap_pax_data *data, 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 id, 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_pax_hdr *req, 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_plen) 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos; 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left, plen; 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-1 (received)"); 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_INIT) { 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 received in " 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected state (%d) - ignored", data->state); 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->flags & EAP_PAX_FLAGS_CE) { 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with CE flag set - " 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignored"); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = req_plen - sizeof(*req); 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 2 + EAP_PAX_RAND_LEN) { 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with too short " 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload"); 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (req + 1); 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != EAP_PAX_RAND_LEN) { 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-1 with incorrect A " 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "length %d (expected %d)", 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(pos), EAP_PAX_RAND_LEN); 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data->rand.r.x, pos, EAP_PAX_RAND_LEN); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: X (server rand)", 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.x, EAP_PAX_RAND_LEN); 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_RAND_LEN; 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= EAP_PAX_RAND_LEN; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, left); 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (random_get_bytes(data->rand.r.y, EAP_PAX_RAND_LEN)) { 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "EAP-PAX: Failed to get random data"); 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: Y (client rand)", 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN); 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap_pax_initial_key_derivation(req->mac_id, data->ak, data->rand.e, 182fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt data->mk, data->ck, data->ick, 183fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt data->mid) < 0) { 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-2 (sending)"); 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt plen = 2 + EAP_PAX_RAND_LEN + 2 + data->cid_len + 2 + EAP_PAX_MAC_LEN + 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_PAX_ICV_LEN; 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_STD_2, plen); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, EAP_PAX_RAND_LEN); 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->rand.r.y, EAP_PAX_RAND_LEN); 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: B = Y (client rand)", 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN); 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, data->cid_len); 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_data(resp, data->cid, data->cid_len); 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PAX: CID", 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len); 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_put_be16(resp, EAP_PAX_MAC_LEN); 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, EAP_PAX_MAC_LEN); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(req->mac_id, data->ck, EAP_PAX_CK_LEN, 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.x, EAP_PAX_RAND_LEN, 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN, 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) data->cid, data->cid_len, rpos); 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(A, B, CID)", 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos, EAP_PAX_MAC_LEN); 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optional ADE could be added here, if needed */ 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0, NULL, 0, rpos); 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PAX_STD_2_SENT; 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mac_id = req->mac_id; 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->dh_group_id = req->dh_group_id; 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->public_key_id = req->public_key_id; 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_process_std_3(struct eap_pax_data *data, 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, u8 id, 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_pax_hdr *req, 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t req_plen) 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rpos, mac[EAP_PAX_MAC_LEN]; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t left; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX_STD-3 (received)"); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_STD_2_SENT) { 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 received in " 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "unexpected state (%d) - ignored", data->state); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->flags & EAP_PAX_FLAGS_CE) { 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with CE flag set - " 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignored"); 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left = req_plen - sizeof(*req); 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left < 2 + EAP_PAX_MAC_LEN) { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with too short " 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "payload"); 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (const u8 *) (req + 1); 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (WPA_GET_BE16(pos) != EAP_PAX_MAC_LEN) { 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: PAX_STD-3 with incorrect " 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MAC_CK length %d (expected %d)", 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_GET_BE16(pos), EAP_PAX_MAC_LEN); 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= 2; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: MAC_CK(B, CID)", 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, EAP_PAX_MAC_LEN); 279de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (eap_pax_mac(data->mac_id, data->ck, EAP_PAX_CK_LEN, 280de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt data->rand.r.y, EAP_PAX_RAND_LEN, 281849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt (u8 *) data->cid, data->cid_len, NULL, 0, mac) < 0) { 282849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt wpa_printf(MSG_INFO, 283849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt "EAP-PAX: Could not derive MAC_CK(B, CID)"); 284849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt ret->methodState = METHOD_DONE; 285849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt ret->decision = DECISION_FAIL; 286849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt return NULL; 287849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt } 288849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt 289849734c8d1847920ed7042463f7480b1e0c1dfeaDmitry Shmidt if (os_memcmp_const(pos, mac, EAP_PAX_MAC_LEN) != 0) { 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Invalid MAC_CK(B, CID) " 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "received"); 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected MAC_CK(B, CID)", 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mac, EAP_PAX_MAC_LEN); 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += EAP_PAX_MAC_LEN; 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt left -= EAP_PAX_MAC_LEN; 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (left > 0) { 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ignored extra payload", 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, left); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: PAX-ACK (sending)"); 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_pax_alloc_resp(req, id, EAP_PAX_OP_ACK, EAP_PAX_ICV_LEN); 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (resp == NULL) 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Optional ADE could be added here, if needed */ 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rpos = wpabuf_put(resp, EAP_PAX_ICV_LEN); 316de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (eap_pax_mac(data->mac_id, data->ick, EAP_PAX_ICK_LEN, 317de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpabuf_head(resp), wpabuf_len(resp) - EAP_PAX_ICV_LEN, 318de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt NULL, 0, NULL, 0, rpos) < 0) { 319de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt wpabuf_free(resp); 320de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt return NULL; 321de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", rpos, EAP_PAX_ICV_LEN); 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->state = PAX_DONE; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_DONE; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_UNCOND_SUCC; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct wpabuf * eap_pax_process(struct eap_sm *sm, void *priv, 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method_ret *ret, 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpabuf *reqData) 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct eap_pax_hdr *req; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpabuf *resp; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 icvbuf[EAP_PAX_ICV_LEN], id; 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *icv, *pos; 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len; 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 flen, mlen; 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PAX, reqData, &len); 346cc00d5dc8483e32158b2ba61ea44b0c38d790ed7Dmitry Shmidt if (pos == NULL || len < sizeof(*req) + EAP_PAX_ICV_LEN) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt id = eap_get_id(reqData); 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req = (const struct eap_pax_hdr *) pos; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt flen = len - EAP_PAX_ICV_LEN; 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mlen = wpabuf_len(reqData) - EAP_PAX_ICV_LEN; 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: received frame: op_code 0x%x " 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "flags 0x%x mac_id 0x%x dh_group_id 0x%x " 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "public_key_id 0x%x", 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->op_code, req->flags, req->mac_id, req->dh_group_id, 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->public_key_id); 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: received payload", 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos, len - EAP_PAX_ICV_LEN); 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_INIT && data->mac_id != req->mac_id) { 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: MAC ID changed during " 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication (was 0x%d, is 0x%d)", 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->mac_id, req->mac_id); 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_INIT && data->dh_group_id != req->dh_group_id) { 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: DH Group ID changed during " 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication (was 0x%d, is 0x%d)", 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->dh_group_id, req->dh_group_id); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_INIT && 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->public_key_id != req->public_key_id) { 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Public Key ID changed during " 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "authentication (was 0x%d, is 0x%d)", 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt data->public_key_id, req->public_key_id); 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support EAP_PAX_HMAC_SHA256_128 */ 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->mac_id != EAP_PAX_MAC_HMAC_SHA1_128) { 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Unsupported MAC ID 0x%x", 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->mac_id); 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->dh_group_id != EAP_PAX_DH_GROUP_NONE) { 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Unsupported DH Group ID 0x%x", 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->dh_group_id); 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->public_key_id != EAP_PAX_PUBLIC_KEY_NONE) { 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: Unsupported Public Key ID 0x%x", 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt req->public_key_id); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->flags & EAP_PAX_FLAGS_MF) { 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: add support for reassembling fragments */ 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "EAP-PAX: fragmentation not supported - " 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "ignored packet"); 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icv = pos + len - EAP_PAX_ICV_LEN; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: ICV", icv, EAP_PAX_ICV_LEN); 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (req->op_code == EAP_PAX_OP_STD_1) { 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(req->mac_id, (u8 *) "", 0, 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf); 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap_pax_mac(req->mac_id, data->ick, EAP_PAX_ICK_LEN, 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpabuf_head(reqData), mlen, NULL, 0, NULL, 0, 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf); 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 429c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt if (os_memcmp_const(icv, icvbuf, EAP_PAX_ICV_LEN) != 0) { 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: invalid ICV - ignoring the " 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "message"); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_MSGDUMP, "EAP-PAX: expected ICV", 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt icvbuf, EAP_PAX_ICV_LEN); 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = FALSE; 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->methodState = METHOD_MAY_CONT; 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->decision = DECISION_FAIL; 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = TRUE; 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (req->op_code) { 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PAX_OP_STD_1: 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_pax_process_std_1(data, ret, id, req, flen); 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case EAP_PAX_OP_STD_3: 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt resp = eap_pax_process_std_3(data, ret, id, req, flen); 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "EAP-PAX: ignoring message with unknown " 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "op_code %d", req->op_code); 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->ignore = TRUE; 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret->methodState == METHOD_DONE) { 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret->allowNotifications = FALSE; 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return resp; 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic Boolean eap_pax_isKeyAvailable(struct eap_sm *sm, void *priv) 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return data->state == PAX_DONE; 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pax_getKey(struct eap_sm *sm, void *priv, size_t *len) 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_DONE) 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_MSK_LEN); 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_MSK_LEN; 485de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, 486de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt "Master Session Key", 487de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt data->rand.e, 2 * EAP_PAX_RAND_LEN, 488de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt EAP_MSK_LEN, key) < 0) { 489de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt os_free(key); 490de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt return NULL; 491de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt } 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * eap_pax_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_pax_data *data = priv; 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *key; 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (data->state != PAX_DONE) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key = os_malloc(EAP_EMSK_LEN); 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (key == NULL) 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *len = EAP_EMSK_LEN; 510de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt if (eap_pax_kdf(data->mac_id, data->mk, EAP_PAX_MK_LEN, 511de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt "Extended Master Session Key", 512de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt data->rand.e, 2 * EAP_PAX_RAND_LEN, 513de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt EAP_EMSK_LEN, key) < 0) { 514de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt os_free(key); 515de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt return NULL; 516de47be75037bccd4a11b62eedb3d4aed1b36fa67Dmitry Shmidt } 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return key; 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 522fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidtstatic u8 * eap_pax_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 523fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt{ 524fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt struct eap_pax_data *data = priv; 525fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt u8 *sid; 526fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 527fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (data->state != PAX_DONE) 528fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 529fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 530fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt sid = os_malloc(1 + EAP_PAX_MID_LEN); 531fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (sid == NULL) 532fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 533fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 534fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt *len = 1 + EAP_PAX_MID_LEN; 535fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt sid[0] = EAP_TYPE_PAX; 536fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt os_memcpy(sid + 1, data->mid, EAP_PAX_MID_LEN); 537fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 538fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return sid; 539fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt} 540fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 541fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint eap_peer_pax_register(void) 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct eap_method *eap; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt EAP_VENDOR_IETF, EAP_TYPE_PAX, "PAX"); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (eap == NULL) 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->init = eap_pax_init; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->deinit = eap_pax_deinit; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->process = eap_pax_process; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->isKeyAvailable = eap_pax_isKeyAvailable; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->getKey = eap_pax_getKey; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eap->get_emsk = eap_pax_get_emsk; 557fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt eap->getSessionId = eap_pax_get_session_id; 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5591d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt return eap_peer_method_register(eap); 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 561