1 /* 2 * EAP peer method: EAP-TLS (RFC 2716) 3 * Copyright (c) 2004-2008, 2012, 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 }; 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 232 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 233 reqData, &left, &flags); 234 if (pos == NULL) 235 return NULL; 236 id = eap_get_id(reqData); 237 238 if (flags & EAP_TLS_FLAGS_START) { 239 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 240 left = 0; /* make sure that this frame is empty, even though it 241 * should always be, anyway */ 242 } 243 244 resp = NULL; 245 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 246 id, pos, left, &resp); 247 248 if (res < 0) { 249 return eap_tls_failure(sm, data, ret, res, resp, id); 250 } 251 252 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 253 eap_tls_success(sm, data, ret); 254 255 if (res == 1) { 256 wpabuf_free(resp); 257 return eap_peer_tls_build_ack(id, data->eap_type, 0); 258 } 259 260 return resp; 261 } 262 263 264 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 265 { 266 struct eap_tls_data *data = priv; 267 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 268 } 269 270 271 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 272 { 273 } 274 275 276 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 277 { 278 struct eap_tls_data *data = priv; 279 eap_tls_free_key(data); 280 os_free(data->session_id); 281 data->session_id = NULL; 282 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 283 os_free(data); 284 return NULL; 285 } 286 return priv; 287 } 288 289 290 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 291 size_t buflen, int verbose) 292 { 293 struct eap_tls_data *data = priv; 294 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 295 } 296 297 298 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 299 { 300 struct eap_tls_data *data = priv; 301 return data->key_data != NULL; 302 } 303 304 305 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 306 { 307 struct eap_tls_data *data = priv; 308 u8 *key; 309 310 if (data->key_data == NULL) 311 return NULL; 312 313 key = os_malloc(EAP_TLS_KEY_LEN); 314 if (key == NULL) 315 return NULL; 316 317 *len = EAP_TLS_KEY_LEN; 318 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 319 320 return key; 321 } 322 323 324 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 325 { 326 struct eap_tls_data *data = priv; 327 u8 *key; 328 329 if (data->key_data == NULL) 330 return NULL; 331 332 key = os_malloc(EAP_EMSK_LEN); 333 if (key == NULL) 334 return NULL; 335 336 *len = EAP_EMSK_LEN; 337 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 338 339 return key; 340 } 341 342 343 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 344 { 345 struct eap_tls_data *data = priv; 346 u8 *id; 347 348 if (data->session_id == NULL) 349 return NULL; 350 351 id = os_malloc(data->id_len); 352 if (id == NULL) 353 return NULL; 354 355 *len = data->id_len; 356 os_memcpy(id, data->session_id, data->id_len); 357 358 return id; 359 } 360 361 362 int eap_peer_tls_register(void) 363 { 364 struct eap_method *eap; 365 int ret; 366 367 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 368 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 369 if (eap == NULL) 370 return -1; 371 372 eap->init = eap_tls_init; 373 eap->deinit = eap_tls_deinit; 374 eap->process = eap_tls_process; 375 eap->isKeyAvailable = eap_tls_isKeyAvailable; 376 eap->getKey = eap_tls_getKey; 377 eap->getSessionId = eap_tls_get_session_id; 378 eap->get_status = eap_tls_get_status; 379 eap->has_reauth_data = eap_tls_has_reauth_data; 380 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 381 eap->init_for_reauth = eap_tls_init_for_reauth; 382 eap->get_emsk = eap_tls_get_emsk; 383 384 ret = eap_peer_method_register(eap); 385 if (ret) 386 eap_peer_method_free(eap); 387 return ret; 388 } 389 390 391 #ifdef EAP_UNAUTH_TLS 392 int eap_peer_unauth_tls_register(void) 393 { 394 struct eap_method *eap; 395 int ret; 396 397 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 398 EAP_VENDOR_UNAUTH_TLS, 399 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 400 if (eap == NULL) 401 return -1; 402 403 eap->init = eap_unauth_tls_init; 404 eap->deinit = eap_tls_deinit; 405 eap->process = eap_tls_process; 406 eap->isKeyAvailable = eap_tls_isKeyAvailable; 407 eap->getKey = eap_tls_getKey; 408 eap->get_status = eap_tls_get_status; 409 eap->has_reauth_data = eap_tls_has_reauth_data; 410 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 411 eap->init_for_reauth = eap_tls_init_for_reauth; 412 eap->get_emsk = eap_tls_get_emsk; 413 414 ret = eap_peer_method_register(eap); 415 if (ret) 416 eap_peer_method_free(eap); 417 return ret; 418 } 419 #endif /* EAP_UNAUTH_TLS */ 420 421 422 #ifdef CONFIG_HS20 423 int eap_peer_wfa_unauth_tls_register(void) 424 { 425 struct eap_method *eap; 426 int ret; 427 428 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 429 EAP_VENDOR_WFA_NEW, 430 EAP_VENDOR_WFA_UNAUTH_TLS, 431 "WFA-UNAUTH-TLS"); 432 if (eap == NULL) 433 return -1; 434 435 eap->init = eap_wfa_unauth_tls_init; 436 eap->deinit = eap_tls_deinit; 437 eap->process = eap_tls_process; 438 eap->isKeyAvailable = eap_tls_isKeyAvailable; 439 eap->getKey = eap_tls_getKey; 440 eap->get_status = eap_tls_get_status; 441 eap->has_reauth_data = eap_tls_has_reauth_data; 442 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 443 eap->init_for_reauth = eap_tls_init_for_reauth; 444 eap->get_emsk = eap_tls_get_emsk; 445 446 ret = eap_peer_method_register(eap); 447 if (ret) 448 eap_peer_method_free(eap); 449 return ret; 450 } 451 #endif /* CONFIG_HS20 */ 452