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