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