⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 eap_fast.c

📁 WLAN无线网络管理的最新程序
💻 C
📖 第 1 页 / 共 4 页
字号:
				   u8 **resp, size_t *resp_len){	size_t len = be_to_host16(hdr->length);	u8 *pos;	struct eap_method_ret iret;	if (len <= sizeof(struct eap_hdr)) {		wpa_printf(MSG_INFO, "EAP-FAST: too short "			   "Phase 2 request (len=%lu)", (unsigned long) len);		return -1;	}	pos = (u8 *) (hdr + 1);	wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 Request: type=%d", *pos);	switch (*pos) {	case EAP_TYPE_IDENTITY:		*resp = eap_sm_buildIdentity(sm, hdr->identifier, resp_len, 1);		break;	default:		if (data->phase2_type.vendor == EAP_VENDOR_IETF &&		    data->phase2_type.method == EAP_TYPE_NONE) {			size_t i;			for (i = 0; i < data->num_phase2_types; i++) {				if (data->phase2_types[i].vendor !=				    EAP_VENDOR_IETF ||				    data->phase2_types[i].method != *pos)					continue;				data->phase2_type.vendor =					data->phase2_types[i].vendor;				data->phase2_type.method =					data->phase2_types[i].method;				wpa_printf(MSG_DEBUG, "EAP-FAST: Selected "					   "Phase 2 EAP vendor %d method %d",					   data->phase2_type.vendor,					   data->phase2_type.method);				break;			}		}		if (*pos != data->phase2_type.method ||		    *pos == EAP_TYPE_NONE) {			if (eap_fast_phase2_nak(data, hdr, resp, resp_len))				return -1;			return 0;		}		if (data->phase2_priv == NULL) {			data->phase2_method = eap_sm_get_eap_methods(				data->phase2_type.vendor,				data->phase2_type.method);			if (data->phase2_method) {				if (data->key_block_p) {					sm->auth_challenge =						data->key_block_p->						server_challenge;					sm->peer_challenge =						data->key_block_p->						client_challenge;				}				sm->init_phase2 = 1;				sm->mschapv2_full_key = 1;				data->phase2_priv =					data->phase2_method->init(sm);				sm->init_phase2 = 0;				sm->mschapv2_full_key = 0;				sm->auth_challenge = NULL;				sm->peer_challenge = NULL;			}		}		if (data->phase2_priv == NULL || data->phase2_method == NULL) {			wpa_printf(MSG_INFO, "EAP-FAST: failed to initialize "				   "Phase 2 EAP method %d", *pos);			ret->methodState = METHOD_DONE;			ret->decision = DECISION_FAIL;			return -1;		}		os_memset(&iret, 0, sizeof(iret));		*resp = data->phase2_method->process(sm, data->phase2_priv,						     &iret, (u8 *) hdr, len,						     resp_len);		if (*resp == NULL ||		    (iret.methodState == METHOD_DONE &&		     iret.decision == DECISION_FAIL)) {			ret->methodState = METHOD_DONE;			ret->decision = DECISION_FAIL;		} else if ((iret.methodState == METHOD_DONE ||			    iret.methodState == METHOD_MAY_CONT) &&			   (iret.decision == DECISION_UNCOND_SUCC ||			    iret.decision == DECISION_COND_SUCC)) {			data->phase2_success = 1;		}		if (*resp == NULL)			return -1;		break;	}	return 0;}static u8 * eap_fast_tlv_nak(int vendor_id, int tlv_type, size_t *len){	struct eap_tlv_nak_tlv *nak;	*len = sizeof(*nak);	nak = os_malloc(*len);	if (nak == NULL)		return NULL;	nak->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY | EAP_TLV_NAK_TLV);	nak->length = host_to_be16(6);	nak->vendor_id = host_to_be32(vendor_id);	nak->nak_type = host_to_be16(tlv_type);	return (u8 *) nak;}static u8 * eap_fast_tlv_result(int status, int intermediate, size_t *len){	struct eap_tlv_intermediate_result_tlv *result;	*len = sizeof(*result);	result = os_malloc(*len);	if (result == NULL)		return NULL;	result->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |					(intermediate ?					 EAP_TLV_INTERMEDIATE_RESULT_TLV :					 EAP_TLV_RESULT_TLV));	result->length = host_to_be16(2);	result->status = host_to_be16(status);	return (u8 *) result;}static u8 * eap_fast_tlv_pac_ack(size_t *len){	struct eap_tlv_result_tlv *res;	struct eap_tlv_pac_ack_tlv *ack;	*len = sizeof(*res) + sizeof(*ack);	res = os_zalloc(*len);	if (res == NULL)		return NULL;	res->tlv_type = host_to_be16(EAP_TLV_RESULT_TLV |				     EAP_TLV_TYPE_MANDATORY);	res->length = host_to_be16(sizeof(*res) - sizeof(struct eap_tlv_hdr));	res->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);	ack = (struct eap_tlv_pac_ack_tlv *) (res + 1);	ack->tlv_type = host_to_be16(EAP_TLV_PAC_TLV |				     EAP_TLV_TYPE_MANDATORY);	ack->length = host_to_be16(sizeof(*ack) - sizeof(struct eap_tlv_hdr));	ack->pac_type = host_to_be16(PAC_TYPE_PAC_ACKNOWLEDGEMENT);	ack->pac_len = host_to_be16(2);	ack->result = host_to_be16(EAP_TLV_RESULT_SUCCESS);	return (u8 *) res;}static u8 * eap_fast_tlv_eap_payload(u8 *buf, size_t *len){	struct eap_tlv_hdr *tlv;	/* Encapsulate EAP packet in EAP Payload TLV */	tlv = os_malloc(sizeof(*tlv) + *len);	if (tlv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to "			   "allocate memory for TLV "			   "encapsulation");		os_free(buf);		return NULL;	}	tlv->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |				     EAP_TLV_EAP_PAYLOAD_TLV);	tlv->length = host_to_be16(*len);	os_memcpy(tlv + 1, buf, *len);	os_free(buf);	*len += sizeof(*tlv);	return (u8 *) tlv;}static u8 * eap_fast_process_crypto_binding(	struct eap_sm *sm, struct eap_fast_data *data,	struct eap_method_ret *ret,	struct eap_tlv_crypto_binding__tlv *_bind, size_t bind_len,	size_t *resp_len, int final){	u8 *resp;	struct eap_tlv_intermediate_result_tlv *rresult;	struct eap_tlv_crypto_binding__tlv *rbind;	u8 isk[32], imck[60], *cmk, cmac[20], *key;	size_t key_len;	int res;	wpa_printf(MSG_DEBUG, "EAP-FAST: Crypto-Binding TLV: Version %d "		   "Received Version %d SubType %d",		   _bind->version, _bind->received_version, _bind->subtype);	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE",		    _bind->nonce, sizeof(_bind->nonce));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC",		    _bind->compound_mac, sizeof(_bind->compound_mac));	if (_bind->version != EAP_FAST_VERSION ||	    _bind->received_version != EAP_FAST_VERSION ||	    _bind->subtype != EAP_TLV_CRYPTO_BINDING_SUBTYPE_REQUEST) {		wpa_printf(MSG_INFO, "EAP-FAST: Invalid version/subtype in "			   "Crypto-Binding TLV: Version %d "			   "Received Version %d SubType %d",			   _bind->version, _bind->received_version,			   _bind->subtype);		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1,					   resp_len);		return resp;	}	wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC "		   "calculation", data->simck_idx + 1);	/*	 * draft-cam-winget-eap-fast-05.txt, 5.2:	 * IMCK[j] = T-PRF(S-IMCK[j-1], "Inner Methods Compound Keys",	 *                 MSK[j], 60)	 * S-IMCK[j] = first 40 octets of IMCK[j]	 * CMK[j] = last 20 octets of IMCK[j]	 */	os_memset(isk, 0, sizeof(isk));	if (data->phase2_method == NULL || data->phase2_priv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not "			   "available");		return NULL;	}	if (data->phase2_method->isKeyAvailable && data->phase2_method->getKey)	{		if (!data->phase2_method->isKeyAvailable(sm, data->phase2_priv)		    ||		    (key = data->phase2_method->getKey(sm, data->phase2_priv,						       &key_len)) == NULL) {			wpa_printf(MSG_DEBUG, "EAP-FAST: Could not get key "				   "material from Phase 2");			return NULL;		}		if (key_len > sizeof(isk))			key_len = sizeof(isk);		os_memcpy(isk, key, key_len);		os_free(key);	}	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[j]", isk, sizeof(isk));	sha1_t_prf(data->simck, EAP_FAST_SIMCK_LEN,		   "Inner Methods Compound Keys",		   isk, sizeof(isk), imck, sizeof(imck));	data->simck_idx++;	os_memcpy(data->simck, imck, EAP_FAST_SIMCK_LEN);	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[j]",			data->simck, EAP_FAST_SIMCK_LEN);	cmk = imck + EAP_FAST_SIMCK_LEN;	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]", cmk, 20);	os_memcpy(cmac, _bind->compound_mac, sizeof(cmac));	os_memset(_bind->compound_mac, 0, sizeof(cmac));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Crypto-Binding TLV for Compound "		    "MAC calculation", (u8 *) _bind, bind_len);	hmac_sha1(cmk, 20, (u8 *) _bind, bind_len, _bind->compound_mac);	res = os_memcmp(cmac, _bind->compound_mac, sizeof(cmac));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Received Compound MAC",		    cmac, sizeof(cmac));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Calculated Compound MAC",		    _bind->compound_mac, sizeof(cmac));	if (res != 0) {		wpa_printf(MSG_INFO, "EAP-FAST: Compound MAC did not match");		resp = eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 1,					   resp_len);		os_memcpy(_bind->compound_mac, cmac, sizeof(cmac));		return resp;	}	*resp_len = sizeof(*rresult) + sizeof(*rbind);	resp = os_zalloc(*resp_len);	if (resp == NULL)		return NULL;	/* Both intermediate and final Result TLVs are identical, so ok to use	 * the same structure definition for them. */	rresult = (struct eap_tlv_intermediate_result_tlv *) resp;	rresult->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |					 (final ? EAP_TLV_RESULT_TLV :					  EAP_TLV_INTERMEDIATE_RESULT_TLV));	rresult->length = host_to_be16(2);	rresult->status = host_to_be16(EAP_TLV_RESULT_SUCCESS);	if (!data->provisioning && data->phase2_success &&	    eap_fast_derive_msk(data) < 0) {		wpa_printf(MSG_INFO, "EAP-FAST: Failed to generate MSK");		ret->methodState = METHOD_DONE;		ret->decision = DECISION_FAIL;		rresult->status = host_to_be16(EAP_TLV_RESULT_FAILURE);		data->phase2_success = 0;	}	rbind = (struct eap_tlv_crypto_binding__tlv *) (rresult + 1);	rbind->tlv_type = host_to_be16(EAP_TLV_TYPE_MANDATORY |				       EAP_TLV_CRYPTO_BINDING_TLV_);	rbind->length = host_to_be16(sizeof(*rbind) -				     sizeof(struct eap_tlv_hdr));	rbind->version = EAP_FAST_VERSION;	rbind->received_version = _bind->version;	rbind->subtype = EAP_TLV_CRYPTO_BINDING_SUBTYPE_RESPONSE;	os_memcpy(rbind->nonce, _bind->nonce, sizeof(_bind->nonce));	inc_byte_array(rbind->nonce, sizeof(rbind->nonce));	hmac_sha1(cmk, 20, (u8 *) rbind, sizeof(*rbind), rbind->compound_mac);	wpa_printf(MSG_DEBUG, "EAP-FAST: Reply Crypto-Binding TLV: Version %d "		   "Received Version %d SubType %d",		   rbind->version, rbind->received_version, rbind->subtype);	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: NONCE",		    rbind->nonce, sizeof(rbind->nonce));	wpa_hexdump(MSG_MSGDUMP, "EAP-FAST: Compound MAC",		    rbind->compound_mac, sizeof(rbind->compound_mac));	if (final && data->phase2_success) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Authentication completed "			   "successfully.");		ret->methodState = METHOD_DONE;		ret->decision = DECISION_UNCOND_SUCC;	}	return resp;}static u8 * eap_fast_process_pac(struct eap_sm *sm, struct eap_fast_data *data,				 struct eap_method_ret *ret,				 u8 *pac, size_t pac_len, size_t *resp_len){	struct wpa_ssid *config = eap_get_config(sm);	struct pac_tlv_hdr *hdr;	u8 *pos;	size_t left, len;	int type, pac_key_found = 0;	struct eap_fast_pac entry;	os_memset(&entry, 0, sizeof(entry));	pos = pac;	left = pac_len;	while (left > sizeof(*hdr)) {		hdr = (struct pac_tlv_hdr *) pos;		type = be_to_host16(hdr->type);		len = be_to_host16(hdr->len);		pos += sizeof(*hdr);		left -= sizeof(*hdr);		if (len > left) {			wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV overrun "				   "(type=%d len=%lu left=%lu)",				   type, (unsigned long) len,				   (unsigned long) left);			return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,						   resp_len);		}		switch (type) {		case PAC_TYPE_PAC_KEY:			wpa_hexdump_key(MSG_DEBUG, "EAP-FAST: PAC-Key",					pos, len);			if (len != EAP_FAST_PAC_KEY_LEN) {				wpa_printf(MSG_DEBUG, "EAP-FAST: Invalid "					   "PAC-Key length %lu",					   (unsigned long) len);				break;			}			pac_key_found = 1;			os_memcpy(entry.pac_key, pos, len);			break;		case PAC_TYPE_PAC_OPAQUE:			wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Opaque",					pos, len);			entry.pac_opaque = pos;			entry.pac_opaque_len = len;			break;		case PAC_TYPE_PAC_INFO:			wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info",				    pos, len);			entry.pac_info = pos;			entry.pac_info_len = len;			break;		default:			wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC "				   "type %d", type);			break;		}		pos += len;		left -= len;	}	if (!pac_key_found || !entry.pac_opaque || !entry.pac_info) {		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC TLV does not include "			   "all the required fields");		return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,					   resp_len);	}	pos = entry.pac_info;	left = entry.pac_info_len;	while (left > sizeof(*hdr)) {		hdr = (struct pac_tlv_hdr *) pos;		type = be_to_host16(hdr->type);		len = be_to_host16(hdr->len);		pos += sizeof(*hdr);		left -= sizeof(*hdr);		if (len > left) {			wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info overrun "				   "(type=%d len=%lu left=%lu)",				   type, (unsigned long) len,				   (unsigned long) left);			return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,						   resp_len);		}		switch (type) {		case PAC_TYPE_A_ID:			wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - "					  "A-ID", pos, len);			entry.a_id = pos;			entry.a_id_len = len;			break;		case PAC_TYPE_I_ID:			wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - "					  "I-ID", pos, len);			entry.i_id = pos;			entry.i_id_len = len;			break;		case PAC_TYPE_A_ID_INFO:			wpa_hexdump_ascii(MSG_DEBUG, "EAP-FAST: PAC-Info - "					  "A-ID-Info", pos, len);			entry.a_id_info = pos;			entry.a_id_info_len = len;			break;		default:			wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown "				   "PAC-Info type %d", type);			break;		}		pos += len;		left -= len;	}	if (entry.a_id == NULL || entry.a_id_info == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info does not include "			   "all the required fields");		return eap_fast_tlv_result(EAP_TLV_RESULT_FAILURE, 0,					   resp_len);	}	eap_fast_add_pac(data, &entry);	eap_fast_save_pac(sm, data, config->pac_file);	if (data->provisioning) {		/* EAP-FAST provisioning does not provide keying material and		 * must end with an EAP-Failure. Authentication will be done		 * separately after this. */		data->success = 0;		ret->decision = DECISION_FAIL;		wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV "			   "- Provisioning completed successfully");	} else {		/* This is PAC refreshing, i.e., normal authentication that is		 * expected to be completed with an EAP-Success. */		wpa_printf(MSG_DEBUG, "EAP-FAST: Send PAC-Acknowledgement TLV "			   "- PAC refreshing completed successfully");		ret->decision = DECISION_UNCOND_SUCC;	}	ret->methodState = METHOD_DONE;	return eap_fast_tlv_pac_ack(resp_len);}static int eap_fast_decrypt(struct eap_sm *sm, struct eap_fast_data *data,			    struct eap_method_ret *ret,			    const struct eap_hdr *req,			    const u8 *in_data, size_t in_len,			    u8 **out_data, size_t *out_len){	u8 *in_decrypted, *pos, *end;	int len_decrypted, len;	struct eap_hdr *hdr;	u8 *resp = NULL;	size_t buf_len, resp_len;	int mandatory, tlv_type;	u8 *eap_payload_tlv = NULL, *pac = NULL;	size_t eap_payload_tlv_len = 0, pac_len = 0;	int iresult = 0, result = 0;	struct eap_tlv_crypto_binding__tlv *crypto_binding = NULL;	size_t crypto_binding_len = 0;	const u8 *msg;	size_t msg_len;	int need_more_input, stop;	wpa_printf(MSG_DEBUG, "EAP-FAST: received %lu bytes encrypted data for"		   " Phase 2", (unsigned long) in_len);	msg = eap_tls_data_reassemble(sm, &data->ssl, in_data, in_len,				      &msg_len, &need_more_input);	if (msg == NULL)		return need_more_input ? 1 : -1;	buf_len = in_len;	if (data->ssl.tls_in_total > buf_len)		buf_len = data->ssl.tls_in_total;	in_decrypted = os_malloc(buf_len);	if (in_decrypted == NULL) {		os_free(data->ssl.tls_in);		data->ssl.tls_in = NULL;		data->ssl.tls_in_len = 0;		wpa_printf(MSG_WARNING, "EAP-FAST: failed to allocate memory "			   "for decryption");		return -1;	}	len_decrypted = tls_connection_decrypt(sm->ssl_ctx, data->ssl.conn,					       msg, msg_len,					       in_decrypted, buf_len);	os_free(data->ssl.tls_in);	data->ssl.tls_in = NULL;	data->ssl.tls_in_len = 0;	if (len_decrypted < 0) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -