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

📄 eap_fast.c

📁 一个Linux下无线网卡的设置工具
💻 C
📖 第 1 页 / 共 4 页
字号:
			   "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, req->identifier, resp_len, 1);		break;	default:		if (data->phase2_type == EAP_TYPE_NONE) {			int i;			for (i = 0; i < data->num_phase2_types; i++) {				if (data->phase2_types[i] != *pos)					continue;				data->phase2_type = *pos;				wpa_printf(MSG_DEBUG, "EAP-FAST: Selected "					   "Phase 2 EAP method %d",					   data->phase2_type);				break;			}		}		if (*pos != data->phase2_type || *pos == EAP_TYPE_NONE) {			if (eap_fast_phase2_nak(sm, data, hdr, resp, resp_len))				return -1;			return 0;		}		if (data->phase2_priv == NULL) {			data->phase2_method = eap_sm_get_eap_methods(*pos);			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;				data->phase2_priv =					data->phase2_method->init(sm);				sm->init_phase2 = 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;		}		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 = 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 = 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 = malloc(*len);	if (res == NULL)		return NULL;	memset(res, 0, *len);	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 = malloc(sizeof(*tlv) + *len);	if (tlv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Failed to "			   "allocate memory for TLV "			   "encapsulation");		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);	memcpy(tlv + 1, buf, *len);	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, *sks = NULL;	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;	}	if (data->provisioning) {		if (data->key_block_p) {			sks = data->key_block_p->session_key_seed;		}	} else {		if (data->key_block_a) {			sks = data->key_block_a->session_key_seed;		}	}	if (sks == NULL) {		wpa_printf(MSG_INFO, "EAP-FAST: No Session Key Seed available "			   "for processing Crypto-Binding TLV");		return NULL;	}	wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK for Compound MIC "		   "calculation");	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[0] = SKS", sks, 40);	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);		/* FIX: which end is being padded? */#if 0		memcpy(isk + (sizeof(isk) - key_len), key, key_len);#else		memcpy(isk, key, key_len);#endif		free(key);	}	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: ISK[0]", isk, sizeof(isk));	sha1_t_prf(sks, 40, "Inner Methods Compound Keys",		   isk, sizeof(isk), imck, sizeof(imck));	/* S-IMCK[1] = imkc[0..39] */	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: S-IMCK[1]", imck, 40);	cmk = imck + 40;	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK", cmk, 20);	memcpy(cmac, bind->compound_mac, sizeof(cmac));	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 = 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);		memcpy(bind->compound_mac, cmac, sizeof(cmac));		return resp;	}	*resp_len = sizeof(*rresult) + sizeof(*rbind);	resp = malloc(*resp_len);	if (resp == NULL)		return NULL;	memset(resp, 0, *resp_len);	/* 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(sm, 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;	memcpy(rbind->nonce, bind->nonce, sizeof(bind->nonce));	inc_byte_array(rbind->nonce, sizeof(bind->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;	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;			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 buf_len, len_decrypted, len;	struct eap_hdr *hdr;	u8 *resp = NULL;	size_t 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;	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;

⌨️ 快捷键说明

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