$search
00001 /* 00002 * hostapd / EAP-GPSK (RFC 5433) server 00003 * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "eap_server/eap_i.h" 00019 #include "eap_common/eap_gpsk_common.h" 00020 00021 00022 struct eap_gpsk_data { 00023 enum { GPSK_1, GPSK_3, SUCCESS, FAILURE } state; 00024 u8 rand_server[EAP_GPSK_RAND_LEN]; 00025 u8 rand_peer[EAP_GPSK_RAND_LEN]; 00026 u8 msk[EAP_MSK_LEN]; 00027 u8 emsk[EAP_EMSK_LEN]; 00028 u8 sk[EAP_GPSK_MAX_SK_LEN]; 00029 size_t sk_len; 00030 u8 pk[EAP_GPSK_MAX_PK_LEN]; 00031 size_t pk_len; 00032 u8 *id_peer; 00033 size_t id_peer_len; 00034 u8 *id_server; 00035 size_t id_server_len; 00036 #define MAX_NUM_CSUITES 2 00037 struct eap_gpsk_csuite csuite_list[MAX_NUM_CSUITES]; 00038 size_t csuite_count; 00039 int vendor; /* CSuite/Vendor */ 00040 int specifier; /* CSuite/Specifier */ 00041 }; 00042 00043 00044 static const char * eap_gpsk_state_txt(int state) 00045 { 00046 switch (state) { 00047 case GPSK_1: 00048 return "GPSK-1"; 00049 case GPSK_3: 00050 return "GPSK-3"; 00051 case SUCCESS: 00052 return "SUCCESS"; 00053 case FAILURE: 00054 return "FAILURE"; 00055 default: 00056 return "?"; 00057 } 00058 } 00059 00060 00061 static void eap_gpsk_state(struct eap_gpsk_data *data, int state) 00062 { 00063 wpa_printf(MSG_DEBUG, "EAP-GPSK: %s -> %s", 00064 eap_gpsk_state_txt(data->state), 00065 eap_gpsk_state_txt(state)); 00066 data->state = state; 00067 } 00068 00069 00070 static void * eap_gpsk_init(struct eap_sm *sm) 00071 { 00072 struct eap_gpsk_data *data; 00073 00074 data = os_zalloc(sizeof(*data)); 00075 if (data == NULL) 00076 return NULL; 00077 data->state = GPSK_1; 00078 00079 /* TODO: add support for configuring ID_Server */ 00080 data->id_server = (u8 *) os_strdup("hostapd"); 00081 if (data->id_server) 00082 data->id_server_len = os_strlen((char *) data->id_server); 00083 00084 data->csuite_count = 0; 00085 if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, 00086 EAP_GPSK_CIPHER_AES)) { 00087 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, 00088 EAP_GPSK_VENDOR_IETF); 00089 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, 00090 EAP_GPSK_CIPHER_AES); 00091 data->csuite_count++; 00092 } 00093 if (eap_gpsk_supported_ciphersuite(EAP_GPSK_VENDOR_IETF, 00094 EAP_GPSK_CIPHER_SHA256)) { 00095 WPA_PUT_BE32(data->csuite_list[data->csuite_count].vendor, 00096 EAP_GPSK_VENDOR_IETF); 00097 WPA_PUT_BE16(data->csuite_list[data->csuite_count].specifier, 00098 EAP_GPSK_CIPHER_SHA256); 00099 data->csuite_count++; 00100 } 00101 00102 return data; 00103 } 00104 00105 00106 static void eap_gpsk_reset(struct eap_sm *sm, void *priv) 00107 { 00108 struct eap_gpsk_data *data = priv; 00109 os_free(data->id_server); 00110 os_free(data->id_peer); 00111 os_free(data); 00112 } 00113 00114 00115 static struct wpabuf * eap_gpsk_build_gpsk_1(struct eap_sm *sm, 00116 struct eap_gpsk_data *data, u8 id) 00117 { 00118 size_t len; 00119 struct wpabuf *req; 00120 00121 wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-1"); 00122 00123 if (os_get_random(data->rand_server, EAP_GPSK_RAND_LEN)) { 00124 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to get random data"); 00125 eap_gpsk_state(data, FAILURE); 00126 return NULL; 00127 } 00128 wpa_hexdump(MSG_MSGDUMP, "EAP-GPSK: RAND_Server", 00129 data->rand_server, EAP_GPSK_RAND_LEN); 00130 00131 len = 1 + 2 + data->id_server_len + EAP_GPSK_RAND_LEN + 2 + 00132 data->csuite_count * sizeof(struct eap_gpsk_csuite); 00133 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 00134 EAP_CODE_REQUEST, id); 00135 if (req == NULL) { 00136 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " 00137 "for request/GPSK-1"); 00138 eap_gpsk_state(data, FAILURE); 00139 return NULL; 00140 } 00141 00142 wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_1); 00143 wpabuf_put_be16(req, data->id_server_len); 00144 wpabuf_put_data(req, data->id_server, data->id_server_len); 00145 wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); 00146 wpabuf_put_be16(req, 00147 data->csuite_count * sizeof(struct eap_gpsk_csuite)); 00148 wpabuf_put_data(req, data->csuite_list, 00149 data->csuite_count * sizeof(struct eap_gpsk_csuite)); 00150 00151 return req; 00152 } 00153 00154 00155 static struct wpabuf * eap_gpsk_build_gpsk_3(struct eap_sm *sm, 00156 struct eap_gpsk_data *data, u8 id) 00157 { 00158 u8 *pos, *start; 00159 size_t len, miclen; 00160 struct eap_gpsk_csuite *csuite; 00161 struct wpabuf *req; 00162 00163 wpa_printf(MSG_DEBUG, "EAP-GPSK: Request/GPSK-3"); 00164 00165 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 00166 len = 1 + 2 * EAP_GPSK_RAND_LEN + 2 + data->id_server_len + 00167 sizeof(struct eap_gpsk_csuite) + 2 + miclen; 00168 req = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_GPSK, len, 00169 EAP_CODE_REQUEST, id); 00170 if (req == NULL) { 00171 wpa_printf(MSG_ERROR, "EAP-GPSK: Failed to allocate memory " 00172 "for request/GPSK-3"); 00173 eap_gpsk_state(data, FAILURE); 00174 return NULL; 00175 } 00176 00177 wpabuf_put_u8(req, EAP_GPSK_OPCODE_GPSK_3); 00178 start = wpabuf_put(req, 0); 00179 00180 wpabuf_put_data(req, data->rand_peer, EAP_GPSK_RAND_LEN); 00181 wpabuf_put_data(req, data->rand_server, EAP_GPSK_RAND_LEN); 00182 wpabuf_put_be16(req, data->id_server_len); 00183 wpabuf_put_data(req, data->id_server, data->id_server_len); 00184 csuite = wpabuf_put(req, sizeof(*csuite)); 00185 WPA_PUT_BE32(csuite->vendor, data->vendor); 00186 WPA_PUT_BE16(csuite->specifier, data->specifier); 00187 00188 /* no PD_Payload_2 */ 00189 wpabuf_put_be16(req, 0); 00190 00191 pos = wpabuf_put(req, miclen); 00192 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 00193 data->specifier, start, pos - start, pos) < 0) 00194 { 00195 os_free(req); 00196 eap_gpsk_state(data, FAILURE); 00197 return NULL; 00198 } 00199 00200 return req; 00201 } 00202 00203 00204 static struct wpabuf * eap_gpsk_buildReq(struct eap_sm *sm, void *priv, u8 id) 00205 { 00206 struct eap_gpsk_data *data = priv; 00207 00208 switch (data->state) { 00209 case GPSK_1: 00210 return eap_gpsk_build_gpsk_1(sm, data, id); 00211 case GPSK_3: 00212 return eap_gpsk_build_gpsk_3(sm, data, id); 00213 default: 00214 wpa_printf(MSG_DEBUG, "EAP-GPSK: Unknown state %d in buildReq", 00215 data->state); 00216 break; 00217 } 00218 return NULL; 00219 } 00220 00221 00222 static Boolean eap_gpsk_check(struct eap_sm *sm, void *priv, 00223 struct wpabuf *respData) 00224 { 00225 struct eap_gpsk_data *data = priv; 00226 const u8 *pos; 00227 size_t len; 00228 00229 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); 00230 if (pos == NULL || len < 1) { 00231 wpa_printf(MSG_INFO, "EAP-GPSK: Invalid frame"); 00232 return TRUE; 00233 } 00234 00235 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received frame: opcode=%d", *pos); 00236 00237 if (data->state == GPSK_1 && *pos == EAP_GPSK_OPCODE_GPSK_2) 00238 return FALSE; 00239 00240 if (data->state == GPSK_3 && *pos == EAP_GPSK_OPCODE_GPSK_4) 00241 return FALSE; 00242 00243 wpa_printf(MSG_INFO, "EAP-GPSK: Unexpected opcode=%d in state=%d", 00244 *pos, data->state); 00245 00246 return TRUE; 00247 } 00248 00249 00250 static void eap_gpsk_process_gpsk_2(struct eap_sm *sm, 00251 struct eap_gpsk_data *data, 00252 const u8 *payload, size_t payloadlen) 00253 { 00254 const u8 *pos, *end; 00255 u16 alen; 00256 const struct eap_gpsk_csuite *csuite; 00257 size_t i, miclen; 00258 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 00259 00260 if (data->state != GPSK_1) 00261 return; 00262 00263 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-2"); 00264 00265 pos = payload; 00266 end = payload + payloadlen; 00267 00268 if (end - pos < 2) { 00269 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00270 "ID_Peer length"); 00271 eap_gpsk_state(data, FAILURE); 00272 return; 00273 } 00274 alen = WPA_GET_BE16(pos); 00275 pos += 2; 00276 if (end - pos < alen) { 00277 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00278 "ID_Peer"); 00279 eap_gpsk_state(data, FAILURE); 00280 return; 00281 } 00282 os_free(data->id_peer); 00283 data->id_peer = os_malloc(alen); 00284 if (data->id_peer == NULL) { 00285 wpa_printf(MSG_DEBUG, "EAP-GPSK: Not enough memory to store " 00286 "%d-octet ID_Peer", alen); 00287 return; 00288 } 00289 os_memcpy(data->id_peer, pos, alen); 00290 data->id_peer_len = alen; 00291 wpa_hexdump_ascii(MSG_DEBUG, "EAP-GPSK: ID_Peer", 00292 data->id_peer, data->id_peer_len); 00293 pos += alen; 00294 00295 if (end - pos < 2) { 00296 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00297 "ID_Server length"); 00298 eap_gpsk_state(data, FAILURE); 00299 return; 00300 } 00301 alen = WPA_GET_BE16(pos); 00302 pos += 2; 00303 if (end - pos < alen) { 00304 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00305 "ID_Server"); 00306 eap_gpsk_state(data, FAILURE); 00307 return; 00308 } 00309 if (alen != data->id_server_len || 00310 os_memcmp(pos, data->id_server, alen) != 0) { 00311 wpa_printf(MSG_DEBUG, "EAP-GPSK: ID_Server in GPSK-1 and " 00312 "GPSK-2 did not match"); 00313 eap_gpsk_state(data, FAILURE); 00314 return; 00315 } 00316 pos += alen; 00317 00318 if (end - pos < EAP_GPSK_RAND_LEN) { 00319 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00320 "RAND_Peer"); 00321 eap_gpsk_state(data, FAILURE); 00322 return; 00323 } 00324 os_memcpy(data->rand_peer, pos, EAP_GPSK_RAND_LEN); 00325 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Peer", 00326 data->rand_peer, EAP_GPSK_RAND_LEN); 00327 pos += EAP_GPSK_RAND_LEN; 00328 00329 if (end - pos < EAP_GPSK_RAND_LEN) { 00330 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00331 "RAND_Server"); 00332 eap_gpsk_state(data, FAILURE); 00333 return; 00334 } 00335 if (os_memcmp(data->rand_server, pos, EAP_GPSK_RAND_LEN) != 0) { 00336 wpa_printf(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1 and " 00337 "GPSK-2 did not match"); 00338 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-1", 00339 data->rand_server, EAP_GPSK_RAND_LEN); 00340 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: RAND_Server in GPSK-2", 00341 pos, EAP_GPSK_RAND_LEN); 00342 eap_gpsk_state(data, FAILURE); 00343 return; 00344 } 00345 pos += EAP_GPSK_RAND_LEN; 00346 00347 if (end - pos < 2) { 00348 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00349 "CSuite_List length"); 00350 eap_gpsk_state(data, FAILURE); 00351 return; 00352 } 00353 alen = WPA_GET_BE16(pos); 00354 pos += 2; 00355 if (end - pos < alen) { 00356 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00357 "CSuite_List"); 00358 eap_gpsk_state(data, FAILURE); 00359 return; 00360 } 00361 if (alen != data->csuite_count * sizeof(struct eap_gpsk_csuite) || 00362 os_memcmp(pos, data->csuite_list, alen) != 0) { 00363 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_List in GPSK-1 and " 00364 "GPSK-2 did not match"); 00365 eap_gpsk_state(data, FAILURE); 00366 return; 00367 } 00368 pos += alen; 00369 00370 if (end - pos < (int) sizeof(*csuite)) { 00371 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00372 "CSuite_Sel"); 00373 eap_gpsk_state(data, FAILURE); 00374 return; 00375 } 00376 csuite = (const struct eap_gpsk_csuite *) pos; 00377 for (i = 0; i < data->csuite_count; i++) { 00378 if (os_memcmp(csuite, &data->csuite_list[i], sizeof(*csuite)) 00379 == 0) 00380 break; 00381 } 00382 if (i == data->csuite_count) { 00383 wpa_printf(MSG_DEBUG, "EAP-GPSK: Peer selected unsupported " 00384 "ciphersuite %d:%d", 00385 WPA_GET_BE32(csuite->vendor), 00386 WPA_GET_BE16(csuite->specifier)); 00387 eap_gpsk_state(data, FAILURE); 00388 return; 00389 } 00390 data->vendor = WPA_GET_BE32(csuite->vendor); 00391 data->specifier = WPA_GET_BE16(csuite->specifier); 00392 wpa_printf(MSG_DEBUG, "EAP-GPSK: CSuite_Sel %d:%d", 00393 data->vendor, data->specifier); 00394 pos += sizeof(*csuite); 00395 00396 if (end - pos < 2) { 00397 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00398 "PD_Payload_1 length"); 00399 eap_gpsk_state(data, FAILURE); 00400 return; 00401 } 00402 alen = WPA_GET_BE16(pos); 00403 pos += 2; 00404 if (end - pos < alen) { 00405 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00406 "PD_Payload_1"); 00407 eap_gpsk_state(data, FAILURE); 00408 return; 00409 } 00410 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); 00411 pos += alen; 00412 00413 if (sm->user == NULL || sm->user->password == NULL) { 00414 wpa_printf(MSG_INFO, "EAP-GPSK: No PSK/password configured " 00415 "for the user"); 00416 eap_gpsk_state(data, FAILURE); 00417 return; 00418 } 00419 00420 if (eap_gpsk_derive_keys(sm->user->password, sm->user->password_len, 00421 data->vendor, data->specifier, 00422 data->rand_peer, data->rand_server, 00423 data->id_peer, data->id_peer_len, 00424 data->id_server, data->id_server_len, 00425 data->msk, data->emsk, 00426 data->sk, &data->sk_len, 00427 data->pk, &data->pk_len) < 0) { 00428 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to derive keys"); 00429 eap_gpsk_state(data, FAILURE); 00430 return; 00431 } 00432 00433 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 00434 if (end - pos < (int) miclen) { 00435 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 00436 "(left=%lu miclen=%lu)", 00437 (unsigned long) (end - pos), 00438 (unsigned long) miclen); 00439 eap_gpsk_state(data, FAILURE); 00440 return; 00441 } 00442 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 00443 data->specifier, payload, pos - payload, mic) 00444 < 0) { 00445 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 00446 eap_gpsk_state(data, FAILURE); 00447 return; 00448 } 00449 if (os_memcmp(mic, pos, miclen) != 0) { 00450 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-2"); 00451 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 00452 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 00453 eap_gpsk_state(data, FAILURE); 00454 return; 00455 } 00456 pos += miclen; 00457 00458 if (pos != end) { 00459 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 00460 "data in the end of GPSK-2", 00461 (unsigned long) (end - pos)); 00462 } 00463 00464 eap_gpsk_state(data, GPSK_3); 00465 } 00466 00467 00468 static void eap_gpsk_process_gpsk_4(struct eap_sm *sm, 00469 struct eap_gpsk_data *data, 00470 const u8 *payload, size_t payloadlen) 00471 { 00472 const u8 *pos, *end; 00473 u16 alen; 00474 size_t miclen; 00475 u8 mic[EAP_GPSK_MAX_MIC_LEN]; 00476 00477 if (data->state != GPSK_3) 00478 return; 00479 00480 wpa_printf(MSG_DEBUG, "EAP-GPSK: Received Response/GPSK-4"); 00481 00482 pos = payload; 00483 end = payload + payloadlen; 00484 00485 if (end - pos < 2) { 00486 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00487 "PD_Payload_1 length"); 00488 eap_gpsk_state(data, FAILURE); 00489 return; 00490 } 00491 alen = WPA_GET_BE16(pos); 00492 pos += 2; 00493 if (end - pos < alen) { 00494 wpa_printf(MSG_DEBUG, "EAP-GPSK: Too short message for " 00495 "PD_Payload_1"); 00496 eap_gpsk_state(data, FAILURE); 00497 return; 00498 } 00499 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: PD_Payload_1", pos, alen); 00500 pos += alen; 00501 00502 miclen = eap_gpsk_mic_len(data->vendor, data->specifier); 00503 if (end - pos < (int) miclen) { 00504 wpa_printf(MSG_DEBUG, "EAP-GPSK: Message too short for MIC " 00505 "(left=%lu miclen=%lu)", 00506 (unsigned long) (end - pos), 00507 (unsigned long) miclen); 00508 eap_gpsk_state(data, FAILURE); 00509 return; 00510 } 00511 if (eap_gpsk_compute_mic(data->sk, data->sk_len, data->vendor, 00512 data->specifier, payload, pos - payload, mic) 00513 < 0) { 00514 wpa_printf(MSG_DEBUG, "EAP-GPSK: Failed to compute MIC"); 00515 eap_gpsk_state(data, FAILURE); 00516 return; 00517 } 00518 if (os_memcmp(mic, pos, miclen) != 0) { 00519 wpa_printf(MSG_INFO, "EAP-GPSK: Incorrect MIC in GPSK-4"); 00520 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Received MIC", pos, miclen); 00521 wpa_hexdump(MSG_DEBUG, "EAP-GPSK: Computed MIC", mic, miclen); 00522 eap_gpsk_state(data, FAILURE); 00523 return; 00524 } 00525 pos += miclen; 00526 00527 if (pos != end) { 00528 wpa_printf(MSG_DEBUG, "EAP-GPSK: Ignored %lu bytes of extra " 00529 "data in the end of GPSK-4", 00530 (unsigned long) (end - pos)); 00531 } 00532 00533 eap_gpsk_state(data, SUCCESS); 00534 } 00535 00536 00537 static void eap_gpsk_process(struct eap_sm *sm, void *priv, 00538 struct wpabuf *respData) 00539 { 00540 struct eap_gpsk_data *data = priv; 00541 const u8 *pos; 00542 size_t len; 00543 00544 pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_GPSK, respData, &len); 00545 if (pos == NULL || len < 1) 00546 return; 00547 00548 switch (*pos) { 00549 case EAP_GPSK_OPCODE_GPSK_2: 00550 eap_gpsk_process_gpsk_2(sm, data, pos + 1, len - 1); 00551 break; 00552 case EAP_GPSK_OPCODE_GPSK_4: 00553 eap_gpsk_process_gpsk_4(sm, data, pos + 1, len - 1); 00554 break; 00555 } 00556 } 00557 00558 00559 static Boolean eap_gpsk_isDone(struct eap_sm *sm, void *priv) 00560 { 00561 struct eap_gpsk_data *data = priv; 00562 return data->state == SUCCESS || data->state == FAILURE; 00563 } 00564 00565 00566 static u8 * eap_gpsk_getKey(struct eap_sm *sm, void *priv, size_t *len) 00567 { 00568 struct eap_gpsk_data *data = priv; 00569 u8 *key; 00570 00571 if (data->state != SUCCESS) 00572 return NULL; 00573 00574 key = os_malloc(EAP_MSK_LEN); 00575 if (key == NULL) 00576 return NULL; 00577 os_memcpy(key, data->msk, EAP_MSK_LEN); 00578 *len = EAP_MSK_LEN; 00579 00580 return key; 00581 } 00582 00583 00584 static u8 * eap_gpsk_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 00585 { 00586 struct eap_gpsk_data *data = priv; 00587 u8 *key; 00588 00589 if (data->state != SUCCESS) 00590 return NULL; 00591 00592 key = os_malloc(EAP_EMSK_LEN); 00593 if (key == NULL) 00594 return NULL; 00595 os_memcpy(key, data->emsk, EAP_EMSK_LEN); 00596 *len = EAP_EMSK_LEN; 00597 00598 return key; 00599 } 00600 00601 00602 static Boolean eap_gpsk_isSuccess(struct eap_sm *sm, void *priv) 00603 { 00604 struct eap_gpsk_data *data = priv; 00605 return data->state == SUCCESS; 00606 } 00607 00608 00609 int eap_server_gpsk_register(void) 00610 { 00611 struct eap_method *eap; 00612 int ret; 00613 00614 eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION, 00615 EAP_VENDOR_IETF, EAP_TYPE_GPSK, "GPSK"); 00616 if (eap == NULL) 00617 return -1; 00618 00619 eap->init = eap_gpsk_init; 00620 eap->reset = eap_gpsk_reset; 00621 eap->buildReq = eap_gpsk_buildReq; 00622 eap->check = eap_gpsk_check; 00623 eap->process = eap_gpsk_process; 00624 eap->isDone = eap_gpsk_isDone; 00625 eap->getKey = eap_gpsk_getKey; 00626 eap->isSuccess = eap_gpsk_isSuccess; 00627 eap->get_emsk = eap_gpsk_get_emsk; 00628 00629 ret = eap_server_method_register(eap); 00630 if (ret) 00631 eap_server_method_free(eap); 00632 return ret; 00633 }