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