1 /* 2 * EAP peer method: EAP-TLS (RFC 2716) 3 * Copyright (c) 2004-2008, 2012, Jouni Malinen <j (at) 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 (res == -1) { 160 struct eap_peer_config *config = eap_get_config(sm); 161 if (config) { 162 /* 163 * The TLS handshake failed. So better forget the old 164 * PIN. It may be wrong, we cannot be sure but trying 165 * the wrong one again might block it on the card--so 166 * better ask the user again. 167 */ 168 os_free(config->pin); 169 config->pin = NULL; 170 } 171 } 172 173 if (resp) { 174 /* 175 * This is likely an alert message, so send it instead of just 176 * ACKing the error. 177 */ 178 return resp; 179 } 180 181 return eap_peer_tls_build_ack(id, data->eap_type, 0); 182 } 183 184 185 static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 186 struct eap_method_ret *ret) 187 { 188 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 189 190 ret->methodState = METHOD_DONE; 191 ret->decision = DECISION_UNCOND_SUCC; 192 193 eap_tls_free_key(data); 194 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 195 "client EAP encryption", 196 EAP_TLS_KEY_LEN + 197 EAP_EMSK_LEN); 198 if (data->key_data) { 199 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 200 data->key_data, EAP_TLS_KEY_LEN); 201 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 202 data->key_data + EAP_TLS_KEY_LEN, 203 EAP_EMSK_LEN); 204 } else { 205 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 206 } 207 208 os_free(data->session_id); 209 data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, 210 EAP_TYPE_TLS, 211 &data->id_len); 212 if (data->session_id) { 213 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", 214 data->session_id, data->id_len); 215 } else { 216 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); 217 } 218 } 219 220 221 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 222 struct eap_method_ret *ret, 223 const struct wpabuf *reqData) 224 { 225 size_t left; 226 int res; 227 struct wpabuf *resp; 228 u8 flags, id; 229 const u8 *pos; 230 struct eap_tls_data *data = priv; 231 struct wpabuf msg; 232 233 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 234 reqData, &left, &flags); 235 if (pos == NULL) 236 return NULL; 237 id = eap_get_id(reqData); 238 239 if (flags & EAP_TLS_FLAGS_START) { 240 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 241 left = 0; /* make sure that this frame is empty, even though it 242 * should always be, anyway */ 243 } 244 245 resp = NULL; 246 wpabuf_set(&msg, pos, left); 247 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 248 id, &msg, &resp); 249 250 if (res < 0) { 251 return eap_tls_failure(sm, data, ret, res, resp, id); 252 } 253 254 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 255 eap_tls_success(sm, data, ret); 256 257 if (res == 1) { 258 wpabuf_free(resp); 259 return eap_peer_tls_build_ack(id, data->eap_type, 0); 260 } 261 262 return resp; 263 } 264 265 266 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 267 { 268 struct eap_tls_data *data = priv; 269 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 270 } 271 272 273 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 274 { 275 } 276 277 278 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 279 { 280 struct eap_tls_data *data = priv; 281 eap_tls_free_key(data); 282 os_free(data->session_id); 283 data->session_id = NULL; 284 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 285 os_free(data); 286 return NULL; 287 } 288 return priv; 289 } 290 291 292 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 293 size_t buflen, int verbose) 294 { 295 struct eap_tls_data *data = priv; 296 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 297 } 298 299 300 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 301 { 302 struct eap_tls_data *data = priv; 303 return data->key_data != NULL; 304 } 305 306 307 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 308 { 309 struct eap_tls_data *data = priv; 310 u8 *key; 311 312 if (data->key_data == NULL) 313 return NULL; 314 315 key = os_malloc(EAP_TLS_KEY_LEN); 316 if (key == NULL) 317 return NULL; 318 319 *len = EAP_TLS_KEY_LEN; 320 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 321 322 return key; 323 } 324 325 326 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 327 { 328 struct eap_tls_data *data = priv; 329 u8 *key; 330 331 if (data->key_data == NULL) 332 return NULL; 333 334 key = os_malloc(EAP_EMSK_LEN); 335 if (key == NULL) 336 return NULL; 337 338 *len = EAP_EMSK_LEN; 339 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 340 341 return key; 342 } 343 344 345 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 346 { 347 struct eap_tls_data *data = priv; 348 u8 *id; 349 350 if (data->session_id == NULL) 351 return NULL; 352 353 id = os_malloc(data->id_len); 354 if (id == NULL) 355 return NULL; 356 357 *len = data->id_len; 358 os_memcpy(id, data->session_id, data->id_len); 359 360 return id; 361 } 362 363 364 int eap_peer_tls_register(void) 365 { 366 struct eap_method *eap; 367 int ret; 368 369 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 370 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 371 if (eap == NULL) 372 return -1; 373 374 eap->init = eap_tls_init; 375 eap->deinit = eap_tls_deinit; 376 eap->process = eap_tls_process; 377 eap->isKeyAvailable = eap_tls_isKeyAvailable; 378 eap->getKey = eap_tls_getKey; 379 eap->getSessionId = eap_tls_get_session_id; 380 eap->get_status = eap_tls_get_status; 381 eap->has_reauth_data = eap_tls_has_reauth_data; 382 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 383 eap->init_for_reauth = eap_tls_init_for_reauth; 384 eap->get_emsk = eap_tls_get_emsk; 385 386 ret = eap_peer_method_register(eap); 387 if (ret) 388 eap_peer_method_free(eap); 389 return ret; 390 } 391 392 393 #ifdef EAP_UNAUTH_TLS 394 int eap_peer_unauth_tls_register(void) 395 { 396 struct eap_method *eap; 397 int ret; 398 399 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 400 EAP_VENDOR_UNAUTH_TLS, 401 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 402 if (eap == NULL) 403 return -1; 404 405 eap->init = eap_unauth_tls_init; 406 eap->deinit = eap_tls_deinit; 407 eap->process = eap_tls_process; 408 eap->isKeyAvailable = eap_tls_isKeyAvailable; 409 eap->getKey = eap_tls_getKey; 410 eap->get_status = eap_tls_get_status; 411 eap->has_reauth_data = eap_tls_has_reauth_data; 412 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 413 eap->init_for_reauth = eap_tls_init_for_reauth; 414 eap->get_emsk = eap_tls_get_emsk; 415 416 ret = eap_peer_method_register(eap); 417 if (ret) 418 eap_peer_method_free(eap); 419 return ret; 420 } 421 #endif /* EAP_UNAUTH_TLS */ 422 423 424 #ifdef CONFIG_HS20 425 int eap_peer_wfa_unauth_tls_register(void) 426 { 427 struct eap_method *eap; 428 int ret; 429 430 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 431 EAP_VENDOR_WFA_NEW, 432 EAP_VENDOR_WFA_UNAUTH_TLS, 433 "WFA-UNAUTH-TLS"); 434 if (eap == NULL) 435 return -1; 436 437 eap->init = eap_wfa_unauth_tls_init; 438 eap->deinit = eap_tls_deinit; 439 eap->process = eap_tls_process; 440 eap->isKeyAvailable = eap_tls_isKeyAvailable; 441 eap->getKey = eap_tls_getKey; 442 eap->get_status = eap_tls_get_status; 443 eap->has_reauth_data = eap_tls_has_reauth_data; 444 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 445 eap->init_for_reauth = eap_tls_init_for_reauth; 446 eap->get_emsk = eap_tls_get_emsk; 447 448 ret = eap_peer_method_register(eap); 449 if (ret) 450 eap_peer_method_free(eap); 451 return ret; 452 } 453 #endif /* CONFIG_HS20 */ 454