eap_psk.c 13 KB

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