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

📄 eap_fast.c

📁 最新的Host AP 新添加了许多pcmcia 的驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
		wpa_printf(MSG_INFO, "EAP-FAST: Phase2 Request processing "			   "failed");		return NULL;	}	return eap_fast_tlv_eap_payload(resp);}static int eap_fast_validate_crypto_binding(	struct eap_tlv_crypto_binding_tlv *_bind){	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);		return -1;	}	return 0;}static void eap_fast_write_crypto_binding(	struct eap_tlv_crypto_binding_tlv *rbind,	struct eap_tlv_crypto_binding_tlv *_bind, const u8 *cmk){	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, EAP_FAST_CMK_LEN, (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));}static int eap_fast_get_phase2_key(struct eap_sm *sm,				   struct eap_fast_data *data,				   u8 *isk, size_t isk_len){	u8 *key;	size_t key_len;	os_memset(isk, 0, isk_len);	if (data->phase2_method == NULL || data->phase2_priv == NULL) {		wpa_printf(MSG_DEBUG, "EAP-FAST: Phase 2 method not "			   "available");		return -1;	}	if (data->phase2_method->isKeyAvailable == NULL ||	    data->phase2_method->getKey == NULL)		return 0;	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 -1;	}	if (key_len > isk_len)		key_len = isk_len;	if (key_len == 32 &&	    data->phase2_method->vendor == EAP_VENDOR_IETF &&	    data->phase2_method->method == EAP_TYPE_MSCHAPV2) {		/*		 * EAP-FAST uses reverse order for MS-MPPE keys when deriving		 * MSK from EAP-MSCHAPv2. Swap the keys here to get the correct		 * ISK for EAP-FAST cryptobinding.		 */		os_memcpy(isk, key + 16, 16);		os_memcpy(isk + 16, key, 16);	} else		os_memcpy(isk, key, key_len);	os_free(key);	return 0;}static int eap_fast_get_cmk(struct eap_sm *sm, struct eap_fast_data *data,			    u8 *cmk){	u8 isk[32], imck[60];	wpa_printf(MSG_DEBUG, "EAP-FAST: Determining CMK[%d] for Compound MIC "		   "calculation", data->simck_idx + 1);	/*	 * RFC 4851, Section 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]	 */	if (eap_fast_get_phase2_key(sm, data, isk, sizeof(isk)) < 0)		return -1;	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);	os_memcpy(cmk, imck + EAP_FAST_SIMCK_LEN, EAP_FAST_CMK_LEN);	wpa_hexdump_key(MSG_MSGDUMP, "EAP-FAST: CMK[j]",			cmk, EAP_FAST_CMK_LEN);	return 0;}static u8 * eap_fast_write_pac_request(u8 *pos, u16 pac_type){	struct eap_tlv_hdr *pac;	struct eap_tlv_request_action_tlv *act;	struct eap_tlv_pac_type_tlv *type;	act = (struct eap_tlv_request_action_tlv *) pos;	act->tlv_type = host_to_be16(EAP_TLV_REQUEST_ACTION_TLV);	act->length = host_to_be16(2);	act->action = host_to_be16(EAP_TLV_ACTION_PROCESS_TLV);	pac = (struct eap_tlv_hdr *) (act + 1);	pac->tlv_type = host_to_be16(EAP_TLV_PAC_TLV);	pac->length = host_to_be16(sizeof(*type));	type = (struct eap_tlv_pac_type_tlv *) (pac + 1);	type->tlv_type = host_to_be16(PAC_TYPE_PAC_TYPE);	type->length = host_to_be16(2);	type->pac_type = host_to_be16(pac_type);	return (u8 *) (type + 1);}static struct wpabuf * 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){	struct wpabuf *resp;	u8 *pos;	u8 cmk[EAP_FAST_CMK_LEN], cmac[SHA1_MAC_LEN];	int res;	size_t len;	if (eap_fast_validate_crypto_binding(_bind) < 0)		return NULL;	if (eap_fast_get_cmk(sm, data, cmk) < 0)		return NULL;	/* Validate received Compound MAC */	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, EAP_FAST_CMK_LEN, (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");		os_memcpy(_bind->compound_mac, cmac, sizeof(cmac));		return NULL;	}	/*	 * Compound MAC was valid, so authentication succeeded. Reply with	 * crypto binding to allow server to complete authentication.	 */	len = sizeof(struct eap_tlv_crypto_binding_tlv);	resp = wpabuf_alloc(len);	if (resp == NULL)		return NULL;	if (!data->anon_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;		data->phase2_success = 0;		wpabuf_free(resp);		return NULL;	}	pos = wpabuf_put(resp, sizeof(struct eap_tlv_crypto_binding_tlv));	eap_fast_write_crypto_binding((struct eap_tlv_crypto_binding_tlv *)				      pos, _bind, cmk);	return resp;}static void eap_fast_parse_pac_tlv(struct eap_fast_pac *entry, int type,				   u8 *pos, size_t len, int *pac_key_found){	switch (type & 0x7fff) {	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;	}}static int eap_fast_process_pac_tlv(struct eap_fast_pac *entry,				    u8 *pac, size_t pac_len){	struct pac_tlv_hdr *hdr;	u8 *pos;	size_t left, len;	int type, pac_key_found = 0;	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 -1;		}		eap_fast_parse_pac_tlv(entry, type, pos, len, &pac_key_found);		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 -1;	}	return 0;}static int eap_fast_parse_pac_info(struct eap_fast_pac *entry, int type,				   u8 *pos, size_t len){	u16 pac_type;	u32 lifetime;	struct os_time now;	switch (type & 0x7fff) {	case PAC_TYPE_CRED_LIFETIME:		if (len != 4) {			wpa_hexdump(MSG_DEBUG, "EAP-FAST: PAC-Info - "				    "Invalid CRED_LIFETIME length - ignored",				    pos, len);			return 0;		}		/*		 * This is not currently saved separately in PAC files since		 * the server can automatically initiate PAC update when		 * needed. Anyway, the information is available from PAC-Info		 * dump if it is needed for something in the future.		 */		lifetime = WPA_GET_BE32(pos);		os_get_time(&now);		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - CRED_LIFETIME %d "			   "(%d days)",			   lifetime, (lifetime - (u32) now.sec) / 86400);		break;	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;	case PAC_TYPE_PAC_TYPE:		/* RFC 5422, Section 4.2.6 - PAC-Type TLV */		if (len != 2) {			wpa_printf(MSG_INFO, "EAP-FAST: Invalid PAC-Type "				   "length %lu (expected 2)",				   (unsigned long) len);			wpa_hexdump_ascii(MSG_DEBUG,					  "EAP-FAST: PAC-Info - PAC-Type",					  pos, len);			return -1;		}		pac_type = WPA_GET_BE16(pos);		if (pac_type != PAC_TYPE_TUNNEL_PAC &&		    pac_type != PAC_TYPE_USER_AUTHORIZATION &&		    pac_type != PAC_TYPE_MACHINE_AUTHENTICATION) {			wpa_printf(MSG_INFO, "EAP-FAST: Unsupported PAC Type "				   "%d", pac_type);			return -1;		}		wpa_printf(MSG_DEBUG, "EAP-FAST: PAC-Info - PAC-Type %d",			   pac_type);		entry->pac_type = pac_type;		break;	default:		wpa_printf(MSG_DEBUG, "EAP-FAST: Ignored unknown PAC-Info "			   "type %d", type);		break;	}	return 0;}static int eap_fast_process_pac_info(struct eap_fast_pac *entry){	struct pac_tlv_hdr *hdr;	u8 *pos;	size_t left, len;	int type;	/* RFC 5422, Section 4.2.4 */	/* PAC-Type defaults to Tunnel PAC (Type 1) */	entry->pac_type = PAC_TYPE_TUNNEL_PAC;	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 -1;		}		if (eap_fast_parse_pac_info(entry, type, pos, len) < 0)			return -1;		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 -1;	}	return 0;}static struct wpabuf * eap_fast_process_pac(struct eap_sm *sm,					    struct eap_fast_data *data,					    struct eap_method_ret *ret,					    u8 *pac, size_t pac_len){	struct eap_peer_config *config = eap_get_config(sm);	struct eap_fast_pac entry;	os_memset(&entry, 0, sizeof(entry));	if (eap_fast_process_pac_tlv(&entry, pac, pac_len) ||	    eap_fast_process_pac_info(&entry))		return NULL;	eap_fast_add_pac(&data->pac, &data->current_pac, &entry);	eap_fast_pac_list_truncate(data->pac, data->max_pac_list_len);	if (data->use_pac_binary_format)		eap_fast_save_pac_bin(sm, data->pac, config->pac_file);	else		eap_fast_save_pac(sm, data->pac, config->pac_file);	if (data->provisioning) {		if (data->anon_provisioning) {			/*			 * Unauthenticated 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;		} else {			/*			 * Server may or may not allow authenticated			 * provisioning also for key generation.			 */			ret->decision = DECISION_COND_SUCC;		}		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();}static int eap_fast_parse_decrypted(struct wpabuf *decrypted,				    struct eap_fast_tlv_parse *tlv,				    struct wpabuf **resp){	int mandatory, tlv_type, len, res;	u8 *pos, *end;	os_memset(tlv, 0, sizeof(*tlv));	/* Parse TLVs from the decrypted Phase 2 data */	pos = wpabuf_mhead(decrypted);	end = pos + wpabuf_len(decrypted);	while (pos + 4 < end) {		mandatory = pos[0] & 0x80;		tlv_type = WPA_GET_BE16(pos) & 0x3fff;		pos += 2;		len = WPA_GET_BE16(pos);		pos += 2;		if (pos + len > end) {			wpa_printf(MSG_INFO, "EAP-FAST: TLV overflow");			return -1;		}		wpa_printf(MSG_DEBUG, "EAP-FAST: Received Phase 2: "			   "TLV type %d length %d%s",			   tlv_type, len, mandatory ? " (mandatory)" : "");		res = eap_fast_parse_tlv(tlv, tlv_type, pos, len);		if (res == -2)			break;		if (res < 0) {			if (mandatory) {				wpa_printf(MSG_DEBUG, "EAP-FAST: Nak unknown "					   "mandatory TLV type %d", tlv_type);				*resp = eap_fast_tlv_nak(0, tlv_type);				break;			} else {				wpa_printf(MSG_DEBUG, "EAP-FAST: ignored "					   "unknown optional TLV type %d",					   tlv_type);			}		}		pos += len;	}	return 0;}static int eap_fast_encrypt_response(struct eap_sm *sm,				     struct eap_fast_data *data,				     struct wpabuf *resp,				     u8 identifier, struct wpabuf **out_data){	if (resp == NULL)		return 0;	wpa_hexdump_buf(MSG_DEBUG, "EAP-FAST: Encrypting Phase 2 data",			resp);	if (eap_peer_tls_encrypt(sm, &data->ssl, EAP_TYPE_FAST,				 data->fast_version, identifier,				 resp, out_data)) {		wpa_printf(MSG_INFO, "EAP-FAST: Failed to encrypt a Phase 2 "			   "frame");	}	wpabuf_free(resp);	return 0;}static struct wpabuf * eap_fast_pac_request(void){	struct wpabuf *tmp;	u8 *pos, *pos2;	tmp = wpabuf_alloc(sizeof(struct eap_tlv_hdr) +			   sizeof(struct eap_tlv_request_action_tlv) +			   sizeof(struct eap_tlv_pac_type_tlv));	if (tmp == NULL)		return NULL;	pos = wpabuf_put(tmp, 0);	pos2 = eap_fast_write_pac_request(pos, PAC_TYPE_TUNNEL_PAC);	wpabuf_put(tmp, pos2 - pos);	return tmp;}static int eap_fast_process_decrypted(struct eap_sm *sm,				      struct eap_fast_data *data,				      struct eap_method_ret *ret,

⌨️ 快捷键说明

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