1/* 2 * EAP peer method: EAP-TLS (RFC 2716) 3 * Copyright (c) 2004-2008, 2012, 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 9#include "includes.h" 10 11#include "common.h" 12#include "crypto/tls.h" 13#include "eap_i.h" 14#include "eap_tls_common.h" 15#include "eap_config.h" 16 17 18static void eap_tls_deinit(struct eap_sm *sm, void *priv); 19 20 21struct eap_tls_data { 22 struct eap_ssl_data ssl; 23 u8 *key_data; 24 void *ssl_ctx; 25 u8 eap_type; 26}; 27 28 29static void * eap_tls_init(struct eap_sm *sm) 30{ 31 struct eap_tls_data *data; 32 struct eap_peer_config *config = eap_get_config(sm); 33 if (config == NULL || 34 ((sm->init_phase2 ? config->private_key2 : config->private_key) 35 == NULL && 36 (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { 37 wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); 38 return NULL; 39 } 40 41 data = os_zalloc(sizeof(*data)); 42 if (data == NULL) 43 return NULL; 44 45 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 46 sm->ssl_ctx; 47 48 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) { 49 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 50 eap_tls_deinit(sm, data); 51 if (config->engine) { 52 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " 53 "PIN"); 54 eap_sm_request_pin(sm); 55 sm->ignore = TRUE; 56 } else if (config->private_key && !config->private_key_passwd) 57 { 58 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " 59 "key passphrase"); 60 eap_sm_request_passphrase(sm); 61 sm->ignore = TRUE; 62 } 63 return NULL; 64 } 65 66 data->eap_type = EAP_TYPE_TLS; 67 68 return data; 69} 70 71 72#ifdef EAP_UNAUTH_TLS 73static void * eap_unauth_tls_init(struct eap_sm *sm) 74{ 75 struct eap_tls_data *data; 76 struct eap_peer_config *config = eap_get_config(sm); 77 78 data = os_zalloc(sizeof(*data)); 79 if (data == NULL) 80 return NULL; 81 82 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 83 sm->ssl_ctx; 84 85 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, 86 EAP_UNAUTH_TLS_TYPE)) { 87 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 88 eap_tls_deinit(sm, data); 89 return NULL; 90 } 91 92 data->eap_type = EAP_UNAUTH_TLS_TYPE; 93 94 return data; 95} 96#endif /* EAP_UNAUTH_TLS */ 97 98 99static void eap_tls_deinit(struct eap_sm *sm, void *priv) 100{ 101 struct eap_tls_data *data = priv; 102 if (data == NULL) 103 return; 104 eap_peer_tls_ssl_deinit(sm, &data->ssl); 105 os_free(data->key_data); 106 os_free(data); 107} 108 109 110static struct wpabuf * eap_tls_failure(struct eap_sm *sm, 111 struct eap_tls_data *data, 112 struct eap_method_ret *ret, int res, 113 struct wpabuf *resp, u8 id) 114{ 115 wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); 116 117 ret->methodState = METHOD_DONE; 118 ret->decision = DECISION_FAIL; 119 120 if (res == -1) { 121 struct eap_peer_config *config = eap_get_config(sm); 122 if (config) { 123 /* 124 * The TLS handshake failed. So better forget the old 125 * PIN. It may be wrong, we cannot be sure but trying 126 * the wrong one again might block it on the card--so 127 * better ask the user again. 128 */ 129 os_free(config->pin); 130 config->pin = NULL; 131 } 132 } 133 134 if (resp) { 135 /* 136 * This is likely an alert message, so send it instead of just 137 * ACKing the error. 138 */ 139 return resp; 140 } 141 142 return eap_peer_tls_build_ack(id, data->eap_type, 0); 143} 144 145 146static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 147 struct eap_method_ret *ret) 148{ 149 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 150 151 ret->methodState = METHOD_DONE; 152 ret->decision = DECISION_UNCOND_SUCC; 153 154 os_free(data->key_data); 155 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 156 "client EAP encryption", 157 EAP_TLS_KEY_LEN + 158 EAP_EMSK_LEN); 159 if (data->key_data) { 160 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 161 data->key_data, EAP_TLS_KEY_LEN); 162 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 163 data->key_data + EAP_TLS_KEY_LEN, 164 EAP_EMSK_LEN); 165 } else { 166 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 167 } 168} 169 170 171static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 172 struct eap_method_ret *ret, 173 const struct wpabuf *reqData) 174{ 175 size_t left; 176 int res; 177 struct wpabuf *resp; 178 u8 flags, id; 179 const u8 *pos; 180 struct eap_tls_data *data = priv; 181 182 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 183 reqData, &left, &flags); 184 if (pos == NULL) 185 return NULL; 186 id = eap_get_id(reqData); 187 188 if (flags & EAP_TLS_FLAGS_START) { 189 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 190 left = 0; /* make sure that this frame is empty, even though it 191 * should always be, anyway */ 192 } 193 194 resp = NULL; 195 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 196 id, pos, left, &resp); 197 198 if (res < 0) { 199 return eap_tls_failure(sm, data, ret, res, resp, id); 200 } 201 202 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 203 eap_tls_success(sm, data, ret); 204 205 if (res == 1) { 206 wpabuf_free(resp); 207 return eap_peer_tls_build_ack(id, data->eap_type, 0); 208 } 209 210 return resp; 211} 212 213 214static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 215{ 216 struct eap_tls_data *data = priv; 217 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 218} 219 220 221static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 222{ 223} 224 225 226static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 227{ 228 struct eap_tls_data *data = priv; 229 os_free(data->key_data); 230 data->key_data = NULL; 231 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 232 os_free(data); 233 return NULL; 234 } 235 return priv; 236} 237 238 239static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 240 size_t buflen, int verbose) 241{ 242 struct eap_tls_data *data = priv; 243 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 244} 245 246 247static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 248{ 249 struct eap_tls_data *data = priv; 250 return data->key_data != NULL; 251} 252 253 254static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 255{ 256 struct eap_tls_data *data = priv; 257 u8 *key; 258 259 if (data->key_data == NULL) 260 return NULL; 261 262 key = os_malloc(EAP_TLS_KEY_LEN); 263 if (key == NULL) 264 return NULL; 265 266 *len = EAP_TLS_KEY_LEN; 267 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 268 269 return key; 270} 271 272 273static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 274{ 275 struct eap_tls_data *data = priv; 276 u8 *key; 277 278 if (data->key_data == NULL) 279 return NULL; 280 281 key = os_malloc(EAP_EMSK_LEN); 282 if (key == NULL) 283 return NULL; 284 285 *len = EAP_EMSK_LEN; 286 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 287 288 return key; 289} 290 291 292int eap_peer_tls_register(void) 293{ 294 struct eap_method *eap; 295 int ret; 296 297 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 298 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 299 if (eap == NULL) 300 return -1; 301 302 eap->init = eap_tls_init; 303 eap->deinit = eap_tls_deinit; 304 eap->process = eap_tls_process; 305 eap->isKeyAvailable = eap_tls_isKeyAvailable; 306 eap->getKey = eap_tls_getKey; 307 eap->get_status = eap_tls_get_status; 308 eap->has_reauth_data = eap_tls_has_reauth_data; 309 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 310 eap->init_for_reauth = eap_tls_init_for_reauth; 311 eap->get_emsk = eap_tls_get_emsk; 312 313 ret = eap_peer_method_register(eap); 314 if (ret) 315 eap_peer_method_free(eap); 316 return ret; 317} 318 319 320#ifdef EAP_UNAUTH_TLS 321int eap_peer_unauth_tls_register(void) 322{ 323 struct eap_method *eap; 324 int ret; 325 326 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 327 EAP_VENDOR_UNAUTH_TLS, 328 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 329 if (eap == NULL) 330 return -1; 331 332 eap->init = eap_unauth_tls_init; 333 eap->deinit = eap_tls_deinit; 334 eap->process = eap_tls_process; 335 eap->isKeyAvailable = eap_tls_isKeyAvailable; 336 eap->getKey = eap_tls_getKey; 337 eap->get_status = eap_tls_get_status; 338 eap->has_reauth_data = eap_tls_has_reauth_data; 339 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 340 eap->init_for_reauth = eap_tls_init_for_reauth; 341 eap->get_emsk = eap_tls_get_emsk; 342 343 ret = eap_peer_method_register(eap); 344 if (ret) 345 eap_peer_method_free(eap); 346 return ret; 347} 348#endif /* EAP_UNAUTH_TLS */ 349