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->cfg->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->cfg->server_id_len); 133 wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->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->cfg->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->cfg->server_id_len); 172 wpabuf_put_data(req, sm->cfg->server_id, sm->cfg->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 wpabuf_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 bool 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_memdup(pos, 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 data->id_peer_len = alen; 279 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 280 data->id_peer, data->id_peer_len); 281 pos += alen; 282 283 if (end - pos < 2) { 284 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 285 "ID_Server length"); 286 eap_gpsk_state(data, FAILURE); 287 return; 288 } 289 alen = WPA_GET_BE16(pos); 290 pos += 2; 291 if (end - pos < alen) { 292 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 293 "ID_Server"); 294 eap_gpsk_state(data, FAILURE); 295 return; 296 } 297 if (alen != sm->cfg->server_id_len || 298 os_memcmp(pos, sm->cfg->server_id, alen) != 0) { 299 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and " 300 "GPSK-2 did not match"); 301 eap_gpsk_state(data, FAILURE); 302 return; 303 } 304 pos += alen; 305 306 if (end - pos < EAP_GPSK_RAND_LEN) { 307 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 308 "RAND_Peer"); 309 eap_gpsk_state(data, FAILURE); 310 return; 311 } 312 os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); 313 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 314 data->rand_peer, EAP_GPSK_RAND_LEN); 315 pos += EAP_GPSK_RAND_LEN; 316 317 if (end - pos < EAP_GPSK_RAND_LEN) { 318 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 319 "RAND_Server"); 320 eap_gpsk_state(data, FAILURE); 321 return; 322 } 323 if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) { 324 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 325 "GPSK-2 did not match"); 326 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 327 data->rand_server, EAP_GPSK_RAND_LEN); 328 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2", 329 pos, EAP_GPSK_RAND_LEN); 330 eap_gpsk_state(data, FAILURE); 331 return; 332 } 333 pos += EAP_GPSK_RAND_LEN; 334 335 if (end - pos < 2) { 336 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 337 "CSuite_List length"); 338 eap_gpsk_state(data, FAILURE); 339 return; 340 } 341 alen = WPA_GET_BE16(pos); 342 pos += 2; 343 if (end - pos < alen) { 344 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 345 "CSuite_List"); 346 eap_gpsk_state(data, FAILURE); 347 return; 348 } 349 if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) || 350 os_memcmp(pos, data->csuite_list, alen) != 0) { 351 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and " 352 "GPSK-2 did not match"); 353 eap_gpsk_state(data, FAILURE); 354 return; 355 } 356 pos += alen; 357 358 if (end - pos < (int) sizeof(*csuite)) { 359 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 360 "CSuite_Sel"); 361 eap_gpsk_state(data, FAILURE); 362 return; 363 } 364 csuite = (const struct eap_gpsk_csuite *) pos; 365 for (i = 0; i < data->csuite_count; i++) { 366 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite)) 367 == 0) 368 break; 369 } 370 if (i == data->csuite_count) { 371 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " 372 "ciphersuite %d:%d", 373 WPA_GET_BE32(csuite->vendor), 374 WPA_GET_BE16(csuite->specifier)); 375 eap_gpsk_state(data, FAILURE); 376 return; 377 } 378 data->vendor = WPA_GET_BE32(csuite->vendor); 379 data->specifier = WPA_GET_BE16(csuite->specifier); 380 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", 381 data->vendor, data->specifier); 382 pos += sizeof(*csuite); 383 384 if (end - pos < 2) { 385 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 386 "PD_Payload_1 length"); 387 eap_gpsk_state(data, FAILURE); 388 return; 389 } 390 alen = WPA_GET_BE16(pos); 391 pos += 2; 392 if (end - pos < alen) { 393 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 394 "PD_Payload_1"); 395 eap_gpsk_state(data, FAILURE); 396 return; 397 } 398 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); 399 pos += alen; 400 401 if (sm->user == NULL || sm->user->password == NULL) { 402 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured " 403 "for the user"); 404 eap_gpsk_state(data, FAILURE); 405 return; 406 } 407 408 if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, 409 data->vendor, data->specifier, 410 data->rand_peer, data->rand_server, 411 data->id_peer, data->id_peer_len, 412 sm->cfg->server_id, sm->cfg->server_id_len, 413 data->msk, data->emsk, 414 data->sk, &data->sk_len, 415 data->pk, &data->pk_len) < 0) { 416 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 417 eap_gpsk_state(data, FAILURE); 418 return; 419 } 420 421 if (eap_gpsk_derive_session_id(sm->user->password, 422 sm->user->password_len, 423 data->vendor, data->specifier, 424 data->rand_peer, data->rand_server, 425 data->id_peer, data->id_peer_len, 426 sm->cfg->server_id, 427 sm->cfg->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 bool 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_memdup(data->msk, EAP_MSK_LEN); 579 if (key == NULL) 580 return NULL; 581 *len = EAP_MSK_LEN; 582 583 return key; 584 } 585 586 587 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 588 { 589 struct eap_gpsk_data *data = priv; 590 u8 *key; 591 592 if (data->state != SUCCESS) 593 return NULL; 594 595 key = os_memdup(data->emsk, EAP_EMSK_LEN); 596 if (key == NULL) 597 return NULL; 598 *len = EAP_EMSK_LEN; 599 600 return key; 601 } 602 603 604 static bool eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) 605 { 606 struct eap_gpsk_data *data = priv; 607 return data->state == SUCCESS; 608 } 609 610 611 static u8 * eap_gpsk_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 612 { 613 struct eap_gpsk_data *data = priv; 614 u8 *sid; 615 616 if (data->state != SUCCESS) 617 return NULL; 618 619 sid = os_memdup(data->session_id, data->id_len); 620 if (sid == NULL) 621 return NULL; 622 *len = data->id_len; 623 624 return sid; 625 } 626 627 628 int eap_server_gpsk_register(void) 629 { 630 struct eap_method *eap; 631 632 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 633 EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 634 if (eap == NULL) 635 return -1; 636 637 eap->init = eap_gpsk_init; 638 eap->reset = eap_gpsk_reset; 639 eap->buildReq = eap_gpsk_buildReq; 640 eap->check = eap_gpsk_check; 641 eap->process = eap_gpsk_process; 642 eap->isDone = eap_gpsk_isDone; 643 eap->getKey = eap_gpsk_getKey; 644 eap->isSuccess = eap_gpsk_isSuccess; 645 eap->get_emsk = eap_gpsk_get_emsk; 646 eap->getSessionId = eap_gpsk_get_session_id; 647 648 return eap_server_method_register(eap); 649 } 650