eap_server_tls.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462
  1. /*
  2. * hostapd / EAP-TLS (RFC 2716)
  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. #include "includes.h"
  9. #include "common.h"
  10. #include "eap_i.h"
  11. #include "eap_tls_common.h"
  12. #include "crypto/tls.h"
  13. static void eap_tls_reset(struct eap_sm *sm, void *priv);
  14. struct eap_tls_data {
  15. struct eap_ssl_data ssl;
  16. enum { START, CONTINUE, SUCCESS, FAILURE } state;
  17. int established;
  18. u8 eap_type;
  19. };
  20. static const char * eap_tls_state_txt(int state)
  21. {
  22. switch (state) {
  23. case START:
  24. return "START";
  25. case CONTINUE:
  26. return "CONTINUE";
  27. case SUCCESS:
  28. return "SUCCESS";
  29. case FAILURE:
  30. return "FAILURE";
  31. default:
  32. return "Unknown?!";
  33. }
  34. }
  35. static void eap_tls_state(struct eap_tls_data *data, int state)
  36. {
  37. wpa_printf(MSG_DEBUG, "EAP-TLS: %s -> %s",
  38. eap_tls_state_txt(data->state),
  39. eap_tls_state_txt(state));
  40. data->state = state;
  41. if (state == FAILURE)
  42. tls_connection_remove_session(data->ssl.conn);
  43. }
  44. static void eap_tls_valid_session(struct eap_sm *sm, struct eap_tls_data *data)
  45. {
  46. struct wpabuf *buf;
  47. if (!sm->tls_session_lifetime)
  48. return;
  49. buf = wpabuf_alloc(1);
  50. if (!buf)
  51. return;
  52. wpabuf_put_u8(buf, data->eap_type);
  53. tls_connection_set_success_data(data->ssl.conn, buf);
  54. }
  55. static void * eap_tls_init(struct eap_sm *sm)
  56. {
  57. struct eap_tls_data *data;
  58. data = os_zalloc(sizeof(*data));
  59. if (data == NULL)
  60. return NULL;
  61. data->state = START;
  62. if (eap_server_tls_ssl_init(sm, &data->ssl, 1, EAP_TYPE_TLS)) {
  63. wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
  64. eap_tls_reset(sm, data);
  65. return NULL;
  66. }
  67. data->eap_type = EAP_TYPE_TLS;
  68. return data;
  69. }
  70. #ifdef EAP_SERVER_UNAUTH_TLS
  71. static void * eap_unauth_tls_init(struct eap_sm *sm)
  72. {
  73. struct eap_tls_data *data;
  74. data = os_zalloc(sizeof(*data));
  75. if (data == NULL)
  76. return NULL;
  77. data->state = START;
  78. if (eap_server_tls_ssl_init(sm, &data->ssl, 0, EAP_UNAUTH_TLS_TYPE)) {
  79. wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
  80. eap_tls_reset(sm, data);
  81. return NULL;
  82. }
  83. data->eap_type = EAP_UNAUTH_TLS_TYPE;
  84. return data;
  85. }
  86. #endif /* EAP_SERVER_UNAUTH_TLS */
  87. #ifdef CONFIG_HS20
  88. static void * eap_wfa_unauth_tls_init(struct eap_sm *sm)
  89. {
  90. struct eap_tls_data *data;
  91. data = os_zalloc(sizeof(*data));
  92. if (data == NULL)
  93. return NULL;
  94. data->state = START;
  95. if (eap_server_tls_ssl_init(sm, &data->ssl, 0,
  96. EAP_WFA_UNAUTH_TLS_TYPE)) {
  97. wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
  98. eap_tls_reset(sm, data);
  99. return NULL;
  100. }
  101. data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE;
  102. return data;
  103. }
  104. #endif /* CONFIG_HS20 */
  105. static void eap_tls_reset(struct eap_sm *sm, void *priv)
  106. {
  107. struct eap_tls_data *data = priv;
  108. if (data == NULL)
  109. return;
  110. eap_server_tls_ssl_deinit(sm, &data->ssl);
  111. os_free(data);
  112. }
  113. static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
  114. struct eap_tls_data *data, u8 id)
  115. {
  116. struct wpabuf *req;
  117. req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id);
  118. if (req == NULL) {
  119. wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
  120. "request");
  121. eap_tls_state(data, FAILURE);
  122. return NULL;
  123. }
  124. wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
  125. eap_tls_state(data, CONTINUE);
  126. return req;
  127. }
  128. static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
  129. {
  130. struct eap_tls_data *data = priv;
  131. struct wpabuf *res;
  132. if (data->ssl.state == FRAG_ACK) {
  133. return eap_server_tls_build_ack(id, data->eap_type, 0);
  134. }
  135. if (data->ssl.state == WAIT_FRAG_ACK) {
  136. res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0,
  137. id);
  138. goto check_established;
  139. }
  140. switch (data->state) {
  141. case START:
  142. return eap_tls_build_start(sm, data, id);
  143. case CONTINUE:
  144. if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
  145. data->established = 1;
  146. break;
  147. default:
  148. wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
  149. __func__, data->state);
  150. return NULL;
  151. }
  152. res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id);
  153. check_established:
  154. if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
  155. /* TLS handshake has been completed and there are no more
  156. * fragments waiting to be sent out. */
  157. wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
  158. eap_tls_state(data, SUCCESS);
  159. eap_tls_valid_session(sm, data);
  160. }
  161. return res;
  162. }
  163. static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
  164. struct wpabuf *respData)
  165. {
  166. struct eap_tls_data *data = priv;
  167. const u8 *pos;
  168. size_t len;
  169. if (data->eap_type == EAP_UNAUTH_TLS_TYPE)
  170. pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
  171. EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
  172. &len);
  173. else if (data->eap_type == EAP_WFA_UNAUTH_TLS_TYPE)
  174. pos = eap_hdr_validate(EAP_VENDOR_WFA_NEW,
  175. EAP_VENDOR_WFA_UNAUTH_TLS, respData,
  176. &len);
  177. else
  178. pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type,
  179. respData, &len);
  180. if (pos == NULL || len < 1) {
  181. wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
  182. return TRUE;
  183. }
  184. return FALSE;
  185. }
  186. static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
  187. const struct wpabuf *respData)
  188. {
  189. struct eap_tls_data *data = priv;
  190. if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) {
  191. wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
  192. "handshake message");
  193. return;
  194. }
  195. if (eap_server_tls_phase1(sm, &data->ssl) < 0)
  196. eap_tls_state(data, FAILURE);
  197. }
  198. static void eap_tls_process(struct eap_sm *sm, void *priv,
  199. struct wpabuf *respData)
  200. {
  201. struct eap_tls_data *data = priv;
  202. const struct wpabuf *buf;
  203. const u8 *pos;
  204. if (eap_server_tls_process(sm, &data->ssl, respData, data,
  205. data->eap_type, NULL, eap_tls_process_msg) <
  206. 0) {
  207. eap_tls_state(data, FAILURE);
  208. return;
  209. }
  210. if (!tls_connection_established(sm->ssl_ctx, data->ssl.conn) ||
  211. !tls_connection_resumed(sm->ssl_ctx, data->ssl.conn))
  212. return;
  213. buf = tls_connection_get_success_data(data->ssl.conn);
  214. if (!buf || wpabuf_len(buf) < 1) {
  215. wpa_printf(MSG_DEBUG,
  216. "EAP-TLS: No success data in resumed session - reject attempt");
  217. eap_tls_state(data, FAILURE);
  218. return;
  219. }
  220. pos = wpabuf_head(buf);
  221. if (*pos != data->eap_type) {
  222. wpa_printf(MSG_DEBUG,
  223. "EAP-TLS: Resumed session for another EAP type (%u) - reject attempt",
  224. *pos);
  225. eap_tls_state(data, FAILURE);
  226. return;
  227. }
  228. wpa_printf(MSG_DEBUG,
  229. "EAP-TLS: Resuming previous session");
  230. eap_tls_state(data, SUCCESS);
  231. tls_connection_set_success_data_resumed(data->ssl.conn);
  232. }
  233. static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
  234. {
  235. struct eap_tls_data *data = priv;
  236. return data->state == SUCCESS || data->state == FAILURE;
  237. }
  238. static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
  239. {
  240. struct eap_tls_data *data = priv;
  241. u8 *eapKeyData;
  242. if (data->state != SUCCESS)
  243. return NULL;
  244. eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
  245. "client EAP encryption",
  246. EAP_TLS_KEY_LEN);
  247. if (eapKeyData) {
  248. *len = EAP_TLS_KEY_LEN;
  249. wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
  250. eapKeyData, EAP_TLS_KEY_LEN);
  251. } else {
  252. wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
  253. }
  254. return eapKeyData;
  255. }
  256. static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
  257. {
  258. struct eap_tls_data *data = priv;
  259. u8 *eapKeyData, *emsk;
  260. if (data->state != SUCCESS)
  261. return NULL;
  262. eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
  263. "client EAP encryption",
  264. EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
  265. if (eapKeyData) {
  266. emsk = os_malloc(EAP_EMSK_LEN);
  267. if (emsk)
  268. os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
  269. EAP_EMSK_LEN);
  270. bin_clear_free(eapKeyData, EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
  271. } else
  272. emsk = NULL;
  273. if (emsk) {
  274. *len = EAP_EMSK_LEN;
  275. wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
  276. emsk, EAP_EMSK_LEN);
  277. } else {
  278. wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
  279. }
  280. return emsk;
  281. }
  282. static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
  283. {
  284. struct eap_tls_data *data = priv;
  285. return data->state == SUCCESS;
  286. }
  287. static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len)
  288. {
  289. struct eap_tls_data *data = priv;
  290. if (data->state != SUCCESS)
  291. return NULL;
  292. return eap_server_tls_derive_session_id(sm, &data->ssl, EAP_TYPE_TLS,
  293. len);
  294. }
  295. int eap_server_tls_register(void)
  296. {
  297. struct eap_method *eap;
  298. int ret;
  299. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  300. EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
  301. if (eap == NULL)
  302. return -1;
  303. eap->init = eap_tls_init;
  304. eap->reset = eap_tls_reset;
  305. eap->buildReq = eap_tls_buildReq;
  306. eap->check = eap_tls_check;
  307. eap->process = eap_tls_process;
  308. eap->isDone = eap_tls_isDone;
  309. eap->getKey = eap_tls_getKey;
  310. eap->isSuccess = eap_tls_isSuccess;
  311. eap->get_emsk = eap_tls_get_emsk;
  312. eap->getSessionId = eap_tls_get_session_id;
  313. ret = eap_server_method_register(eap);
  314. if (ret)
  315. eap_server_method_free(eap);
  316. return ret;
  317. }
  318. #ifdef EAP_SERVER_UNAUTH_TLS
  319. int eap_server_unauth_tls_register(void)
  320. {
  321. struct eap_method *eap;
  322. int ret;
  323. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  324. EAP_VENDOR_UNAUTH_TLS,
  325. EAP_VENDOR_TYPE_UNAUTH_TLS,
  326. "UNAUTH-TLS");
  327. if (eap == NULL)
  328. return -1;
  329. eap->init = eap_unauth_tls_init;
  330. eap->reset = eap_tls_reset;
  331. eap->buildReq = eap_tls_buildReq;
  332. eap->check = eap_tls_check;
  333. eap->process = eap_tls_process;
  334. eap->isDone = eap_tls_isDone;
  335. eap->getKey = eap_tls_getKey;
  336. eap->isSuccess = eap_tls_isSuccess;
  337. eap->get_emsk = eap_tls_get_emsk;
  338. ret = eap_server_method_register(eap);
  339. if (ret)
  340. eap_server_method_free(eap);
  341. return ret;
  342. }
  343. #endif /* EAP_SERVER_UNAUTH_TLS */
  344. #ifdef CONFIG_HS20
  345. int eap_server_wfa_unauth_tls_register(void)
  346. {
  347. struct eap_method *eap;
  348. int ret;
  349. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  350. EAP_VENDOR_WFA_NEW,
  351. EAP_VENDOR_WFA_UNAUTH_TLS,
  352. "WFA-UNAUTH-TLS");
  353. if (eap == NULL)
  354. return -1;
  355. eap->init = eap_wfa_unauth_tls_init;
  356. eap->reset = eap_tls_reset;
  357. eap->buildReq = eap_tls_buildReq;
  358. eap->check = eap_tls_check;
  359. eap->process = eap_tls_process;
  360. eap->isDone = eap_tls_isDone;
  361. eap->getKey = eap_tls_getKey;
  362. eap->isSuccess = eap_tls_isSuccess;
  363. eap->get_emsk = eap_tls_get_emsk;
  364. ret = eap_server_method_register(eap);
  365. if (ret)
  366. eap_server_method_free(eap);
  367. return ret;
  368. }
  369. #endif /* CONFIG_HS20 */