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 const u8 eap_tls13_context[] = { EAP_TYPE_TLS }; 178 const u8 *context = NULL; 179 size_t context_len = 0; 180 181 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 182 183 if (data->ssl.tls_out) { 184 wpa_printf(MSG_DEBUG, "EAP-TLS: Fragment(s) remaining"); 185 return; 186 } 187 188 if (data->ssl.tls_v13) { 189 label = "EXPORTER_EAP_TLS_Key_Material"; 190 context = eap_tls13_context; 191 context_len = 1; 192 193 /* A possible NewSessionTicket may be received before 194 * EAP-Success, so need to allow it to be received. */ 195 ret->methodState = METHOD_MAY_CONT; 196 ret->decision = DECISION_COND_SUCC; 197 } else { 198 label = "client EAP encryption"; 199 200 ret->methodState = METHOD_DONE; 201 ret->decision = DECISION_UNCOND_SUCC; 202 } 203 204 eap_tls_free_key(data); 205 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, label, 206 context, context_len, 207 EAP_TLS_KEY_LEN + 208 EAP_EMSK_LEN); 209 if (data->key_data) { 210 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 211 data->key_data, EAP_TLS_KEY_LEN); 212 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 213 data->key_data + EAP_TLS_KEY_LEN, 214 EAP_EMSK_LEN); 215 } else { 216 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 217 } 218 219 os_free(data->session_id); 220 data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, 221 EAP_TYPE_TLS, 222 &data->id_len); 223 if (data->session_id) { 224 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", 225 data->session_id, data->id_len); 226 } else { 227 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); 228 } 229 } 230 231 232 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 233 struct eap_method_ret *ret, 234 const struct wpabuf *reqData) 235 { 236 size_t left; 237 int res; 238 struct wpabuf *resp; 239 u8 flags, id; 240 const u8 *pos; 241 struct eap_tls_data *data = priv; 242 struct wpabuf msg; 243 244 if (sm->waiting_ext_cert_check && data->pending_resp) { 245 struct eap_peer_config *config = eap_get_config(sm); 246 247 if (config->pending_ext_cert_check == EXT_CERT_CHECK_GOOD) { 248 wpa_printf(MSG_DEBUG, 249 "EAP-TLS: External certificate check succeeded - continue handshake"); 250 resp = data->pending_resp; 251 data->pending_resp = NULL; 252 sm->waiting_ext_cert_check = 0; 253 return resp; 254 } 255 256 if (config->pending_ext_cert_check == EXT_CERT_CHECK_BAD) { 257 wpa_printf(MSG_DEBUG, 258 "EAP-TLS: External certificate check failed - force authentication failure"); 259 ret->methodState = METHOD_DONE; 260 ret->decision = DECISION_FAIL; 261 sm->waiting_ext_cert_check = 0; 262 return NULL; 263 } 264 265 wpa_printf(MSG_DEBUG, 266 "EAP-TLS: Continuing to wait external server certificate validation"); 267 return NULL; 268 } 269 270 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 271 reqData, &left, &flags); 272 if (pos == NULL) 273 return NULL; 274 id = eap_get_id(reqData); 275 276 if (flags & EAP_TLS_FLAGS_START) { 277 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 278 left = 0; /* make sure that this frame is empty, even though it 279 * should always be, anyway */ 280 } 281 282 resp = NULL; 283 wpabuf_set(&msg, pos, left); 284 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 285 id, &msg, &resp); 286 287 if (res < 0) { 288 return eap_tls_failure(sm, data, ret, res, resp, id); 289 } 290 291 if (sm->waiting_ext_cert_check) { 292 wpa_printf(MSG_DEBUG, 293 "EAP-TLS: Waiting external server certificate validation"); 294 wpabuf_free(data->pending_resp); 295 data->pending_resp = resp; 296 return NULL; 297 } 298 299 if (res == 2) { 300 /* Application data included in the handshake message (used by 301 * EAP-TLS 1.3 to indicate conclusion of the exchange). */ 302 wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Received Application Data", 303 resp); 304 wpa_hexdump_buf(MSG_DEBUG, "EAP-TLS: Remaining tls_out data", 305 data->ssl.tls_out); 306 eap_peer_tls_reset_output(&data->ssl); 307 /* Send an ACK to allow the server to complete exchange */ 308 res = 1; 309 } 310 311 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 312 eap_tls_success(sm, data, ret); 313 314 if (res == 1) { 315 wpabuf_free(resp); 316 return eap_peer_tls_build_ack(id, data->eap_type, 0); 317 } 318 319 return resp; 320 } 321 322 323 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 324 { 325 struct eap_tls_data *data = priv; 326 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 327 } 328 329 330 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 331 { 332 struct eap_tls_data *data = priv; 333 334 wpabuf_free(data->pending_resp); 335 data->pending_resp = NULL; 336 } 337 338 339 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 340 { 341 struct eap_tls_data *data = priv; 342 eap_tls_free_key(data); 343 os_free(data->session_id); 344 data->session_id = NULL; 345 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 346 os_free(data); 347 return NULL; 348 } 349 return priv; 350 } 351 352 353 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 354 size_t buflen, int verbose) 355 { 356 struct eap_tls_data *data = priv; 357 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 358 } 359 360 361 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 362 { 363 struct eap_tls_data *data = priv; 364 return data->key_data != NULL; 365 } 366 367 368 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 369 { 370 struct eap_tls_data *data = priv; 371 u8 *key; 372 373 if (data->key_data == NULL) 374 return NULL; 375 376 key = os_memdup(data->key_data, EAP_TLS_KEY_LEN); 377 if (key == NULL) 378 return NULL; 379 380 *len = EAP_TLS_KEY_LEN; 381 382 return key; 383 } 384 385 386 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 387 { 388 struct eap_tls_data *data = priv; 389 u8 *key; 390 391 if (data->key_data == NULL) 392 return NULL; 393 394 key = os_memdup(data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 395 if (key == NULL) 396 return NULL; 397 398 *len = EAP_EMSK_LEN; 399 400 return key; 401 } 402 403 404 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 405 { 406 struct eap_tls_data *data = priv; 407 u8 *id; 408 409 if (data->session_id == NULL) 410 return NULL; 411 412 id = os_memdup(data->session_id, data->id_len); 413 if (id == NULL) 414 return NULL; 415 416 *len = data->id_len; 417 418 return id; 419 } 420 421 422 int eap_peer_tls_register(void) 423 { 424 struct eap_method *eap; 425 426 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 427 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 428 if (eap == NULL) 429 return -1; 430 431 eap->init = eap_tls_init; 432 eap->deinit = eap_tls_deinit; 433 eap->process = eap_tls_process; 434 eap->isKeyAvailable = eap_tls_isKeyAvailable; 435 eap->getKey = eap_tls_getKey; 436 eap->getSessionId = eap_tls_get_session_id; 437 eap->get_status = eap_tls_get_status; 438 eap->has_reauth_data = eap_tls_has_reauth_data; 439 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 440 eap->init_for_reauth = eap_tls_init_for_reauth; 441 eap->get_emsk = eap_tls_get_emsk; 442 443 return eap_peer_method_register(eap); 444 } 445 446 447 #ifdef EAP_UNAUTH_TLS 448 int eap_peer_unauth_tls_register(void) 449 { 450 struct eap_method *eap; 451 452 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 453 EAP_VENDOR_UNAUTH_TLS, 454 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 455 if (eap == NULL) 456 return -1; 457 458 eap->init = eap_unauth_tls_init; 459 eap->deinit = eap_tls_deinit; 460 eap->process = eap_tls_process; 461 eap->isKeyAvailable = eap_tls_isKeyAvailable; 462 eap->getKey = eap_tls_getKey; 463 eap->get_status = eap_tls_get_status; 464 eap->has_reauth_data = eap_tls_has_reauth_data; 465 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 466 eap->init_for_reauth = eap_tls_init_for_reauth; 467 eap->get_emsk = eap_tls_get_emsk; 468 469 return eap_peer_method_register(eap); 470 } 471 #endif /* EAP_UNAUTH_TLS */ 472 473 474 #ifdef CONFIG_HS20 475 int eap_peer_wfa_unauth_tls_register(void) 476 { 477 struct eap_method *eap; 478 479 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 480 EAP_VENDOR_WFA_NEW, 481 EAP_VENDOR_WFA_UNAUTH_TLS, 482 "WFA-UNAUTH-TLS"); 483 if (eap == NULL) 484 return -1; 485 486 eap->init = eap_wfa_unauth_tls_init; 487 eap->deinit = eap_tls_deinit; 488 eap->process = eap_tls_process; 489 eap->isKeyAvailable = eap_tls_isKeyAvailable; 490 eap->getKey = eap_tls_getKey; 491 eap->get_status = eap_tls_get_status; 492 eap->has_reauth_data = eap_tls_has_reauth_data; 493 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 494 eap->init_for_reauth = eap_tls_init_for_reauth; 495 eap->get_emsk = eap_tls_get_emsk; 496 497 return eap_peer_method_register(eap); 498 } 499 #endif /* CONFIG_HS20 */ 500