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