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