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