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