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 18 static void eap_tls_deinit(struct eap_sm *sm, void *priv); 19 20 21 struct eap_tls_data { 22 struct eap_ssl_data ssl; 23 u8 *key_data; 24 u8 *session_id; 25 size_t id_len; 26 void *ssl_ctx; 27 u8 eap_type; 28 }; 29 30 31 static void * eap_tls_init(struct eap_sm *sm) 32 { 33 struct eap_tls_data *data; 34 struct eap_peer_config *config = eap_get_config(sm); 35 if (config == NULL || 36 ((sm->init_phase2 ? config->private_key2 : config->private_key) 37 == NULL && 38 (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { 39 wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); 40 return NULL; 41 } 42 43 data = os_zalloc(sizeof(*data)); 44 if (data == NULL) 45 return NULL; 46 47 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 48 sm->ssl_ctx; 49 50 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) { 51 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 52 eap_tls_deinit(sm, data); 53 if (config->engine) { 54 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " 55 "PIN"); 56 eap_sm_request_pin(sm); 57 sm->ignore = TRUE; 58 } else if (config->private_key && !config->private_key_passwd) 59 { 60 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " 61 "key passphrase"); 62 eap_sm_request_passphrase(sm); 63 sm->ignore = TRUE; 64 } 65 return NULL; 66 } 67 68 data->eap_type = EAP_TYPE_TLS; 69 70 return data; 71 } 72 73 74 #ifdef EAP_UNAUTH_TLS 75 static void * eap_unauth_tls_init(struct eap_sm *sm) 76 { 77 struct eap_tls_data *data; 78 struct eap_peer_config *config = eap_get_config(sm); 79 80 data = os_zalloc(sizeof(*data)); 81 if (data == NULL) 82 return NULL; 83 84 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 85 sm->ssl_ctx; 86 87 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, 88 EAP_UNAUTH_TLS_TYPE)) { 89 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 90 eap_tls_deinit(sm, data); 91 return NULL; 92 } 93 94 data->eap_type = EAP_UNAUTH_TLS_TYPE; 95 96 return data; 97 } 98 #endif /* EAP_UNAUTH_TLS */ 99 100 101 #ifdef CONFIG_HS20 102 static void * eap_wfa_unauth_tls_init(struct eap_sm *sm) 103 { 104 struct eap_tls_data *data; 105 struct eap_peer_config *config = eap_get_config(sm); 106 107 data = os_zalloc(sizeof(*data)); 108 if (data == NULL) 109 return NULL; 110 111 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 112 sm->ssl_ctx; 113 114 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, 115 EAP_WFA_UNAUTH_TLS_TYPE)) { 116 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 117 eap_tls_deinit(sm, data); 118 return NULL; 119 } 120 121 data->eap_type = EAP_WFA_UNAUTH_TLS_TYPE; 122 123 return data; 124 } 125 #endif /* CONFIG_HS20 */ 126 127 128 static void eap_tls_free_key(struct eap_tls_data *data) 129 { 130 if (data->key_data) { 131 bin_clear_free(data->key_data, EAP_TLS_KEY_LEN + EAP_EMSK_LEN); 132 data->key_data = NULL; 133 } 134 } 135 136 137 static void eap_tls_deinit(struct eap_sm *sm, void *priv) 138 { 139 struct eap_tls_data *data = priv; 140 if (data == NULL) 141 return; 142 eap_peer_tls_ssl_deinit(sm, &data->ssl); 143 eap_tls_free_key(data); 144 os_free(data->session_id); 145 os_free(data); 146 } 147 148 149 static struct wpabuf * eap_tls_failure(struct eap_sm *sm, 150 struct eap_tls_data *data, 151 struct eap_method_ret *ret, int res, 152 struct wpabuf *resp, u8 id) 153 { 154 wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); 155 156 ret->methodState = METHOD_DONE; 157 ret->decision = DECISION_FAIL; 158 159 if (resp) { 160 /* 161 * This is likely an alert message, so send it instead of just 162 * ACKing the error. 163 */ 164 return resp; 165 } 166 167 return eap_peer_tls_build_ack(id, data->eap_type, 0); 168 } 169 170 171 static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 172 struct eap_method_ret *ret) 173 { 174 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 175 176 ret->methodState = METHOD_DONE; 177 ret->decision = DECISION_UNCOND_SUCC; 178 179 eap_tls_free_key(data); 180 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 181 "client EAP encryption", 182 EAP_TLS_KEY_LEN + 183 EAP_EMSK_LEN); 184 if (data->key_data) { 185 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 186 data->key_data, EAP_TLS_KEY_LEN); 187 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 188 data->key_data + EAP_TLS_KEY_LEN, 189 EAP_EMSK_LEN); 190 } else { 191 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 192 } 193 194 os_free(data->session_id); 195 data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, 196 EAP_TYPE_TLS, 197 &data->id_len); 198 if (data->session_id) { 199 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", 200 data->session_id, data->id_len); 201 } else { 202 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); 203 } 204 } 205 206 207 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 208 struct eap_method_ret *ret, 209 const struct wpabuf *reqData) 210 { 211 size_t left; 212 int res; 213 struct wpabuf *resp; 214 u8 flags, id; 215 const u8 *pos; 216 struct eap_tls_data *data = priv; 217 struct wpabuf msg; 218 219 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 220 reqData, &left, &flags); 221 if (pos == NULL) 222 return NULL; 223 id = eap_get_id(reqData); 224 225 if (flags & EAP_TLS_FLAGS_START) { 226 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 227 left = 0; /* make sure that this frame is empty, even though it 228 * should always be, anyway */ 229 } 230 231 resp = NULL; 232 wpabuf_set(&msg, pos, left); 233 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 234 id, &msg, &resp); 235 236 if (res < 0) { 237 return eap_tls_failure(sm, data, ret, res, resp, id); 238 } 239 240 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 241 eap_tls_success(sm, data, ret); 242 243 if (res == 1) { 244 wpabuf_free(resp); 245 return eap_peer_tls_build_ack(id, data->eap_type, 0); 246 } 247 248 return resp; 249 } 250 251 252 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 253 { 254 struct eap_tls_data *data = priv; 255 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 256 } 257 258 259 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 260 { 261 } 262 263 264 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 265 { 266 struct eap_tls_data *data = priv; 267 eap_tls_free_key(data); 268 os_free(data->session_id); 269 data->session_id = NULL; 270 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 271 os_free(data); 272 return NULL; 273 } 274 return priv; 275 } 276 277 278 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 279 size_t buflen, int verbose) 280 { 281 struct eap_tls_data *data = priv; 282 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 283 } 284 285 286 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 287 { 288 struct eap_tls_data *data = priv; 289 return data->key_data != NULL; 290 } 291 292 293 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 294 { 295 struct eap_tls_data *data = priv; 296 u8 *key; 297 298 if (data->key_data == NULL) 299 return NULL; 300 301 key = os_malloc(EAP_TLS_KEY_LEN); 302 if (key == NULL) 303 return NULL; 304 305 *len = EAP_TLS_KEY_LEN; 306 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 307 308 return key; 309 } 310 311 312 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 313 { 314 struct eap_tls_data *data = priv; 315 u8 *key; 316 317 if (data->key_data == NULL) 318 return NULL; 319 320 key = os_malloc(EAP_EMSK_LEN); 321 if (key == NULL) 322 return NULL; 323 324 *len = EAP_EMSK_LEN; 325 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 326 327 return key; 328 } 329 330 331 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 332 { 333 struct eap_tls_data *data = priv; 334 u8 *id; 335 336 if (data->session_id == NULL) 337 return NULL; 338 339 id = os_malloc(data->id_len); 340 if (id == NULL) 341 return NULL; 342 343 *len = data->id_len; 344 os_memcpy(id, data->session_id, data->id_len); 345 346 return id; 347 } 348 349 350 int eap_peer_tls_register(void) 351 { 352 struct eap_method *eap; 353 int ret; 354 355 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 356 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 357 if (eap == NULL) 358 return -1; 359 360 eap->init = eap_tls_init; 361 eap->deinit = eap_tls_deinit; 362 eap->process = eap_tls_process; 363 eap->isKeyAvailable = eap_tls_isKeyAvailable; 364 eap->getKey = eap_tls_getKey; 365 eap->getSessionId = eap_tls_get_session_id; 366 eap->get_status = eap_tls_get_status; 367 eap->has_reauth_data = eap_tls_has_reauth_data; 368 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 369 eap->init_for_reauth = eap_tls_init_for_reauth; 370 eap->get_emsk = eap_tls_get_emsk; 371 372 ret = eap_peer_method_register(eap); 373 if (ret) 374 eap_peer_method_free(eap); 375 return ret; 376 } 377 378 379 #ifdef EAP_UNAUTH_TLS 380 int eap_peer_unauth_tls_register(void) 381 { 382 struct eap_method *eap; 383 int ret; 384 385 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 386 EAP_VENDOR_UNAUTH_TLS, 387 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 388 if (eap == NULL) 389 return -1; 390 391 eap->init = eap_unauth_tls_init; 392 eap->deinit = eap_tls_deinit; 393 eap->process = eap_tls_process; 394 eap->isKeyAvailable = eap_tls_isKeyAvailable; 395 eap->getKey = eap_tls_getKey; 396 eap->get_status = eap_tls_get_status; 397 eap->has_reauth_data = eap_tls_has_reauth_data; 398 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 399 eap->init_for_reauth = eap_tls_init_for_reauth; 400 eap->get_emsk = eap_tls_get_emsk; 401 402 ret = eap_peer_method_register(eap); 403 if (ret) 404 eap_peer_method_free(eap); 405 return ret; 406 } 407 #endif /* EAP_UNAUTH_TLS */ 408 409 410 #ifdef CONFIG_HS20 411 int eap_peer_wfa_unauth_tls_register(void) 412 { 413 struct eap_method *eap; 414 int ret; 415 416 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 417 EAP_VENDOR_WFA_NEW, 418 EAP_VENDOR_WFA_UNAUTH_TLS, 419 "WFA-UNAUTH-TLS"); 420 if (eap == NULL) 421 return -1; 422 423 eap->init = eap_wfa_unauth_tls_init; 424 eap->deinit = eap_tls_deinit; 425 eap->process = eap_tls_process; 426 eap->isKeyAvailable = eap_tls_isKeyAvailable; 427 eap->getKey = eap_tls_getKey; 428 eap->get_status = eap_tls_get_status; 429 eap->has_reauth_data = eap_tls_has_reauth_data; 430 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 431 eap->init_for_reauth = eap_tls_init_for_reauth; 432 eap->get_emsk = eap_tls_get_emsk; 433 434 ret = eap_peer_method_register(eap); 435 if (ret) 436 eap_peer_method_free(eap); 437 return ret; 438 } 439 #endif /* CONFIG_HS20 */ 440