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 void *ssl_ctx; 25 u8 eap_type; 26 }; 27 28 29 static void * eap_tls_init(struct eap_sm *sm) 30 { 31 struct eap_tls_data *data; 32 struct eap_peer_config *config = eap_get_config(sm); 33 if (config == NULL || 34 ((sm->init_phase2 ? config->private_key2 : config->private_key) 35 == NULL && 36 (sm->init_phase2 ? config->engine2 : config->engine) == 0)) { 37 wpa_printf(MSG_INFO, "EAP-TLS: Private key not configured"); 38 return NULL; 39 } 40 41 data = os_zalloc(sizeof(*data)); 42 if (data == NULL) 43 return NULL; 44 45 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 46 sm->ssl_ctx; 47 48 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, EAP_TYPE_TLS)) { 49 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 50 eap_tls_deinit(sm, data); 51 if (config->engine) { 52 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting Smartcard " 53 "PIN"); 54 eap_sm_request_pin(sm); 55 sm->ignore = TRUE; 56 } else if (config->private_key && !config->private_key_passwd) 57 { 58 wpa_printf(MSG_DEBUG, "EAP-TLS: Requesting private " 59 "key passphrase"); 60 eap_sm_request_passphrase(sm); 61 sm->ignore = TRUE; 62 } 63 return NULL; 64 } 65 66 data->eap_type = EAP_TYPE_TLS; 67 68 return data; 69 } 70 71 72 #ifdef EAP_UNAUTH_TLS 73 static void * eap_unauth_tls_init(struct eap_sm *sm) 74 { 75 struct eap_tls_data *data; 76 struct eap_peer_config *config = eap_get_config(sm); 77 78 data = os_zalloc(sizeof(*data)); 79 if (data == NULL) 80 return NULL; 81 82 data->ssl_ctx = sm->init_phase2 && sm->ssl_ctx2 ? sm->ssl_ctx2 : 83 sm->ssl_ctx; 84 85 if (eap_peer_tls_ssl_init(sm, &data->ssl, config, 86 EAP_UNAUTH_TLS_TYPE)) { 87 wpa_printf(MSG_INFO, "EAP-TLS: Failed to initialize SSL."); 88 eap_tls_deinit(sm, data); 89 return NULL; 90 } 91 92 data->eap_type = EAP_UNAUTH_TLS_TYPE; 93 94 return data; 95 } 96 #endif /* EAP_UNAUTH_TLS */ 97 98 99 static void eap_tls_deinit(struct eap_sm *sm, void *priv) 100 { 101 struct eap_tls_data *data = priv; 102 if (data == NULL) 103 return; 104 eap_peer_tls_ssl_deinit(sm, &data->ssl); 105 os_free(data->key_data); 106 os_free(data); 107 } 108 109 110 static struct wpabuf * eap_tls_failure(struct eap_sm *sm, 111 struct eap_tls_data *data, 112 struct eap_method_ret *ret, int res, 113 struct wpabuf *resp, u8 id) 114 { 115 wpa_printf(MSG_DEBUG, "EAP-TLS: TLS processing failed"); 116 117 ret->methodState = METHOD_DONE; 118 ret->decision = DECISION_FAIL; 119 120 if (res == -1) { 121 struct eap_peer_config *config = eap_get_config(sm); 122 if (config) { 123 /* 124 * The TLS handshake failed. So better forget the old 125 * PIN. It may be wrong, we cannot be sure but trying 126 * the wrong one again might block it on the card--so 127 * better ask the user again. 128 */ 129 os_free(config->pin); 130 config->pin = NULL; 131 } 132 } 133 134 if (resp) { 135 /* 136 * This is likely an alert message, so send it instead of just 137 * ACKing the error. 138 */ 139 return resp; 140 } 141 142 return eap_peer_tls_build_ack(id, data->eap_type, 0); 143 } 144 145 146 static void eap_tls_success(struct eap_sm *sm, struct eap_tls_data *data, 147 struct eap_method_ret *ret) 148 { 149 wpa_printf(MSG_DEBUG, "EAP-TLS: Done"); 150 151 ret->methodState = METHOD_DONE; 152 ret->decision = DECISION_UNCOND_SUCC; 153 154 os_free(data->key_data); 155 data->key_data = eap_peer_tls_derive_key(sm, &data->ssl, 156 "client EAP encryption", 157 EAP_TLS_KEY_LEN + 158 EAP_EMSK_LEN); 159 if (data->key_data) { 160 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived key", 161 data->key_data, EAP_TLS_KEY_LEN); 162 wpa_hexdump_key(MSG_DEBUG, "EAP-TLS: Derived EMSK", 163 data->key_data + EAP_TLS_KEY_LEN, 164 EAP_EMSK_LEN); 165 } else { 166 wpa_printf(MSG_INFO, "EAP-TLS: Failed to derive key"); 167 } 168 } 169 170 171 static struct wpabuf * eap_tls_process(struct eap_sm *sm, void *priv, 172 struct eap_method_ret *ret, 173 const struct wpabuf *reqData) 174 { 175 size_t left; 176 int res; 177 struct wpabuf *resp; 178 u8 flags, id; 179 const u8 *pos; 180 struct eap_tls_data *data = priv; 181 182 pos = eap_peer_tls_process_init(sm, &data->ssl, data->eap_type, ret, 183 reqData, &left, &flags); 184 if (pos == NULL) 185 return NULL; 186 id = eap_get_id(reqData); 187 188 if (flags & EAP_TLS_FLAGS_START) { 189 wpa_printf(MSG_DEBUG, "EAP-TLS: Start"); 190 left = 0; /* make sure that this frame is empty, even though it 191 * should always be, anyway */ 192 } 193 194 resp = NULL; 195 res = eap_peer_tls_process_helper(sm, &data->ssl, data->eap_type, 0, 196 id, pos, left, &resp); 197 198 if (res < 0) { 199 return eap_tls_failure(sm, data, ret, res, resp, id); 200 } 201 202 if (tls_connection_established(data->ssl_ctx, data->ssl.conn)) 203 eap_tls_success(sm, data, ret); 204 205 if (res == 1) { 206 wpabuf_free(resp); 207 return eap_peer_tls_build_ack(id, data->eap_type, 0); 208 } 209 210 return resp; 211 } 212 213 214 static Boolean eap_tls_has_reauth_data(struct eap_sm *sm, void *priv) 215 { 216 struct eap_tls_data *data = priv; 217 return tls_connection_established(data->ssl_ctx, data->ssl.conn); 218 } 219 220 221 static void eap_tls_deinit_for_reauth(struct eap_sm *sm, void *priv) 222 { 223 } 224 225 226 static void * eap_tls_init_for_reauth(struct eap_sm *sm, void *priv) 227 { 228 struct eap_tls_data *data = priv; 229 os_free(data->key_data); 230 data->key_data = NULL; 231 if (eap_peer_tls_reauth_init(sm, &data->ssl)) { 232 os_free(data); 233 return NULL; 234 } 235 return priv; 236 } 237 238 239 static int eap_tls_get_status(struct eap_sm *sm, void *priv, char *buf, 240 size_t buflen, int verbose) 241 { 242 struct eap_tls_data *data = priv; 243 return eap_peer_tls_status(sm, &data->ssl, buf, buflen, verbose); 244 } 245 246 247 static Boolean eap_tls_isKeyAvailable(struct eap_sm *sm, void *priv) 248 { 249 struct eap_tls_data *data = priv; 250 return data->key_data != NULL; 251 } 252 253 254 static u8 * eap_tls_getKey(struct eap_sm *sm, void *priv, size_t *len) 255 { 256 struct eap_tls_data *data = priv; 257 u8 *key; 258 259 if (data->key_data == NULL) 260 return NULL; 261 262 key = os_malloc(EAP_TLS_KEY_LEN); 263 if (key == NULL) 264 return NULL; 265 266 *len = EAP_TLS_KEY_LEN; 267 os_memcpy(key, data->key_data, EAP_TLS_KEY_LEN); 268 269 return key; 270 } 271 272 273 static u8 * eap_tls_get_emsk(struct eap_sm *sm, void *priv, size_t *len) 274 { 275 struct eap_tls_data *data = priv; 276 u8 *key; 277 278 if (data->key_data == NULL) 279 return NULL; 280 281 key = os_malloc(EAP_EMSK_LEN); 282 if (key == NULL) 283 return NULL; 284 285 *len = EAP_EMSK_LEN; 286 os_memcpy(key, data->key_data + EAP_TLS_KEY_LEN, EAP_EMSK_LEN); 287 288 return key; 289 } 290 291 292 int eap_peer_tls_register(void) 293 { 294 struct eap_method *eap; 295 int ret; 296 297 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 298 EAP_VENDOR_IETF, EAP_TYPE_TLS, "TLS"); 299 if (eap == NULL) 300 return -1; 301 302 eap->init = eap_tls_init; 303 eap->deinit = eap_tls_deinit; 304 eap->process = eap_tls_process; 305 eap->isKeyAvailable = eap_tls_isKeyAvailable; 306 eap->getKey = eap_tls_getKey; 307 eap->get_status = eap_tls_get_status; 308 eap->has_reauth_data = eap_tls_has_reauth_data; 309 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 310 eap->init_for_reauth = eap_tls_init_for_reauth; 311 eap->get_emsk = eap_tls_get_emsk; 312 313 ret = eap_peer_method_register(eap); 314 if (ret) 315 eap_peer_method_free(eap); 316 return ret; 317 } 318 319 320 #ifdef EAP_UNAUTH_TLS 321 int eap_peer_unauth_tls_register(void) 322 { 323 struct eap_method *eap; 324 int ret; 325 326 eap = eap_peer_method_alloc(EAP_PEER_METHOD_INTERFACE_VERSION, 327 EAP_VENDOR_UNAUTH_TLS, 328 EAP_VENDOR_TYPE_UNAUTH_TLS, "UNAUTH-TLS"); 329 if (eap == NULL) 330 return -1; 331 332 eap->init = eap_unauth_tls_init; 333 eap->deinit = eap_tls_deinit; 334 eap->process = eap_tls_process; 335 eap->isKeyAvailable = eap_tls_isKeyAvailable; 336 eap->getKey = eap_tls_getKey; 337 eap->get_status = eap_tls_get_status; 338 eap->has_reauth_data = eap_tls_has_reauth_data; 339 eap->deinit_for_reauth = eap_tls_deinit_for_reauth; 340 eap->init_for_reauth = eap_tls_init_for_reauth; 341 eap->get_emsk = eap_tls_get_emsk; 342 343 ret = eap_peer_method_register(eap); 344 if (ret) 345 eap_peer_method_free(eap); 346 return ret; 347 } 348 #endif /* EAP_UNAUTH_TLS */ 349