1 /* 2 * EAP peer method: EAP-GPSK (RFC 5433) 3 * Copyright (c) 2006-2008, 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; 27 int session_id_set; 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 /* No PD_Payload_1 */ 358 wpabuf_put_be16(resp, 0); 359 360 rpos = wpabuf_put(resp, miclen); 361 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 362 data->specifier, start, rpos - start, rpos) < 363 0) { 364 eap_gpsk_state(data, FAILURE); 365 wpabuf_free(resp); 366 return NULL; 367 } 368 369 return resp; 370 } 371 372 373 static const u8 * eap_gpsk_validate_rand(struct eap_gpsk_data *data, 374 const u8 *pos, const u8 *end) 375 { 376 if (end - pos < EAP_GPSK_RAND_LEN) { 377 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 378 "RAND_Peer"); 379 return NULL; 380 } 381 if (os_memcmp(pos, data->rand_peer, EAP_GPSK_RAND_LEN) != 0) { 382 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2 and " 383 "GPSK-3 did not match"); 384 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-2", 385 data->rand_peer, EAP_GPSK_RAND_LEN); 386 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer in GPSK-3", 387 pos, EAP_GPSK_RAND_LEN); 388 return NULL; 389 } 390 pos += EAP_GPSK_RAND_LEN; 391 392 if (end - pos < EAP_GPSK_RAND_LEN) { 393 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 394 "RAND_Server"); 395 return NULL; 396 } 397 if (os_memcmp(pos, data->rand_server, EAP_GPSK_RAND_LEN) != 0) { 398 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 399 "GPSK-3 did not match"); 400 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 401 data->rand_server, EAP_GPSK_RAND_LEN); 402 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-3", 403 pos, EAP_GPSK_RAND_LEN); 404 return NULL; 405 } 406 pos += EAP_GPSK_RAND_LEN; 407 408 return pos; 409 } 410 411 412 static const u8 * eap_gpsk_validate_id_server(struct eap_gpsk_data *data, 413 const u8 *pos, const u8 *end) 414 { 415 size_t len; 416 417 if (pos == NULL) 418 return NULL; 419 420 if (end - pos < (int) 2) { 421 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 422 "length(ID_Server)"); 423 return NULL; 424 } 425 426 len = WPA_GET_BE16(pos); 427 pos += 2; 428 429 if (end - pos < (int) len) { 430 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 431 "ID_Server"); 432 return NULL; 433 } 434 435 if (len != data->id_server_len || 436 os_memcmp(pos, data->id_server, len) != 0) { 437 wpa_printf(MSG_INFO, "EAP-GPSK: ID_Server did not match with " 438 "the one used in GPSK-1"); 439 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1", 440 data->id_server, data->id_server_len); 441 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-3", 442 pos, len); 443 return NULL; 444 } 445 446 pos += len; 447 448 return pos; 449 } 450 451 452 static const u8 * eap_gpsk_validate_csuite(struct eap_gpsk_data *data, 453 const u8 *pos, const u8 *end) 454 { 455 int vendor, specifier; 456 const struct eap_gpsk_csuite *csuite; 457 458 if (pos == NULL) 459 return NULL; 460 461 if (end - pos < (int) sizeof(*csuite)) { 462 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 463 "CSuite_Sel"); 464 return NULL; 465 } 466 csuite = (const struct eap_gpsk_csuite *) pos; 467 vendor = WPA_GET_BE32(csuite->vendor); 468 specifier = WPA_GET_BE16(csuite->specifier); 469 pos += sizeof(*csuite); 470 if (vendor != data->vendor || specifier != data->specifier) { 471 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel (%d:%d) does not " 472 "match with the one sent in GPSK-2 (%d:%d)", 473 vendor, specifier, data->vendor, data->specifier); 474 return NULL; 475 } 476 477 return pos; 478 } 479 480 481 static const u8 * eap_gpsk_validate_pd_payload_2(struct eap_gpsk_data *data, 482 const u8 *pos, const u8 *end) 483 { 484 u16 alen; 485 486 if (pos == NULL) 487 return NULL; 488 489 if (end - pos < 2) { 490 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 491 "PD_Payload_2 length"); 492 return NULL; 493 } 494 alen = WPA_GET_BE16(pos); 495 pos += 2; 496 if (end - pos < alen) { 497 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for " 498 "%d-octet PD_Payload_2", alen); 499 return NULL; 500 } 501 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_2", pos, alen); 502 pos += alen; 503 504 return pos; 505 } 506 507 508 static const u8 * eap_gpsk_validate_gpsk_3_mic(struct eap_gpsk_data *data, 509 const u8 *payload, 510 const u8 *pos, const u8 *end) 511 { 512 size_t miclen; 513 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 514 515 if (pos == NULL) 516 return NULL; 517 518 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 519 if (end - pos < (int) miclen) { 520 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 521 "(left=%lu miclen=%lu)", 522 (unsigned long) (end - pos), 523 (unsigned long) miclen); 524 return NULL; 525 } 526 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 527 data->specifier, payload, pos - payload, mic) 528 < 0) { 529 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 530 return NULL; 531 } 532 if (os_memcmp(mic, pos, miclen) != 0) { 533 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-3"); 534 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 535 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 536 return NULL; 537 } 538 pos += miclen; 539 540 return pos; 541 } 542 543 544 static struct wpabuf * eap_gpsk_process_gpsk_3(struct eap_sm *sm, 545 struct eap_gpsk_data *data, 546 struct eap_method_ret *ret, 547 const struct wpabuf *reqData, 548 const u8 *payload, 549 size_t payload_len) 550 { 551 struct wpabuf *resp; 552 const u8 *pos, *end; 553 554 if (data->state != GPSK_3) { 555 ret->ignore = TRUE; 556 return NULL; 557 } 558 559 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Request/GPSK-3"); 560 561 end = payload + payload_len; 562 563 pos = eap_gpsk_validate_rand(data, payload, end); 564 pos = eap_gpsk_validate_id_server(data, pos, end); 565 pos = eap_gpsk_validate_csuite(data, pos, end); 566 pos = eap_gpsk_validate_pd_payload_2(data, pos, end); 567 pos = eap_gpsk_validate_gpsk_3_mic(data, payload, pos, end); 568 569 if (pos == NULL) { 570 eap_gpsk_state(data, FAILURE); 571 return NULL; 572 } 573 if (pos != end) { 574 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 575 "data in the end of GPSK-2", 576 (unsigned long) (end - pos)); 577 } 578 579 resp = eap_gpsk_send_gpsk_4(data, eap_get_id(reqData)); 580 if (resp == NULL) 581 return NULL; 582 583 eap_gpsk_state(data, SUCCESS); 584 ret->methodState = METHOD_DONE; 585 ret->decision = DECISION_UNCOND_SUCC; 586 587 return resp; 588 } 589 590 591 static struct wpabuf * eap_gpsk_send_gpsk_4(struct eap_gpsk_data *data, 592 u8 identifier) 593 { 594 struct wpabuf *resp; 595 u8 *rpos, *start; 596 size_t mlen; 597 598 wpa_printf(MSG_DEBUG, "EAP-GPSK: Sending Response/GPSK-4"); 599 600 mlen = eap_gpsk_mic_len(data->vendor, data->specifier); 601 602 resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, 1 + 2 + mlen, 603 EAP_CODE_RESPONSE, identifier); 604 if (resp == NULL) 605 return NULL; 606 607 wpabuf_put_u8(resp, EAP_GPSK_OPCODE_GPSK_4); 608 start = wpabuf_put(resp, 0); 609 610 /* No PD_Payload_3 */ 611 wpabuf_put_be16(resp, 0); 612 613 rpos = wpabuf_put(resp, mlen); 614 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 615 data->specifier, start, rpos - start, rpos) < 616 0) { 617 eap_gpsk_state(data, FAILURE); 618 wpabuf_free(resp); 619 return NULL; 620 } 621 622 return resp; 623 } 624 625 626 static struct wpabuf * eap_gpsk_process(struct eap_sm *sm, void *priv, 627 struct eap_method_ret *ret, 628 const struct wpabuf *reqData) 629 { 630 struct eap_gpsk_data *data = priv; 631 struct wpabuf *resp; 632 const u8 *pos; 633 size_t len; 634 635 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, reqData, &len); 636 if (pos == NULL || len < 1) { 637 ret->ignore = TRUE; 638 return NULL; 639 } 640 641 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode %d", *pos); 642 643 ret->ignore = FALSE; 644 ret->methodState = METHOD_MAY_CONT; 645 ret->decision = DECISION_FAIL; 646 ret->allowNotifications = FALSE; 647 648 switch (*pos) { 649 case EAP_GPSK_OPCODE_GPSK_1: 650 resp = eap_gpsk_process_gpsk_1(sm, data, ret, reqData, 651 pos + 1, len - 1); 652 break; 653 case EAP_GPSK_OPCODE_GPSK_3: 654 resp = eap_gpsk_process_gpsk_3(sm, data, ret, reqData, 655 pos + 1, len - 1); 656 break; 657 default: 658 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignoring message with " 659 "unknown opcode %d", *pos); 660 ret->ignore = TRUE; 661 return NULL; 662 } 663 664 return resp; 665 } 666 667 668 static Boolean eap_gpsk_isKeyAvailable(struct eap_sm *sm, void *priv) 669 { 670 struct eap_gpsk_data *data = priv; 671 return data->state == SUCCESS; 672 } 673 674 675 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 676 { 677 struct eap_gpsk_data *data = priv; 678 u8 *key; 679 680 if (data->state != SUCCESS) 681 return NULL; 682 683 key = os_malloc(EAP_MSK_LEN); 684 if (key == NULL) 685 return NULL; 686 os_memcpy(key, data->msk, EAP_MSK_LEN); 687 *len = EAP_MSK_LEN; 688 689 return key; 690 } 691 692 693 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 694 { 695 struct eap_gpsk_data *data = priv; 696 u8 *key; 697 698 if (data->state != SUCCESS) 699 return NULL; 700 701 key = os_malloc(EAP_EMSK_LEN); 702 if (key == NULL) 703 return NULL; 704 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 705 *len = EAP_EMSK_LEN; 706 707 return key; 708 } 709 710 711 int eap_peer_gpsk_register(void) 712 { 713 struct eap_method *eap; 714 int ret; 715 716 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 717 EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 718 if (eap == NULL) 719 return -1; 720 721 eap->init = eap_gpsk_init; 722 eap->deinit = eap_gpsk_deinit; 723 eap->process = eap_gpsk_process; 724 eap->isKeyAvailable = eap_gpsk_isKeyAvailable; 725 eap->getKey = eap_gpsk_getKey; 726 eap->get_emsk = eap_gpsk_get_emsk; 727 728 ret = eap_peer_method_register(eap); 729 if (ret) 730 eap_peer_method_free(eap); 731 return ret; 732 } 733