$search
00001 /* 00002 * EAP peer: EAP-TLS/PEAP/TTLS/FAST common functions 00003 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation. 00008 * 00009 * Alternatively, this software may be distributed under the terms of BSD 00010 * license. 00011 * 00012 * See README and COPYING for more details. 00013 */ 00014 00015 #include "includes.h" 00016 00017 #include "common.h" 00018 #include "crypto/sha1.h" 00019 #include "crypto/tls.h" 00020 #include "eap_i.h" 00021 #include "eap_tls_common.h" 00022 #include "eap_config.h" 00023 00024 00025 static int eap_tls_check_blob(struct eap_sm *sm, const char **name, 00026 const u8 **data, size_t *data_len) 00027 { 00028 const struct wpa_config_blob *blob; 00029 00030 if (*name == NULL || os_strncmp(*name, "blob://", 7) != 0) 00031 return 0; 00032 00033 blob = eap_get_config_blob(sm, *name + 7); 00034 if (blob == NULL) { 00035 wpa_printf(MSG_ERROR, "%s: Named configuration blob '%s' not " 00036 "found", __func__, *name + 7); 00037 return -1; 00038 } 00039 00040 *name = NULL; 00041 *data = blob->data; 00042 *data_len = blob->len; 00043 00044 return 0; 00045 } 00046 00047 00048 static void eap_tls_params_flags(struct tls_connection_params *params, 00049 const char *txt) 00050 { 00051 if (txt == NULL) 00052 return; 00053 if (os_strstr(txt, "tls_allow_md5=1")) 00054 params->flags |= TLS_CONN_ALLOW_SIGN_RSA_MD5; 00055 if (os_strstr(txt, "tls_disable_time_checks=1")) 00056 params->flags |= TLS_CONN_DISABLE_TIME_CHECKS; 00057 } 00058 00059 00060 static void eap_tls_params_from_conf1(struct tls_connection_params *params, 00061 struct eap_peer_config *config) 00062 { 00063 params->ca_cert = (char *) config->ca_cert; 00064 params->ca_path = (char *) config->ca_path; 00065 params->client_cert = (char *) config->client_cert; 00066 params->private_key = (char *) config->private_key; 00067 params->private_key_passwd = (char *) config->private_key_passwd; 00068 params->dh_file = (char *) config->dh_file; 00069 params->subject_match = (char *) config->subject_match; 00070 params->altsubject_match = (char *) config->altsubject_match; 00071 params->engine = config->engine; 00072 params->engine_id = config->engine_id; 00073 params->pin = config->pin; 00074 params->key_id = config->key_id; 00075 params->cert_id = config->cert_id; 00076 params->ca_cert_id = config->ca_cert_id; 00077 eap_tls_params_flags(params, config->phase1); 00078 } 00079 00080 00081 static void eap_tls_params_from_conf2(struct tls_connection_params *params, 00082 struct eap_peer_config *config) 00083 { 00084 params->ca_cert = (char *) config->ca_cert2; 00085 params->ca_path = (char *) config->ca_path2; 00086 params->client_cert = (char *) config->client_cert2; 00087 params->private_key = (char *) config->private_key2; 00088 params->private_key_passwd = (char *) config->private_key2_passwd; 00089 params->dh_file = (char *) config->dh_file2; 00090 params->subject_match = (char *) config->subject_match2; 00091 params->altsubject_match = (char *) config->altsubject_match2; 00092 params->engine = config->engine2; 00093 params->engine_id = config->engine2_id; 00094 params->pin = config->pin2; 00095 params->key_id = config->key2_id; 00096 params->cert_id = config->cert2_id; 00097 params->ca_cert_id = config->ca_cert2_id; 00098 eap_tls_params_flags(params, config->phase2); 00099 } 00100 00101 00102 static int eap_tls_params_from_conf(struct eap_sm *sm, 00103 struct eap_ssl_data *data, 00104 struct tls_connection_params *params, 00105 struct eap_peer_config *config, int phase2) 00106 { 00107 os_memset(params, 0, sizeof(*params)); 00108 if (phase2) { 00109 wpa_printf(MSG_DEBUG, "TLS: using phase2 config options"); 00110 eap_tls_params_from_conf2(params, config); 00111 } else { 00112 wpa_printf(MSG_DEBUG, "TLS: using phase1 config options"); 00113 eap_tls_params_from_conf1(params, config); 00114 } 00115 params->tls_ia = data->tls_ia; 00116 00117 /* 00118 * Use blob data, if available. Otherwise, leave reference to external 00119 * file as-is. 00120 */ 00121 if (eap_tls_check_blob(sm, ¶ms->ca_cert, ¶ms->ca_cert_blob, 00122 ¶ms->ca_cert_blob_len) || 00123 eap_tls_check_blob(sm, ¶ms->client_cert, 00124 ¶ms->client_cert_blob, 00125 ¶ms->client_cert_blob_len) || 00126 eap_tls_check_blob(sm, ¶ms->private_key, 00127 ¶ms->private_key_blob, 00128 ¶ms->private_key_blob_len) || 00129 eap_tls_check_blob(sm, ¶ms->dh_file, ¶ms->dh_blob, 00130 ¶ms->dh_blob_len)) { 00131 wpa_printf(MSG_INFO, "SSL: Failed to get configuration blobs"); 00132 return -1; 00133 } 00134 00135 return 0; 00136 } 00137 00138 00139 static int eap_tls_init_connection(struct eap_sm *sm, 00140 struct eap_ssl_data *data, 00141 struct eap_peer_config *config, 00142 struct tls_connection_params *params) 00143 { 00144 int res; 00145 00146 data->conn = tls_connection_init(sm->ssl_ctx); 00147 if (data->conn == NULL) { 00148 wpa_printf(MSG_INFO, "SSL: Failed to initialize new TLS " 00149 "connection"); 00150 return -1; 00151 } 00152 00153 res = tls_connection_set_params(sm->ssl_ctx, data->conn, params); 00154 if (res == TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED) { 00155 /* 00156 * At this point with the pkcs11 engine the PIN might be wrong. 00157 * We reset the PIN in the configuration to be sure to not use 00158 * it again and the calling function must request a new one. 00159 */ 00160 os_free(config->pin); 00161 config->pin = NULL; 00162 } else if (res == TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED) { 00163 wpa_printf(MSG_INFO, "TLS: Failed to load private key"); 00164 /* 00165 * We do not know exactly but maybe the PIN was wrong, 00166 * so ask for a new one. 00167 */ 00168 os_free(config->pin); 00169 config->pin = NULL; 00170 eap_sm_request_pin(sm); 00171 sm->ignore = TRUE; 00172 tls_connection_deinit(sm->ssl_ctx, data->conn); 00173 data->conn = NULL; 00174 return -1; 00175 } else if (res) { 00176 wpa_printf(MSG_INFO, "TLS: Failed to set TLS connection " 00177 "parameters"); 00178 tls_connection_deinit(sm->ssl_ctx, data->conn); 00179 data->conn = NULL; 00180 return -1; 00181 } 00182 00183 return 0; 00184 } 00185 00186 00197 int eap_peer_tls_ssl_init(struct eap_sm *sm, struct eap_ssl_data *data, 00198 struct eap_peer_config *config) 00199 { 00200 struct tls_connection_params params; 00201 00202 if (config == NULL) 00203 return -1; 00204 00205 data->eap = sm; 00206 data->phase2 = sm->init_phase2; 00207 if (eap_tls_params_from_conf(sm, data, ¶ms, config, data->phase2) < 00208 0) 00209 return -1; 00210 00211 if (eap_tls_init_connection(sm, data, config, ¶ms) < 0) 00212 return -1; 00213 00214 data->tls_out_limit = config->fragment_size; 00215 if (data->phase2) { 00216 /* Limit the fragment size in the inner TLS authentication 00217 * since the outer authentication with EAP-PEAP does not yet 00218 * support fragmentation */ 00219 if (data->tls_out_limit > 100) 00220 data->tls_out_limit -= 100; 00221 } 00222 00223 if (config->phase1 && 00224 os_strstr(config->phase1, "include_tls_length=1")) { 00225 wpa_printf(MSG_DEBUG, "TLS: Include TLS Message Length in " 00226 "unfragmented packets"); 00227 data->include_tls_length = 1; 00228 } 00229 00230 return 0; 00231 } 00232 00233 00242 void eap_peer_tls_ssl_deinit(struct eap_sm *sm, struct eap_ssl_data *data) 00243 { 00244 tls_connection_deinit(sm->ssl_ctx, data->conn); 00245 eap_peer_tls_reset_input(data); 00246 eap_peer_tls_reset_output(data); 00247 } 00248 00249 00264 u8 * eap_peer_tls_derive_key(struct eap_sm *sm, struct eap_ssl_data *data, 00265 const char *label, size_t len) 00266 { 00267 struct tls_keys keys; 00268 u8 *rnd = NULL, *out; 00269 00270 out = os_malloc(len); 00271 if (out == NULL) 00272 return NULL; 00273 00274 /* First, try to use TLS library function for PRF, if available. */ 00275 if (tls_connection_prf(sm->ssl_ctx, data->conn, label, 0, out, len) == 00276 0) 00277 return out; 00278 00279 /* 00280 * TLS library did not support key generation, so get the needed TLS 00281 * session parameters and use an internal implementation of TLS PRF to 00282 * derive the key. 00283 */ 00284 if (tls_connection_get_keys(sm->ssl_ctx, data->conn, &keys)) 00285 goto fail; 00286 00287 if (keys.client_random == NULL || keys.server_random == NULL || 00288 keys.master_key == NULL) 00289 goto fail; 00290 00291 rnd = os_malloc(keys.client_random_len + keys.server_random_len); 00292 if (rnd == NULL) 00293 goto fail; 00294 os_memcpy(rnd, keys.client_random, keys.client_random_len); 00295 os_memcpy(rnd + keys.client_random_len, keys.server_random, 00296 keys.server_random_len); 00297 00298 if (tls_prf(keys.master_key, keys.master_key_len, 00299 label, rnd, keys.client_random_len + 00300 keys.server_random_len, out, len)) 00301 goto fail; 00302 00303 os_free(rnd); 00304 return out; 00305 00306 fail: 00307 os_free(out); 00308 os_free(rnd); 00309 return NULL; 00310 } 00311 00312 00320 static int eap_peer_tls_reassemble_fragment(struct eap_ssl_data *data, 00321 const struct wpabuf *in_data) 00322 { 00323 size_t tls_in_len, in_len; 00324 00325 tls_in_len = data->tls_in ? wpabuf_len(data->tls_in) : 0; 00326 in_len = in_data ? wpabuf_len(in_data) : 0; 00327 00328 if (tls_in_len + in_len == 0) { 00329 /* No message data received?! */ 00330 wpa_printf(MSG_WARNING, "SSL: Invalid reassembly state: " 00331 "tls_in_left=%lu tls_in_len=%lu in_len=%lu", 00332 (unsigned long) data->tls_in_left, 00333 (unsigned long) tls_in_len, 00334 (unsigned long) in_len); 00335 eap_peer_tls_reset_input(data); 00336 return -1; 00337 } 00338 00339 if (tls_in_len + in_len > 65536) { 00340 /* 00341 * Limit length to avoid rogue servers from causing large 00342 * memory allocations. 00343 */ 00344 wpa_printf(MSG_INFO, "SSL: Too long TLS fragment (size over " 00345 "64 kB)"); 00346 eap_peer_tls_reset_input(data); 00347 return -1; 00348 } 00349 00350 if (in_len > data->tls_in_left) { 00351 /* Sender is doing something odd - reject message */ 00352 wpa_printf(MSG_INFO, "SSL: more data than TLS message length " 00353 "indicated"); 00354 eap_peer_tls_reset_input(data); 00355 return -1; 00356 } 00357 00358 if (wpabuf_resize(&data->tls_in, in_len) < 0) { 00359 wpa_printf(MSG_INFO, "SSL: Could not allocate memory for TLS " 00360 "data"); 00361 eap_peer_tls_reset_input(data); 00362 return -1; 00363 } 00364 wpabuf_put_buf(data->tls_in, in_data); 00365 data->tls_in_left -= in_len; 00366 00367 if (data->tls_in_left > 0) { 00368 wpa_printf(MSG_DEBUG, "SSL: Need %lu bytes more input " 00369 "data", (unsigned long) data->tls_in_left); 00370 return 1; 00371 } 00372 00373 return 0; 00374 } 00375 00376 00389 static const struct wpabuf * eap_peer_tls_data_reassemble( 00390 struct eap_ssl_data *data, const struct wpabuf *in_data, 00391 int *need_more_input) 00392 { 00393 *need_more_input = 0; 00394 00395 if (data->tls_in_left > wpabuf_len(in_data) || data->tls_in) { 00396 /* Message has fragments */ 00397 int res = eap_peer_tls_reassemble_fragment(data, in_data); 00398 if (res) { 00399 if (res == 1) 00400 *need_more_input = 1; 00401 return NULL; 00402 } 00403 00404 /* Message is now fully reassembled. */ 00405 } else { 00406 /* No fragments in this message, so just make a copy of it. */ 00407 data->tls_in_left = 0; 00408 data->tls_in = wpabuf_dup(in_data); 00409 if (data->tls_in == NULL) 00410 return NULL; 00411 } 00412 00413 return data->tls_in; 00414 } 00415 00416 00427 static int eap_tls_process_input(struct eap_sm *sm, struct eap_ssl_data *data, 00428 const u8 *in_data, size_t in_len, 00429 struct wpabuf **out_data) 00430 { 00431 const struct wpabuf *msg; 00432 int need_more_input; 00433 struct wpabuf *appl_data; 00434 struct wpabuf buf; 00435 00436 wpabuf_set(&buf, in_data, in_len); 00437 msg = eap_peer_tls_data_reassemble(data, &buf, &need_more_input); 00438 if (msg == NULL) 00439 return need_more_input ? 1 : -1; 00440 00441 /* Full TLS message reassembled - continue handshake processing */ 00442 if (data->tls_out) { 00443 /* This should not happen.. */ 00444 wpa_printf(MSG_INFO, "SSL: eap_tls_process_input - pending " 00445 "tls_out data even though tls_out_len = 0"); 00446 wpabuf_free(data->tls_out); 00447 WPA_ASSERT(data->tls_out == NULL); 00448 } 00449 appl_data = NULL; 00450 data->tls_out = tls_connection_handshake(sm->ssl_ctx, data->conn, 00451 msg, &appl_data); 00452 00453 eap_peer_tls_reset_input(data); 00454 00455 if (appl_data && 00456 tls_connection_established(sm->ssl_ctx, data->conn) && 00457 !tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 00458 wpa_hexdump_buf_key(MSG_MSGDUMP, "SSL: Application data", 00459 appl_data); 00460 *out_data = appl_data; 00461 return 2; 00462 } 00463 00464 wpabuf_free(appl_data); 00465 00466 return 0; 00467 } 00468 00469 00480 static int eap_tls_process_output(struct eap_ssl_data *data, EapType eap_type, 00481 int peap_version, u8 id, int ret, 00482 struct wpabuf **out_data) 00483 { 00484 size_t len; 00485 u8 *flags; 00486 int more_fragments, length_included; 00487 00488 if (data->tls_out == NULL) 00489 return -1; 00490 len = wpabuf_len(data->tls_out) - data->tls_out_pos; 00491 wpa_printf(MSG_DEBUG, "SSL: %lu bytes left to be sent out (of total " 00492 "%lu bytes)", 00493 (unsigned long) len, 00494 (unsigned long) wpabuf_len(data->tls_out)); 00495 00496 /* 00497 * Limit outgoing message to the configured maximum size. Fragment 00498 * message if needed. 00499 */ 00500 if (len > data->tls_out_limit) { 00501 more_fragments = 1; 00502 len = data->tls_out_limit; 00503 wpa_printf(MSG_DEBUG, "SSL: sending %lu bytes, more fragments " 00504 "will follow", (unsigned long) len); 00505 } else 00506 more_fragments = 0; 00507 00508 length_included = data->tls_out_pos == 0 && 00509 (wpabuf_len(data->tls_out) > data->tls_out_limit || 00510 data->include_tls_length); 00511 if (!length_included && 00512 eap_type == EAP_TYPE_PEAP && peap_version == 0 && 00513 !tls_connection_established(data->eap->ssl_ctx, data->conn)) { 00514 /* 00515 * Windows Server 2008 NPS really wants to have the TLS Message 00516 * length included in phase 0 even for unfragmented frames or 00517 * it will get very confused with Compound MAC calculation and 00518 * Outer TLVs. 00519 */ 00520 length_included = 1; 00521 } 00522 00523 *out_data = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 00524 1 + length_included * 4 + len, 00525 EAP_CODE_RESPONSE, id); 00526 if (*out_data == NULL) 00527 return -1; 00528 00529 flags = wpabuf_put(*out_data, 1); 00530 *flags = peap_version; 00531 if (more_fragments) 00532 *flags |= EAP_TLS_FLAGS_MORE_FRAGMENTS; 00533 if (length_included) { 00534 *flags |= EAP_TLS_FLAGS_LENGTH_INCLUDED; 00535 wpabuf_put_be32(*out_data, wpabuf_len(data->tls_out)); 00536 } 00537 00538 wpabuf_put_data(*out_data, 00539 wpabuf_head_u8(data->tls_out) + data->tls_out_pos, 00540 len); 00541 data->tls_out_pos += len; 00542 00543 if (!more_fragments) 00544 eap_peer_tls_reset_output(data); 00545 00546 return ret; 00547 } 00548 00549 00579 int eap_peer_tls_process_helper(struct eap_sm *sm, struct eap_ssl_data *data, 00580 EapType eap_type, int peap_version, 00581 u8 id, const u8 *in_data, size_t in_len, 00582 struct wpabuf **out_data) 00583 { 00584 int ret = 0; 00585 00586 *out_data = NULL; 00587 00588 if (data->tls_out && wpabuf_len(data->tls_out) > 0 && in_len > 0) { 00589 wpa_printf(MSG_DEBUG, "SSL: Received non-ACK when output " 00590 "fragments are waiting to be sent out"); 00591 return -1; 00592 } 00593 00594 if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 00595 /* 00596 * No more data to send out - expect to receive more data from 00597 * the AS. 00598 */ 00599 int res = eap_tls_process_input(sm, data, in_data, in_len, 00600 out_data); 00601 if (res) { 00602 /* 00603 * Input processing failed (res = -1) or more data is 00604 * needed (res = 1). 00605 */ 00606 return res; 00607 } 00608 00609 /* 00610 * The incoming message has been reassembled and processed. The 00611 * response was allocated into data->tls_out buffer. 00612 */ 00613 } 00614 00615 if (data->tls_out == NULL) { 00616 /* 00617 * No outgoing fragments remaining from the previous message 00618 * and no new message generated. This indicates an error in TLS 00619 * processing. 00620 */ 00621 eap_peer_tls_reset_output(data); 00622 return -1; 00623 } 00624 00625 if (tls_connection_get_failed(sm->ssl_ctx, data->conn)) { 00626 /* TLS processing has failed - return error */ 00627 wpa_printf(MSG_DEBUG, "SSL: Failed - tls_out available to " 00628 "report error"); 00629 ret = -1; 00630 /* TODO: clean pin if engine used? */ 00631 } 00632 00633 if (data->tls_out == NULL || wpabuf_len(data->tls_out) == 0) { 00634 /* 00635 * TLS negotiation should now be complete since all other cases 00636 * needing more data should have been caught above based on 00637 * the TLS Message Length field. 00638 */ 00639 wpa_printf(MSG_DEBUG, "SSL: No data to be sent out"); 00640 wpabuf_free(data->tls_out); 00641 data->tls_out = NULL; 00642 return 1; 00643 } 00644 00645 /* Send the pending message (in fragments, if needed). */ 00646 return eap_tls_process_output(data, eap_type, peap_version, id, ret, 00647 out_data); 00648 } 00649 00650 00658 struct wpabuf * eap_peer_tls_build_ack(u8 id, EapType eap_type, 00659 int peap_version) 00660 { 00661 struct wpabuf *resp; 00662 00663 resp = eap_msg_alloc(EAP_VENDOR_IETF, eap_type, 1, EAP_CODE_RESPONSE, 00664 id); 00665 if (resp == NULL) 00666 return NULL; 00667 wpa_printf(MSG_DEBUG, "SSL: Building ACK (type=%d id=%d ver=%d)", 00668 (int) eap_type, id, peap_version); 00669 wpabuf_put_u8(resp, peap_version); /* Flags */ 00670 return resp; 00671 } 00672 00673 00680 int eap_peer_tls_reauth_init(struct eap_sm *sm, struct eap_ssl_data *data) 00681 { 00682 eap_peer_tls_reset_input(data); 00683 eap_peer_tls_reset_output(data); 00684 return tls_connection_shutdown(sm->ssl_ctx, data->conn); 00685 } 00686 00687 00697 int eap_peer_tls_status(struct eap_sm *sm, struct eap_ssl_data *data, 00698 char *buf, size_t buflen, int verbose) 00699 { 00700 char name[128]; 00701 int len = 0, ret; 00702 00703 if (tls_get_cipher(sm->ssl_ctx, data->conn, name, sizeof(name)) == 0) { 00704 ret = os_snprintf(buf + len, buflen - len, 00705 "EAP TLS cipher=%s\n", name); 00706 if (ret < 0 || (size_t) ret >= buflen - len) 00707 return len; 00708 len += ret; 00709 } 00710 00711 return len; 00712 } 00713 00714 00739 const u8 * eap_peer_tls_process_init(struct eap_sm *sm, 00740 struct eap_ssl_data *data, 00741 EapType eap_type, 00742 struct eap_method_ret *ret, 00743 const struct wpabuf *reqData, 00744 size_t *len, u8 *flags) 00745 { 00746 const u8 *pos; 00747 size_t left; 00748 unsigned int tls_msg_len; 00749 00750 if (tls_get_errors(sm->ssl_ctx)) { 00751 wpa_printf(MSG_INFO, "SSL: TLS errors detected"); 00752 ret->ignore = TRUE; 00753 return NULL; 00754 } 00755 00756 pos = eap_hdr_validate(EAP_VENDOR_IETF, eap_type, reqData, &left); 00757 if (pos == NULL) { 00758 ret->ignore = TRUE; 00759 return NULL; 00760 } 00761 if (left == 0) { 00762 wpa_printf(MSG_DEBUG, "SSL: Invalid TLS message: no Flags " 00763 "octet included"); 00764 if (!sm->workaround) { 00765 ret->ignore = TRUE; 00766 return NULL; 00767 } 00768 00769 wpa_printf(MSG_DEBUG, "SSL: Workaround - assume no Flags " 00770 "indicates ACK frame"); 00771 *flags = 0; 00772 } else { 00773 *flags = *pos++; 00774 left--; 00775 } 00776 wpa_printf(MSG_DEBUG, "SSL: Received packet(len=%lu) - " 00777 "Flags 0x%02x", (unsigned long) wpabuf_len(reqData), 00778 *flags); 00779 if (*flags & EAP_TLS_FLAGS_LENGTH_INCLUDED) { 00780 if (left < 4) { 00781 wpa_printf(MSG_INFO, "SSL: Short frame with TLS " 00782 "length"); 00783 ret->ignore = TRUE; 00784 return NULL; 00785 } 00786 tls_msg_len = WPA_GET_BE32(pos); 00787 wpa_printf(MSG_DEBUG, "SSL: TLS Message Length: %d", 00788 tls_msg_len); 00789 if (data->tls_in_left == 0) { 00790 data->tls_in_total = tls_msg_len; 00791 data->tls_in_left = tls_msg_len; 00792 wpabuf_free(data->tls_in); 00793 data->tls_in = NULL; 00794 } 00795 pos += 4; 00796 left -= 4; 00797 } 00798 00799 ret->ignore = FALSE; 00800 ret->methodState = METHOD_MAY_CONT; 00801 ret->decision = DECISION_FAIL; 00802 ret->allowNotifications = TRUE; 00803 00804 *len = left; 00805 return pos; 00806 } 00807 00808 00816 void eap_peer_tls_reset_input(struct eap_ssl_data *data) 00817 { 00818 data->tls_in_left = data->tls_in_total = 0; 00819 wpabuf_free(data->tls_in); 00820 data->tls_in = NULL; 00821 } 00822 00823 00831 void eap_peer_tls_reset_output(struct eap_ssl_data *data) 00832 { 00833 data->tls_out_pos = 0; 00834 wpabuf_free(data->tls_out); 00835 data->tls_out = NULL; 00836 } 00837 00838 00847 int eap_peer_tls_decrypt(struct eap_sm *sm, struct eap_ssl_data *data, 00848 const struct wpabuf *in_data, 00849 struct wpabuf **in_decrypted) 00850 { 00851 const struct wpabuf *msg; 00852 int need_more_input; 00853 00854 msg = eap_peer_tls_data_reassemble(data, in_data, &need_more_input); 00855 if (msg == NULL) 00856 return need_more_input ? 1 : -1; 00857 00858 *in_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->conn, msg); 00859 eap_peer_tls_reset_input(data); 00860 if (*in_decrypted == NULL) { 00861 wpa_printf(MSG_INFO, "SSL: Failed to decrypt Phase 2 data"); 00862 return -1; 00863 } 00864 return 0; 00865 } 00866 00867 00879 int eap_peer_tls_encrypt(struct eap_sm *sm, struct eap_ssl_data *data, 00880 EapType eap_type, int peap_version, u8 id, 00881 const struct wpabuf *in_data, 00882 struct wpabuf **out_data) 00883 { 00884 if (in_data) { 00885 eap_peer_tls_reset_output(data); 00886 data->tls_out = tls_connection_encrypt(sm->ssl_ctx, data->conn, 00887 in_data); 00888 if (data->tls_out == NULL) { 00889 wpa_printf(MSG_INFO, "SSL: Failed to encrypt Phase 2 " 00890 "data (in_len=%lu)", 00891 (unsigned long) wpabuf_len(in_data)); 00892 eap_peer_tls_reset_output(data); 00893 return -1; 00894 } 00895 } 00896 00897 return eap_tls_process_output(data, eap_type, peap_version, id, 0, 00898 out_data); 00899 } 00900 00901 00913 int eap_peer_select_phase2_methods(struct eap_peer_config *config, 00914 const char *prefix, 00915 struct eap_method_type **types, 00916 size_t *num_types) 00917 { 00918 char *start, *pos, *buf; 00919 struct eap_method_type *methods = NULL, *_methods; 00920 u8 method; 00921 size_t num_methods = 0, prefix_len; 00922 00923 if (config == NULL || config->phase2 == NULL) 00924 goto get_defaults; 00925 00926 start = buf = os_strdup(config->phase2); 00927 if (buf == NULL) 00928 return -1; 00929 00930 prefix_len = os_strlen(prefix); 00931 00932 while (start && *start != '\0') { 00933 int vendor; 00934 pos = os_strstr(start, prefix); 00935 if (pos == NULL) 00936 break; 00937 if (start != pos && *(pos - 1) != ' ') { 00938 start = pos + prefix_len; 00939 continue; 00940 } 00941 00942 start = pos + prefix_len; 00943 pos = os_strchr(start, ' '); 00944 if (pos) 00945 *pos++ = '\0'; 00946 method = eap_get_phase2_type(start, &vendor); 00947 if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) { 00948 wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP " 00949 "method '%s'", start); 00950 } else { 00951 num_methods++; 00952 _methods = os_realloc(methods, 00953 num_methods * sizeof(*methods)); 00954 if (_methods == NULL) { 00955 os_free(methods); 00956 os_free(buf); 00957 return -1; 00958 } 00959 methods = _methods; 00960 methods[num_methods - 1].vendor = vendor; 00961 methods[num_methods - 1].method = method; 00962 } 00963 00964 start = pos; 00965 } 00966 00967 os_free(buf); 00968 00969 get_defaults: 00970 if (methods == NULL) 00971 methods = eap_get_phase2_types(config, &num_methods); 00972 00973 if (methods == NULL) { 00974 wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available"); 00975 return -1; 00976 } 00977 wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types", 00978 (u8 *) methods, 00979 num_methods * sizeof(struct eap_method_type)); 00980 00981 *types = methods; 00982 *num_types = num_methods; 00983 00984 return 0; 00985 } 00986 00987 00996 int eap_peer_tls_phase2_nak(struct eap_method_type *types, size_t num_types, 00997 struct eap_hdr *hdr, struct wpabuf **resp) 00998 { 00999 u8 *pos = (u8 *) (hdr + 1); 01000 size_t i; 01001 01002 /* TODO: add support for expanded Nak */ 01003 wpa_printf(MSG_DEBUG, "TLS: Phase 2 Request: Nak type=%d", *pos); 01004 wpa_hexdump(MSG_DEBUG, "TLS: Allowed Phase2 EAP types", 01005 (u8 *) types, num_types * sizeof(struct eap_method_type)); 01006 *resp = eap_msg_alloc(EAP_VENDOR_IETF, EAP_TYPE_NAK, num_types, 01007 EAP_CODE_RESPONSE, hdr->identifier); 01008 if (*resp == NULL) 01009 return -1; 01010 01011 for (i = 0; i < num_types; i++) { 01012 if (types[i].vendor == EAP_VENDOR_IETF && 01013 types[i].method < 256) 01014 wpabuf_put_u8(*resp, types[i].method); 01015 } 01016 01017 eap_update_len(*resp); 01018 01019 return 0; 01020 }