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 static void eap_tls_deinit(struct eap_sm *sm, void *priv) 102 { 103 struct eap_tls_data *data = priv; 104 if (data == NULL) 105 return; 106 eap_peer_tls_ssl_deinit(sm, &data->ssl); 107 os_free(data->key_data); 108 os_free(data->session_id); 109 os_free(data); 110 } 111 112 113 static struct wpabuf * eap_tls_failure(struct eap_sm *sm, 114 struct eap_tls_data *data, 115 struct eap_method_ret *ret, int res, 116 struct wpabuf *resp, u8 id) 117 { 118 wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); 119 120 ret->methodState = METHOD_DONE; 121 ret->decision = DECISION_FAIL; 122 123 if (res == -1) { 124 struct eap_peer_config *config = eap_get_config(sm); 125 if (config) { 126 /* 127 * The TLS handshake failed. So better forget the old 128 * PIN. It may be wrong, we cannot be sure but trying 129 * the wrong one again might block it on the card--so 130 * better ask the user again. 131 */ 132 os_free(config->pin); 133 config->pin = NULL; 134 } 135 } 136 137 if (resp) { 138 /* 139 * This is likely an alert message, so send it instead of just 140 * ACKing the error. 141 */ 142 return resp; 143 } 144 145 return eap_peer_tls_build_ack(id, data->eap_type, 0); 146 } 147 148 149 static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 150 struct eap_method_ret *ret) 151 { 152 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 153 154 ret->methodState = METHOD_DONE; 155 ret->decision = DECISION_UNCOND_SUCC; 156 157 os_free(data->key_data); 158 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 159 "client EAP encryption", 160 EAP_TLS_KEY_LEN + 161 EAP_EMSK_LEN); 162 if (data->key_data) { 163 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 164 data->key_data, EAP_TLS_KEY_LEN); 165 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 166 data->key_data + EAP_TLS_KEY_LEN, 167 EAP_EMSK_LEN); 168 } else { 169 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 170 } 171 172 os_free(data->session_id); 173 data->session_id = eap_peer_tls_derive_session_id(sm, &data->ssl, 174 EAP_TYPE_TLS, 175 &data->id_len); 176 if (data->session_id) { 177 wpa_hexdump(MSG_DEBUG, "EAP-TLS: Derived Session-Id", 178 data->session_id, data->id_len); 179 } else { 180 wpa_printf(MSG_ERROR, "EAP-TLS: Failed to derive Session-Id"); 181 } 182 } 183 184 185 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 186 struct eap_method_ret *ret, 187 const struct wpabuf *reqData) 188 { 189 size_t left; 190 int res; 191 struct wpabuf *resp; 192 u8 flags, id; 193 const u8 *pos; 194 struct eap_tls_data *data = priv; 195 196 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 197 reqData, &left, &flags); 198 if (pos == NULL) 199 return NULL; 200 id = eap_get_id(reqData); 201 202 if (flags & EAP_TLS_FLAGS_START) { 203 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 204 left = 0; /* make sure that this frame is empty, even though it 205 * should always be, anyway */ 206 } 207 208 resp = NULL; 209 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 210 id, pos, left, &resp); 211 212 if (res < 0) { 213 return eap_tls_failure(sm, data, ret, res, resp, id); 214 } 215 216 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 217 eap_tls_success(sm, data, ret); 218 219 if (res == 1) { 220 wpabuf_free(resp); 221 return eap_peer_tls_build_ack(id, data->eap_type, 0); 222 } 223 224 return resp; 225 } 226 227 228 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 229 { 230 struct eap_tls_data *data = priv; 231 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 232 } 233 234 235 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 236 { 237 } 238 239 240 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 241 { 242 struct eap_tls_data *data = priv; 243 os_free(data->key_data); 244 data->key_data = NULL; 245 os_free(data->session_id); 246 data->session_id = NULL; 247 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 248 os_free(data); 249 return NULL; 250 } 251 return priv; 252 } 253 254 255 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 256 size_t buflen, int verbose) 257 { 258 struct eap_tls_data *data = priv; 259 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 260 } 261 262 263 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 264 { 265 struct eap_tls_data *data = priv; 266 return data->key_data != NULL; 267 } 268 269 270 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 271 { 272 struct eap_tls_data *data = priv; 273 u8 *key; 274 275 if (data->key_data == NULL) 276 return NULL; 277 278 key = os_malloc(EAP_TLS_KEY_LEN); 279 if (key == NULL) 280 return NULL; 281 282 *len = EAP_TLS_KEY_LEN; 283 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 284 285 return key; 286 } 287 288 289 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 290 { 291 struct eap_tls_data *data = priv; 292 u8 *key; 293 294 if (data->key_data == NULL) 295 return NULL; 296 297 key = os_malloc(EAP_EMSK_LEN); 298 if (key == NULL) 299 return NULL; 300 301 *len = EAP_EMSK_LEN; 302 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 303 304 return key; 305 } 306 307 308 static u8 * eap_tls_get_session_id(struct eap_sm *sm, void *priv, size_t *len) 309 { 310 struct eap_tls_data *data = priv; 311 u8 *id; 312 313 if (data->session_id == NULL) 314 return NULL; 315 316 id = os_malloc(data->id_len); 317 if (id == NULL) 318 return NULL; 319 320 *len = data->id_len; 321 os_memcpy(id, data->session_id, data->id_len); 322 323 return id; 324 } 325 326 327 int eap_peer_tls_register(void) 328 { 329 struct eap_method *eap; 330 int ret; 331 332 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 333 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 334 if (eap == NULL) 335 return -1; 336 337 eap->init = eap_tls_init; 338 eap->deinit = eap_tls_deinit; 339 eap->process = eap_tls_process; 340 eap->isKeyAvailable = eap_tls_isKeyAvailable; 341 eap->getKey = eap_tls_getKey; 342 eap->getSessionId = eap_tls_get_session_id; 343 eap->get_status = eap_tls_get_status; 344 eap->has_reauth_data = eap_tls_has_reauth_data; 345 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 346 eap->init_for_reauth = eap_tls_init_for_reauth; 347 eap->get_emsk = eap_tls_get_emsk; 348 349 ret = eap_peer_method_register(eap); 350 if (ret) 351 eap_peer_method_free(eap); 352 return ret; 353 } 354 355 356 #ifdef EAP_UNAUTH_TLS 357 int eap_peer_unauth_tls_register(void) 358 { 359 struct eap_method *eap; 360 int ret; 361 362 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 363 EAP_VENDOR_UNAUTH_TLS, 364 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 365 if (eap == NULL) 366 return -1; 367 368 eap->init = eap_unauth_tls_init; 369 eap->deinit = eap_tls_deinit; 370 eap->process = eap_tls_process; 371 eap->isKeyAvailable = eap_tls_isKeyAvailable; 372 eap->getKey = eap_tls_getKey; 373 eap->get_status = eap_tls_get_status; 374 eap->has_reauth_data = eap_tls_has_reauth_data; 375 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 376 eap->init_for_reauth = eap_tls_init_for_reauth; 377 eap->get_emsk = eap_tls_get_emsk; 378 379 ret = eap_peer_method_register(eap); 380 if (ret) 381 eap_peer_method_free(eap); 382 return ret; 383 } 384 #endif /* EAP_UNAUTH_TLS */ 385