eap_psk.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. /*
  2. * EAP peer method: EAP-PSK (RFC 4764)
  3. * Copyright (c) 2004-2008, 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. * Note: EAP-PSK is an EAP authentication method and as such, completely
  15. * different from WPA-PSK. This file is not needed for WPA-PSK functionality.
  16. */
  17. #include "includes.h"
  18. #include "common.h"
  19. #include "eap_peer/eap_i.h"
  20. #include "aes_wrap.h"
  21. #include "eap_common/eap_psk_common.h"
  22. struct eap_psk_data {
  23. enum { PSK_INIT, PSK_MAC_SENT, PSK_DONE } state;
  24. u8 rand_p[EAP_PSK_RAND_LEN];
  25. u8 ak[EAP_PSK_AK_LEN], kdk[EAP_PSK_KDK_LEN], tek[EAP_PSK_TEK_LEN];
  26. u8 *id_s, *id_p;
  27. size_t id_s_len, id_p_len;
  28. u8 msk[EAP_MSK_LEN];
  29. u8 emsk[EAP_EMSK_LEN];
  30. };
  31. static void * eap_psk_init(struct eap_sm *sm)
  32. {
  33. struct eap_psk_data *data;
  34. const u8 *identity, *password;
  35. size_t identity_len, password_len;
  36. password = eap_get_config_password(sm, &password_len);
  37. if (!password || password_len != 16) {
  38. wpa_printf(MSG_INFO, "EAP-PSK: 16-octet pre-shared key not "
  39. "configured");
  40. return NULL;
  41. }
  42. data = os_zalloc(sizeof(*data));
  43. if (data == NULL)
  44. return NULL;
  45. if (eap_psk_key_setup(password, data->ak, data->kdk)) {
  46. os_free(data);
  47. return NULL;
  48. }
  49. wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: AK", data->ak, EAP_PSK_AK_LEN);
  50. wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: KDK", data->kdk, EAP_PSK_KDK_LEN);
  51. data->state = PSK_INIT;
  52. identity = eap_get_config_identity(sm, &identity_len);
  53. if (identity) {
  54. data->id_p = os_malloc(identity_len);
  55. if (data->id_p)
  56. os_memcpy(data->id_p, identity, identity_len);
  57. data->id_p_len = identity_len;
  58. }
  59. if (data->id_p == NULL) {
  60. wpa_printf(MSG_INFO, "EAP-PSK: could not get own identity");
  61. os_free(data);
  62. return NULL;
  63. }
  64. return data;
  65. }
  66. static void eap_psk_deinit(struct eap_sm *sm, void *priv)
  67. {
  68. struct eap_psk_data *data = priv;
  69. os_free(data->id_s);
  70. os_free(data->id_p);
  71. os_free(data);
  72. }
  73. static struct wpabuf * eap_psk_process_1(struct eap_psk_data *data,
  74. struct eap_method_ret *ret,
  75. const struct wpabuf *reqData)
  76. {
  77. const struct eap_psk_hdr_1 *hdr1;
  78. struct eap_psk_hdr_2 *hdr2;
  79. struct wpabuf *resp;
  80. u8 *buf, *pos;
  81. size_t buflen, len;
  82. const u8 *cpos;
  83. wpa_printf(MSG_DEBUG, "EAP-PSK: in INIT state");
  84. cpos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len);
  85. hdr1 = (const struct eap_psk_hdr_1 *) cpos;
  86. if (cpos == NULL || len < sizeof(*hdr1)) {
  87. wpa_printf(MSG_INFO, "EAP-PSK: Invalid first message "
  88. "length (%lu; expected %lu or more)",
  89. (unsigned long) len,
  90. (unsigned long) sizeof(*hdr1));
  91. ret->ignore = TRUE;
  92. return NULL;
  93. }
  94. wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr1->flags);
  95. if (EAP_PSK_FLAGS_GET_T(hdr1->flags) != 0) {
  96. wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 0)",
  97. EAP_PSK_FLAGS_GET_T(hdr1->flags));
  98. ret->methodState = METHOD_DONE;
  99. ret->decision = DECISION_FAIL;
  100. return NULL;
  101. }
  102. wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr1->rand_s,
  103. EAP_PSK_RAND_LEN);
  104. os_free(data->id_s);
  105. data->id_s_len = len - sizeof(*hdr1);
  106. data->id_s = os_malloc(data->id_s_len);
  107. if (data->id_s == NULL) {
  108. wpa_printf(MSG_ERROR, "EAP-PSK: Failed to allocate memory for "
  109. "ID_S (len=%lu)", (unsigned long) data->id_s_len);
  110. ret->ignore = TRUE;
  111. return NULL;
  112. }
  113. os_memcpy(data->id_s, (u8 *) (hdr1 + 1), data->id_s_len);
  114. wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_S",
  115. data->id_s, data->id_s_len);
  116. if (os_get_random(data->rand_p, EAP_PSK_RAND_LEN)) {
  117. wpa_printf(MSG_ERROR, "EAP-PSK: Failed to get random data");
  118. ret->ignore = TRUE;
  119. return NULL;
  120. }
  121. resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK,
  122. sizeof(*hdr2) + data->id_p_len, EAP_CODE_RESPONSE,
  123. eap_get_id(reqData));
  124. if (resp == NULL)
  125. return NULL;
  126. hdr2 = wpabuf_put(resp, sizeof(*hdr2));
  127. hdr2->flags = EAP_PSK_FLAGS_SET_T(1); /* T=1 */
  128. os_memcpy(hdr2->rand_s, hdr1->rand_s, EAP_PSK_RAND_LEN);
  129. os_memcpy(hdr2->rand_p, data->rand_p, EAP_PSK_RAND_LEN);
  130. wpabuf_put_data(resp, data->id_p, data->id_p_len);
  131. /* MAC_P = OMAC1-AES-128(AK, ID_P||ID_S||RAND_S||RAND_P) */
  132. buflen = data->id_p_len + data->id_s_len + 2 * EAP_PSK_RAND_LEN;
  133. buf = os_malloc(buflen);
  134. if (buf == NULL) {
  135. wpabuf_free(resp);
  136. return NULL;
  137. }
  138. os_memcpy(buf, data->id_p, data->id_p_len);
  139. pos = buf + data->id_p_len;
  140. os_memcpy(pos, data->id_s, data->id_s_len);
  141. pos += data->id_s_len;
  142. os_memcpy(pos, hdr1->rand_s, EAP_PSK_RAND_LEN);
  143. pos += EAP_PSK_RAND_LEN;
  144. os_memcpy(pos, data->rand_p, EAP_PSK_RAND_LEN);
  145. if (omac1_aes_128(data->ak, buf, buflen, hdr2->mac_p)) {
  146. os_free(buf);
  147. wpabuf_free(resp);
  148. return NULL;
  149. }
  150. os_free(buf);
  151. wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_P", hdr2->rand_p,
  152. EAP_PSK_RAND_LEN);
  153. wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_P", hdr2->mac_p, EAP_PSK_MAC_LEN);
  154. wpa_hexdump_ascii(MSG_DEBUG, "EAP-PSK: ID_P",
  155. data->id_p, data->id_p_len);
  156. data->state = PSK_MAC_SENT;
  157. return resp;
  158. }
  159. static struct wpabuf * eap_psk_process_3(struct eap_psk_data *data,
  160. struct eap_method_ret *ret,
  161. const struct wpabuf *reqData)
  162. {
  163. const struct eap_psk_hdr_3 *hdr3;
  164. struct eap_psk_hdr_4 *hdr4;
  165. struct wpabuf *resp;
  166. u8 *buf, *rpchannel, nonce[16], *decrypted;
  167. const u8 *pchannel, *tag, *msg;
  168. u8 mac[EAP_PSK_MAC_LEN];
  169. size_t buflen, left, data_len, len, plen;
  170. int failed = 0;
  171. const u8 *pos;
  172. wpa_printf(MSG_DEBUG, "EAP-PSK: in MAC_SENT state");
  173. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK,
  174. reqData, &len);
  175. hdr3 = (const struct eap_psk_hdr_3 *) pos;
  176. if (pos == NULL || len < sizeof(*hdr3)) {
  177. wpa_printf(MSG_INFO, "EAP-PSK: Invalid third message "
  178. "length (%lu; expected %lu or more)",
  179. (unsigned long) len,
  180. (unsigned long) sizeof(*hdr3));
  181. ret->ignore = TRUE;
  182. return NULL;
  183. }
  184. left = len - sizeof(*hdr3);
  185. pchannel = (const u8 *) (hdr3 + 1);
  186. wpa_printf(MSG_DEBUG, "EAP-PSK: Flags=0x%x", hdr3->flags);
  187. if (EAP_PSK_FLAGS_GET_T(hdr3->flags) != 2) {
  188. wpa_printf(MSG_INFO, "EAP-PSK: Unexpected T=%d (expected 2)",
  189. EAP_PSK_FLAGS_GET_T(hdr3->flags));
  190. ret->methodState = METHOD_DONE;
  191. ret->decision = DECISION_FAIL;
  192. return NULL;
  193. }
  194. wpa_hexdump(MSG_DEBUG, "EAP-PSK: RAND_S", hdr3->rand_s,
  195. EAP_PSK_RAND_LEN);
  196. wpa_hexdump(MSG_DEBUG, "EAP-PSK: MAC_S", hdr3->mac_s, EAP_PSK_MAC_LEN);
  197. wpa_hexdump(MSG_DEBUG, "EAP-PSK: PCHANNEL", pchannel, left);
  198. if (left < 4 + 16 + 1) {
  199. wpa_printf(MSG_INFO, "EAP-PSK: Too short PCHANNEL data in "
  200. "third message (len=%lu, expected 21)",
  201. (unsigned long) left);
  202. ret->ignore = TRUE;
  203. return NULL;
  204. }
  205. /* MAC_S = OMAC1-AES-128(AK, ID_S||RAND_P) */
  206. buflen = data->id_s_len + EAP_PSK_RAND_LEN;
  207. buf = os_malloc(buflen);
  208. if (buf == NULL)
  209. return NULL;
  210. os_memcpy(buf, data->id_s, data->id_s_len);
  211. os_memcpy(buf + data->id_s_len, data->rand_p, EAP_PSK_RAND_LEN);
  212. if (omac1_aes_128(data->ak, buf, buflen, mac)) {
  213. os_free(buf);
  214. return NULL;
  215. }
  216. os_free(buf);
  217. if (os_memcmp(mac, hdr3->mac_s, EAP_PSK_MAC_LEN) != 0) {
  218. wpa_printf(MSG_WARNING, "EAP-PSK: Invalid MAC_S in third "
  219. "message");
  220. ret->methodState = METHOD_DONE;
  221. ret->decision = DECISION_FAIL;
  222. return NULL;
  223. }
  224. wpa_printf(MSG_DEBUG, "EAP-PSK: MAC_S verified successfully");
  225. if (eap_psk_derive_keys(data->kdk, data->rand_p, data->tek,
  226. data->msk, data->emsk)) {
  227. ret->methodState = METHOD_DONE;
  228. ret->decision = DECISION_FAIL;
  229. return NULL;
  230. }
  231. wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: TEK", data->tek, EAP_PSK_TEK_LEN);
  232. wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: MSK", data->msk, EAP_MSK_LEN);
  233. wpa_hexdump_key(MSG_DEBUG, "EAP-PSK: EMSK", data->emsk, EAP_EMSK_LEN);
  234. os_memset(nonce, 0, 12);
  235. os_memcpy(nonce + 12, pchannel, 4);
  236. pchannel += 4;
  237. left -= 4;
  238. tag = pchannel;
  239. pchannel += 16;
  240. left -= 16;
  241. msg = pchannel;
  242. wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - nonce",
  243. nonce, sizeof(nonce));
  244. wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - hdr",
  245. wpabuf_head(reqData), 5);
  246. wpa_hexdump(MSG_MSGDUMP, "EAP-PSK: PCHANNEL - cipher msg", msg, left);
  247. decrypted = os_malloc(left);
  248. if (decrypted == NULL) {
  249. ret->methodState = METHOD_DONE;
  250. ret->decision = DECISION_FAIL;
  251. return NULL;
  252. }
  253. os_memcpy(decrypted, msg, left);
  254. if (aes_128_eax_decrypt(data->tek, nonce, sizeof(nonce),
  255. wpabuf_head(reqData),
  256. sizeof(struct eap_hdr) + 1 +
  257. sizeof(*hdr3) - EAP_PSK_MAC_LEN, decrypted,
  258. left, tag)) {
  259. wpa_printf(MSG_WARNING, "EAP-PSK: PCHANNEL decryption failed");
  260. os_free(decrypted);
  261. return NULL;
  262. }
  263. wpa_hexdump(MSG_DEBUG, "EAP-PSK: Decrypted PCHANNEL message",
  264. decrypted, left);
  265. /* Verify R flag */
  266. switch (decrypted[0] >> 6) {
  267. case EAP_PSK_R_FLAG_CONT:
  268. wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - CONT - unsupported");
  269. failed = 1;
  270. break;
  271. case EAP_PSK_R_FLAG_DONE_SUCCESS:
  272. wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_SUCCESS");
  273. break;
  274. case EAP_PSK_R_FLAG_DONE_FAILURE:
  275. wpa_printf(MSG_DEBUG, "EAP-PSK: R flag - DONE_FAILURE");
  276. wpa_printf(MSG_INFO, "EAP-PSK: Authentication server rejected "
  277. "authentication");
  278. failed = 1;
  279. break;
  280. }
  281. data_len = 1;
  282. if ((decrypted[0] & EAP_PSK_E_FLAG) && left > 1)
  283. data_len++;
  284. plen = sizeof(*hdr4) + 4 + 16 + data_len;
  285. resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_PSK, plen,
  286. EAP_CODE_RESPONSE, eap_get_id(reqData));
  287. if (resp == NULL) {
  288. os_free(decrypted);
  289. return NULL;
  290. }
  291. hdr4 = wpabuf_put(resp, sizeof(*hdr4));
  292. hdr4->flags = EAP_PSK_FLAGS_SET_T(3); /* T=3 */
  293. os_memcpy(hdr4->rand_s, hdr3->rand_s, EAP_PSK_RAND_LEN);
  294. rpchannel = wpabuf_put(resp, 4 + 16 + data_len);
  295. /* nonce++ */
  296. inc_byte_array(nonce, sizeof(nonce));
  297. os_memcpy(rpchannel, nonce + 12, 4);
  298. if (decrypted[0] & EAP_PSK_E_FLAG) {
  299. wpa_printf(MSG_DEBUG, "EAP-PSK: Unsupported E (Ext) flag");
  300. failed = 1;
  301. rpchannel[4 + 16] = (EAP_PSK_R_FLAG_DONE_FAILURE << 6) |
  302. EAP_PSK_E_FLAG;
  303. if (left > 1) {
  304. /* Add empty EXT_Payload with same EXT_Type */
  305. rpchannel[4 + 16 + 1] = decrypted[1];
  306. }
  307. } else if (failed)
  308. rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_FAILURE << 6;
  309. else
  310. rpchannel[4 + 16] = EAP_PSK_R_FLAG_DONE_SUCCESS << 6;
  311. wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (plaintext)",
  312. rpchannel + 4 + 16, data_len);
  313. if (aes_128_eax_encrypt(data->tek, nonce, sizeof(nonce),
  314. wpabuf_head(resp),
  315. sizeof(struct eap_hdr) + 1 + sizeof(*hdr4),
  316. rpchannel + 4 + 16, data_len, rpchannel + 4)) {
  317. os_free(decrypted);
  318. wpabuf_free(resp);
  319. return NULL;
  320. }
  321. wpa_hexdump(MSG_DEBUG, "EAP-PSK: reply message (PCHANNEL)",
  322. rpchannel, 4 + 16 + data_len);
  323. wpa_printf(MSG_DEBUG, "EAP-PSK: Completed %ssuccessfully",
  324. failed ? "un" : "");
  325. data->state = PSK_DONE;
  326. ret->methodState = METHOD_DONE;
  327. ret->decision = failed ? DECISION_FAIL : DECISION_UNCOND_SUCC;
  328. os_free(decrypted);
  329. return resp;
  330. }
  331. static struct wpabuf * eap_psk_process(struct eap_sm *sm, void *priv,
  332. struct eap_method_ret *ret,
  333. const struct wpabuf *reqData)
  334. {
  335. struct eap_psk_data *data = priv;
  336. const u8 *pos;
  337. struct wpabuf *resp = NULL;
  338. size_t len;
  339. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_PSK, reqData, &len);
  340. if (pos == NULL) {
  341. ret->ignore = TRUE;
  342. return NULL;
  343. }
  344. ret->ignore = FALSE;
  345. ret->methodState = METHOD_MAY_CONT;
  346. ret->decision = DECISION_FAIL;
  347. ret->allowNotifications = TRUE;
  348. switch (data->state) {
  349. case PSK_INIT:
  350. resp = eap_psk_process_1(data, ret, reqData);
  351. break;
  352. case PSK_MAC_SENT:
  353. resp = eap_psk_process_3(data, ret, reqData);
  354. break;
  355. case PSK_DONE:
  356. wpa_printf(MSG_DEBUG, "EAP-PSK: in DONE state - ignore "
  357. "unexpected message");
  358. ret->ignore = TRUE;
  359. return NULL;
  360. }
  361. if (ret->methodState == METHOD_DONE) {
  362. ret->allowNotifications = FALSE;
  363. }
  364. return resp;
  365. }
  366. static Boolean eap_psk_isKeyAvailable(struct eap_sm *sm, void *priv)
  367. {
  368. struct eap_psk_data *data = priv;
  369. return data->state == PSK_DONE;
  370. }
  371. static u8 * eap_psk_getKey(struct eap_sm *sm, void *priv, size_t *len)
  372. {
  373. struct eap_psk_data *data = priv;
  374. u8 *key;
  375. if (data->state != PSK_DONE)
  376. return NULL;
  377. key = os_malloc(EAP_MSK_LEN);
  378. if (key == NULL)
  379. return NULL;
  380. *len = EAP_MSK_LEN;
  381. os_memcpy(key, data->msk, EAP_MSK_LEN);
  382. return key;
  383. }
  384. static u8 * eap_psk_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
  385. {
  386. struct eap_psk_data *data = priv;
  387. u8 *key;
  388. if (data->state != PSK_DONE)
  389. return NULL;
  390. key = os_malloc(EAP_EMSK_LEN);
  391. if (key == NULL)
  392. return NULL;
  393. *len = EAP_EMSK_LEN;
  394. os_memcpy(key, data->emsk, EAP_EMSK_LEN);
  395. return key;
  396. }
  397. int eap_peer_psk_register(void)
  398. {
  399. struct eap_method *eap;
  400. int ret;
  401. eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
  402. EAP_VENDOR_IETF, EAP_TYPE_PSK, "PSK");
  403. if (eap == NULL)
  404. return -1;
  405. eap->init = eap_psk_init;
  406. eap->deinit = eap_psk_deinit;
  407. eap->process = eap_psk_process;
  408. eap->isKeyAvailable = eap_psk_isKeyAvailable;
  409. eap->getKey = eap_psk_getKey;
  410. eap->get_emsk = eap_psk_get_emsk;
  411. ret = eap_peer_method_register(eap);
  412. if (ret)
  413. eap_peer_method_free(eap);
  414. return ret;
  415. }