1214501Srpaulo/* 2214501Srpaulo * hostapd / EAP-PSK (RFC 4764) server 3214501Srpaulo * Copyright (c) 2005-2007, Jouni Malinen <j@w1.fi> 4214501Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214501Srpaulo * 8214501Srpaulo * Note: EAP-PSK is an EAP authentication method and as such, completely 9214501Srpaulo * different from WPA-PSK. This file is not needed for WPA-PSK functionality. 10214501Srpaulo */ 11214501Srpaulo 12214501Srpaulo#include "includes.h" 13214501Srpaulo 14214501Srpaulo#include "common.h" 15214501Srpaulo#include "crypto/aes_wrap.h" 16252726Srpaulo#include "crypto/random.h" 17214501Srpaulo#include "eap_common/eap_psk_common.h" 18214501Srpaulo#include "eap_server/eap_i.h" 19214501Srpaulo 20214501Srpaulo 21214501Srpaulostruct eap_psk_data { 22214501Srpaulo enum { PSK_1, PSK_3, SUCCESS, FAILURE } state; 23214501Srpaulo u8 rand_s[EAP_PSK_RAND_LEN]; 24214501Srpaulo u8 rand_p[EAP_PSK_RAND_LEN]; 25214501Srpaulo u8 *id_p, *id_s; 26214501Srpaulo size_t id_p_len, id_s_len; 27214501Srpaulo u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN]; 28214501Srpaulo u8 msk[EAP_MSK_LEN]; 29214501Srpaulo u8 emsk[EAP_EMSK_LEN]; 30214501Srpaulo}; 31214501Srpaulo 32214501Srpaulo 33214501Srpaulostatic void * eap_psk_init(struct eap_sm *sm) 34214501Srpaulo{ 35214501Srpaulo struct eap_psk_data *data; 36214501Srpaulo 37214501Srpaulo data = os_zalloc(sizeof(*data)); 38214501Srpaulo if (data == NULL) 39214501Srpaulo return NULL; 40214501Srpaulo data->state = PSK_1; 41214501Srpaulo data->id_s = (u8 *) "hostapd"; 42214501Srpaulo data->id_s_len = 7; 43214501Srpaulo 44214501Srpaulo return data; 45214501Srpaulo} 46214501Srpaulo 47214501Srpaulo 48214501Srpaulostatic void eap_psk_reset(struct eap_sm *sm, void *priv) 49214501Srpaulo{ 50214501Srpaulo struct eap_psk_data *data = priv; 51214501Srpaulo os_free(data->id_p); 52214501Srpaulo os_free(data); 53214501Srpaulo} 54214501Srpaulo 55214501Srpaulo 56214501Srpaulostatic struct wpabuf * eap_psk_build_1(struct eap_sm *sm, 57214501Srpaulo struct eap_psk_data *data, u8 id) 58214501Srpaulo{ 59214501Srpaulo struct wpabuf *req; 60214501Srpaulo struct eap_psk_hdr_1 *psk; 61214501Srpaulo 62214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-1 (sending)"); 63214501Srpaulo 64252726Srpaulo if (random_get_bytes(data->rand_s, EAP_PSK_RAND_LEN)) { 65214501Srpaulo wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data"); 66214501Srpaulo data->state = FAILURE; 67214501Srpaulo return NULL; 68214501Srpaulo } 69214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_S (server rand)", 70214501Srpaulo data->rand_s, EAP_PSK_RAND_LEN); 71214501Srpaulo 72214501Srpaulo req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 73214501Srpaulo sizeof(*psk) + data->id_s_len, 74214501Srpaulo EAP_CODE_REQUEST, id); 75214501Srpaulo if (req == NULL) { 76214501Srpaulo wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 77214501Srpaulo "request"); 78214501Srpaulo data->state = FAILURE; 79214501Srpaulo return NULL; 80214501Srpaulo } 81214501Srpaulo 82214501Srpaulo psk = wpabuf_put(req, sizeof(*psk)); 83214501Srpaulo psk->flags = EAP_PSK_FLAGS_SET_T(0); /* T=0 */ 84214501Srpaulo os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 85214501Srpaulo wpabuf_put_data(req, data->id_s, data->id_s_len); 86214501Srpaulo 87214501Srpaulo return req; 88214501Srpaulo} 89214501Srpaulo 90214501Srpaulo 91214501Srpaulostatic struct wpabuf * eap_psk_build_3(struct eap_sm *sm, 92214501Srpaulo struct eap_psk_data *data, u8 id) 93214501Srpaulo{ 94214501Srpaulo struct wpabuf *req; 95214501Srpaulo struct eap_psk_hdr_3 *psk; 96214501Srpaulo u8 *buf, *pchannel, nonce[16]; 97214501Srpaulo size_t buflen; 98214501Srpaulo 99214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: PSK-3 (sending)"); 100214501Srpaulo 101214501Srpaulo req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, 102214501Srpaulo sizeof(*psk) + 4 + 16 + 1, EAP_CODE_REQUEST, id); 103214501Srpaulo if (req == NULL) { 104214501Srpaulo wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory " 105214501Srpaulo "request"); 106214501Srpaulo data->state = FAILURE; 107214501Srpaulo return NULL; 108214501Srpaulo } 109214501Srpaulo 110214501Srpaulo psk = wpabuf_put(req, sizeof(*psk)); 111214501Srpaulo psk->flags = EAP_PSK_FLAGS_SET_T(2); /* T=2 */ 112214501Srpaulo os_memcpy(psk->rand_s, data->rand_s, EAP_PSK_RAND_LEN); 113214501Srpaulo 114214501Srpaulo /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */ 115214501Srpaulo buflen = data->id_s_len + EAP_PSK_RAND_LEN; 116214501Srpaulo buf = os_malloc(buflen); 117214501Srpaulo if (buf == NULL) 118214501Srpaulo goto fail; 119214501Srpaulo 120214501Srpaulo os_memcpy(buf, data->id_s, data->id_s_len); 121214501Srpaulo os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN); 122252726Srpaulo if (omac1_aes_128(data->ak, buf, buflen, psk->mac_s)) { 123252726Srpaulo os_free(buf); 124214501Srpaulo goto fail; 125252726Srpaulo } 126214501Srpaulo os_free(buf); 127214501Srpaulo 128214501Srpaulo if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek, data->msk, 129214501Srpaulo data->emsk)) 130214501Srpaulo goto fail; 131214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN); 132214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN); 133214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN); 134214501Srpaulo 135214501Srpaulo os_memset(nonce, 0, sizeof(nonce)); 136214501Srpaulo pchannel = wpabuf_put(req, 4 + 16 + 1); 137214501Srpaulo os_memcpy(pchannel, nonce + 12, 4); 138214501Srpaulo os_memset(pchannel + 4, 0, 16); /* Tag */ 139214501Srpaulo pchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6; 140214501Srpaulo wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (plaintext)", 141214501Srpaulo pchannel, 4 + 16 + 1); 142214501Srpaulo if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce), 143214501Srpaulo wpabuf_head(req), 22, 144214501Srpaulo pchannel + 4 + 16, 1, pchannel + 4)) 145214501Srpaulo goto fail; 146214501Srpaulo wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL (encrypted)", 147214501Srpaulo pchannel, 4 + 16 + 1); 148214501Srpaulo 149214501Srpaulo return req; 150214501Srpaulo 151214501Srpaulofail: 152214501Srpaulo wpabuf_free(req); 153214501Srpaulo data->state = FAILURE; 154214501Srpaulo return NULL; 155214501Srpaulo} 156214501Srpaulo 157214501Srpaulo 158214501Srpaulostatic struct wpabuf * eap_psk_buildReq(struct eap_sm *sm, void *priv, u8 id) 159214501Srpaulo{ 160214501Srpaulo struct eap_psk_data *data = priv; 161214501Srpaulo 162214501Srpaulo switch (data->state) { 163214501Srpaulo case PSK_1: 164214501Srpaulo return eap_psk_build_1(sm, data, id); 165214501Srpaulo case PSK_3: 166214501Srpaulo return eap_psk_build_3(sm, data, id); 167214501Srpaulo default: 168214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Unknown state %d in buildReq", 169214501Srpaulo data->state); 170214501Srpaulo break; 171214501Srpaulo } 172214501Srpaulo return NULL; 173214501Srpaulo} 174214501Srpaulo 175214501Srpaulo 176214501Srpaulostatic Boolean eap_psk_check(struct eap_sm *sm, void *priv, 177214501Srpaulo struct wpabuf *respData) 178214501Srpaulo{ 179214501Srpaulo struct eap_psk_data *data = priv; 180214501Srpaulo size_t len; 181214501Srpaulo u8 t; 182214501Srpaulo const u8 *pos; 183214501Srpaulo 184214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 185214501Srpaulo if (pos == NULL || len < 1) { 186214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 187214501Srpaulo return TRUE; 188214501Srpaulo } 189214501Srpaulo t = EAP_PSK_FLAGS_GET_T(*pos); 190214501Srpaulo 191214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: received frame: T=%d", t); 192214501Srpaulo 193214501Srpaulo if (data->state == PSK_1 && t != 1) { 194214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-2 - " 195214501Srpaulo "ignore T=%d", t); 196214501Srpaulo return TRUE; 197214501Srpaulo } 198214501Srpaulo 199214501Srpaulo if (data->state == PSK_3 && t != 3) { 200214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Expected PSK-4 - " 201214501Srpaulo "ignore T=%d", t); 202214501Srpaulo return TRUE; 203214501Srpaulo } 204214501Srpaulo 205214501Srpaulo if ((t == 1 && len < sizeof(struct eap_psk_hdr_2)) || 206214501Srpaulo (t == 3 && len < sizeof(struct eap_psk_hdr_4))) { 207214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Too short frame"); 208214501Srpaulo return TRUE; 209214501Srpaulo } 210214501Srpaulo 211214501Srpaulo return FALSE; 212214501Srpaulo} 213214501Srpaulo 214214501Srpaulo 215214501Srpaulostatic void eap_psk_process_2(struct eap_sm *sm, 216214501Srpaulo struct eap_psk_data *data, 217214501Srpaulo struct wpabuf *respData) 218214501Srpaulo{ 219214501Srpaulo const struct eap_psk_hdr_2 *resp; 220214501Srpaulo u8 *pos, mac[EAP_PSK_MAC_LEN], *buf; 221214501Srpaulo size_t left, buflen; 222214501Srpaulo int i; 223214501Srpaulo const u8 *cpos; 224214501Srpaulo 225214501Srpaulo if (data->state != PSK_1) 226214501Srpaulo return; 227214501Srpaulo 228214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-2"); 229214501Srpaulo 230214501Srpaulo cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, 231214501Srpaulo &left); 232214501Srpaulo if (cpos == NULL || left < sizeof(*resp)) { 233214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 234214501Srpaulo return; 235214501Srpaulo } 236214501Srpaulo resp = (const struct eap_psk_hdr_2 *) cpos; 237214501Srpaulo cpos = (const u8 *) (resp + 1); 238214501Srpaulo left -= sizeof(*resp); 239214501Srpaulo 240214501Srpaulo os_free(data->id_p); 241214501Srpaulo data->id_p = os_malloc(left); 242214501Srpaulo if (data->id_p == NULL) { 243214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Failed to allocate memory for " 244214501Srpaulo "ID_P"); 245214501Srpaulo return; 246214501Srpaulo } 247214501Srpaulo os_memcpy(data->id_p, cpos, left); 248214501Srpaulo data->id_p_len = left; 249214501Srpaulo wpa_hexdump_ascii(MSG_MSGDUMP, "EAP-PSK: ID_P", 250214501Srpaulo data->id_p, data->id_p_len); 251214501Srpaulo 252214501Srpaulo if (eap_user_get(sm, data->id_p, data->id_p_len, 0) < 0) { 253214501Srpaulo wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: unknown ID_P", 254214501Srpaulo data->id_p, data->id_p_len); 255214501Srpaulo data->state = FAILURE; 256214501Srpaulo return; 257214501Srpaulo } 258214501Srpaulo 259214501Srpaulo for (i = 0; 260214501Srpaulo i < EAP_MAX_METHODS && 261214501Srpaulo (sm->user->methods[i].vendor != EAP_VENDOR_IETF || 262214501Srpaulo sm->user->methods[i].method != EAP_TYPE_NONE); 263214501Srpaulo i++) { 264214501Srpaulo if (sm->user->methods[i].vendor == EAP_VENDOR_IETF && 265214501Srpaulo sm->user->methods[i].method == EAP_TYPE_PSK) 266214501Srpaulo break; 267214501Srpaulo } 268214501Srpaulo 269214501Srpaulo if (i >= EAP_MAX_METHODS || 270214501Srpaulo sm->user->methods[i].vendor != EAP_VENDOR_IETF || 271214501Srpaulo sm->user->methods[i].method != EAP_TYPE_PSK) { 272214501Srpaulo wpa_hexdump_ascii(MSG_DEBUG, 273214501Srpaulo "EAP-PSK: EAP-PSK not enabled for ID_P", 274214501Srpaulo data->id_p, data->id_p_len); 275214501Srpaulo data->state = FAILURE; 276214501Srpaulo return; 277214501Srpaulo } 278214501Srpaulo 279214501Srpaulo if (sm->user->password == NULL || 280214501Srpaulo sm->user->password_len != EAP_PSK_PSK_LEN) { 281214501Srpaulo wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: invalid password in " 282214501Srpaulo "user database for ID_P", 283214501Srpaulo data->id_p, data->id_p_len); 284214501Srpaulo data->state = FAILURE; 285214501Srpaulo return; 286214501Srpaulo } 287214501Srpaulo if (eap_psk_key_setup(sm->user->password, data->ak, data->kdk)) { 288214501Srpaulo data->state = FAILURE; 289214501Srpaulo return; 290214501Srpaulo } 291214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN); 292214501Srpaulo wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN); 293214501Srpaulo 294214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: RAND_P (client rand)", 295214501Srpaulo resp->rand_p, EAP_PSK_RAND_LEN); 296214501Srpaulo os_memcpy(data->rand_p, resp->rand_p, EAP_PSK_RAND_LEN); 297214501Srpaulo 298214501Srpaulo /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */ 299214501Srpaulo buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN; 300214501Srpaulo buf = os_malloc(buflen); 301214501Srpaulo if (buf == NULL) { 302214501Srpaulo data->state = FAILURE; 303214501Srpaulo return; 304214501Srpaulo } 305214501Srpaulo os_memcpy(buf, data->id_p, data->id_p_len); 306214501Srpaulo pos = buf + data->id_p_len; 307214501Srpaulo os_memcpy(pos, data->id_s, data->id_s_len); 308214501Srpaulo pos += data->id_s_len; 309214501Srpaulo os_memcpy(pos, data->rand_s, EAP_PSK_RAND_LEN); 310214501Srpaulo pos += EAP_PSK_RAND_LEN; 311214501Srpaulo os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN); 312214501Srpaulo if (omac1_aes_128(data->ak, buf, buflen, mac)) { 313214501Srpaulo os_free(buf); 314214501Srpaulo data->state = FAILURE; 315214501Srpaulo return; 316214501Srpaulo } 317214501Srpaulo os_free(buf); 318214501Srpaulo wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", resp->mac_p, EAP_PSK_MAC_LEN); 319214501Srpaulo if (os_memcmp(mac, resp->mac_p, EAP_PSK_MAC_LEN) != 0) { 320214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Invalid MAC_P"); 321214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Expected MAC_P", 322214501Srpaulo mac, EAP_PSK_MAC_LEN); 323214501Srpaulo data->state = FAILURE; 324214501Srpaulo return; 325214501Srpaulo } 326214501Srpaulo 327214501Srpaulo data->state = PSK_3; 328214501Srpaulo} 329214501Srpaulo 330214501Srpaulo 331214501Srpaulostatic void eap_psk_process_4(struct eap_sm *sm, 332214501Srpaulo struct eap_psk_data *data, 333214501Srpaulo struct wpabuf *respData) 334214501Srpaulo{ 335214501Srpaulo const struct eap_psk_hdr_4 *resp; 336214501Srpaulo u8 *decrypted, nonce[16]; 337214501Srpaulo size_t left; 338214501Srpaulo const u8 *pos, *tag; 339214501Srpaulo 340214501Srpaulo if (data->state != PSK_3) 341214501Srpaulo return; 342214501Srpaulo 343214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Received PSK-4"); 344214501Srpaulo 345214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &left); 346214501Srpaulo if (pos == NULL || left < sizeof(*resp)) { 347214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Invalid frame"); 348214501Srpaulo return; 349214501Srpaulo } 350214501Srpaulo resp = (const struct eap_psk_hdr_4 *) pos; 351214501Srpaulo pos = (const u8 *) (resp + 1); 352214501Srpaulo left -= sizeof(*resp); 353214501Srpaulo 354214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: Encrypted PCHANNEL", pos, left); 355214501Srpaulo 356214501Srpaulo if (left < 4 + 16 + 1) { 357214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in " 358214501Srpaulo "PSK-4 (len=%lu, expected 21)", 359214501Srpaulo (unsigned long) left); 360214501Srpaulo return; 361214501Srpaulo } 362214501Srpaulo 363214501Srpaulo if (pos[0] == 0 && pos[1] == 0 && pos[2] == 0 && pos[3] == 0) { 364214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: Nonce did not increase"); 365214501Srpaulo return; 366214501Srpaulo } 367214501Srpaulo 368214501Srpaulo os_memset(nonce, 0, 12); 369214501Srpaulo os_memcpy(nonce + 12, pos, 4); 370214501Srpaulo pos += 4; 371214501Srpaulo left -= 4; 372214501Srpaulo tag = pos; 373214501Srpaulo pos += 16; 374214501Srpaulo left -= 16; 375214501Srpaulo 376214501Srpaulo decrypted = os_malloc(left); 377214501Srpaulo if (decrypted == NULL) 378214501Srpaulo return; 379214501Srpaulo os_memcpy(decrypted, pos, left); 380214501Srpaulo 381214501Srpaulo if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce), 382214501Srpaulo wpabuf_head(respData), 22, decrypted, left, 383214501Srpaulo tag)) { 384214501Srpaulo wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed"); 385214501Srpaulo os_free(decrypted); 386214501Srpaulo data->state = FAILURE; 387214501Srpaulo return; 388214501Srpaulo } 389214501Srpaulo wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message", 390214501Srpaulo decrypted, left); 391214501Srpaulo 392214501Srpaulo /* Verify R flag */ 393214501Srpaulo switch (decrypted[0] >> 6) { 394214501Srpaulo case EAP_PSK_R_FLAG_CONT: 395214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported"); 396214501Srpaulo data->state = FAILURE; 397214501Srpaulo break; 398214501Srpaulo case EAP_PSK_R_FLAG_DONE_SUCCESS: 399214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS"); 400214501Srpaulo data->state = SUCCESS; 401214501Srpaulo break; 402214501Srpaulo case EAP_PSK_R_FLAG_DONE_FAILURE: 403214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE"); 404214501Srpaulo data->state = FAILURE; 405214501Srpaulo break; 406214501Srpaulo } 407214501Srpaulo os_free(decrypted); 408214501Srpaulo} 409214501Srpaulo 410214501Srpaulo 411214501Srpaulostatic void eap_psk_process(struct eap_sm *sm, void *priv, 412214501Srpaulo struct wpabuf *respData) 413214501Srpaulo{ 414214501Srpaulo struct eap_psk_data *data = priv; 415214501Srpaulo const u8 *pos; 416214501Srpaulo size_t len; 417214501Srpaulo 418214501Srpaulo if (sm->user == NULL || sm->user->password == NULL) { 419214501Srpaulo wpa_printf(MSG_INFO, "EAP-PSK: Plaintext password not " 420214501Srpaulo "configured"); 421214501Srpaulo data->state = FAILURE; 422214501Srpaulo return; 423214501Srpaulo } 424214501Srpaulo 425214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, respData, &len); 426214501Srpaulo if (pos == NULL || len < 1) 427214501Srpaulo return; 428214501Srpaulo 429214501Srpaulo switch (EAP_PSK_FLAGS_GET_T(*pos)) { 430214501Srpaulo case 1: 431214501Srpaulo eap_psk_process_2(sm, data, respData); 432214501Srpaulo break; 433214501Srpaulo case 3: 434214501Srpaulo eap_psk_process_4(sm, data, respData); 435214501Srpaulo break; 436214501Srpaulo } 437214501Srpaulo} 438214501Srpaulo 439214501Srpaulo 440214501Srpaulostatic Boolean eap_psk_isDone(struct eap_sm *sm, void *priv) 441214501Srpaulo{ 442214501Srpaulo struct eap_psk_data *data = priv; 443214501Srpaulo return data->state == SUCCESS || data->state == FAILURE; 444214501Srpaulo} 445214501Srpaulo 446214501Srpaulo 447214501Srpaulostatic u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len) 448214501Srpaulo{ 449214501Srpaulo struct eap_psk_data *data = priv; 450214501Srpaulo u8 *key; 451214501Srpaulo 452214501Srpaulo if (data->state != SUCCESS) 453214501Srpaulo return NULL; 454214501Srpaulo 455214501Srpaulo key = os_malloc(EAP_MSK_LEN); 456214501Srpaulo if (key == NULL) 457214501Srpaulo return NULL; 458214501Srpaulo os_memcpy(key, data->msk, EAP_MSK_LEN); 459214501Srpaulo *len = EAP_MSK_LEN; 460214501Srpaulo 461214501Srpaulo return key; 462214501Srpaulo} 463214501Srpaulo 464214501Srpaulo 465214501Srpaulostatic u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 466214501Srpaulo{ 467214501Srpaulo struct eap_psk_data *data = priv; 468214501Srpaulo u8 *key; 469214501Srpaulo 470214501Srpaulo if (data->state != SUCCESS) 471214501Srpaulo return NULL; 472214501Srpaulo 473214501Srpaulo key = os_malloc(EAP_EMSK_LEN); 474214501Srpaulo if (key == NULL) 475214501Srpaulo return NULL; 476214501Srpaulo os_memcpy(key, data->emsk, EAP_EMSK_LEN); 477214501Srpaulo *len = EAP_EMSK_LEN; 478214501Srpaulo 479214501Srpaulo return key; 480214501Srpaulo} 481214501Srpaulo 482214501Srpaulo 483214501Srpaulostatic Boolean eap_psk_isSuccess(struct eap_sm *sm, void *priv) 484214501Srpaulo{ 485214501Srpaulo struct eap_psk_data *data = priv; 486214501Srpaulo return data->state == SUCCESS; 487214501Srpaulo} 488214501Srpaulo 489214501Srpaulo 490214501Srpauloint eap_server_psk_register(void) 491214501Srpaulo{ 492214501Srpaulo struct eap_method *eap; 493214501Srpaulo int ret; 494214501Srpaulo 495214501Srpaulo eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 496214501Srpaulo EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK"); 497214501Srpaulo if (eap == NULL) 498214501Srpaulo return -1; 499214501Srpaulo 500214501Srpaulo eap->init = eap_psk_init; 501214501Srpaulo eap->reset = eap_psk_reset; 502214501Srpaulo eap->buildReq = eap_psk_buildReq; 503214501Srpaulo eap->check = eap_psk_check; 504214501Srpaulo eap->process = eap_psk_process; 505214501Srpaulo eap->isDone = eap_psk_isDone; 506214501Srpaulo eap->getKey = eap_psk_getKey; 507214501Srpaulo eap->isSuccess = eap_psk_isSuccess; 508214501Srpaulo eap->get_emsk = eap_psk_get_emsk; 509214501Srpaulo 510214501Srpaulo ret = eap_server_method_register(eap); 511214501Srpaulo if (ret) 512214501Srpaulo eap_server_method_free(eap); 513214501Srpaulo return ret; 514214501Srpaulo} 515