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