1 /* 2 * hostapd / EAP-GPSK (RFC 5433) server 3 * Copyright (c) 2006-2007, 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_server/eap_i.h" 14 #include "eap_common/eap_gpsk_common.h" 15 16 17 struct eap_gpsk_data { 18 enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; 19 u8 rand_server[EAP_GPSK_RAND_LEN]; 20 u8 rand_peer[EAP_GPSK_RAND_LEN]; 21 u8 msk[EAP_MSK_LEN]; 22 u8 emsk[EAP_EMSK_LEN]; 23 u8 sk[EAP_GPSK_MAX_SK_LEN]; 24 size_t sk_len; 25 u8 pk[EAP_GPSK_MAX_PK_LEN]; 26 size_t pk_len; 27 u8 *id_peer; 28 size_t id_peer_len; 29 #define MAX_NUM_CSUITES 2 30 struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES]; 31 size_t csuite_count; 32 int vendor; /* CSuite/Vendor */ 33 int specifier; /* CSuite/Specifier */ 34 }; 35 36 37 static const char * eap_gpsk_state_txt(int state) 38 { 39 switch (state) { 40 case GPSK_1: 41 return "GPSK-1"; 42 case GPSK_3: 43 return "GPSK-3"; 44 case SUCCESS: 45 return "SUCCESS"; 46 case FAILURE: 47 return "FAILURE"; 48 default: 49 return "?"; 50 } 51 } 52 53 54 static void eap_gpsk_state(struct eap_gpsk_data *data, int state) 55 { 56 wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", 57 eap_gpsk_state_txt(data->state), 58 eap_gpsk_state_txt(state)); 59 data->state = state; 60 } 61 62 63 static void * eap_gpsk_init(struct eap_sm *sm) 64 { 65 struct eap_gpsk_data *data; 66 67 data = os_zalloc(sizeof(*data)); 68 if (data == NULL) 69 return NULL; 70 data->state = GPSK_1; 71 72 data->csuite_count = 0; 73 if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, 74 EAP_GPSK_CIPHER_AES)) { 75 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, 76 EAP_GPSK_VENDOR_IETF); 77 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, 78 EAP_GPSK_CIPHER_AES); 79 data->csuite_count++; 80 } 81 if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, 82 EAP_GPSK_CIPHER_SHA256)) { 83 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, 84 EAP_GPSK_VENDOR_IETF); 85 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, 86 EAP_GPSK_CIPHER_SHA256); 87 data->csuite_count++; 88 } 89 90 return data; 91 } 92 93 94 static void eap_gpsk_reset(struct eap_sm *sm, void *priv) 95 { 96 struct eap_gpsk_data *data = priv; 97 os_free(data->id_peer); 98 os_free(data); 99 } 100 101 102 static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm, 103 struct eap_gpsk_data *data, u8 id) 104 { 105 size_t len; 106 struct wpabuf *req; 107 108 wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1"); 109 110 if (random_get_bytes(data->rand_server, EAP_GPSK_RAND_LEN)) { 111 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data"); 112 eap_gpsk_state(data, FAILURE); 113 return NULL; 114 } 115 wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server", 116 data->rand_server, EAP_GPSK_RAND_LEN); 117 118 len = 1 + 2 + sm->server_id_len + EAP_GPSK_RAND_LEN + 2 + 119 data->csuite_count * sizeof(struct eap_gpsk_csuite); 120 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 121 EAP_CODE_REQUEST, id); 122 if (req == NULL) { 123 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " 124 "for request/GPSK-1"); 125 eap_gpsk_state(data, FAILURE); 126 return NULL; 127 } 128 129 wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1); 130 wpabuf_put_be16(req, sm->server_id_len); 131 wpabuf_put_data(req, sm->server_id, sm->server_id_len); 132 wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); 133 wpabuf_put_be16(req, 134 data->csuite_count * sizeof(struct eap_gpsk_csuite)); 135 wpabuf_put_data(req, data->csuite_list, 136 data->csuite_count * sizeof(struct eap_gpsk_csuite)); 137 138 return req; 139 } 140 141 142 static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm, 143 struct eap_gpsk_data *data, u8 id) 144 { 145 u8 *pos, *start; 146 size_t len, miclen; 147 struct eap_gpsk_csuite *csuite; 148 struct wpabuf *req; 149 150 wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3"); 151 152 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 153 len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + sm->server_id_len + 154 sizeof(struct eap_gpsk_csuite) + 2 + miclen; 155 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 156 EAP_CODE_REQUEST, id); 157 if (req == NULL) { 158 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " 159 "for request/GPSK-3"); 160 eap_gpsk_state(data, FAILURE); 161 return NULL; 162 } 163 164 wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3); 165 start = wpabuf_put(req, 0); 166 167 wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN); 168 wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); 169 wpabuf_put_be16(req, sm->server_id_len); 170 wpabuf_put_data(req, sm->server_id, sm->server_id_len); 171 csuite = wpabuf_put(req, sizeof(*csuite)); 172 WPA_PUT_BE32(csuite->vendor, data->vendor); 173 WPA_PUT_BE16(csuite->specifier, data->specifier); 174 175 /* no PD_Payload_2 */ 176 wpabuf_put_be16(req, 0); 177 178 pos = wpabuf_put(req, miclen); 179 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 180 data->specifier, start, pos - start, pos) < 0) 181 { 182 os_free(req); 183 eap_gpsk_state(data, FAILURE); 184 return NULL; 185 } 186 187 return req; 188 } 189 190 191 static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) 192 { 193 struct eap_gpsk_data *data = priv; 194 195 switch (data->state) { 196 case GPSK_1: 197 return eap_gpsk_build_gpsk_1(sm, data, id); 198 case GPSK_3: 199 return eap_gpsk_build_gpsk_3(sm, data, id); 200 default: 201 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq", 202 data->state); 203 break; 204 } 205 return NULL; 206 } 207 208 209 static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, 210 struct wpabuf *respData) 211 { 212 struct eap_gpsk_data *data = priv; 213 const u8 *pos; 214 size_t len; 215 216 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); 217 if (pos == NULL || len < 1) { 218 wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); 219 return TRUE; 220 } 221 222 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); 223 224 if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) 225 return FALSE; 226 227 if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) 228 return FALSE; 229 230 wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", 231 *pos, data->state); 232 233 return TRUE; 234 } 235 236 237 static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, 238 struct eap_gpsk_data *data, 239 const u8 *payload, size_t payloadlen) 240 { 241 const u8 *pos, *end; 242 u16 alen; 243 const struct eap_gpsk_csuite *csuite; 244 size_t i, miclen; 245 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 246 247 if (data->state != GPSK_1) 248 return; 249 250 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2"); 251 252 pos = payload; 253 end = payload + payloadlen; 254 255 if (end - pos < 2) { 256 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 257 "ID_Peer length"); 258 eap_gpsk_state(data, FAILURE); 259 return; 260 } 261 alen = WPA_GET_BE16(pos); 262 pos += 2; 263 if (end - pos < alen) { 264 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 265 "ID_Peer"); 266 eap_gpsk_state(data, FAILURE); 267 return; 268 } 269 os_free(data->id_peer); 270 data->id_peer = os_malloc(alen); 271 if (data->id_peer == NULL) { 272 wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " 273 "%d-octet ID_Peer", alen); 274 return; 275 } 276 os_memcpy(data->id_peer, pos, alen); 277 data->id_peer_len = alen; 278 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 279 data->id_peer, data->id_peer_len); 280 pos += alen; 281 282 if (end - pos < 2) { 283 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 284 "ID_Server length"); 285 eap_gpsk_state(data, FAILURE); 286 return; 287 } 288 alen = WPA_GET_BE16(pos); 289 pos += 2; 290 if (end - pos < alen) { 291 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 292 "ID_Server"); 293 eap_gpsk_state(data, FAILURE); 294 return; 295 } 296 if (alen != sm->server_id_len || 297 os_memcmp(pos, sm->server_id, alen) != 0) { 298 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and " 299 "GPSK-2 did not match"); 300 eap_gpsk_state(data, FAILURE); 301 return; 302 } 303 pos += alen; 304 305 if (end - pos < EAP_GPSK_RAND_LEN) { 306 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 307 "RAND_Peer"); 308 eap_gpsk_state(data, FAILURE); 309 return; 310 } 311 os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); 312 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 313 data->rand_peer, EAP_GPSK_RAND_LEN); 314 pos += EAP_GPSK_RAND_LEN; 315 316 if (end - pos < EAP_GPSK_RAND_LEN) { 317 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 318 "RAND_Server"); 319 eap_gpsk_state(data, FAILURE); 320 return; 321 } 322 if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) { 323 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 324 "GPSK-2 did not match"); 325 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 326 data->rand_server, EAP_GPSK_RAND_LEN); 327 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2", 328 pos, EAP_GPSK_RAND_LEN); 329 eap_gpsk_state(data, FAILURE); 330 return; 331 } 332 pos += EAP_GPSK_RAND_LEN; 333 334 if (end - pos < 2) { 335 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 336 "CSuite_List length"); 337 eap_gpsk_state(data, FAILURE); 338 return; 339 } 340 alen = WPA_GET_BE16(pos); 341 pos += 2; 342 if (end - pos < alen) { 343 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 344 "CSuite_List"); 345 eap_gpsk_state(data, FAILURE); 346 return; 347 } 348 if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) || 349 os_memcmp(pos, data->csuite_list, alen) != 0) { 350 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and " 351 "GPSK-2 did not match"); 352 eap_gpsk_state(data, FAILURE); 353 return; 354 } 355 pos += alen; 356 357 if (end - pos < (int) sizeof(*csuite)) { 358 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 359 "CSuite_Sel"); 360 eap_gpsk_state(data, FAILURE); 361 return; 362 } 363 csuite = (const struct eap_gpsk_csuite *) pos; 364 for (i = 0; i < data->csuite_count; i++) { 365 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite)) 366 == 0) 367 break; 368 } 369 if (i == data->csuite_count) { 370 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " 371 "ciphersuite %d:%d", 372 WPA_GET_BE32(csuite->vendor), 373 WPA_GET_BE16(csuite->specifier)); 374 eap_gpsk_state(data, FAILURE); 375 return; 376 } 377 data->vendor = WPA_GET_BE32(csuite->vendor); 378 data->specifier = WPA_GET_BE16(csuite->specifier); 379 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", 380 data->vendor, data->specifier); 381 pos += sizeof(*csuite); 382 383 if (end - pos < 2) { 384 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 385 "PD_Payload_1 length"); 386 eap_gpsk_state(data, FAILURE); 387 return; 388 } 389 alen = WPA_GET_BE16(pos); 390 pos += 2; 391 if (end - pos < alen) { 392 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 393 "PD_Payload_1"); 394 eap_gpsk_state(data, FAILURE); 395 return; 396 } 397 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); 398 pos += alen; 399 400 if (sm->user == NULL || sm->user->password == NULL) { 401 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured " 402 "for the user"); 403 eap_gpsk_state(data, FAILURE); 404 return; 405 } 406 407 if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, 408 data->vendor, data->specifier, 409 data->rand_peer, data->rand_server, 410 data->id_peer, data->id_peer_len, 411 sm->server_id, sm->server_id_len, 412 data->msk, data->emsk, 413 data->sk, &data->sk_len, 414 data->pk, &data->pk_len) < 0) { 415 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 416 eap_gpsk_state(data, FAILURE); 417 return; 418 } 419 420 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 421 if (end - pos < (int) miclen) { 422 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 423 "(left=%lu miclen=%lu)", 424 (unsigned long) (end - pos), 425 (unsigned long) miclen); 426 eap_gpsk_state(data, FAILURE); 427 return; 428 } 429 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 430 data->specifier, payload, pos - payload, mic) 431 < 0) { 432 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 433 eap_gpsk_state(data, FAILURE); 434 return; 435 } 436 if (os_memcmp(mic, pos, miclen) != 0) { 437 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2"); 438 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 439 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 440 eap_gpsk_state(data, FAILURE); 441 return; 442 } 443 pos += miclen; 444 445 if (pos != end) { 446 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 447 "data in the end of GPSK-2", 448 (unsigned long) (end - pos)); 449 } 450 451 eap_gpsk_state(data, GPSK_3); 452 } 453 454 455 static void eap_gpsk_process_gpsk_4(struct eap_sm *sm, 456 struct eap_gpsk_data *data, 457 const u8 *payload, size_t payloadlen) 458 { 459 const u8 *pos, *end; 460 u16 alen; 461 size_t miclen; 462 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 463 464 if (data->state != GPSK_3) 465 return; 466 467 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4"); 468 469 pos = payload; 470 end = payload + payloadlen; 471 472 if (end - pos < 2) { 473 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 474 "PD_Payload_1 length"); 475 eap_gpsk_state(data, FAILURE); 476 return; 477 } 478 alen = WPA_GET_BE16(pos); 479 pos += 2; 480 if (end - pos < alen) { 481 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 482 "PD_Payload_1"); 483 eap_gpsk_state(data, FAILURE); 484 return; 485 } 486 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); 487 pos += alen; 488 489 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 490 if (end - pos < (int) miclen) { 491 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 492 "(left=%lu miclen=%lu)", 493 (unsigned long) (end - pos), 494 (unsigned long) miclen); 495 eap_gpsk_state(data, FAILURE); 496 return; 497 } 498 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 499 data->specifier, payload, pos - payload, mic) 500 < 0) { 501 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 502 eap_gpsk_state(data, FAILURE); 503 return; 504 } 505 if (os_memcmp(mic, pos, miclen) != 0) { 506 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4"); 507 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 508 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 509 eap_gpsk_state(data, FAILURE); 510 return; 511 } 512 pos += miclen; 513 514 if (pos != end) { 515 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 516 "data in the end of GPSK-4", 517 (unsigned long) (end - pos)); 518 } 519 520 eap_gpsk_state(data, SUCCESS); 521 } 522 523 524 static void eap_gpsk_process(struct eap_sm *sm, void *priv, 525 struct wpabuf *respData) 526 { 527 struct eap_gpsk_data *data = priv; 528 const u8 *pos; 529 size_t len; 530 531 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); 532 if (pos == NULL || len < 1) 533 return; 534 535 switch (*pos) { 536 case EAP_GPSK_OPCODE_GPSK_2: 537 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1); 538 break; 539 case EAP_GPSK_OPCODE_GPSK_4: 540 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1); 541 break; 542 } 543 } 544 545 546 static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) 547 { 548 struct eap_gpsk_data *data = priv; 549 return data->state == SUCCESS || data->state == FAILURE; 550 } 551 552 553 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 554 { 555 struct eap_gpsk_data *data = priv; 556 u8 *key; 557 558 if (data->state != SUCCESS) 559 return NULL; 560 561 key = os_malloc(EAP_MSK_LEN); 562 if (key == NULL) 563 return NULL; 564 os_memcpy(key, data->msk, EAP_MSK_LEN); 565 *len = EAP_MSK_LEN; 566 567 return key; 568 } 569 570 571 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 572 { 573 struct eap_gpsk_data *data = priv; 574 u8 *key; 575 576 if (data->state != SUCCESS) 577 return NULL; 578 579 key = os_malloc(EAP_EMSK_LEN); 580 if (key == NULL) 581 return NULL; 582 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 583 *len = EAP_EMSK_LEN; 584 585 return key; 586 } 587 588 589 static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) 590 { 591 struct eap_gpsk_data *data = priv; 592 return data->state == SUCCESS; 593 } 594 595 596 int eap_server_gpsk_register(void) 597 { 598 struct eap_method *eap; 599 int ret; 600 601 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 602 EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 603 if (eap == NULL) 604 return -1; 605 606 eap->init = eap_gpsk_init; 607 eap->reset = eap_gpsk_reset; 608 eap->buildReq = eap_gpsk_buildReq; 609 eap->check = eap_gpsk_check; 610 eap->process = eap_gpsk_process; 611 eap->isDone = eap_gpsk_isDone; 612 eap->getKey = eap_gpsk_getKey; 613 eap->isSuccess = eap_gpsk_isSuccess; 614 eap->get_emsk = eap_gpsk_get_emsk; 615 616 ret = eap_server_method_register(eap); 617 if (ret) 618 eap_server_method_free(eap); 619 return ret; 620 } 621