eap_server_tls.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. }
  42. static void * eap_tls_init(struct eap_sm *sm)
  43. {
  44. struct eap_tls_data *data;
  45. data = os_zalloc(sizeof(*data));
  46. if (data == NULL)
  47. return NULL;
  48. data->state = START;
  49. if (eap_server_tls_ssl_init(sm, &data->ssl, 1)) {
  50. wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
  51. eap_tls_reset(sm, data);
  52. return NULL;
  53. }
  54. data->eap_type = EAP_TYPE_TLS;
  55. return data;
  56. }
  57. #ifdef EAP_SERVER_UNAUTH_TLS
  58. static void * eap_unauth_tls_init(struct eap_sm *sm)
  59. {
  60. struct eap_tls_data *data;
  61. data = os_zalloc(sizeof(*data));
  62. if (data == NULL)
  63. return NULL;
  64. data->state = START;
  65. if (eap_server_tls_ssl_init(sm, &data->ssl, 0)) {
  66. wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL.");
  67. eap_tls_reset(sm, data);
  68. return NULL;
  69. }
  70. data->eap_type = EAP_UNAUTH_TLS_TYPE;
  71. return data;
  72. }
  73. #endif /* EAP_SERVER_UNAUTH_TLS */
  74. static void eap_tls_reset(struct eap_sm *sm, void *priv)
  75. {
  76. struct eap_tls_data *data = priv;
  77. if (data == NULL)
  78. return;
  79. eap_server_tls_ssl_deinit(sm, &data->ssl);
  80. os_free(data);
  81. }
  82. static struct wpabuf * eap_tls_build_start(struct eap_sm *sm,
  83. struct eap_tls_data *data, u8 id)
  84. {
  85. struct wpabuf *req;
  86. req = eap_tls_msg_alloc(data->eap_type, 1, EAP_CODE_REQUEST, id);
  87. if (req == NULL) {
  88. wpa_printf(MSG_ERROR, "EAP-TLS: Failed to allocate memory for "
  89. "request");
  90. eap_tls_state(data, FAILURE);
  91. return NULL;
  92. }
  93. wpabuf_put_u8(req, EAP_TLS_FLAGS_START);
  94. eap_tls_state(data, CONTINUE);
  95. return req;
  96. }
  97. static struct wpabuf * eap_tls_buildReq(struct eap_sm *sm, void *priv, u8 id)
  98. {
  99. struct eap_tls_data *data = priv;
  100. struct wpabuf *res;
  101. if (data->ssl.state == FRAG_ACK) {
  102. return eap_server_tls_build_ack(id, data->eap_type, 0);
  103. }
  104. if (data->ssl.state == WAIT_FRAG_ACK) {
  105. res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0,
  106. id);
  107. goto check_established;
  108. }
  109. switch (data->state) {
  110. case START:
  111. return eap_tls_build_start(sm, data, id);
  112. case CONTINUE:
  113. if (tls_connection_established(sm->ssl_ctx, data->ssl.conn))
  114. data->established = 1;
  115. break;
  116. default:
  117. wpa_printf(MSG_DEBUG, "EAP-TLS: %s - unexpected state %d",
  118. __func__, data->state);
  119. return NULL;
  120. }
  121. res = eap_server_tls_build_msg(&data->ssl, data->eap_type, 0, id);
  122. check_established:
  123. if (data->established && data->ssl.state != WAIT_FRAG_ACK) {
  124. /* TLS handshake has been completed and there are no more
  125. * fragments waiting to be sent out. */
  126. wpa_printf(MSG_DEBUG, "EAP-TLS: Done");
  127. eap_tls_state(data, SUCCESS);
  128. }
  129. return res;
  130. }
  131. static Boolean eap_tls_check(struct eap_sm *sm, void *priv,
  132. struct wpabuf *respData)
  133. {
  134. struct eap_tls_data *data = priv;
  135. const u8 *pos;
  136. size_t len;
  137. if (data->eap_type == EAP_UNAUTH_TLS_TYPE)
  138. pos = eap_hdr_validate(EAP_VENDOR_UNAUTH_TLS,
  139. EAP_VENDOR_TYPE_UNAUTH_TLS, respData,
  140. &len);
  141. else
  142. pos = eap_hdr_validate(EAP_VENDOR_IETF, data->eap_type,
  143. respData, &len);
  144. if (pos == NULL || len < 1) {
  145. wpa_printf(MSG_INFO, "EAP-TLS: Invalid frame");
  146. return TRUE;
  147. }
  148. return FALSE;
  149. }
  150. static void eap_tls_process_msg(struct eap_sm *sm, void *priv,
  151. const struct wpabuf *respData)
  152. {
  153. struct eap_tls_data *data = priv;
  154. if (data->state == SUCCESS && wpabuf_len(data->ssl.tls_in) == 0) {
  155. wpa_printf(MSG_DEBUG, "EAP-TLS: Client acknowledged final TLS "
  156. "handshake message");
  157. return;
  158. }
  159. if (eap_server_tls_phase1(sm, &data->ssl) < 0)
  160. eap_tls_state(data, FAILURE);
  161. }
  162. static void eap_tls_process(struct eap_sm *sm, void *priv,
  163. struct wpabuf *respData)
  164. {
  165. struct eap_tls_data *data = priv;
  166. if (eap_server_tls_process(sm, &data->ssl, respData, data,
  167. data->eap_type, NULL, eap_tls_process_msg) <
  168. 0)
  169. eap_tls_state(data, FAILURE);
  170. }
  171. static Boolean eap_tls_isDone(struct eap_sm *sm, void *priv)
  172. {
  173. struct eap_tls_data *data = priv;
  174. return data->state == SUCCESS || data->state == FAILURE;
  175. }
  176. static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len)
  177. {
  178. struct eap_tls_data *data = priv;
  179. u8 *eapKeyData;
  180. if (data->state != SUCCESS)
  181. return NULL;
  182. eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
  183. "client EAP encryption",
  184. EAP_TLS_KEY_LEN);
  185. if (eapKeyData) {
  186. *len = EAP_TLS_KEY_LEN;
  187. wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived key",
  188. eapKeyData, EAP_TLS_KEY_LEN);
  189. } else {
  190. wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive key");
  191. }
  192. return eapKeyData;
  193. }
  194. static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len)
  195. {
  196. struct eap_tls_data *data = priv;
  197. u8 *eapKeyData, *emsk;
  198. if (data->state != SUCCESS)
  199. return NULL;
  200. eapKeyData = eap_server_tls_derive_key(sm, &data->ssl,
  201. "client EAP encryption",
  202. EAP_TLS_KEY_LEN + EAP_EMSK_LEN);
  203. if (eapKeyData) {
  204. emsk = os_malloc(EAP_EMSK_LEN);
  205. if (emsk)
  206. os_memcpy(emsk, eapKeyData + EAP_TLS_KEY_LEN,
  207. EAP_EMSK_LEN);
  208. os_free(eapKeyData);
  209. } else
  210. emsk = NULL;
  211. if (emsk) {
  212. *len = EAP_EMSK_LEN;
  213. wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived EMSK",
  214. emsk, EAP_EMSK_LEN);
  215. } else {
  216. wpa_printf(MSG_DEBUG, "EAP-TLS: Failed to derive EMSK");
  217. }
  218. return emsk;
  219. }
  220. static Boolean eap_tls_isSuccess(struct eap_sm *sm, void *priv)
  221. {
  222. struct eap_tls_data *data = priv;
  223. return data->state == SUCCESS;
  224. }
  225. int eap_server_tls_register(void)
  226. {
  227. struct eap_method *eap;
  228. int ret;
  229. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  230. EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS");
  231. if (eap == NULL)
  232. return -1;
  233. eap->init = eap_tls_init;
  234. eap->reset = eap_tls_reset;
  235. eap->buildReq = eap_tls_buildReq;
  236. eap->check = eap_tls_check;
  237. eap->process = eap_tls_process;
  238. eap->isDone = eap_tls_isDone;
  239. eap->getKey = eap_tls_getKey;
  240. eap->isSuccess = eap_tls_isSuccess;
  241. eap->get_emsk = eap_tls_get_emsk;
  242. ret = eap_server_method_register(eap);
  243. if (ret)
  244. eap_server_method_free(eap);
  245. return ret;
  246. }
  247. #ifdef EAP_SERVER_UNAUTH_TLS
  248. int eap_server_unauth_tls_register(void)
  249. {
  250. struct eap_method *eap;
  251. int ret;
  252. eap = eap_server_method_alloc(EAP_SERVER_METHOD_INTERFACE_VERSION,
  253. EAP_VENDOR_UNAUTH_TLS,
  254. EAP_VENDOR_TYPE_UNAUTH_TLS,
  255. "UNAUTH-TLS");
  256. if (eap == NULL)
  257. return -1;
  258. eap->init = eap_unauth_tls_init;
  259. eap->reset = eap_tls_reset;
  260. eap->buildReq = eap_tls_buildReq;
  261. eap->check = eap_tls_check;
  262. eap->process = eap_tls_process;
  263. eap->isDone = eap_tls_isDone;
  264. eap->getKey = eap_tls_getKey;
  265. eap->isSuccess = eap_tls_isSuccess;
  266. eap->get_emsk = eap_tls_get_emsk;
  267. ret = eap_server_method_register(eap);
  268. if (ret)
  269. eap_server_method_free(eap);
  270. return ret;
  271. }
  272. #endif /* EAP_SERVER_UNAUTH_TLS */