eap_peap.c 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288
  1. /*
  2. * EAP peer method: EAP-PEAP (draft-josefsson-pppext-eap-tls-eap-10.txt)
  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. #include "includes.h"
  15. #include "common.h"
  16. #include "crypto/sha1.h"
  17. #include "eap_i.h"
  18. #include "eap_tls_common.h"
  19. #include "eap_config.h"
  20. #include "tls.h"
  21. #include "eap_common/eap_tlv_common.h"
  22. #include "eap_common/eap_peap_common.h"
  23. #include "tncc.h"
  24. /* Maximum supported PEAP version
  25. * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt
  26. * 1 = draft-josefsson-ppext-eap-tls-eap-05.txt
  27. * 2 = draft-josefsson-ppext-eap-tls-eap-10.txt
  28. */
  29. #define EAP_PEAP_VERSION 1
  30. static void eap_peap_deinit(struct eap_sm *sm, void *priv);
  31. struct eap_peap_data {
  32. struct eap_ssl_data ssl;
  33. int peap_version, force_peap_version, force_new_label;
  34. const struct eap_method *phase2_method;
  35. void *phase2_priv;
  36. int phase2_success;
  37. int phase2_eap_success;
  38. int phase2_eap_started;
  39. struct eap_method_type phase2_type;
  40. struct eap_method_type *phase2_types;
  41. size_t num_phase2_types;
  42. int peap_outer_success; /* 0 = PEAP terminated on Phase 2 inner
  43. * EAP-Success
  44. * 1 = reply with tunneled EAP-Success to inner
  45. * EAP-Success and expect AS to send outer
  46. * (unencrypted) EAP-Success after this
  47. * 2 = reply with PEAP/TLS ACK to inner
  48. * EAP-Success and expect AS to send outer
  49. * (unencrypted) EAP-Success after this */
  50. int resuming; /* starting a resumed session */
  51. int reauth; /* reauthentication */
  52. u8 *key_data;
  53. struct wpabuf *pending_phase2_req;
  54. enum { NO_BINDING, OPTIONAL_BINDING, REQUIRE_BINDING } crypto_binding;
  55. int crypto_binding_used;
  56. u8 binding_nonce[32];
  57. u8 ipmk[40];
  58. u8 cmk[20];
  59. int soh; /* Whether IF-TNCCS-SOH (Statement of Health; Microsoft NAP)
  60. * is enabled. */
  61. };
  62. static int eap_peap_parse_phase1(struct eap_peap_data *data,
  63. const char *phase1)
  64. {
  65. const char *pos;
  66. pos = os_strstr(phase1, "peapver=");
  67. if (pos) {
  68. data->force_peap_version = atoi(pos + 8);
  69. data->peap_version = data->force_peap_version;
  70. wpa_printf(MSG_DEBUG, "EAP-PEAP: Forced PEAP version %d",
  71. data->force_peap_version);
  72. }
  73. if (os_strstr(phase1, "peaplabel=1")) {
  74. data->force_new_label = 1;
  75. wpa_printf(MSG_DEBUG, "EAP-PEAP: Force new label for key "
  76. "derivation");
  77. }
  78. if (os_strstr(phase1, "peap_outer_success=0")) {
  79. data->peap_outer_success = 0;
  80. wpa_printf(MSG_DEBUG, "EAP-PEAP: terminate authentication on "
  81. "tunneled EAP-Success");
  82. } else if (os_strstr(phase1, "peap_outer_success=1")) {
  83. data->peap_outer_success = 1;
  84. wpa_printf(MSG_DEBUG, "EAP-PEAP: send tunneled EAP-Success "
  85. "after receiving tunneled EAP-Success");
  86. } else if (os_strstr(phase1, "peap_outer_success=2")) {
  87. data->peap_outer_success = 2;
  88. wpa_printf(MSG_DEBUG, "EAP-PEAP: send PEAP/TLS ACK after "
  89. "receiving tunneled EAP-Success");
  90. }
  91. if (os_strstr(phase1, "crypto_binding=0")) {
  92. data->crypto_binding = NO_BINDING;
  93. wpa_printf(MSG_DEBUG, "EAP-PEAP: Do not use cryptobinding");
  94. } else if (os_strstr(phase1, "crypto_binding=1")) {
  95. data->crypto_binding = OPTIONAL_BINDING;
  96. wpa_printf(MSG_DEBUG, "EAP-PEAP: Optional cryptobinding");
  97. } else if (os_strstr(phase1, "crypto_binding=2")) {
  98. data->crypto_binding = REQUIRE_BINDING;
  99. wpa_printf(MSG_DEBUG, "EAP-PEAP: Require cryptobinding");
  100. }
  101. #ifdef EAP_TNC
  102. if (os_strstr(phase1, "tnc=soh2")) {
  103. data->soh = 2;
  104. wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
  105. } else if (os_strstr(phase1, "tnc=soh1")) {
  106. data->soh = 1;
  107. wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 1 enabled");
  108. } else if (os_strstr(phase1, "tnc=soh")) {
  109. data->soh = 2;
  110. wpa_printf(MSG_DEBUG, "EAP-PEAP: SoH version 2 enabled");
  111. }
  112. #endif /* EAP_TNC */
  113. return 0;
  114. }
  115. static void * eap_peap_init(struct eap_sm *sm)
  116. {
  117. struct eap_peap_data *data;
  118. struct eap_peer_config *config = eap_get_config(sm);
  119. data = os_zalloc(sizeof(*data));
  120. if (data == NULL)
  121. return NULL;
  122. sm->peap_done = FALSE;
  123. data->peap_version = EAP_PEAP_VERSION;
  124. data->force_peap_version = -1;
  125. data->peap_outer_success = 2;
  126. data->crypto_binding = OPTIONAL_BINDING;
  127. if (config && config->phase1 &&
  128. eap_peap_parse_phase1(data, config->phase1) < 0) {
  129. eap_peap_deinit(sm, data);
  130. return NULL;
  131. }
  132. if (eap_peer_select_phase2_methods(config, "auth=",
  133. &data->phase2_types,
  134. &data->num_phase2_types) < 0) {
  135. eap_peap_deinit(sm, data);
  136. return NULL;
  137. }
  138. data->phase2_type.vendor = EAP_VENDOR_IETF;
  139. data->phase2_type.method = EAP_TYPE_NONE;
  140. if (eap_peer_tls_ssl_init(sm, &data->ssl, config)) {
  141. wpa_printf(MSG_INFO, "EAP-PEAP: Failed to initialize SSL.");
  142. eap_peap_deinit(sm, data);
  143. return NULL;
  144. }
  145. return data;
  146. }
  147. static void eap_peap_deinit(struct eap_sm *sm, void *priv)
  148. {
  149. struct eap_peap_data *data = priv;
  150. if (data == NULL)
  151. return;
  152. if (data->phase2_priv && data->phase2_method)
  153. data->phase2_method->deinit(sm, data->phase2_priv);
  154. os_free(data->phase2_types);
  155. eap_peer_tls_ssl_deinit(sm, &data->ssl);
  156. os_free(data->key_data);
  157. wpabuf_free(data->pending_phase2_req);
  158. os_free(data);
  159. }
  160. /**
  161. * eap_tlv_build_nak - Build EAP-TLV NAK message
  162. * @id: EAP identifier for the header
  163. * @nak_type: TLV type (EAP_TLV_*)
  164. * Returns: Buffer to the allocated EAP-TLV NAK message or %NULL on failure
  165. *
  166. * This funtion builds an EAP-TLV NAK message. The caller is responsible for
  167. * freeing the returned buffer.
  168. */
  169. static struct wpabuf * eap_tlv_build_nak(int id, u16 nak_type)
  170. {
  171. struct wpabuf *msg;
  172. msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, 10,
  173. EAP_CODE_RESPONSE, id);
  174. if (msg == NULL)
  175. return NULL;
  176. wpabuf_put_u8(msg, 0x80); /* Mandatory */
  177. wpabuf_put_u8(msg, EAP_TLV_NAK_TLV);
  178. wpabuf_put_be16(msg, 6); /* Length */
  179. wpabuf_put_be32(msg, 0); /* Vendor-Id */
  180. wpabuf_put_be16(msg, nak_type); /* NAK-Type */
  181. return msg;
  182. }
  183. static int eap_peap_get_isk(struct eap_sm *sm, struct eap_peap_data *data,
  184. u8 *isk, size_t isk_len)
  185. {
  186. u8 *key;
  187. size_t key_len;
  188. os_memset(isk, 0, isk_len);
  189. if (data->phase2_method == NULL || data->phase2_priv == NULL ||
  190. data->phase2_method->isKeyAvailable == NULL ||
  191. data->phase2_method->getKey == NULL)
  192. return 0;
  193. if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv) ||
  194. (key = data->phase2_method->getKey(sm, data->phase2_priv,
  195. &key_len)) == NULL) {
  196. wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not get key material "
  197. "from Phase 2");
  198. return -1;
  199. }
  200. if (key_len > isk_len)
  201. key_len = isk_len;
  202. os_memcpy(isk, key, key_len);
  203. os_free(key);
  204. return 0;
  205. }
  206. static int eap_peap_derive_cmk(struct eap_sm *sm, struct eap_peap_data *data)
  207. {
  208. u8 *tk;
  209. u8 isk[32], imck[60];
  210. /*
  211. * Tunnel key (TK) is the first 60 octets of the key generated by
  212. * phase 1 of PEAP (based on TLS).
  213. */
  214. tk = data->key_data;
  215. if (tk == NULL)
  216. return -1;
  217. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TK", tk, 60);
  218. if (data->reauth &&
  219. tls_connection_resumed(sm->ssl_ctx, data->ssl.conn)) {
  220. /* Fast-connect: IPMK|CMK = TK */
  221. os_memcpy(data->ipmk, tk, 40);
  222. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK from TK",
  223. data->ipmk, 40);
  224. os_memcpy(data->cmk, tk + 40, 20);
  225. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK from TK",
  226. data->cmk, 20);
  227. return 0;
  228. }
  229. if (eap_peap_get_isk(sm, data, isk, sizeof(isk)) < 0)
  230. return -1;
  231. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: ISK", isk, sizeof(isk));
  232. /*
  233. * IPMK Seed = "Inner Methods Compound Keys" | ISK
  234. * TempKey = First 40 octets of TK
  235. * IPMK|CMK = PRF+(TempKey, IPMK Seed, 60)
  236. * (note: draft-josefsson-pppext-eap-tls-eap-10.txt includes a space
  237. * in the end of the label just before ISK; is that just a typo?)
  238. */
  239. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: TempKey", tk, 40);
  240. peap_prfplus(data->peap_version, tk, 40, "Inner Methods Compound Keys",
  241. isk, sizeof(isk), imck, sizeof(imck));
  242. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IMCK (IPMKj)",
  243. imck, sizeof(imck));
  244. os_memcpy(data->ipmk, imck, 40);
  245. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: IPMK (S-IPMKj)", data->ipmk, 40);
  246. os_memcpy(data->cmk, imck + 40, 20);
  247. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CMK (CMKj)", data->cmk, 20);
  248. return 0;
  249. }
  250. static int eap_tlv_add_cryptobinding(struct eap_sm *sm,
  251. struct eap_peap_data *data,
  252. struct wpabuf *buf)
  253. {
  254. u8 *mac;
  255. u8 eap_type = EAP_TYPE_PEAP;
  256. const u8 *addr[2];
  257. size_t len[2];
  258. u16 tlv_type;
  259. /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
  260. addr[0] = wpabuf_put(buf, 0);
  261. len[0] = 60;
  262. addr[1] = &eap_type;
  263. len[1] = 1;
  264. tlv_type = EAP_TLV_CRYPTO_BINDING_TLV;
  265. if (data->peap_version >= 2)
  266. tlv_type |= EAP_TLV_TYPE_MANDATORY;
  267. wpabuf_put_be16(buf, tlv_type);
  268. wpabuf_put_be16(buf, 56);
  269. wpabuf_put_u8(buf, 0); /* Reserved */
  270. wpabuf_put_u8(buf, data->peap_version); /* Version */
  271. wpabuf_put_u8(buf, data->peap_version); /* RecvVersion */
  272. wpabuf_put_u8(buf, 1); /* SubType: 0 = Request, 1 = Response */
  273. wpabuf_put_data(buf, data->binding_nonce, 32); /* Nonce */
  274. mac = wpabuf_put(buf, 20); /* Compound_MAC */
  275. wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC CMK", data->cmk, 20);
  276. wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 1",
  277. addr[0], len[0]);
  278. wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC data 2",
  279. addr[1], len[1]);
  280. hmac_sha1_vector(data->cmk, 20, 2, addr, len, mac);
  281. wpa_hexdump(MSG_MSGDUMP, "EAP-PEAP: Compound_MAC", mac, SHA1_MAC_LEN);
  282. data->crypto_binding_used = 1;
  283. return 0;
  284. }
  285. /**
  286. * eap_tlv_build_result - Build EAP-TLV Result message
  287. * @id: EAP identifier for the header
  288. * @status: Status (EAP_TLV_RESULT_SUCCESS or EAP_TLV_RESULT_FAILURE)
  289. * Returns: Buffer to the allocated EAP-TLV Result message or %NULL on failure
  290. *
  291. * This funtion builds an EAP-TLV Result message. The caller is responsible for
  292. * freeing the returned buffer.
  293. */
  294. static struct wpabuf * eap_tlv_build_result(struct eap_sm *sm,
  295. struct eap_peap_data *data,
  296. int crypto_tlv_used,
  297. int id, u16 status)
  298. {
  299. struct wpabuf *msg;
  300. size_t len;
  301. if (data->crypto_binding == NO_BINDING)
  302. crypto_tlv_used = 0;
  303. len = 6;
  304. if (crypto_tlv_used)
  305. len += 60; /* Cryptobinding TLV */
  306. msg = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_TLV, len,
  307. EAP_CODE_RESPONSE, id);
  308. if (msg == NULL)
  309. return NULL;
  310. wpabuf_put_u8(msg, 0x80); /* Mandatory */
  311. wpabuf_put_u8(msg, EAP_TLV_RESULT_TLV);
  312. wpabuf_put_be16(msg, 2); /* Length */
  313. wpabuf_put_be16(msg, status); /* Status */
  314. if (crypto_tlv_used && eap_tlv_add_cryptobinding(sm, data, msg)) {
  315. wpabuf_free(msg);
  316. return NULL;
  317. }
  318. return msg;
  319. }
  320. static int eap_tlv_validate_cryptobinding(struct eap_sm *sm,
  321. struct eap_peap_data *data,
  322. const u8 *crypto_tlv,
  323. size_t crypto_tlv_len)
  324. {
  325. u8 buf[61], mac[SHA1_MAC_LEN];
  326. const u8 *pos;
  327. if (eap_peap_derive_cmk(sm, data) < 0) {
  328. wpa_printf(MSG_DEBUG, "EAP-PEAP: Could not derive CMK");
  329. return -1;
  330. }
  331. if (crypto_tlv_len != 4 + 56) {
  332. wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid cryptobinding TLV "
  333. "length %d", (int) crypto_tlv_len);
  334. return -1;
  335. }
  336. pos = crypto_tlv;
  337. pos += 4; /* TLV header */
  338. if (pos[1] != data->peap_version) {
  339. wpa_printf(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV Version "
  340. "mismatch (was %d; expected %d)",
  341. pos[1], data->peap_version);
  342. return -1;
  343. }
  344. if (pos[3] != 0) {
  345. wpa_printf(MSG_DEBUG, "EAP-PEAP: Unexpected Cryptobinding TLV "
  346. "SubType %d", pos[3]);
  347. return -1;
  348. }
  349. pos += 4;
  350. os_memcpy(data->binding_nonce, pos, 32);
  351. pos += 32; /* Nonce */
  352. /* Compound_MAC: HMAC-SHA1-160(cryptobinding TLV | EAP type) */
  353. os_memcpy(buf, crypto_tlv, 60);
  354. os_memset(buf + 4 + 4 + 32, 0, 20); /* Compound_MAC */
  355. buf[60] = EAP_TYPE_PEAP;
  356. wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Compound_MAC data",
  357. buf, sizeof(buf));
  358. hmac_sha1(data->cmk, 20, buf, sizeof(buf), mac);
  359. if (os_memcmp(mac, pos, SHA1_MAC_LEN) != 0) {
  360. wpa_printf(MSG_DEBUG, "EAP-PEAP: Invalid Compound_MAC in "
  361. "cryptobinding TLV");
  362. wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Received MAC",
  363. pos, SHA1_MAC_LEN);
  364. wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Expected MAC",
  365. mac, SHA1_MAC_LEN);
  366. return -1;
  367. }
  368. wpa_printf(MSG_DEBUG, "EAP-PEAP: Valid cryptobinding TLV received");
  369. return 0;
  370. }
  371. /**
  372. * eap_tlv_process - Process a received EAP-TLV message and generate a response
  373. * @sm: Pointer to EAP state machine allocated with eap_peer_sm_init()
  374. * @ret: Return values from EAP request validation and processing
  375. * @req: EAP-TLV request to be processed. The caller must have validated that
  376. * the buffer is large enough to contain full request (hdr->length bytes) and
  377. * that the EAP type is EAP_TYPE_TLV.
  378. * @resp: Buffer to return a pointer to the allocated response message. This
  379. * field should be initialized to %NULL before the call. The value will be
  380. * updated if a response message is generated. The caller is responsible for
  381. * freeing the allocated message.
  382. * @force_failure: Force negotiation to fail
  383. * Returns: 0 on success, -1 on failure
  384. */
  385. static int eap_tlv_process(struct eap_sm *sm, struct eap_peap_data *data,
  386. struct eap_method_ret *ret,
  387. const struct wpabuf *req, struct wpabuf **resp,
  388. int force_failure)
  389. {
  390. size_t left, tlv_len;
  391. const u8 *pos;
  392. const u8 *result_tlv = NULL, *crypto_tlv = NULL;
  393. size_t result_tlv_len = 0, crypto_tlv_len = 0;
  394. int tlv_type, mandatory;
  395. /* Parse TLVs */
  396. pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_TLV, req, &left);
  397. if (pos == NULL)
  398. return -1;
  399. wpa_hexdump(MSG_DEBUG, "EAP-TLV: Received TLVs", pos, left);
  400. while (left >= 4) {
  401. mandatory = !!(pos[0] & 0x80);
  402. tlv_type = WPA_GET_BE16(pos) & 0x3fff;
  403. pos += 2;
  404. tlv_len = WPA_GET_BE16(pos);
  405. pos += 2;
  406. left -= 4;
  407. if (tlv_len > left) {
  408. wpa_printf(MSG_DEBUG, "EAP-TLV: TLV underrun "
  409. "(tlv_len=%lu left=%lu)",
  410. (unsigned long) tlv_len,
  411. (unsigned long) left);
  412. return -1;
  413. }
  414. switch (tlv_type) {
  415. case EAP_TLV_RESULT_TLV:
  416. result_tlv = pos;
  417. result_tlv_len = tlv_len;
  418. break;
  419. case EAP_TLV_CRYPTO_BINDING_TLV:
  420. crypto_tlv = pos;
  421. crypto_tlv_len = tlv_len;
  422. break;
  423. default:
  424. wpa_printf(MSG_DEBUG, "EAP-TLV: Unsupported TLV Type "
  425. "%d%s", tlv_type,
  426. mandatory ? " (mandatory)" : "");
  427. if (mandatory) {
  428. /* NAK TLV and ignore all TLVs in this packet.
  429. */
  430. *resp = eap_tlv_build_nak(eap_get_id(req),
  431. tlv_type);
  432. return *resp == NULL ? -1 : 0;
  433. }
  434. /* Ignore this TLV, but process other TLVs */
  435. break;
  436. }
  437. pos += tlv_len;
  438. left -= tlv_len;
  439. }
  440. if (left) {
  441. wpa_printf(MSG_DEBUG, "EAP-TLV: Last TLV too short in "
  442. "Request (left=%lu)", (unsigned long) left);
  443. return -1;
  444. }
  445. /* Process supported TLVs */
  446. if (crypto_tlv && data->crypto_binding != NO_BINDING) {
  447. wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Cryptobinding TLV",
  448. crypto_tlv, crypto_tlv_len);
  449. if (eap_tlv_validate_cryptobinding(sm, data, crypto_tlv - 4,
  450. crypto_tlv_len + 4) < 0) {
  451. if (result_tlv == NULL)
  452. return -1;
  453. force_failure = 1;
  454. crypto_tlv = NULL; /* do not include Cryptobinding TLV
  455. * in response, if the received
  456. * cryptobinding was invalid. */
  457. }
  458. } else if (!crypto_tlv && data->crypto_binding == REQUIRE_BINDING) {
  459. wpa_printf(MSG_DEBUG, "EAP-PEAP: No cryptobinding TLV");
  460. return -1;
  461. }
  462. if (result_tlv) {
  463. int status, resp_status;
  464. wpa_hexdump(MSG_DEBUG, "EAP-TLV: Result TLV",
  465. result_tlv, result_tlv_len);
  466. if (result_tlv_len < 2) {
  467. wpa_printf(MSG_INFO, "EAP-TLV: Too short Result TLV "
  468. "(len=%lu)",
  469. (unsigned long) result_tlv_len);
  470. return -1;
  471. }
  472. status = WPA_GET_BE16(result_tlv);
  473. if (status == EAP_TLV_RESULT_SUCCESS) {
  474. wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Success "
  475. "- EAP-TLV/Phase2 Completed");
  476. if (force_failure) {
  477. wpa_printf(MSG_INFO, "EAP-TLV: Earlier failure"
  478. " - force failed Phase 2");
  479. resp_status = EAP_TLV_RESULT_FAILURE;
  480. ret->decision = DECISION_FAIL;
  481. } else {
  482. resp_status = EAP_TLV_RESULT_SUCCESS;
  483. ret->decision = DECISION_UNCOND_SUCC;
  484. }
  485. } else if (status == EAP_TLV_RESULT_FAILURE) {
  486. wpa_printf(MSG_INFO, "EAP-TLV: TLV Result - Failure");
  487. resp_status = EAP_TLV_RESULT_FAILURE;
  488. ret->decision = DECISION_FAIL;
  489. } else {
  490. wpa_printf(MSG_INFO, "EAP-TLV: Unknown TLV Result "
  491. "Status %d", status);
  492. resp_status = EAP_TLV_RESULT_FAILURE;
  493. ret->decision = DECISION_FAIL;
  494. }
  495. ret->methodState = METHOD_DONE;
  496. *resp = eap_tlv_build_result(sm, data, crypto_tlv != NULL,
  497. eap_get_id(req), resp_status);
  498. }
  499. return 0;
  500. }
  501. static struct wpabuf * eap_peapv2_tlv_eap_payload(struct wpabuf *buf)
  502. {
  503. struct wpabuf *e;
  504. struct eap_tlv_hdr *tlv;
  505. if (buf == NULL)
  506. return NULL;
  507. /* Encapsulate EAP packet in EAP-Payload TLV */
  508. wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Add EAP-Payload TLV");
  509. e = wpabuf_alloc(sizeof(*tlv) + wpabuf_len(buf));
  510. if (e == NULL) {
  511. wpa_printf(MSG_DEBUG, "EAP-PEAPv2: Failed to allocate memory "
  512. "for TLV encapsulation");
  513. wpabuf_free(buf);
  514. return NULL;
  515. }
  516. tlv = wpabuf_put(e, sizeof(*tlv));
  517. tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |
  518. EAP_TLV_EAP_PAYLOAD_TLV);
  519. tlv->length = host_to_be16(wpabuf_len(buf));
  520. wpabuf_put_buf(e, buf);
  521. wpabuf_free(buf);
  522. return e;
  523. }
  524. static int eap_peap_phase2_request(struct eap_sm *sm,
  525. struct eap_peap_data *data,
  526. struct eap_method_ret *ret,
  527. struct wpabuf *req,
  528. struct wpabuf **resp)
  529. {
  530. struct eap_hdr *hdr = wpabuf_mhead(req);
  531. size_t len = be_to_host16(hdr->length);
  532. u8 *pos;
  533. struct eap_method_ret iret;
  534. struct eap_peer_config *config = eap_get_config(sm);
  535. if (len <= sizeof(struct eap_hdr)) {
  536. wpa_printf(MSG_INFO, "EAP-PEAP: too short "
  537. "Phase 2 request (len=%lu)", (unsigned long) len);
  538. return -1;
  539. }
  540. pos = (u8 *) (hdr + 1);
  541. wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Request: type=%d", *pos);
  542. switch (*pos) {
  543. case EAP_TYPE_IDENTITY:
  544. *resp = eap_sm_buildIdentity(sm, hdr->identifier, 1);
  545. break;
  546. case EAP_TYPE_TLV:
  547. os_memset(&iret, 0, sizeof(iret));
  548. if (eap_tlv_process(sm, data, &iret, req, resp,
  549. data->phase2_eap_started &&
  550. !data->phase2_eap_success)) {
  551. ret->methodState = METHOD_DONE;
  552. ret->decision = DECISION_FAIL;
  553. return -1;
  554. }
  555. if (iret.methodState == METHOD_DONE ||
  556. iret.methodState == METHOD_MAY_CONT) {
  557. ret->methodState = iret.methodState;
  558. ret->decision = iret.decision;
  559. data->phase2_success = 1;
  560. }
  561. break;
  562. case EAP_TYPE_EXPANDED:
  563. #ifdef EAP_TNC
  564. if (data->soh) {
  565. const u8 *epos;
  566. size_t eleft;
  567. epos = eap_hdr_validate(EAP_VENDOR_MICROSOFT, 0x21,
  568. req, &eleft);
  569. if (epos) {
  570. struct wpabuf *buf;
  571. wpa_printf(MSG_DEBUG,
  572. "EAP-PEAP: SoH EAP Extensions");
  573. buf = tncc_process_soh_request(data->soh,
  574. epos, eleft);
  575. if (buf) {
  576. *resp = eap_msg_alloc(
  577. EAP_VENDOR_MICROSOFT, 0x21,
  578. wpabuf_len(buf),
  579. EAP_CODE_RESPONSE,
  580. hdr->identifier);
  581. if (*resp == NULL) {
  582. ret->methodState = METHOD_DONE;
  583. ret->decision = DECISION_FAIL;
  584. return -1;
  585. }
  586. wpabuf_put_buf(*resp, buf);
  587. wpabuf_free(buf);
  588. break;
  589. }
  590. }
  591. }
  592. #endif /* EAP_TNC */
  593. /* fall through */
  594. default:
  595. if (data->phase2_type.vendor == EAP_VENDOR_IETF &&
  596. data->phase2_type.method == EAP_TYPE_NONE) {
  597. size_t i;
  598. for (i = 0; i < data->num_phase2_types; i++) {
  599. if (data->phase2_types[i].vendor !=
  600. EAP_VENDOR_IETF ||
  601. data->phase2_types[i].method != *pos)
  602. continue;
  603. data->phase2_type.vendor =
  604. data->phase2_types[i].vendor;
  605. data->phase2_type.method =
  606. data->phase2_types[i].method;
  607. wpa_printf(MSG_DEBUG, "EAP-PEAP: Selected "
  608. "Phase 2 EAP vendor %d method %d",
  609. data->phase2_type.vendor,
  610. data->phase2_type.method);
  611. break;
  612. }
  613. }
  614. if (*pos != data->phase2_type.method ||
  615. *pos == EAP_TYPE_NONE) {
  616. if (eap_peer_tls_phase2_nak(data->phase2_types,
  617. data->num_phase2_types,
  618. hdr, resp))
  619. return -1;
  620. return 0;
  621. }
  622. if (data->phase2_priv == NULL) {
  623. data->phase2_method = eap_peer_get_eap_method(
  624. data->phase2_type.vendor,
  625. data->phase2_type.method);
  626. if (data->phase2_method) {
  627. sm->init_phase2 = 1;
  628. data->phase2_priv =
  629. data->phase2_method->init(sm);
  630. sm->init_phase2 = 0;
  631. }
  632. }
  633. if (data->phase2_priv == NULL || data->phase2_method == NULL) {
  634. wpa_printf(MSG_INFO, "EAP-PEAP: failed to initialize "
  635. "Phase 2 EAP method %d", *pos);
  636. ret->methodState = METHOD_DONE;
  637. ret->decision = DECISION_FAIL;
  638. return -1;
  639. }
  640. data->phase2_eap_started = 1;
  641. os_memset(&iret, 0, sizeof(iret));
  642. *resp = data->phase2_method->process(sm, data->phase2_priv,
  643. &iret, req);
  644. if ((iret.methodState == METHOD_DONE ||
  645. iret.methodState == METHOD_MAY_CONT) &&
  646. (iret.decision == DECISION_UNCOND_SUCC ||
  647. iret.decision == DECISION_COND_SUCC)) {
  648. data->phase2_eap_success = 1;
  649. data->phase2_success = 1;
  650. }
  651. break;
  652. }
  653. if (*resp == NULL &&
  654. (config->pending_req_identity || config->pending_req_password ||
  655. config->pending_req_otp || config->pending_req_new_password)) {
  656. wpabuf_free(data->pending_phase2_req);
  657. data->pending_phase2_req = wpabuf_alloc_copy(hdr, len);
  658. }
  659. return 0;
  660. }
  661. static int eap_peap_decrypt(struct eap_sm *sm, struct eap_peap_data *data,
  662. struct eap_method_ret *ret,
  663. const struct eap_hdr *req,
  664. const struct wpabuf *in_data,
  665. struct wpabuf **out_data)
  666. {
  667. struct wpabuf *in_decrypted = NULL;
  668. int res, skip_change = 0;
  669. struct eap_hdr *hdr, *rhdr;
  670. struct wpabuf *resp = NULL;
  671. size_t len;
  672. wpa_printf(MSG_DEBUG, "EAP-PEAP: received %lu bytes encrypted data for"
  673. " Phase 2", (unsigned long) wpabuf_len(in_data));
  674. if (data->pending_phase2_req) {
  675. wpa_printf(MSG_DEBUG, "EAP-PEAP: Pending Phase 2 request - "
  676. "skip decryption and use old data");
  677. /* Clear TLS reassembly state. */
  678. eap_peer_tls_reset_input(&data->ssl);
  679. in_decrypted = data->pending_phase2_req;
  680. data->pending_phase2_req = NULL;
  681. skip_change = 1;
  682. goto continue_req;
  683. }
  684. if (wpabuf_len(in_data) == 0 && sm->workaround &&
  685. data->phase2_success) {
  686. /*
  687. * Cisco ACS seems to be using TLS ACK to terminate
  688. * EAP-PEAPv0/GTC. Try to reply with TLS ACK.
  689. */
  690. wpa_printf(MSG_DEBUG, "EAP-PEAP: Received TLS ACK, but "
  691. "expected data - acknowledge with TLS ACK since "
  692. "Phase 2 has been completed");
  693. ret->decision = DECISION_COND_SUCC;
  694. ret->methodState = METHOD_DONE;
  695. return 1;
  696. } else if (wpabuf_len(in_data) == 0) {
  697. /* Received TLS ACK - requesting more fragments */
  698. return eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
  699. data->peap_version,
  700. req->identifier, NULL, out_data);
  701. }
  702. res = eap_peer_tls_decrypt(sm, &data->ssl, in_data, &in_decrypted);
  703. if (res)
  704. return res;
  705. continue_req:
  706. wpa_hexdump_buf(MSG_DEBUG, "EAP-PEAP: Decrypted Phase 2 EAP",
  707. in_decrypted);
  708. hdr = wpabuf_mhead(in_decrypted);
  709. if (wpabuf_len(in_decrypted) == 5 && hdr->code == EAP_CODE_REQUEST &&
  710. be_to_host16(hdr->length) == 5 &&
  711. eap_get_type(in_decrypted) == EAP_TYPE_IDENTITY) {
  712. /* At least FreeRADIUS seems to send full EAP header with
  713. * EAP Request Identity */
  714. skip_change = 1;
  715. }
  716. if (wpabuf_len(in_decrypted) >= 5 && hdr->code == EAP_CODE_REQUEST &&
  717. eap_get_type(in_decrypted) == EAP_TYPE_TLV) {
  718. skip_change = 1;
  719. }
  720. if (data->peap_version == 0 && !skip_change) {
  721. struct eap_hdr *nhdr;
  722. struct wpabuf *nmsg = wpabuf_alloc(sizeof(struct eap_hdr) +
  723. wpabuf_len(in_decrypted));
  724. if (nmsg == NULL) {
  725. wpabuf_free(in_decrypted);
  726. return 0;
  727. }
  728. nhdr = wpabuf_put(nmsg, sizeof(*nhdr));
  729. wpabuf_put_buf(nmsg, in_decrypted);
  730. nhdr->code = req->code;
  731. nhdr->identifier = req->identifier;
  732. nhdr->length = host_to_be16(sizeof(struct eap_hdr) +
  733. wpabuf_len(in_decrypted));
  734. wpabuf_free(in_decrypted);
  735. in_decrypted = nmsg;
  736. }
  737. if (data->peap_version >= 2) {
  738. struct eap_tlv_hdr *tlv;
  739. struct wpabuf *nmsg;
  740. if (wpabuf_len(in_decrypted) < sizeof(*tlv) + sizeof(*hdr)) {
  741. wpa_printf(MSG_INFO, "EAP-PEAPv2: Too short Phase 2 "
  742. "EAP TLV");
  743. wpabuf_free(in_decrypted);
  744. return 0;
  745. }
  746. tlv = wpabuf_mhead(in_decrypted);
  747. if ((be_to_host16(tlv->tlv_type) & 0x3fff) !=
  748. EAP_TLV_EAP_PAYLOAD_TLV) {
  749. wpa_printf(MSG_INFO, "EAP-PEAPv2: Not an EAP TLV");
  750. wpabuf_free(in_decrypted);
  751. return 0;
  752. }
  753. if (sizeof(*tlv) + be_to_host16(tlv->length) >
  754. wpabuf_len(in_decrypted)) {
  755. wpa_printf(MSG_INFO, "EAP-PEAPv2: Invalid EAP TLV "
  756. "length");
  757. wpabuf_free(in_decrypted);
  758. return 0;
  759. }
  760. hdr = (struct eap_hdr *) (tlv + 1);
  761. if (be_to_host16(hdr->length) > be_to_host16(tlv->length)) {
  762. wpa_printf(MSG_INFO, "EAP-PEAPv2: No room for full "
  763. "EAP packet in EAP TLV");
  764. wpabuf_free(in_decrypted);
  765. return 0;
  766. }
  767. nmsg = wpabuf_alloc(be_to_host16(hdr->length));
  768. if (nmsg == NULL) {
  769. wpabuf_free(in_decrypted);
  770. return 0;
  771. }
  772. wpabuf_put_data(nmsg, hdr, be_to_host16(hdr->length));
  773. wpabuf_free(in_decrypted);
  774. in_decrypted = nmsg;
  775. }
  776. hdr = wpabuf_mhead(in_decrypted);
  777. if (wpabuf_len(in_decrypted) < sizeof(*hdr)) {
  778. wpa_printf(MSG_INFO, "EAP-PEAP: Too short Phase 2 "
  779. "EAP frame (len=%lu)",
  780. (unsigned long) wpabuf_len(in_decrypted));
  781. wpabuf_free(in_decrypted);
  782. return 0;
  783. }
  784. len = be_to_host16(hdr->length);
  785. if (len > wpabuf_len(in_decrypted)) {
  786. wpa_printf(MSG_INFO, "EAP-PEAP: Length mismatch in "
  787. "Phase 2 EAP frame (len=%lu hdr->length=%lu)",
  788. (unsigned long) wpabuf_len(in_decrypted),
  789. (unsigned long) len);
  790. wpabuf_free(in_decrypted);
  791. return 0;
  792. }
  793. if (len < wpabuf_len(in_decrypted)) {
  794. wpa_printf(MSG_INFO, "EAP-PEAP: Odd.. Phase 2 EAP header has "
  795. "shorter length than full decrypted data "
  796. "(%lu < %lu)",
  797. (unsigned long) len,
  798. (unsigned long) wpabuf_len(in_decrypted));
  799. }
  800. wpa_printf(MSG_DEBUG, "EAP-PEAP: received Phase 2: code=%d "
  801. "identifier=%d length=%lu", hdr->code, hdr->identifier,
  802. (unsigned long) len);
  803. switch (hdr->code) {
  804. case EAP_CODE_REQUEST:
  805. if (eap_peap_phase2_request(sm, data, ret, in_decrypted,
  806. &resp)) {
  807. wpabuf_free(in_decrypted);
  808. wpa_printf(MSG_INFO, "EAP-PEAP: Phase2 Request "
  809. "processing failed");
  810. return 0;
  811. }
  812. break;
  813. case EAP_CODE_SUCCESS:
  814. wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Success");
  815. if (data->peap_version == 1) {
  816. /* EAP-Success within TLS tunnel is used to indicate
  817. * shutdown of the TLS channel. The authentication has
  818. * been completed. */
  819. if (data->phase2_eap_started &&
  820. !data->phase2_eap_success) {
  821. wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 "
  822. "Success used to indicate success, "
  823. "but Phase 2 EAP was not yet "
  824. "completed successfully");
  825. ret->methodState = METHOD_DONE;
  826. ret->decision = DECISION_FAIL;
  827. wpabuf_free(in_decrypted);
  828. return 0;
  829. }
  830. wpa_printf(MSG_DEBUG, "EAP-PEAP: Version 1 - "
  831. "EAP-Success within TLS tunnel - "
  832. "authentication completed");
  833. ret->decision = DECISION_UNCOND_SUCC;
  834. ret->methodState = METHOD_DONE;
  835. data->phase2_success = 1;
  836. if (data->peap_outer_success == 2) {
  837. wpabuf_free(in_decrypted);
  838. wpa_printf(MSG_DEBUG, "EAP-PEAP: Use TLS ACK "
  839. "to finish authentication");
  840. return 1;
  841. } else if (data->peap_outer_success == 1) {
  842. /* Reply with EAP-Success within the TLS
  843. * channel to complete the authentication. */
  844. resp = wpabuf_alloc(sizeof(struct eap_hdr));
  845. if (resp) {
  846. rhdr = wpabuf_put(resp, sizeof(*rhdr));
  847. rhdr->code = EAP_CODE_SUCCESS;
  848. rhdr->identifier = hdr->identifier;
  849. rhdr->length =
  850. host_to_be16(sizeof(*rhdr));
  851. }
  852. } else {
  853. /* No EAP-Success expected for Phase 1 (outer,
  854. * unencrypted auth), so force EAP state
  855. * machine to SUCCESS state. */
  856. sm->peap_done = TRUE;
  857. }
  858. } else {
  859. /* FIX: ? */
  860. }
  861. break;
  862. case EAP_CODE_FAILURE:
  863. wpa_printf(MSG_DEBUG, "EAP-PEAP: Phase 2 Failure");
  864. ret->decision = DECISION_FAIL;
  865. ret->methodState = METHOD_MAY_CONT;
  866. ret->allowNotifications = FALSE;
  867. /* Reply with EAP-Failure within the TLS channel to complete
  868. * failure reporting. */
  869. resp = wpabuf_alloc(sizeof(struct eap_hdr));
  870. if (resp) {
  871. rhdr = wpabuf_put(resp, sizeof(*rhdr));
  872. rhdr->code = EAP_CODE_FAILURE;
  873. rhdr->identifier = hdr->identifier;
  874. rhdr->length = host_to_be16(sizeof(*rhdr));
  875. }
  876. break;
  877. default:
  878. wpa_printf(MSG_INFO, "EAP-PEAP: Unexpected code=%d in "
  879. "Phase 2 EAP header", hdr->code);
  880. break;
  881. }
  882. wpabuf_free(in_decrypted);
  883. if (resp) {
  884. int skip_change2 = 0;
  885. struct wpabuf *rmsg, buf;
  886. wpa_hexdump_buf_key(MSG_DEBUG,
  887. "EAP-PEAP: Encrypting Phase 2 data", resp);
  888. /* PEAP version changes */
  889. if (data->peap_version >= 2) {
  890. resp = eap_peapv2_tlv_eap_payload(resp);
  891. if (resp == NULL)
  892. return -1;
  893. }
  894. if (wpabuf_len(resp) >= 5 &&
  895. wpabuf_head_u8(resp)[0] == EAP_CODE_RESPONSE &&
  896. eap_get_type(resp) == EAP_TYPE_TLV)
  897. skip_change2 = 1;
  898. rmsg = resp;
  899. if (data->peap_version == 0 && !skip_change2) {
  900. wpabuf_set(&buf, wpabuf_head_u8(resp) +
  901. sizeof(struct eap_hdr),
  902. wpabuf_len(resp) - sizeof(struct eap_hdr));
  903. rmsg = &buf;
  904. }
  905. if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_PEAP,
  906. data->peap_version, req->identifier,
  907. rmsg, out_data)) {
  908. wpa_printf(MSG_INFO, "EAP-PEAP: Failed to encrypt "
  909. "a Phase 2 frame");
  910. }
  911. wpabuf_free(resp);
  912. }
  913. return 0;
  914. }
  915. static struct wpabuf * eap_peap_process(struct eap_sm *sm, void *priv,
  916. struct eap_method_ret *ret,
  917. const struct wpabuf *reqData)
  918. {
  919. const struct eap_hdr *req;
  920. size_t left;
  921. int res;
  922. u8 flags, id;
  923. struct wpabuf *resp;
  924. const u8 *pos;
  925. struct eap_peap_data *data = priv;
  926. pos = eap_peer_tls_process_init(sm, &data->ssl, EAP_TYPE_PEAP, ret,
  927. reqData, &left, &flags);
  928. if (pos == NULL)
  929. return NULL;
  930. req = wpabuf_head(reqData);
  931. id = req->identifier;
  932. if (flags & EAP_TLS_FLAGS_START) {
  933. wpa_printf(MSG_DEBUG, "EAP-PEAP: Start (server ver=%d, own "
  934. "ver=%d)", flags & EAP_PEAP_VERSION_MASK,
  935. data->peap_version);
  936. if ((flags & EAP_PEAP_VERSION_MASK) < data->peap_version)
  937. data->peap_version = flags & EAP_PEAP_VERSION_MASK;
  938. if (data->force_peap_version >= 0 &&
  939. data->force_peap_version != data->peap_version) {
  940. wpa_printf(MSG_WARNING, "EAP-PEAP: Failed to select "
  941. "forced PEAP version %d",
  942. data->force_peap_version);
  943. ret->methodState = METHOD_DONE;
  944. ret->decision = DECISION_FAIL;
  945. ret->allowNotifications = FALSE;
  946. return NULL;
  947. }
  948. wpa_printf(MSG_DEBUG, "EAP-PEAP: Using PEAP version %d",
  949. data->peap_version);
  950. left = 0; /* make sure that this frame is empty, even though it
  951. * should always be, anyway */
  952. }
  953. resp = NULL;
  954. if (tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
  955. !data->resuming) {
  956. struct wpabuf msg;
  957. wpabuf_set(&msg, pos, left);
  958. res = eap_peap_decrypt(sm, data, ret, req, &msg, &resp);
  959. } else {
  960. res = eap_peer_tls_process_helper(sm, &data->ssl,
  961. EAP_TYPE_PEAP,
  962. data->peap_version, id, pos,
  963. left, &resp);
  964. if (tls_connection_established(sm->ssl_ctx, data->ssl.conn)) {
  965. char *label;
  966. wpa_printf(MSG_DEBUG,
  967. "EAP-PEAP: TLS done, proceed to Phase 2");
  968. os_free(data->key_data);
  969. /* draft-josefsson-ppext-eap-tls-eap-05.txt
  970. * specifies that PEAPv1 would use "client PEAP
  971. * encryption" as the label. However, most existing
  972. * PEAPv1 implementations seem to be using the old
  973. * label, "client EAP encryption", instead. Use the old
  974. * label by default, but allow it to be configured with
  975. * phase1 parameter peaplabel=1. */
  976. if (data->peap_version > 1 || data->force_new_label)
  977. label = "client PEAP encryption";
  978. else
  979. label = "client EAP encryption";
  980. wpa_printf(MSG_DEBUG, "EAP-PEAP: using label '%s' in "
  981. "key derivation", label);
  982. data->key_data =
  983. eap_peer_tls_derive_key(sm, &data->ssl, label,
  984. EAP_TLS_KEY_LEN);
  985. if (data->key_data) {
  986. wpa_hexdump_key(MSG_DEBUG,
  987. "EAP-PEAP: Derived key",
  988. data->key_data,
  989. EAP_TLS_KEY_LEN);
  990. } else {
  991. wpa_printf(MSG_DEBUG, "EAP-PEAP: Failed to "
  992. "derive key");
  993. }
  994. if (sm->workaround && data->resuming) {
  995. /*
  996. * At least few RADIUS servers (Aegis v1.1.6;
  997. * but not v1.1.4; and Cisco ACS) seem to be
  998. * terminating PEAPv1 (Aegis) or PEAPv0 (Cisco
  999. * ACS) session resumption with outer
  1000. * EAP-Success. This does not seem to follow
  1001. * draft-josefsson-pppext-eap-tls-eap-05.txt
  1002. * section 4.2, so only allow this if EAP
  1003. * workarounds are enabled.
  1004. */
  1005. wpa_printf(MSG_DEBUG, "EAP-PEAP: Workaround - "
  1006. "allow outer EAP-Success to "
  1007. "terminate PEAP resumption");
  1008. ret->decision = DECISION_COND_SUCC;
  1009. data->phase2_success = 1;
  1010. }
  1011. data->resuming = 0;
  1012. }
  1013. if (res == 2) {
  1014. struct wpabuf msg;
  1015. /*
  1016. * Application data included in the handshake message.
  1017. */
  1018. wpabuf_free(data->pending_phase2_req);
  1019. data->pending_phase2_req = resp;
  1020. resp = NULL;
  1021. wpabuf_set(&msg, pos, left);
  1022. res = eap_peap_decrypt(sm, data, ret, req, &msg,
  1023. &resp);
  1024. }
  1025. }
  1026. if (ret->methodState == METHOD_DONE) {
  1027. ret->allowNotifications = FALSE;
  1028. }
  1029. if (res == 1) {
  1030. wpabuf_free(resp);
  1031. return eap_peer_tls_build_ack(id, EAP_TYPE_PEAP,
  1032. data->peap_version);
  1033. }
  1034. return resp;
  1035. }
  1036. static Boolean eap_peap_has_reauth_data(struct eap_sm *sm, void *priv)
  1037. {
  1038. struct eap_peap_data *data = priv;
  1039. return tls_connection_established(sm->ssl_ctx, data->ssl.conn) &&
  1040. data->phase2_success;
  1041. }
  1042. static void eap_peap_deinit_for_reauth(struct eap_sm *sm, void *priv)
  1043. {
  1044. struct eap_peap_data *data = priv;
  1045. wpabuf_free(data->pending_phase2_req);
  1046. data->pending_phase2_req = NULL;
  1047. data->crypto_binding_used = 0;
  1048. }
  1049. static void * eap_peap_init_for_reauth(struct eap_sm *sm, void *priv)
  1050. {
  1051. struct eap_peap_data *data = priv;
  1052. os_free(data->key_data);
  1053. data->key_data = NULL;
  1054. if (eap_peer_tls_reauth_init(sm, &data->ssl)) {
  1055. os_free(data);
  1056. return NULL;
  1057. }
  1058. if (data->phase2_priv && data->phase2_method &&
  1059. data->phase2_method->init_for_reauth)
  1060. data->phase2_method->init_for_reauth(sm, data->phase2_priv);
  1061. data->phase2_success = 0;
  1062. data->phase2_eap_success = 0;
  1063. data->phase2_eap_started = 0;
  1064. data->resuming = 1;
  1065. data->reauth = 1;
  1066. sm->peap_done = FALSE;
  1067. return priv;
  1068. }
  1069. static int eap_peap_get_status(struct eap_sm *sm, void *priv, char *buf,
  1070. size_t buflen, int verbose)
  1071. {
  1072. struct eap_peap_data *data = priv;
  1073. int len, ret;
  1074. len = eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose);
  1075. if (data->phase2_method) {
  1076. ret = os_snprintf(buf + len, buflen - len,
  1077. "EAP-PEAPv%d Phase2 method=%s\n",
  1078. data->peap_version,
  1079. data->phase2_method->name);
  1080. if (ret < 0 || (size_t) ret >= buflen - len)
  1081. return len;
  1082. len += ret;
  1083. }
  1084. return len;
  1085. }
  1086. static Boolean eap_peap_isKeyAvailable(struct eap_sm *sm, void *priv)
  1087. {
  1088. struct eap_peap_data *data = priv;
  1089. return data->key_data != NULL && data->phase2_success;
  1090. }
  1091. static u8 * eap_peap_getKey(struct eap_sm *sm, void *priv, size_t *len)
  1092. {
  1093. struct eap_peap_data *data = priv;
  1094. u8 *key;
  1095. if (data->key_data == NULL || !data->phase2_success)
  1096. return NULL;
  1097. key = os_malloc(EAP_TLS_KEY_LEN);
  1098. if (key == NULL)
  1099. return NULL;
  1100. *len = EAP_TLS_KEY_LEN;
  1101. if (data->crypto_binding_used) {
  1102. u8 csk[128];
  1103. /*
  1104. * Note: It looks like Microsoft implementation requires null
  1105. * termination for this label while the one used for deriving
  1106. * IPMK|CMK did not use null termination.
  1107. */
  1108. peap_prfplus(data->peap_version, data->ipmk, 40,
  1109. "Session Key Generating Function",
  1110. (u8 *) "\00", 1, csk, sizeof(csk));
  1111. wpa_hexdump_key(MSG_DEBUG, "EAP-PEAP: CSK", csk, sizeof(csk));
  1112. os_memcpy(key, csk, EAP_TLS_KEY_LEN);
  1113. wpa_hexdump(MSG_DEBUG, "EAP-PEAP: Derived key",
  1114. key, EAP_TLS_KEY_LEN);
  1115. } else
  1116. os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN);
  1117. return key;
  1118. }
  1119. int eap_peer_peap_register(void)
  1120. {
  1121. struct eap_method *eap;
  1122. int ret;
  1123. eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION,
  1124. EAP_VENDOR_IETF, EAP_TYPE_PEAP, "PEAP");
  1125. if (eap == NULL)
  1126. return -1;
  1127. eap->init = eap_peap_init;
  1128. eap->deinit = eap_peap_deinit;
  1129. eap->process = eap_peap_process;
  1130. eap->isKeyAvailable = eap_peap_isKeyAvailable;
  1131. eap->getKey = eap_peap_getKey;
  1132. eap->get_status = eap_peap_get_status;
  1133. eap->has_reauth_data = eap_peap_has_reauth_data;
  1134. eap->deinit_for_reauth = eap_peap_deinit_for_reauth;
  1135. eap->init_for_reauth = eap_peap_init_for_reauth;
  1136. ret = eap_peer_method_register(eap);
  1137. if (ret)
  1138. eap_peer_method_free(eap);
  1139. return ret;
  1140. }