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