eap_eke.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785
  1. /*
  2. * EAP peer method: EAP-EKE (RFC 6124)
  3. * Copyright (c) 2013, 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. #include "includes.h"
  9. #include "common.h"
  10. #include "crypto/random.h"
  11. #include "eap_peer/eap_i.h"
  12. #include "eap_common/eap_eke_common.h"
  13. struct eap_eke_data {
  14. enum {
  15. IDENTITY, COMMIT, CONFIRM, SUCCESS, FAILURE
  16. } state;
  17. u8 msk[EAP_MSK_LEN];
  18. u8 emsk[EAP_EMSK_LEN];
  19. u8 *peerid;
  20. size_t peerid_len;
  21. u8 *serverid;
  22. size_t serverid_len;
  23. u8 dh_priv[EAP_EKE_MAX_DH_LEN];
  24. struct eap_eke_session sess;
  25. u8 nonce_p[EAP_EKE_MAX_NONCE_LEN];
  26. u8 nonce_s[EAP_EKE_MAX_NONCE_LEN];
  27. struct wpabuf *msgs;
  28. u8 dhgroup; /* forced DH group or 0 to allow all supported */
  29. u8 encr; /* forced encryption algorithm or 0 to allow all supported */
  30. u8 prf; /* forced PRF or 0 to allow all supported */
  31. u8 mac; /* forced MAC or 0 to allow all supported */
  32. };
  33. static const char * eap_eke_state_txt(int state)
  34. {
  35. switch (state) {
  36. case IDENTITY:
  37. return "IDENTITY";
  38. case COMMIT:
  39. return "COMMIT";
  40. case CONFIRM:
  41. return "CONFIRM";
  42. case SUCCESS:
  43. return "SUCCESS";
  44. case FAILURE:
  45. return "FAILURE";
  46. default:
  47. return "?";
  48. }
  49. }
  50. static void eap_eke_state(struct eap_eke_data *data, int state)
  51. {
  52. wpa_printf(MSG_DEBUG, "EAP-EKE: %s -> %s",
  53. eap_eke_state_txt(data->state), eap_eke_state_txt(state));
  54. data->state = state;
  55. }
  56. static void eap_eke_deinit(struct eap_sm *sm, void *priv);
  57. static void * eap_eke_init(struct eap_sm *sm)
  58. {
  59. struct eap_eke_data *data;
  60. const u8 *identity, *password;
  61. size_t identity_len, password_len;
  62. const char *phase1;
  63. password = eap_get_config_password(sm, &password_len);
  64. if (!password) {
  65. wpa_printf(MSG_INFO, "EAP-EKE: No password configured");
  66. return NULL;
  67. }
  68. data = os_zalloc(sizeof(*data));
  69. if (data == NULL)
  70. return NULL;
  71. eap_eke_state(data, IDENTITY);
  72. identity = eap_get_config_identity(sm, &identity_len);
  73. if (identity) {
  74. data->peerid = os_memdup(identity, identity_len);
  75. if (data->peerid == NULL) {
  76. eap_eke_deinit(sm, data);
  77. return NULL;
  78. }
  79. data->peerid_len = identity_len;
  80. }
  81. phase1 = eap_get_config_phase1(sm);
  82. if (phase1) {
  83. const char *pos;
  84. pos = os_strstr(phase1, "dhgroup=");
  85. if (pos) {
  86. data->dhgroup = atoi(pos + 8);
  87. wpa_printf(MSG_DEBUG, "EAP-EKE: Forced dhgroup %u",
  88. data->dhgroup);
  89. }
  90. pos = os_strstr(phase1, "encr=");
  91. if (pos) {
  92. data->encr = atoi(pos + 5);
  93. wpa_printf(MSG_DEBUG, "EAP-EKE: Forced encr %u",
  94. data->encr);
  95. }
  96. pos = os_strstr(phase1, "prf=");
  97. if (pos) {
  98. data->prf = atoi(pos + 4);
  99. wpa_printf(MSG_DEBUG, "EAP-EKE: Forced prf %u",
  100. data->prf);
  101. }
  102. pos = os_strstr(phase1, "mac=");
  103. if (pos) {
  104. data->mac = atoi(pos + 4);
  105. wpa_printf(MSG_DEBUG, "EAP-EKE: Forced mac %u",
  106. data->mac);
  107. }
  108. }
  109. return data;
  110. }
  111. static void eap_eke_deinit(struct eap_sm *sm, void *priv)
  112. {
  113. struct eap_eke_data *data = priv;
  114. eap_eke_session_clean(&data->sess);
  115. os_free(data->serverid);
  116. os_free(data->peerid);
  117. wpabuf_free(data->msgs);
  118. bin_clear_free(data, sizeof(*data));
  119. }
  120. static struct wpabuf * eap_eke_build_msg(struct eap_eke_data *data, int id,
  121. size_t length, u8 eke_exch)
  122. {
  123. struct wpabuf *msg;
  124. size_t plen;
  125. plen = 1 + length;
  126. msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_EKE, plen,
  127. EAP_CODE_RESPONSE, id);
  128. if (msg == NULL) {
  129. wpa_printf(MSG_ERROR, "EAP-EKE: Failed to allocate memory");
  130. return NULL;
  131. }
  132. wpabuf_put_u8(msg, eke_exch);
  133. return msg;
  134. }
  135. static int eap_eke_supp_dhgroup(u8 dhgroup)
  136. {
  137. return dhgroup == EAP_EKE_DHGROUP_EKE_2 ||
  138. dhgroup == EAP_EKE_DHGROUP_EKE_5 ||
  139. dhgroup == EAP_EKE_DHGROUP_EKE_14 ||
  140. dhgroup == EAP_EKE_DHGROUP_EKE_15 ||
  141. dhgroup == EAP_EKE_DHGROUP_EKE_16;
  142. }
  143. static int eap_eke_supp_encr(u8 encr)
  144. {
  145. return encr == EAP_EKE_ENCR_AES128_CBC;
  146. }
  147. static int eap_eke_supp_prf(u8 prf)
  148. {
  149. return prf == EAP_EKE_PRF_HMAC_SHA1 ||
  150. prf == EAP_EKE_PRF_HMAC_SHA2_256;
  151. }
  152. static int eap_eke_supp_mac(u8 mac)
  153. {
  154. return mac == EAP_EKE_MAC_HMAC_SHA1 ||
  155. mac == EAP_EKE_MAC_HMAC_SHA2_256;
  156. }
  157. static struct wpabuf * eap_eke_build_fail(struct eap_eke_data *data,
  158. struct eap_method_ret *ret,
  159. u8 id, u32 failure_code)
  160. {
  161. struct wpabuf *resp;
  162. wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Failure/Response - code=0x%x",
  163. failure_code);
  164. resp = eap_eke_build_msg(data, id, 4, EAP_EKE_FAILURE);
  165. if (resp)
  166. wpabuf_put_be32(resp, failure_code);
  167. os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
  168. eap_eke_session_clean(&data->sess);
  169. eap_eke_state(data, FAILURE);
  170. ret->methodState = METHOD_DONE;
  171. ret->decision = DECISION_FAIL;
  172. ret->allowNotifications = FALSE;
  173. return resp;
  174. }
  175. static struct wpabuf * eap_eke_process_id(struct eap_eke_data *data,
  176. struct eap_method_ret *ret,
  177. const struct wpabuf *reqData,
  178. const u8 *payload,
  179. size_t payload_len)
  180. {
  181. struct wpabuf *resp;
  182. unsigned num_prop, i;
  183. const u8 *pos, *end;
  184. const u8 *prop = NULL;
  185. u8 idtype;
  186. u8 id = eap_get_id(reqData);
  187. if (data->state != IDENTITY) {
  188. return eap_eke_build_fail(data, ret, id,
  189. EAP_EKE_FAIL_PROTO_ERROR);
  190. }
  191. wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-ID/Request");
  192. if (payload_len < 2 + 4) {
  193. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data");
  194. return eap_eke_build_fail(data, ret, id,
  195. EAP_EKE_FAIL_PROTO_ERROR);
  196. }
  197. pos = payload;
  198. end = payload + payload_len;
  199. num_prop = *pos++;
  200. pos++; /* Ignore Reserved field */
  201. if (pos + num_prop * 4 > end) {
  202. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data (num_prop=%u)",
  203. num_prop);
  204. return eap_eke_build_fail(data, ret, id,
  205. EAP_EKE_FAIL_PROTO_ERROR);
  206. }
  207. for (i = 0; i < num_prop; i++) {
  208. const u8 *tmp = pos;
  209. wpa_printf(MSG_DEBUG, "EAP-EKE: Proposal #%u: dh=%u encr=%u prf=%u mac=%u",
  210. i, pos[0], pos[1], pos[2], pos[3]);
  211. pos += 4;
  212. if ((data->dhgroup && data->dhgroup != *tmp) ||
  213. !eap_eke_supp_dhgroup(*tmp))
  214. continue;
  215. tmp++;
  216. if ((data->encr && data->encr != *tmp) ||
  217. !eap_eke_supp_encr(*tmp))
  218. continue;
  219. tmp++;
  220. if ((data->prf && data->prf != *tmp) ||
  221. !eap_eke_supp_prf(*tmp))
  222. continue;
  223. tmp++;
  224. if ((data->mac && data->mac != *tmp) ||
  225. !eap_eke_supp_mac(*tmp))
  226. continue;
  227. prop = tmp - 3;
  228. if (eap_eke_session_init(&data->sess, prop[0], prop[1], prop[2],
  229. prop[3]) < 0) {
  230. prop = NULL;
  231. continue;
  232. }
  233. wpa_printf(MSG_DEBUG, "EAP-EKE: Selected proposal");
  234. break;
  235. }
  236. if (prop == NULL) {
  237. wpa_printf(MSG_DEBUG, "EAP-EKE: No acceptable proposal found");
  238. return eap_eke_build_fail(data, ret, id,
  239. EAP_EKE_FAIL_NO_PROPOSAL_CHOSEN);
  240. }
  241. pos += (num_prop - i - 1) * 4;
  242. if (pos == end) {
  243. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short ID/Request Data to include IDType/Identity");
  244. return eap_eke_build_fail(data, ret, id,
  245. EAP_EKE_FAIL_PROTO_ERROR);
  246. }
  247. idtype = *pos++;
  248. wpa_printf(MSG_DEBUG, "EAP-EKE: Server IDType %u", idtype);
  249. wpa_hexdump_ascii(MSG_DEBUG, "EAP-EKE: Server Identity",
  250. pos, end - pos);
  251. os_free(data->serverid);
  252. data->serverid = os_memdup(pos, end - pos);
  253. if (data->serverid == NULL) {
  254. return eap_eke_build_fail(data, ret, id,
  255. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  256. }
  257. data->serverid_len = end - pos;
  258. wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-ID/Response");
  259. resp = eap_eke_build_msg(data, id,
  260. 2 + 4 + 1 + data->peerid_len,
  261. EAP_EKE_ID);
  262. if (resp == NULL) {
  263. return eap_eke_build_fail(data, ret, id,
  264. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  265. }
  266. wpabuf_put_u8(resp, 1); /* NumProposals */
  267. wpabuf_put_u8(resp, 0); /* Reserved */
  268. wpabuf_put_data(resp, prop, 4); /* Selected Proposal */
  269. wpabuf_put_u8(resp, EAP_EKE_ID_NAI);
  270. if (data->peerid)
  271. wpabuf_put_data(resp, data->peerid, data->peerid_len);
  272. wpabuf_free(data->msgs);
  273. data->msgs = wpabuf_alloc(wpabuf_len(reqData) + wpabuf_len(resp));
  274. if (data->msgs == NULL) {
  275. wpabuf_free(resp);
  276. return eap_eke_build_fail(data, ret, id,
  277. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  278. }
  279. wpabuf_put_buf(data->msgs, reqData);
  280. wpabuf_put_buf(data->msgs, resp);
  281. eap_eke_state(data, COMMIT);
  282. return resp;
  283. }
  284. static struct wpabuf * eap_eke_process_commit(struct eap_sm *sm,
  285. struct eap_eke_data *data,
  286. struct eap_method_ret *ret,
  287. const struct wpabuf *reqData,
  288. const u8 *payload,
  289. size_t payload_len)
  290. {
  291. struct wpabuf *resp;
  292. const u8 *pos, *end, *dhcomp;
  293. size_t prot_len;
  294. u8 *rpos;
  295. u8 key[EAP_EKE_MAX_KEY_LEN];
  296. u8 pub[EAP_EKE_MAX_DH_LEN];
  297. const u8 *password;
  298. size_t password_len;
  299. u8 id = eap_get_id(reqData);
  300. if (data->state != COMMIT) {
  301. wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Commit/Request received in unexpected state (%d)", data->state);
  302. return eap_eke_build_fail(data, ret, id,
  303. EAP_EKE_FAIL_PROTO_ERROR);
  304. }
  305. wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Commit/Request");
  306. password = eap_get_config_password(sm, &password_len);
  307. if (password == NULL) {
  308. wpa_printf(MSG_INFO, "EAP-EKE: No password configured!");
  309. return eap_eke_build_fail(data, ret, id,
  310. EAP_EKE_FAIL_PASSWD_NOT_FOUND);
  311. }
  312. pos = payload;
  313. end = payload + payload_len;
  314. if (pos + data->sess.dhcomp_len > end) {
  315. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Commit");
  316. return eap_eke_build_fail(data, ret, id,
  317. EAP_EKE_FAIL_PROTO_ERROR);
  318. }
  319. wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_S",
  320. pos, data->sess.dhcomp_len);
  321. dhcomp = pos;
  322. pos += data->sess.dhcomp_len;
  323. wpa_hexdump(MSG_DEBUG, "EAP-EKE: CBValue", pos, end - pos);
  324. /*
  325. * temp = prf(0+, password)
  326. * key = prf+(temp, ID_S | ID_P)
  327. */
  328. if (eap_eke_derive_key(&data->sess, password, password_len,
  329. data->serverid, data->serverid_len,
  330. data->peerid, data->peerid_len, key) < 0) {
  331. wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive key");
  332. return eap_eke_build_fail(data, ret, id,
  333. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  334. }
  335. /*
  336. * y_p = g ^ x_p (mod p)
  337. * x_p = random number 2 .. p-1
  338. */
  339. if (eap_eke_dh_init(data->sess.dhgroup, data->dh_priv, pub) < 0) {
  340. wpa_printf(MSG_INFO, "EAP-EKE: Failed to initialize DH");
  341. os_memset(key, 0, sizeof(key));
  342. return eap_eke_build_fail(data, ret, id,
  343. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  344. }
  345. if (eap_eke_shared_secret(&data->sess, key, data->dh_priv, dhcomp) < 0)
  346. {
  347. wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive shared secret");
  348. os_memset(key, 0, sizeof(key));
  349. return eap_eke_build_fail(data, ret, id,
  350. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  351. }
  352. if (eap_eke_derive_ke_ki(&data->sess,
  353. data->serverid, data->serverid_len,
  354. data->peerid, data->peerid_len) < 0) {
  355. wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive Ke/Ki");
  356. os_memset(key, 0, sizeof(key));
  357. return eap_eke_build_fail(data, ret, id,
  358. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  359. }
  360. wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Commit/Response");
  361. resp = eap_eke_build_msg(data, id,
  362. data->sess.dhcomp_len + data->sess.pnonce_len,
  363. EAP_EKE_COMMIT);
  364. if (resp == NULL) {
  365. os_memset(key, 0, sizeof(key));
  366. return eap_eke_build_fail(data, ret, id,
  367. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  368. }
  369. /* DHComponent_P = Encr(key, y_p) */
  370. rpos = wpabuf_put(resp, data->sess.dhcomp_len);
  371. if (eap_eke_dhcomp(&data->sess, key, pub, rpos) < 0) {
  372. wpabuf_free(resp);
  373. wpa_printf(MSG_INFO, "EAP-EKE: Failed to build DHComponent_P");
  374. os_memset(key, 0, sizeof(key));
  375. return eap_eke_build_fail(data, ret, id,
  376. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  377. }
  378. os_memset(key, 0, sizeof(key));
  379. wpa_hexdump(MSG_DEBUG, "EAP-EKE: DHComponent_P",
  380. rpos, data->sess.dhcomp_len);
  381. if (random_get_bytes(data->nonce_p, data->sess.nonce_len)) {
  382. wpabuf_free(resp);
  383. return eap_eke_build_fail(data, ret, id,
  384. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  385. }
  386. wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_P",
  387. data->nonce_p, data->sess.nonce_len);
  388. prot_len = wpabuf_tailroom(resp);
  389. if (eap_eke_prot(&data->sess, data->nonce_p, data->sess.nonce_len,
  390. wpabuf_put(resp, 0), &prot_len) < 0) {
  391. wpabuf_free(resp);
  392. return eap_eke_build_fail(data, ret, id,
  393. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  394. }
  395. wpa_hexdump(MSG_DEBUG, "EAP-EKE: PNonce_P",
  396. wpabuf_put(resp, 0), prot_len);
  397. wpabuf_put(resp, prot_len);
  398. /* TODO: CBValue */
  399. if (wpabuf_resize(&data->msgs, wpabuf_len(reqData) + wpabuf_len(resp))
  400. < 0) {
  401. wpabuf_free(resp);
  402. return eap_eke_build_fail(data, ret, id,
  403. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  404. }
  405. wpabuf_put_buf(data->msgs, reqData);
  406. wpabuf_put_buf(data->msgs, resp);
  407. eap_eke_state(data, CONFIRM);
  408. return resp;
  409. }
  410. static struct wpabuf * eap_eke_process_confirm(struct eap_eke_data *data,
  411. struct eap_method_ret *ret,
  412. const struct wpabuf *reqData,
  413. const u8 *payload,
  414. size_t payload_len)
  415. {
  416. struct wpabuf *resp;
  417. const u8 *pos, *end;
  418. size_t prot_len;
  419. u8 nonces[2 * EAP_EKE_MAX_NONCE_LEN];
  420. u8 auth_s[EAP_EKE_MAX_HASH_LEN];
  421. size_t decrypt_len;
  422. u8 *auth;
  423. u8 id = eap_get_id(reqData);
  424. if (data->state != CONFIRM) {
  425. wpa_printf(MSG_DEBUG, "EAP-EKE: EAP-EKE-Confirm/Request received in unexpected state (%d)",
  426. data->state);
  427. return eap_eke_build_fail(data, ret, id,
  428. EAP_EKE_FAIL_PROTO_ERROR);
  429. }
  430. wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Confirm/Request");
  431. pos = payload;
  432. end = payload + payload_len;
  433. if (pos + data->sess.pnonce_ps_len + data->sess.prf_len > end) {
  434. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Confirm");
  435. return eap_eke_build_fail(data, ret, id,
  436. EAP_EKE_FAIL_PROTO_ERROR);
  437. }
  438. decrypt_len = sizeof(nonces);
  439. if (eap_eke_decrypt_prot(&data->sess, pos, data->sess.pnonce_ps_len,
  440. nonces, &decrypt_len) < 0) {
  441. wpa_printf(MSG_INFO, "EAP-EKE: Failed to decrypt PNonce_PS");
  442. return eap_eke_build_fail(data, ret, id,
  443. EAP_EKE_FAIL_AUTHENTICATION_FAIL);
  444. }
  445. if (decrypt_len != (size_t) 2 * data->sess.nonce_len) {
  446. wpa_printf(MSG_INFO, "EAP-EKE: PNonce_PS protected data length does not match length of Nonce_P and Nonce_S");
  447. return eap_eke_build_fail(data, ret, id,
  448. EAP_EKE_FAIL_AUTHENTICATION_FAIL);
  449. }
  450. wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Received Nonce_P | Nonce_S",
  451. nonces, 2 * data->sess.nonce_len);
  452. if (os_memcmp(data->nonce_p, nonces, data->sess.nonce_len) != 0) {
  453. wpa_printf(MSG_INFO, "EAP-EKE: Received Nonce_P does not match transmitted Nonce_P");
  454. return eap_eke_build_fail(data, ret, id,
  455. EAP_EKE_FAIL_AUTHENTICATION_FAIL);
  456. }
  457. os_memcpy(data->nonce_s, nonces + data->sess.nonce_len,
  458. data->sess.nonce_len);
  459. wpa_hexdump_key(MSG_DEBUG, "EAP-EKE: Nonce_S",
  460. data->nonce_s, data->sess.nonce_len);
  461. if (eap_eke_derive_ka(&data->sess, data->serverid, data->serverid_len,
  462. data->peerid, data->peerid_len,
  463. data->nonce_p, data->nonce_s) < 0) {
  464. return eap_eke_build_fail(data, ret, id,
  465. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  466. }
  467. if (eap_eke_auth(&data->sess, "EAP-EKE server", data->msgs, auth_s) < 0)
  468. {
  469. return eap_eke_build_fail(data, ret, id,
  470. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  471. }
  472. wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_S", auth_s, data->sess.prf_len);
  473. if (os_memcmp_const(auth_s, pos + data->sess.pnonce_ps_len,
  474. data->sess.prf_len) != 0) {
  475. wpa_printf(MSG_INFO, "EAP-EKE: Auth_S does not match");
  476. return eap_eke_build_fail(data, ret, id,
  477. EAP_EKE_FAIL_AUTHENTICATION_FAIL);
  478. }
  479. wpa_printf(MSG_DEBUG, "EAP-EKE: Sending EAP-EKE-Confirm/Response");
  480. resp = eap_eke_build_msg(data, id,
  481. data->sess.pnonce_len + data->sess.prf_len,
  482. EAP_EKE_CONFIRM);
  483. if (resp == NULL) {
  484. return eap_eke_build_fail(data, ret, id,
  485. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  486. }
  487. prot_len = wpabuf_tailroom(resp);
  488. if (eap_eke_prot(&data->sess, data->nonce_s, data->sess.nonce_len,
  489. wpabuf_put(resp, 0), &prot_len) < 0) {
  490. wpabuf_free(resp);
  491. return eap_eke_build_fail(data, ret, id,
  492. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  493. }
  494. wpabuf_put(resp, prot_len);
  495. auth = wpabuf_put(resp, data->sess.prf_len);
  496. if (eap_eke_auth(&data->sess, "EAP-EKE peer", data->msgs, auth) < 0) {
  497. wpabuf_free(resp);
  498. return eap_eke_build_fail(data, ret, id,
  499. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  500. }
  501. wpa_hexdump(MSG_DEBUG, "EAP-EKE: Auth_P", auth, data->sess.prf_len);
  502. if (eap_eke_derive_msk(&data->sess, data->serverid, data->serverid_len,
  503. data->peerid, data->peerid_len,
  504. data->nonce_s, data->nonce_p,
  505. data->msk, data->emsk) < 0) {
  506. wpa_printf(MSG_INFO, "EAP-EKE: Failed to derive MSK/EMSK");
  507. wpabuf_free(resp);
  508. return eap_eke_build_fail(data, ret, id,
  509. EAP_EKE_FAIL_PRIVATE_INTERNAL_ERROR);
  510. }
  511. os_memset(data->dh_priv, 0, sizeof(data->dh_priv));
  512. eap_eke_session_clean(&data->sess);
  513. eap_eke_state(data, SUCCESS);
  514. ret->methodState = METHOD_MAY_CONT;
  515. ret->decision = DECISION_COND_SUCC;
  516. ret->allowNotifications = FALSE;
  517. return resp;
  518. }
  519. static struct wpabuf * eap_eke_process_failure(struct eap_eke_data *data,
  520. struct eap_method_ret *ret,
  521. const struct wpabuf *reqData,
  522. const u8 *payload,
  523. size_t payload_len)
  524. {
  525. wpa_printf(MSG_DEBUG, "EAP-EKE: Received EAP-EKE-Failure/Request");
  526. if (payload_len < 4) {
  527. wpa_printf(MSG_DEBUG, "EAP-EKE: Too short EAP-EKE-Failure");
  528. } else {
  529. u32 code;
  530. code = WPA_GET_BE32(payload);
  531. wpa_printf(MSG_INFO, "EAP-EKE: Failure-Code 0x%x", code);
  532. }
  533. return eap_eke_build_fail(data, ret, eap_get_id(reqData),
  534. EAP_EKE_FAIL_NO_ERROR);
  535. }
  536. static struct wpabuf * eap_eke_process(struct eap_sm *sm, void *priv,
  537. struct eap_method_ret *ret,
  538. const struct wpabuf *reqData)
  539. {
  540. struct eap_eke_data *data = priv;
  541. struct wpabuf *resp;
  542. const u8 *pos, *end;
  543. size_t len;
  544. u8 eke_exch;
  545. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_EKE, reqData, &len);
  546. if (pos == NULL || len < 1) {
  547. ret->ignore = TRUE;
  548. return NULL;
  549. }
  550. end = pos + len;
  551. eke_exch = *pos++;
  552. wpa_printf(MSG_DEBUG, "EAP-EKE: Received frame: exch %d", eke_exch);
  553. wpa_hexdump(MSG_DEBUG, "EAP-EKE: Received Data", pos, end - pos);
  554. ret->ignore = FALSE;
  555. ret->methodState = METHOD_MAY_CONT;
  556. ret->decision = DECISION_FAIL;
  557. ret->allowNotifications = TRUE;
  558. switch (eke_exch) {
  559. case EAP_EKE_ID:
  560. resp = eap_eke_process_id(data, ret, reqData, pos, end - pos);
  561. break;
  562. case EAP_EKE_COMMIT:
  563. resp = eap_eke_process_commit(sm, data, ret, reqData,
  564. pos, end - pos);
  565. break;
  566. case EAP_EKE_CONFIRM:
  567. resp = eap_eke_process_confirm(data, ret, reqData,
  568. pos, end - pos);
  569. break;
  570. case EAP_EKE_FAILURE:
  571. resp = eap_eke_process_failure(data, ret, reqData,
  572. pos, end - pos);
  573. break;
  574. default:
  575. wpa_printf(MSG_DEBUG, "EAP-EKE: Ignoring message with unknown EKE-Exch %d", eke_exch);
  576. ret->ignore = TRUE;
  577. return NULL;
  578. }
  579. if (ret->methodState == METHOD_DONE)
  580. ret->allowNotifications = FALSE;
  581. return resp;
  582. }
  583. static Boolean eap_eke_isKeyAvailable(struct eap_sm *sm, void *priv)
  584. {
  585. struct eap_eke_data *data = priv;
  586. return data->state == SUCCESS;
  587. }
  588. static u8 * eap_eke_getKey(struct eap_sm *sm, void *priv, size_t *len)
  589. {
  590. struct eap_eke_data *data = priv;
  591. u8 *key;
  592. if (data->state != SUCCESS)
  593. return NULL;
  594. key = os_memdup(data->msk, EAP_MSK_LEN);
  595. if (key == NULL)
  596. return NULL;
  597. *len = EAP_MSK_LEN;
  598. return key;
  599. }
  600. static u8 * eap_eke_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
  601. {
  602. struct eap_eke_data *data = priv;
  603. u8 *key;
  604. if (data->state != SUCCESS)
  605. return NULL;
  606. key = os_memdup(data->emsk, EAP_EMSK_LEN);
  607. if (key == NULL)
  608. return NULL;
  609. *len = EAP_EMSK_LEN;
  610. return key;
  611. }
  612. static u8 * eap_eke_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
  613. {
  614. struct eap_eke_data *data = priv;
  615. u8 *sid;
  616. size_t sid_len;
  617. if (data->state != SUCCESS)
  618. return NULL;
  619. sid_len = 1 + 2 * data->sess.nonce_len;
  620. sid = os_malloc(sid_len);
  621. if (sid == NULL)
  622. return NULL;
  623. sid[0] = EAP_TYPE_EKE;
  624. os_memcpy(sid + 1, data->nonce_p, data->sess.nonce_len);
  625. os_memcpy(sid + 1 + data->sess.nonce_len, data->nonce_s,
  626. data->sess.nonce_len);
  627. *len = sid_len;
  628. return sid;
  629. }
  630. int eap_peer_eke_register(void)
  631. {
  632. struct eap_method *eap;
  633. eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
  634. EAP_VENDOR_IETF, EAP_TYPE_EKE, "EKE");
  635. if (eap == NULL)
  636. return -1;
  637. eap->init = eap_eke_init;
  638. eap->deinit = eap_eke_deinit;
  639. eap->process = eap_eke_process;
  640. eap->isKeyAvailable = eap_eke_isKeyAvailable;
  641. eap->getKey = eap_eke_getKey;
  642. eap->get_emsk = eap_eke_get_emsk;
  643. eap->getSessionId = eap_eke_get_session_id;
  644. return eap_peer_method_register(eap);
  645. }