1 /* 2 * EAP peer method: EAP-GPSK (draft-ietf-emu-eap-gpsk-08.txt) 3 * Copyright (c) 2006-2007, Jouni Malinen <j (at) w1.fi> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 * 9 * Alternatively, this software may be distributed under the terms of BSD 10 * license. 11 * 12 * See README and COPYING for more details. 13 */ 14 15 #include "includes.h" 16 17 #include "common.h" 18 #include "eap_i.h" 19 #include "config_ssid.h" 20 #include "eap_gpsk_common.h" 21 22 struct eap_gpsk_data { 23 enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; 24 u8 rand_server[EAP_GPSK_RAND_LEN]; 25 u8 rand_peer[EAP_GPSK_RAND_LEN]; 26 u8 msk[EAP_MSK_LEN]; 27 u8 emsk[EAP_EMSK_LEN]; 28 u8 sk[EAP_GPSK_MAX_SK_LEN]; 29 size_t sk_len; 30 u8 pk[EAP_GPSK_MAX_PK_LEN]; 31 size_t pk_len; 32 u8 session_id; 33 int session_id_set; 34 u8 *id_peer; 35 size_t id_peer_len; 36 u8 *id_server; 37 size_t id_server_len; 38 int vendor; /* CSuite/Specifier */ 39 int specifier; /* CSuite/Specifier */ 40 u8 *psk; 41 size_t psk_len; 42 }; 43 44 45 static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, 46 const u8 *csuite_list, size_t csuite_list_len, 47 size_t *respDataLen); 48 static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, 49 size_t *respDataLen); 50 51 52 #ifndef CONFIG_NO_STDOUT_DEBUG 53 static const char * eap_gpsk_state_txt(int state) 54 { 55 switch (state) { 56 case GPSK_1: 57 return "GPSK-1"; 58 case GPSK_3: 59 return "GPSK-3"; 60 case SUCCESS: 61 return "SUCCESS"; 62 case FAILURE: 63 return "FAILURE"; 64 default: 65 return "?"; 66 } 67 } 68 #endif /* CONFIG_NO_STDOUT_DEBUG */ 69 70 71 static void eap_gpsk_state(struct eap_gpsk_data *data, int state) 72 { 73 wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", 74 eap_gpsk_state_txt(data->state), 75 eap_gpsk_state_txt(state)); 76 data->state = state; 77 } 78 79 80 static void eap_gpsk_deinit(struct eap_sm *sm, void *priv); 81 82 83 static void * eap_gpsk_init(struct eap_sm *sm) 84 { 85 struct wpa_ssid *config = eap_get_config(sm); 86 struct eap_gpsk_data *data; 87 88 if (config == NULL) { 89 wpa_printf(MSG_INFO, "EAP-GPSK: No configuration found"); 90 return NULL; 91 } 92 93 if (config->eappsk == NULL) { 94 wpa_printf(MSG_INFO, "EAP-GPSK: No key (eappsk) configured"); 95 return NULL; 96 } 97 98 data = os_zalloc(sizeof(*data)); 99 if (data == NULL) 100 return NULL; 101 data->state = GPSK_1; 102 103 if (config->nai) { 104 data->id_peer = os_malloc(config->nai_len); 105 if (data->id_peer == NULL) { 106 eap_gpsk_deinit(sm, data); 107 return NULL; 108 } 109 os_memcpy(data->id_peer, config->nai, config->nai_len); 110 data->id_peer_len = config->nai_len; 111 } 112 113 data->psk = os_malloc(config->eappsk_len); 114 if (data->psk == NULL) { 115 eap_gpsk_deinit(sm, data); 116 return NULL; 117 } 118 os_memcpy(data->psk, config->eappsk, config->eappsk_len); 119 data->psk_len = config->eappsk_len; 120 121 return data; 122 } 123 124 125 static void eap_gpsk_deinit(struct eap_sm *sm, void *priv) 126 { 127 struct eap_gpsk_data *data = priv; 128 os_free(data->id_server); 129 os_free(data->id_peer); 130 os_free(data->psk); 131 os_free(data); 132 } 133 134 135 const u8 * eap_gpsk_process_id_server(struct eap_gpsk_data *data, 136 const u8 *pos, const u8 *end) 137 { 138 u16 alen; 139 140 if (end - pos < 2) { 141 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 142 return NULL; 143 } 144 alen = WPA_GET_BE16(pos); 145 pos += 2; 146 if (end - pos < alen) { 147 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server overflow"); 148 return NULL; 149 } 150 os_free(data->id_server); 151 data->id_server = os_malloc(alen); 152 if (data->id_server == NULL) { 153 wpa_printf(MSG_DEBUG, "EAP-GPSK: No memory for ID_Server"); 154 return NULL; 155 } 156 os_memcpy(data->id_server, pos, alen); 157 data->id_server_len = alen; 158 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server", 159 data->id_server, data->id_server_len); 160 pos += alen; 161 162 return pos; 163 } 164 165 166 const u8 * eap_gpsk_process_rand_server(struct eap_gpsk_data *data, 167 const u8 *pos, const u8 *end) 168 { 169 if (pos == NULL) 170 return NULL; 171 172 if (end - pos < EAP_GPSK_RAND_LEN) { 173 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server overflow"); 174 return NULL; 175 } 176 os_memcpy(data->rand_server, pos, EAP_GPSK_RAND_LEN); 177 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server", 178 data->rand_server, EAP_GPSK_RAND_LEN); 179 pos += EAP_GPSK_RAND_LEN; 180 181 return pos; 182 } 183 184 185 static int eap_gpsk_select_csuite(struct eap_sm *sm, 186 struct eap_gpsk_data *data, 187 const u8 *csuite_list, 188 size_t csuite_list_len) 189 { 190 struct eap_gpsk_csuite *csuite; 191 int i, count; 192 193 count = csuite_list_len / sizeof(struct eap_gpsk_csuite); 194 data->vendor = EAP_GPSK_VENDOR_IETF; 195 data->specifier = EAP_GPSK_CIPHER_RESERVED; 196 csuite = (struct eap_gpsk_csuite *) csuite_list; 197 for (i = 0; i < count; i++) { 198 int vendor, specifier; 199 vendor = WPA_GET_BE32(csuite->vendor); 200 specifier = WPA_GET_BE16(csuite->specifier); 201 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite[%d]: %d:%d", 202 i, vendor, specifier); 203 if (data->vendor == EAP_GPSK_VENDOR_IETF && 204 data->specifier == EAP_GPSK_CIPHER_RESERVED && 205 eap_gpsk_supported_ciphersuite(vendor, specifier)) { 206 data->vendor = vendor; 207 data->specifier = specifier; 208 } 209 csuite++; 210 } 211 if (data->vendor == EAP_GPSK_VENDOR_IETF && 212 data->specifier == EAP_GPSK_CIPHER_RESERVED) { 213 wpa_msg(sm->msg_ctx, MSG_INFO, "EAP-GPSK: No supported " 214 "ciphersuite found"); 215 return -1; 216 } 217 wpa_printf(MSG_DEBUG, "EAP-GPSK: Selected ciphersuite %d:%d", 218 data->vendor, data->specifier); 219 220 return 0; 221 } 222 223 224 const u8 * eap_gpsk_process_csuite_list(struct eap_sm *sm, 225 struct eap_gpsk_data *data, 226 const u8 **list, size_t *list_len, 227 const u8 *pos, const u8 *end) 228 { 229 if (pos == NULL) 230 return NULL; 231 232 if (end - pos < 2) { 233 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short GPSK-1 packet"); 234 return NULL; 235 } 236 *list_len = WPA_GET_BE16(pos); 237 pos += 2; 238 if (end - pos < (int) *list_len) { 239 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List overflow"); 240 return NULL; 241 } 242 if (*list_len == 0 || (*list_len % sizeof(struct eap_gpsk_csuite))) { 243 wpa_printf(MSG_DEBUG, "EAP-GPSK: Invalid CSuite_List len %lu", 244 (unsigned long) *list_len); 245 return NULL; 246 } 247 *list = pos; 248 pos += *list_len; 249 250 if (eap_gpsk_select_csuite(sm, data, *list, *list_len) < 0) 251 return NULL; 252 253 return pos; 254 } 255 256 257 static u8 * eap_gpsk_process_gpsk_1(struct eap_sm *sm, 258 struct eap_gpsk_data *data, 259 struct eap_method_ret *ret, 260 const u8 *reqData, size_t reqDataLen, 261 const u8 *payload, size_t payload_len, 262 size_t *respDataLen) 263 { 264 size_t csuite_list_len; 265 const u8 *csuite_list, *pos, *end; 266 const struct eap_hdr *req; 267 u8 *resp; 268 269 if (data->state != GPSK_1) { 270 ret->ignore = TRUE; 271 return NULL; 272 } 273 274 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-1"); 275 276 end = payload + payload_len; 277 278 pos = eap_gpsk_process_id_server(data, payload, end); 279 pos = eap_gpsk_process_rand_server(data, pos, end); 280 pos = eap_gpsk_process_csuite_list(sm, data, &csuite_list, 281 &csuite_list_len, pos, end); 282 if (pos == NULL) { 283 eap_gpsk_state(data, FAILURE); 284 return NULL; 285 } 286 287 req = (const struct eap_hdr *) reqData; 288 resp = eap_gpsk_send_gpsk_2(data, req->identifier, 289 csuite_list, csuite_list_len, 290 respDataLen); 291 if (resp == NULL) 292 return NULL; 293 294 eap_gpsk_state(data, GPSK_3); 295 296 return (u8 *) resp; 297 } 298 299 300 static u8 * eap_gpsk_send_gpsk_2(struct eap_gpsk_data *data, u8 identifier, 301 const u8 *csuite_list, size_t csuite_list_len, 302 size_t *respDataLen) 303 { 304 struct eap_hdr *resp; 305 size_t len, miclen; 306 u8 *rpos, *start; 307 struct eap_gpsk_csuite *csuite; 308 309 wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-2"); 310 311 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 312 len = 1 + 2 + data->id_peer_len + 2 + data->id_server_len + 313 2 * EAP_GPSK_RAND_LEN + 2 + csuite_list_len + 314 sizeof(struct eap_gpsk_csuite) + 2 + miclen; 315 316 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len, 317 EAP_CODE_RESPONSE, identifier, &rpos); 318 if (resp == NULL) 319 return NULL; 320 321 *rpos++ = EAP_GPSK_OPCODE_GPSK_2; 322 start = rpos; 323 324 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 325 data->id_peer, data->id_peer_len); 326 WPA_PUT_BE16(rpos, data->id_peer_len); 327 rpos += 2; 328 if (data->id_peer) 329 os_memcpy(rpos, data->id_peer, data->id_peer_len); 330 rpos += data->id_peer_len; 331 332 WPA_PUT_BE16(rpos, data->id_server_len); 333 rpos += 2; 334 if (data->id_server) 335 os_memcpy(rpos, data->id_server, data->id_server_len); 336 rpos += data->id_server_len; 337 338 if (os_get_random(data->rand_peer, EAP_GPSK_RAND_LEN)) { 339 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to get random data " 340 "for RAND_Peer"); 341 eap_gpsk_state(data, FAILURE); 342 os_free(resp); 343 return NULL; 344 } 345 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 346 data->rand_peer, EAP_GPSK_RAND_LEN); 347 os_memcpy(rpos, data->rand_peer, EAP_GPSK_RAND_LEN); 348 rpos += EAP_GPSK_RAND_LEN; 349 350 os_memcpy(rpos, data->rand_server, EAP_GPSK_RAND_LEN); 351 rpos += EAP_GPSK_RAND_LEN; 352 353 WPA_PUT_BE16(rpos, csuite_list_len); 354 rpos += 2; 355 os_memcpy(rpos, csuite_list, csuite_list_len); 356 rpos += csuite_list_len; 357 358 csuite = (struct eap_gpsk_csuite *) rpos; 359 WPA_PUT_BE32(csuite->vendor, data->vendor); 360 WPA_PUT_BE16(csuite->specifier, data->specifier); 361 rpos = (u8 *) (csuite + 1); 362 363 if (eap_gpsk_derive_keys(data->psk, data->psk_len, 364 data->vendor, data->specifier, 365 data->rand_peer, data->rand_server, 366 data->id_peer, data->id_peer_len, 367 data->id_server, data->id_server_len, 368 data->msk, data->emsk, 369 data->sk, &data->sk_len, 370 data->pk, &data->pk_len) < 0) { 371 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 372 eap_gpsk_state(data, FAILURE); 373 os_free(resp); 374 return NULL; 375 } 376 377 /* No PD_Payload_1 */ 378 WPA_PUT_BE16(rpos, 0); 379 rpos += 2; 380 381 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 382 data->specifier, start, rpos - start, rpos) < 383 0) { 384 eap_gpsk_state(data, FAILURE); 385 os_free(resp); 386 return NULL; 387 } 388 389 return (u8 *) resp; 390 } 391 392 393 const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, const u8 *pos, 394 const u8 *end) 395 { 396 if (end - pos < EAP_GPSK_RAND_LEN) { 397 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 398 "RAND_Peer"); 399 return NULL; 400 } 401 if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { 402 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " 403 "GPSK-3 did not match"); 404 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", 405 data->rand_peer, EAP_GPSK_RAND_LEN); 406 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", 407 pos, EAP_GPSK_RAND_LEN); 408 return NULL; 409 } 410 pos += EAP_GPSK_RAND_LEN; 411 412 if (end - pos < EAP_GPSK_RAND_LEN) { 413 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 414 "RAND_Server"); 415 return NULL; 416 } 417 if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { 418 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 419 "GPSK-3 did not match"); 420 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 421 data->rand_server, EAP_GPSK_RAND_LEN); 422 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", 423 pos, EAP_GPSK_RAND_LEN); 424 return NULL; 425 } 426 pos += EAP_GPSK_RAND_LEN; 427 428 return pos; 429 } 430 431 432 const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, 433 const u8 *pos, const u8 *end) 434 { 435 size_t len; 436 437 if (pos == NULL) 438 return NULL; 439 440 if (end - pos < (int) 2) { 441 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 442 "length(ID_Server)"); 443 return NULL; 444 } 445 446 len = WPA_GET_BE16(pos); 447 pos += 2; 448 449 if (end - pos < (int) len) { 450 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 451 "ID_Server"); 452 return NULL; 453 } 454 455 if (len != data->id_server_len || 456 os_memcmp(pos, data->id_server, len) != 0) { 457 wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " 458 "the one used in GPSK-1"); 459 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", 460 data->id_server, data->id_server_len); 461 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", 462 pos, len); 463 return NULL; 464 } 465 466 pos += len; 467 468 return pos; 469 } 470 471 472 const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, const u8 *pos, 473 const u8 *end) 474 { 475 int vendor, specifier; 476 const struct eap_gpsk_csuite *csuite; 477 478 if (pos == NULL) 479 return NULL; 480 481 if (end - pos < (int) sizeof(*csuite)) { 482 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 483 "CSuite_Sel"); 484 return NULL; 485 } 486 csuite = (const struct eap_gpsk_csuite *) pos; 487 vendor = WPA_GET_BE32(csuite->vendor); 488 specifier = WPA_GET_BE16(csuite->specifier); 489 pos += sizeof(*csuite); 490 if (vendor != data->vendor || specifier != data->specifier) { 491 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " 492 "match with the one sent in GPSK-2 (%d:%d)", 493 vendor, specifier, data->vendor, data->specifier); 494 return NULL; 495 } 496 497 return pos; 498 } 499 500 501 const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, 502 const u8 *pos, const u8 *end) 503 { 504 u16 alen; 505 506 if (pos == NULL) 507 return NULL; 508 509 if (end - pos < 2) { 510 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 511 "PD_Payload_2 length"); 512 return NULL; 513 } 514 alen = WPA_GET_BE16(pos); 515 pos += 2; 516 if (end - pos < alen) { 517 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 518 "%d-octet PD_Payload_2", alen); 519 return NULL; 520 } 521 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); 522 pos += alen; 523 524 return pos; 525 } 526 527 528 const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, 529 const u8 *payload, 530 const u8 *pos, const u8 *end) 531 { 532 size_t miclen; 533 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 534 535 if (pos == NULL) 536 return NULL; 537 538 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 539 if (end - pos < (int) miclen) { 540 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 541 "(left=%lu miclen=%lu)", 542 (unsigned long) (end - pos), 543 (unsigned long) miclen); 544 return NULL; 545 } 546 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 547 data->specifier, payload, pos - payload, mic) 548 < 0) { 549 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 550 return NULL; 551 } 552 if (os_memcmp(mic, pos, miclen) != 0) { 553 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); 554 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 555 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 556 return NULL; 557 } 558 pos += miclen; 559 560 return pos; 561 } 562 563 564 static u8 * eap_gpsk_process_gpsk_3(struct eap_sm *sm, 565 struct eap_gpsk_data *data, 566 struct eap_method_ret *ret, 567 const u8 *reqData, size_t reqDataLen, 568 const u8 *payload, size_t payload_len, 569 size_t *respDataLen) 570 { 571 u8 *resp; 572 const struct eap_hdr *req; 573 const u8 *pos, *end; 574 575 if (data->state != GPSK_3) { 576 ret->ignore = TRUE; 577 return NULL; 578 } 579 580 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); 581 582 end = payload + payload_len; 583 584 pos = eap_gpsk_validate_rand(data, payload, end); 585 pos = eap_gpsk_validate_id_server(data, pos, end); 586 pos = eap_gpsk_validate_csuite(data, pos, end); 587 pos = eap_gpsk_validate_pd_payload_2(data, pos, end); 588 pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); 589 590 if (pos == NULL) { 591 eap_gpsk_state(data, FAILURE); 592 return NULL; 593 } 594 if (pos != end) { 595 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 596 "data in the end of GPSK-2", 597 (unsigned long) (end - pos)); 598 } 599 600 req = (const struct eap_hdr *) reqData; 601 resp = eap_gpsk_send_gpsk_4(data, req->identifier, respDataLen); 602 if (resp == NULL) 603 return NULL; 604 605 eap_gpsk_state(data, SUCCESS); 606 ret->methodState = METHOD_DONE; 607 ret->decision = DECISION_UNCOND_SUCC; 608 609 return (u8 *) resp; 610 } 611 612 613 static u8 * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, u8 identifier, 614 size_t *respDataLen) 615 { 616 struct eap_hdr *resp; 617 u8 *rpos, *start; 618 size_t len; 619 620 wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); 621 622 len = 1 + 2 + eap_gpsk_mic_len(data->vendor, data->specifier); 623 624 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respDataLen, len, 625 EAP_CODE_RESPONSE, identifier, &rpos); 626 if (resp == NULL) 627 return NULL; 628 629 *rpos++ = EAP_GPSK_OPCODE_GPSK_4; 630 start = rpos; 631 632 /* No PD_Payload_3 */ 633 WPA_PUT_BE16(rpos, 0); 634 rpos += 2; 635 636 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 637 data->specifier, start, rpos - start, rpos) < 638 0) { 639 eap_gpsk_state(data, FAILURE); 640 os_free(resp); 641 return NULL; 642 } 643 644 return (u8 *) resp; 645 } 646 647 648 static u8 * eap_gpsk_process(struct eap_sm *sm, void *priv, 649 struct eap_method_ret *ret, 650 const u8 *reqData, size_t reqDataLen, 651 size_t *respDataLen) 652 { 653 struct eap_gpsk_data *data = priv; 654 u8 *resp; 655 const u8 *pos; 656 size_t len; 657 658 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 659 reqData, reqDataLen, &len); 660 if (pos == NULL || len < 1) { 661 ret->ignore = TRUE; 662 return NULL; 663 } 664 665 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); 666 667 ret->ignore = FALSE; 668 ret->methodState = METHOD_MAY_CONT; 669 ret->decision = DECISION_FAIL; 670 ret->allowNotifications = FALSE; 671 672 switch (*pos) { 673 case EAP_GPSK_OPCODE_GPSK_1: 674 resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, 675 reqDataLen, pos + 1, len - 1, 676 respDataLen); 677 break; 678 case EAP_GPSK_OPCODE_GPSK_3: 679 resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, 680 reqDataLen, pos + 1, len - 1, 681 respDataLen); 682 break; 683 default: 684 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " 685 "unknown opcode %d", *pos); 686 ret->ignore = TRUE; 687 return NULL; 688 } 689 690 return resp; 691 } 692 693 694 static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) 695 { 696 struct eap_gpsk_data *data = priv; 697 return data->state == SUCCESS; 698 } 699 700 701 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 702 { 703 struct eap_gpsk_data *data = priv; 704 u8 *key; 705 706 if (data->state != SUCCESS) 707 return NULL; 708 709 key = os_malloc(EAP_MSK_LEN); 710 if (key == NULL) 711 return NULL; 712 os_memcpy(key, data->msk, EAP_MSK_LEN); 713 *len = EAP_MSK_LEN; 714 715 return key; 716 } 717 718 719 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 720 { 721 struct eap_gpsk_data *data = priv; 722 u8 *key; 723 724 if (data->state != SUCCESS) 725 return NULL; 726 727 key = os_malloc(EAP_EMSK_LEN); 728 if (key == NULL) 729 return NULL; 730 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 731 *len = EAP_EMSK_LEN; 732 733 return key; 734 } 735 736 737 int eap_peer_gpsk_register(void) 738 { 739 struct eap_method *eap; 740 int ret; 741 742 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 743 EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 744 if (eap == NULL) 745 return -1; 746 747 eap->init = eap_gpsk_init; 748 eap->deinit = eap_gpsk_deinit; 749 eap->process = eap_gpsk_process; 750 eap->isKeyAvailable = eap_gpsk_isKeyAvailable; 751 eap->getKey = eap_gpsk_getKey; 752 eap->get_emsk = eap_gpsk_get_emsk; 753 754 ret = eap_peer_method_register(eap); 755 if (ret) 756 eap_peer_method_free(eap); 757 return ret; 758 } 759