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