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