eap_server_eke.c 21 KB

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