eap_gpsk.c 16 KB

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