1214501Srpaulo/* 2214501Srpaulo * hostapd / EAP-SAKE (RFC 4763) server 3214501Srpaulo * Copyright (c) 2006-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 9214501Srpaulo#include "includes.h" 10214501Srpaulo 11214501Srpaulo#include "common.h" 12252726Srpaulo#include "crypto/random.h" 13214501Srpaulo#include "eap_server/eap_i.h" 14214501Srpaulo#include "eap_common/eap_sake_common.h" 15214501Srpaulo 16214501Srpaulo 17214501Srpaulostruct eap_sake_data { 18214501Srpaulo enum { IDENTITY, CHALLENGE, CONFIRM, SUCCESS, FAILURE } state; 19214501Srpaulo u8 rand_s[EAP_SAKE_RAND_LEN]; 20214501Srpaulo u8 rand_p[EAP_SAKE_RAND_LEN]; 21214501Srpaulo struct { 22214501Srpaulo u8 auth[EAP_SAKE_TEK_AUTH_LEN]; 23214501Srpaulo u8 cipher[EAP_SAKE_TEK_CIPHER_LEN]; 24214501Srpaulo } tek; 25214501Srpaulo u8 msk[EAP_MSK_LEN]; 26214501Srpaulo u8 emsk[EAP_EMSK_LEN]; 27214501Srpaulo u8 session_id; 28214501Srpaulo u8 *peerid; 29214501Srpaulo size_t peerid_len; 30214501Srpaulo u8 *serverid; 31214501Srpaulo size_t serverid_len; 32214501Srpaulo}; 33214501Srpaulo 34214501Srpaulo 35214501Srpaulostatic const char * eap_sake_state_txt(int state) 36214501Srpaulo{ 37214501Srpaulo switch (state) { 38214501Srpaulo case IDENTITY: 39214501Srpaulo return "IDENTITY"; 40214501Srpaulo case CHALLENGE: 41214501Srpaulo return "CHALLENGE"; 42214501Srpaulo case CONFIRM: 43214501Srpaulo return "CONFIRM"; 44214501Srpaulo case SUCCESS: 45214501Srpaulo return "SUCCESS"; 46214501Srpaulo case FAILURE: 47214501Srpaulo return "FAILURE"; 48214501Srpaulo default: 49214501Srpaulo return "?"; 50214501Srpaulo } 51214501Srpaulo} 52214501Srpaulo 53214501Srpaulo 54214501Srpaulostatic void eap_sake_state(struct eap_sake_data *data, int state) 55214501Srpaulo{ 56214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: %s -> %s", 57214501Srpaulo eap_sake_state_txt(data->state), 58214501Srpaulo eap_sake_state_txt(state)); 59214501Srpaulo data->state = state; 60214501Srpaulo} 61214501Srpaulo 62214501Srpaulo 63214501Srpaulostatic void * eap_sake_init(struct eap_sm *sm) 64214501Srpaulo{ 65214501Srpaulo struct eap_sake_data *data; 66214501Srpaulo 67214501Srpaulo data = os_zalloc(sizeof(*data)); 68214501Srpaulo if (data == NULL) 69214501Srpaulo return NULL; 70214501Srpaulo data->state = CHALLENGE; 71214501Srpaulo 72214501Srpaulo if (os_get_random(&data->session_id, 1)) { 73214501Srpaulo wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); 74214501Srpaulo os_free(data); 75214501Srpaulo return NULL; 76214501Srpaulo } 77214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Initialized Session ID %d", 78214501Srpaulo data->session_id); 79214501Srpaulo 80214501Srpaulo /* TODO: add support for configuring SERVERID */ 81214501Srpaulo data->serverid = (u8 *) os_strdup("hostapd"); 82214501Srpaulo if (data->serverid) 83214501Srpaulo data->serverid_len = os_strlen((char *) data->serverid); 84214501Srpaulo 85214501Srpaulo return data; 86214501Srpaulo} 87214501Srpaulo 88214501Srpaulo 89214501Srpaulostatic void eap_sake_reset(struct eap_sm *sm, void *priv) 90214501Srpaulo{ 91214501Srpaulo struct eap_sake_data *data = priv; 92214501Srpaulo os_free(data->serverid); 93214501Srpaulo os_free(data->peerid); 94214501Srpaulo os_free(data); 95214501Srpaulo} 96214501Srpaulo 97214501Srpaulo 98214501Srpaulostatic struct wpabuf * eap_sake_build_msg(struct eap_sake_data *data, 99214501Srpaulo u8 id, size_t length, u8 subtype) 100214501Srpaulo{ 101214501Srpaulo struct eap_sake_hdr *sake; 102214501Srpaulo struct wpabuf *msg; 103214501Srpaulo size_t plen; 104214501Srpaulo 105214501Srpaulo plen = sizeof(struct eap_sake_hdr) + length; 106214501Srpaulo 107214501Srpaulo msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_SAKE, plen, 108214501Srpaulo EAP_CODE_REQUEST, id); 109214501Srpaulo if (msg == NULL) { 110214501Srpaulo wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to allocate memory " 111214501Srpaulo "request"); 112214501Srpaulo return NULL; 113214501Srpaulo } 114214501Srpaulo 115214501Srpaulo sake = wpabuf_put(msg, sizeof(*sake)); 116214501Srpaulo sake->version = EAP_SAKE_VERSION; 117214501Srpaulo sake->session_id = data->session_id; 118214501Srpaulo sake->subtype = subtype; 119214501Srpaulo 120214501Srpaulo return msg; 121214501Srpaulo} 122214501Srpaulo 123214501Srpaulo 124214501Srpaulostatic struct wpabuf * eap_sake_build_identity(struct eap_sm *sm, 125214501Srpaulo struct eap_sake_data *data, 126214501Srpaulo u8 id) 127214501Srpaulo{ 128214501Srpaulo struct wpabuf *msg; 129214501Srpaulo size_t plen; 130214501Srpaulo 131214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Identity"); 132214501Srpaulo 133214501Srpaulo plen = 4; 134214501Srpaulo if (data->serverid) 135214501Srpaulo plen += 2 + data->serverid_len; 136214501Srpaulo msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_IDENTITY); 137214501Srpaulo if (msg == NULL) { 138214501Srpaulo data->state = FAILURE; 139214501Srpaulo return NULL; 140214501Srpaulo } 141214501Srpaulo 142214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_PERM_ID_REQ"); 143214501Srpaulo eap_sake_add_attr(msg, EAP_SAKE_AT_PERM_ID_REQ, NULL, 2); 144214501Srpaulo 145214501Srpaulo if (data->serverid) { 146214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); 147214501Srpaulo eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, 148214501Srpaulo data->serverid, data->serverid_len); 149214501Srpaulo } 150214501Srpaulo 151214501Srpaulo return msg; 152214501Srpaulo} 153214501Srpaulo 154214501Srpaulo 155214501Srpaulostatic struct wpabuf * eap_sake_build_challenge(struct eap_sm *sm, 156214501Srpaulo struct eap_sake_data *data, 157214501Srpaulo u8 id) 158214501Srpaulo{ 159214501Srpaulo struct wpabuf *msg; 160214501Srpaulo size_t plen; 161214501Srpaulo 162214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Challenge"); 163214501Srpaulo 164252726Srpaulo if (random_get_bytes(data->rand_s, EAP_SAKE_RAND_LEN)) { 165214501Srpaulo wpa_printf(MSG_ERROR, "EAP-SAKE: Failed to get random data"); 166214501Srpaulo data->state = FAILURE; 167214501Srpaulo return NULL; 168214501Srpaulo } 169214501Srpaulo wpa_hexdump(MSG_MSGDUMP, "EAP-SAKE: RAND_S (server rand)", 170214501Srpaulo data->rand_s, EAP_SAKE_RAND_LEN); 171214501Srpaulo 172214501Srpaulo plen = 2 + EAP_SAKE_RAND_LEN; 173214501Srpaulo if (data->serverid) 174214501Srpaulo plen += 2 + data->serverid_len; 175214501Srpaulo msg = eap_sake_build_msg(data, id, plen, EAP_SAKE_SUBTYPE_CHALLENGE); 176214501Srpaulo if (msg == NULL) { 177214501Srpaulo data->state = FAILURE; 178214501Srpaulo return NULL; 179214501Srpaulo } 180214501Srpaulo 181214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_RAND_S"); 182214501Srpaulo eap_sake_add_attr(msg, EAP_SAKE_AT_RAND_S, 183214501Srpaulo data->rand_s, EAP_SAKE_RAND_LEN); 184214501Srpaulo 185214501Srpaulo if (data->serverid) { 186214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_SERVERID"); 187214501Srpaulo eap_sake_add_attr(msg, EAP_SAKE_AT_SERVERID, 188214501Srpaulo data->serverid, data->serverid_len); 189214501Srpaulo } 190214501Srpaulo 191214501Srpaulo return msg; 192214501Srpaulo} 193214501Srpaulo 194214501Srpaulo 195214501Srpaulostatic struct wpabuf * eap_sake_build_confirm(struct eap_sm *sm, 196214501Srpaulo struct eap_sake_data *data, 197214501Srpaulo u8 id) 198214501Srpaulo{ 199214501Srpaulo struct wpabuf *msg; 200214501Srpaulo u8 *mic; 201214501Srpaulo 202214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Request/Confirm"); 203214501Srpaulo 204214501Srpaulo msg = eap_sake_build_msg(data, id, 2 + EAP_SAKE_MIC_LEN, 205214501Srpaulo EAP_SAKE_SUBTYPE_CONFIRM); 206214501Srpaulo if (msg == NULL) { 207214501Srpaulo data->state = FAILURE; 208214501Srpaulo return NULL; 209214501Srpaulo } 210214501Srpaulo 211214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: * AT_MIC_S"); 212214501Srpaulo wpabuf_put_u8(msg, EAP_SAKE_AT_MIC_S); 213214501Srpaulo wpabuf_put_u8(msg, 2 + EAP_SAKE_MIC_LEN); 214214501Srpaulo mic = wpabuf_put(msg, EAP_SAKE_MIC_LEN); 215214501Srpaulo if (eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, 216214501Srpaulo data->serverid, data->serverid_len, 217214501Srpaulo data->peerid, data->peerid_len, 0, 218214501Srpaulo wpabuf_head(msg), wpabuf_len(msg), mic, mic)) 219214501Srpaulo { 220214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Failed to compute MIC"); 221214501Srpaulo data->state = FAILURE; 222214501Srpaulo os_free(msg); 223214501Srpaulo return NULL; 224214501Srpaulo } 225214501Srpaulo 226214501Srpaulo return msg; 227214501Srpaulo} 228214501Srpaulo 229214501Srpaulo 230214501Srpaulostatic struct wpabuf * eap_sake_buildReq(struct eap_sm *sm, void *priv, u8 id) 231214501Srpaulo{ 232214501Srpaulo struct eap_sake_data *data = priv; 233214501Srpaulo 234214501Srpaulo switch (data->state) { 235214501Srpaulo case IDENTITY: 236214501Srpaulo return eap_sake_build_identity(sm, data, id); 237214501Srpaulo case CHALLENGE: 238214501Srpaulo return eap_sake_build_challenge(sm, data, id); 239214501Srpaulo case CONFIRM: 240214501Srpaulo return eap_sake_build_confirm(sm, data, id); 241214501Srpaulo default: 242214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Unknown state %d in buildReq", 243214501Srpaulo data->state); 244214501Srpaulo break; 245214501Srpaulo } 246214501Srpaulo return NULL; 247214501Srpaulo} 248214501Srpaulo 249214501Srpaulo 250214501Srpaulostatic Boolean eap_sake_check(struct eap_sm *sm, void *priv, 251214501Srpaulo struct wpabuf *respData) 252214501Srpaulo{ 253214501Srpaulo struct eap_sake_data *data = priv; 254214501Srpaulo struct eap_sake_hdr *resp; 255214501Srpaulo size_t len; 256214501Srpaulo u8 version, session_id, subtype; 257214501Srpaulo const u8 *pos; 258214501Srpaulo 259214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); 260214501Srpaulo if (pos == NULL || len < sizeof(struct eap_sake_hdr)) { 261214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Invalid frame"); 262214501Srpaulo return TRUE; 263214501Srpaulo } 264214501Srpaulo 265214501Srpaulo resp = (struct eap_sake_hdr *) pos; 266214501Srpaulo version = resp->version; 267214501Srpaulo session_id = resp->session_id; 268214501Srpaulo subtype = resp->subtype; 269214501Srpaulo 270214501Srpaulo if (version != EAP_SAKE_VERSION) { 271214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Unknown version %d", version); 272214501Srpaulo return TRUE; 273214501Srpaulo } 274214501Srpaulo 275214501Srpaulo if (session_id != data->session_id) { 276214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Session ID mismatch (%d,%d)", 277214501Srpaulo session_id, data->session_id); 278214501Srpaulo return TRUE; 279214501Srpaulo } 280214501Srpaulo 281214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Received frame: subtype=%d", subtype); 282214501Srpaulo 283214501Srpaulo if (data->state == IDENTITY && subtype == EAP_SAKE_SUBTYPE_IDENTITY) 284214501Srpaulo return FALSE; 285214501Srpaulo 286214501Srpaulo if (data->state == CHALLENGE && subtype == EAP_SAKE_SUBTYPE_CHALLENGE) 287214501Srpaulo return FALSE; 288214501Srpaulo 289214501Srpaulo if (data->state == CONFIRM && subtype == EAP_SAKE_SUBTYPE_CONFIRM) 290214501Srpaulo return FALSE; 291214501Srpaulo 292214501Srpaulo if (subtype == EAP_SAKE_SUBTYPE_AUTH_REJECT) 293214501Srpaulo return FALSE; 294214501Srpaulo 295214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Unexpected subtype=%d in state=%d", 296214501Srpaulo subtype, data->state); 297214501Srpaulo 298214501Srpaulo return TRUE; 299214501Srpaulo} 300214501Srpaulo 301214501Srpaulo 302214501Srpaulostatic void eap_sake_process_identity(struct eap_sm *sm, 303214501Srpaulo struct eap_sake_data *data, 304214501Srpaulo const struct wpabuf *respData, 305214501Srpaulo const u8 *payload, size_t payloadlen) 306214501Srpaulo{ 307214501Srpaulo if (data->state != IDENTITY) 308214501Srpaulo return; 309214501Srpaulo 310214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Identity"); 311214501Srpaulo /* TODO: update identity and select new user data */ 312214501Srpaulo eap_sake_state(data, CHALLENGE); 313214501Srpaulo} 314214501Srpaulo 315214501Srpaulo 316214501Srpaulostatic void eap_sake_process_challenge(struct eap_sm *sm, 317214501Srpaulo struct eap_sake_data *data, 318214501Srpaulo const struct wpabuf *respData, 319214501Srpaulo const u8 *payload, size_t payloadlen) 320214501Srpaulo{ 321214501Srpaulo struct eap_sake_parse_attr attr; 322214501Srpaulo u8 mic_p[EAP_SAKE_MIC_LEN]; 323214501Srpaulo 324214501Srpaulo if (data->state != CHALLENGE) 325214501Srpaulo return; 326214501Srpaulo 327214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Challenge"); 328214501Srpaulo 329214501Srpaulo if (eap_sake_parse_attributes(payload, payloadlen, &attr)) 330214501Srpaulo return; 331214501Srpaulo 332214501Srpaulo if (!attr.rand_p || !attr.mic_p) { 333214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Response/Challenge did not " 334214501Srpaulo "include AT_RAND_P or AT_MIC_P"); 335214501Srpaulo return; 336214501Srpaulo } 337214501Srpaulo 338214501Srpaulo os_memcpy(data->rand_p, attr.rand_p, EAP_SAKE_RAND_LEN); 339214501Srpaulo 340214501Srpaulo os_free(data->peerid); 341214501Srpaulo data->peerid = NULL; 342214501Srpaulo data->peerid_len = 0; 343214501Srpaulo if (attr.peerid) { 344214501Srpaulo data->peerid = os_malloc(attr.peerid_len); 345214501Srpaulo if (data->peerid == NULL) 346214501Srpaulo return; 347214501Srpaulo os_memcpy(data->peerid, attr.peerid, attr.peerid_len); 348214501Srpaulo data->peerid_len = attr.peerid_len; 349214501Srpaulo } 350214501Srpaulo 351214501Srpaulo if (sm->user == NULL || sm->user->password == NULL || 352214501Srpaulo sm->user->password_len != 2 * EAP_SAKE_ROOT_SECRET_LEN) { 353214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Plaintext password with " 354214501Srpaulo "%d-byte key not configured", 355214501Srpaulo 2 * EAP_SAKE_ROOT_SECRET_LEN); 356214501Srpaulo data->state = FAILURE; 357214501Srpaulo return; 358214501Srpaulo } 359214501Srpaulo eap_sake_derive_keys(sm->user->password, 360214501Srpaulo sm->user->password + EAP_SAKE_ROOT_SECRET_LEN, 361214501Srpaulo data->rand_s, data->rand_p, 362214501Srpaulo (u8 *) &data->tek, data->msk, data->emsk); 363214501Srpaulo 364214501Srpaulo eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, 365214501Srpaulo data->serverid, data->serverid_len, 366214501Srpaulo data->peerid, data->peerid_len, 1, 367214501Srpaulo wpabuf_head(respData), wpabuf_len(respData), 368214501Srpaulo attr.mic_p, mic_p); 369214501Srpaulo if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { 370214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); 371214501Srpaulo eap_sake_state(data, FAILURE); 372214501Srpaulo return; 373214501Srpaulo } 374214501Srpaulo 375214501Srpaulo eap_sake_state(data, CONFIRM); 376214501Srpaulo} 377214501Srpaulo 378214501Srpaulo 379214501Srpaulostatic void eap_sake_process_confirm(struct eap_sm *sm, 380214501Srpaulo struct eap_sake_data *data, 381214501Srpaulo const struct wpabuf *respData, 382214501Srpaulo const u8 *payload, size_t payloadlen) 383214501Srpaulo{ 384214501Srpaulo struct eap_sake_parse_attr attr; 385214501Srpaulo u8 mic_p[EAP_SAKE_MIC_LEN]; 386214501Srpaulo 387214501Srpaulo if (data->state != CONFIRM) 388214501Srpaulo return; 389214501Srpaulo 390214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Confirm"); 391214501Srpaulo 392214501Srpaulo if (eap_sake_parse_attributes(payload, payloadlen, &attr)) 393214501Srpaulo return; 394214501Srpaulo 395214501Srpaulo if (!attr.mic_p) { 396214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Response/Confirm did not " 397214501Srpaulo "include AT_MIC_P"); 398214501Srpaulo return; 399214501Srpaulo } 400214501Srpaulo 401214501Srpaulo eap_sake_compute_mic(data->tek.auth, data->rand_s, data->rand_p, 402214501Srpaulo data->serverid, data->serverid_len, 403214501Srpaulo data->peerid, data->peerid_len, 1, 404214501Srpaulo wpabuf_head(respData), wpabuf_len(respData), 405214501Srpaulo attr.mic_p, mic_p); 406214501Srpaulo if (os_memcmp(attr.mic_p, mic_p, EAP_SAKE_MIC_LEN) != 0) { 407214501Srpaulo wpa_printf(MSG_INFO, "EAP-SAKE: Incorrect AT_MIC_P"); 408214501Srpaulo eap_sake_state(data, FAILURE); 409214501Srpaulo } else 410214501Srpaulo eap_sake_state(data, SUCCESS); 411214501Srpaulo} 412214501Srpaulo 413214501Srpaulo 414214501Srpaulostatic void eap_sake_process_auth_reject(struct eap_sm *sm, 415214501Srpaulo struct eap_sake_data *data, 416214501Srpaulo const struct wpabuf *respData, 417214501Srpaulo const u8 *payload, size_t payloadlen) 418214501Srpaulo{ 419214501Srpaulo wpa_printf(MSG_DEBUG, "EAP-SAKE: Received Response/Auth-Reject"); 420214501Srpaulo eap_sake_state(data, FAILURE); 421214501Srpaulo} 422214501Srpaulo 423214501Srpaulo 424214501Srpaulostatic void eap_sake_process(struct eap_sm *sm, void *priv, 425214501Srpaulo struct wpabuf *respData) 426214501Srpaulo{ 427214501Srpaulo struct eap_sake_data *data = priv; 428214501Srpaulo struct eap_sake_hdr *resp; 429214501Srpaulo u8 subtype; 430214501Srpaulo size_t len; 431214501Srpaulo const u8 *pos, *end; 432214501Srpaulo 433214501Srpaulo pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_SAKE, respData, &len); 434214501Srpaulo if (pos == NULL || len < sizeof(struct eap_sake_hdr)) 435214501Srpaulo return; 436214501Srpaulo 437214501Srpaulo resp = (struct eap_sake_hdr *) pos; 438214501Srpaulo end = pos + len; 439214501Srpaulo subtype = resp->subtype; 440214501Srpaulo pos = (u8 *) (resp + 1); 441214501Srpaulo 442214501Srpaulo wpa_hexdump(MSG_DEBUG, "EAP-SAKE: Received attributes", 443214501Srpaulo pos, end - pos); 444214501Srpaulo 445214501Srpaulo switch (subtype) { 446214501Srpaulo case EAP_SAKE_SUBTYPE_IDENTITY: 447214501Srpaulo eap_sake_process_identity(sm, data, respData, pos, end - pos); 448214501Srpaulo break; 449214501Srpaulo case EAP_SAKE_SUBTYPE_CHALLENGE: 450214501Srpaulo eap_sake_process_challenge(sm, data, respData, pos, end - pos); 451214501Srpaulo break; 452214501Srpaulo case EAP_SAKE_SUBTYPE_CONFIRM: 453214501Srpaulo eap_sake_process_confirm(sm, data, respData, pos, end - pos); 454214501Srpaulo break; 455214501Srpaulo case EAP_SAKE_SUBTYPE_AUTH_REJECT: 456214501Srpaulo eap_sake_process_auth_reject(sm, data, respData, pos, 457214501Srpaulo end - pos); 458214501Srpaulo break; 459214501Srpaulo } 460214501Srpaulo} 461214501Srpaulo 462214501Srpaulo 463214501Srpaulostatic Boolean eap_sake_isDone(struct eap_sm *sm, void *priv) 464214501Srpaulo{ 465214501Srpaulo struct eap_sake_data *data = priv; 466214501Srpaulo return data->state == SUCCESS || data->state == FAILURE; 467214501Srpaulo} 468214501Srpaulo 469214501Srpaulo 470214501Srpaulostatic u8 * eap_sake_getKey(struct eap_sm *sm, void *priv, size_t *len) 471214501Srpaulo{ 472214501Srpaulo struct eap_sake_data *data = priv; 473214501Srpaulo u8 *key; 474214501Srpaulo 475214501Srpaulo if (data->state != SUCCESS) 476214501Srpaulo return NULL; 477214501Srpaulo 478214501Srpaulo key = os_malloc(EAP_MSK_LEN); 479214501Srpaulo if (key == NULL) 480214501Srpaulo return NULL; 481214501Srpaulo os_memcpy(key, data->msk, EAP_MSK_LEN); 482214501Srpaulo *len = EAP_MSK_LEN; 483214501Srpaulo 484214501Srpaulo return key; 485214501Srpaulo} 486214501Srpaulo 487214501Srpaulo 488214501Srpaulostatic u8 * eap_sake_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 489214501Srpaulo{ 490214501Srpaulo struct eap_sake_data *data = priv; 491214501Srpaulo u8 *key; 492214501Srpaulo 493214501Srpaulo if (data->state != SUCCESS) 494214501Srpaulo return NULL; 495214501Srpaulo 496214501Srpaulo key = os_malloc(EAP_EMSK_LEN); 497214501Srpaulo if (key == NULL) 498214501Srpaulo return NULL; 499214501Srpaulo os_memcpy(key, data->emsk, EAP_EMSK_LEN); 500214501Srpaulo *len = EAP_EMSK_LEN; 501214501Srpaulo 502214501Srpaulo return key; 503214501Srpaulo} 504214501Srpaulo 505214501Srpaulo 506214501Srpaulostatic Boolean eap_sake_isSuccess(struct eap_sm *sm, void *priv) 507214501Srpaulo{ 508214501Srpaulo struct eap_sake_data *data = priv; 509214501Srpaulo return data->state == SUCCESS; 510214501Srpaulo} 511214501Srpaulo 512214501Srpaulo 513214501Srpauloint eap_server_sake_register(void) 514214501Srpaulo{ 515214501Srpaulo struct eap_method *eap; 516214501Srpaulo int ret; 517214501Srpaulo 518214501Srpaulo eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 519214501Srpaulo EAP_VENDOR_IETF, EAP_TYPE_SAKE, "SAKE"); 520214501Srpaulo if (eap == NULL) 521214501Srpaulo return -1; 522214501Srpaulo 523214501Srpaulo eap->init = eap_sake_init; 524214501Srpaulo eap->reset = eap_sake_reset; 525214501Srpaulo eap->buildReq = eap_sake_buildReq; 526214501Srpaulo eap->check = eap_sake_check; 527214501Srpaulo eap->process = eap_sake_process; 528214501Srpaulo eap->isDone = eap_sake_isDone; 529214501Srpaulo eap->getKey = eap_sake_getKey; 530214501Srpaulo eap->isSuccess = eap_sake_isSuccess; 531214501Srpaulo eap->get_emsk = eap_sake_get_emsk; 532214501Srpaulo 533214501Srpaulo ret = eap_server_method_register(eap); 534214501Srpaulo if (ret) 535214501Srpaulo eap_server_method_free(eap); 536214501Srpaulo return ret; 537214501Srpaulo} 538