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

📄 wps_enrollee.c

📁 WiFi Protected Setup (WPS) 又叫Simple config。 是无线局域网领域推出的新协议
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 *  WPS_ENROLLEE.C : WPS ENROLLEE Porcess Module
 * 
 *  ver       date      author     comment
 *  0.0.1     06/08/27  Gao Hua    First
 *  0.0.2     07/09/05  D.W.Yan    Refactor code
 */

#include "wps_types.h"
#include "wps_common.h"
#include "wps_osfunc.h"
#include "wps_crypto.h"
#include "wps_wlandrv.h"
#include "wps_lib.h"
#include "wps_eap_pkt.h"
#include "wps_data_element.h"
#include "wps_callback.h"

#include "wps_enrollee.h"

#define SEND_BUFFER_SIZE (800)

///////////////////////////////////////////////////////////////////////////
static const WPS_char
    g_rnd_seed[] = "enrollee string to make the random number generator think it has entropy";

///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////

static void wps_enrol_save_credential(struct enrollee* enrollee,
                                      WPS_u8 *Attribute);
static WPS_s32 wps_enrol_build_enc_set(struct enrollee *enrollee,
                                       const WPS_u8 *DataToEncrypt,
                                       WPS_s32 DataLen, WPS_u8 *Output,
                                       WPS_s32 OutputBuffLen);
static WPS_s32 wps_enrol_analyze_enc_set(struct enrollee *enrollee,
                                         const WPS_u8 *Input, WPS_s32 InputLen,
                                         WPS_u8 *Output, WPS_s32 OutputBuffLen);
static WPS_s32 wps_enrol_key_derivation(struct enrollee *enrollee);
static WPS_s32 wps_enrol_check_rh1_using_rsn1(struct enrollee *enrollee);
static WPS_s32 wps_enrol_check_rh2_using_rsn2(struct enrollee *enrollee);
static WPS_s32 wps_enrol_upt_last_msg_for_snd(struct enrollee *enrollee,
                                              WPS_u8 *SendBuff,
                                              WPS_s16 MessageLength);
static WPS_s32 wps_enrol_upt_last_msg_for_rcv(struct enrollee *enrollee,
                                              struct eap_packet *packet);
static WPS_s32 wps_enrol_snd_m1(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m3(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m5(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_m7(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_ack(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_nack(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_done(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_eap_fail(struct enrollee *enrollee);
static WPS_s32 wps_enrol_snd_eap_rsp_ident(struct enrollee *enrollee);
static WPS_s32 wps_enrol_rcv_start(struct enrollee *enrollee,
                                   struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m2(struct enrollee *enrollee,
                                struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m2d(struct enrollee *enrollee,
                                 struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m4(struct enrollee *enrollee,
                                struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m6(struct enrollee *enrollee,
                                struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_m8(struct enrollee *enrollee,
                                struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_nack(struct enrollee *enrollee,
                                  struct eap_packet *packet);
static WPS_s32 wps_enrol_rcv_eap_req_ident(struct enrollee *enrollee,
                                           struct eap_packet *packet);


void wps_enrol_save_credential(struct enrollee* enrollee, WPS_u8 *Attribute)
{
	WPS_u8 *p = Attribute;
	int count;
	ENROLLEE_CREDENTIAL tmp_credential;
	WPS_u8 *CredentialStart;
	WPS_s16 CredentialDataLen;
	WPS_s16 DataLen;
#if ENROLLEE_DEBUG
	WPS_s16 i;
#endif

	for (count = 0; ; count++) {

		CredentialStart = p;
		
		if (WPS_get_word(p) == WPS_h2n16(E_Credential_ID)) {
			CredentialDataLen = WPS_n2h16(WPS_get_word(p+2));
			p += 2+2;
		}
		else {
			break;
		}
		
		
#if ENROLLEE_DEBUG
		WPS_PRINTF("\n-----------WLAN Credential(%d) information in M8----------\n", count+1);
#endif

		if (WPS_get_word(p) == WPS_h2n16(E_NetworkIndex_ID)&& WPS_get_word(p+2)
		    == WPS_h2n16(E_NetworkIndex_Length)) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tNetwork Index:\t\t%d\n", *(p+4));
#endif
			tmp_credential.Cre_NetworkIndex = *(p+4);
			p += 2+2+1;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		if (WPS_get_word(p) == WPS_h2n16(E_SSID_ID)&& WPS_n2h16(WPS_get_word(p+2))
		    <= E_SSID_MaxLength) {
			DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tSSID:\t\t\t");
			for (i=0; i<DataLen; i++) {
				WPS_PRINTF("\t%c", *(p+4+i));
			}
			WPS_PRINTF("\n");
#endif
			WPS_MEM_FILL(tmp_credential.Cre_SSID, 0, E_SSID_MaxLength);
			WPS_MEM_CPY(tmp_credential.Cre_SSID, p+4, DataLen);
			tmp_credential.Cre_SSID_Length = DataLen;
			p += 2+2+DataLen;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		if (WPS_get_word(p) == WPS_h2n16(E_AuthenticationType_ID)&& WPS_get_word(p
		    +2) == WPS_h2n16(E_AuthenticationType_Length)) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tAuthentication Type:\t");
			switch (WPS_n2h16(WPS_get_word(p+4))) {
			case AUTHENTICATION_TYPE_OPEN:
				WPS_PRINTF("\tOPEN");
				break;
			case AUTHENTICATION_TYPE_WPAPSK:
				WPS_PRINTF("\tWPAPSK");
				break;
			case AUTHENTICATION_TYPE_SHARED:
				WPS_PRINTF("\tSHARED");
				break;
			case AUTHENTICATION_TYPE_WPA:
				WPS_PRINTF("\tWPA");
				break;
			case AUTHENTICATION_TYPE_WPA2:
				WPS_PRINTF("\tWPA2");
				break;
			case AUTHENTICATION_TYPE_WPA2PSK:
				WPS_PRINTF("\tWPA2PSK");
				break;
			default:
				break;
			}
			WPS_PRINTF("\n");
#endif
			tmp_credential.Cre_AuthenticationType = WPS_n2h16(WPS_get_word(p+4));
			p += 2+2+E_AuthenticationType_Length;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		if (WPS_get_word(p) == WPS_h2n16(E_EncryptionType_ID)&& WPS_get_word(p+2)
		    == WPS_h2n16(E_EncryptionType_Length)) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tEncryption Type:\t");
			switch (WPS_n2h16(WPS_get_word(p+4))) {
			case ENCRYPTION_TYPE_NONE:
				WPS_PRINTF("\tNONE");
				break;
			case ENCRYPTION_TYPE_WEP:
				WPS_PRINTF("\tWEP");
				break;
			case ENCRYPTION_TYPE_TKIP:
				WPS_PRINTF("\tTKIP");
				break;
			case ENCRYPTION_TYPE_AES:
				WPS_PRINTF("\tAES");
				break;
			default:
				break;
			}
			WPS_PRINTF("\n");
#endif
			tmp_credential.Cre_EncryptionType = WPS_n2h16(WPS_get_word(p+4));
			p += 2+2+E_EncryptionType_Length;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		//
		// Optional elemnet: Network Key Index
		//
		if (WPS_get_word(p) == WPS_h2n16(E_NetworkKeyIndex_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) == E_NetworkKeyIndex_Length) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tNetwork Key Index:\t%d\n", *(p+4));
#endif
			tmp_credential.Cre_NetworkKeyIndex = *(p+4);
			p += 2+2+E_NetworkKeyIndex_Length;
		}

		if (WPS_get_word(p) == WPS_h2n16(E_NetworkKey_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) <= E_NetworkKey_MaxLength) {
			DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
			if (DataLen > 0) {
				WPS_PRINTF("\tNetwork Key:\t\t");
				for (i=0; i<DataLen; i++) {
					WPS_PRINTF("\t%x", *(p+4+i));
				}
				WPS_PRINTF("\n");
			}
#endif
			if (DataLen > 0) {
				WPS_MEM_FILL(tmp_credential.Cre_NetworkKey, 0, E_NetworkKey_MaxLength);
				WPS_MEM_CPY(tmp_credential.Cre_NetworkKey, p+4, DataLen);
			}
			tmp_credential.Cre_NetworkKey_Length = DataLen;
			p += 2+2+DataLen;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		if (WPS_get_word(p) == WPS_h2n16(E_MACAddress_ID)&& WPS_get_word(p+2)
		    == WPS_h2n16(E_MACAddress_Length)) {
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tMAC Address:\t\t");
			for (i=0; i<E_MACAddress_Length; i++) {
				WPS_PRINTF("\t%x ", *(p+4+i));
			}
			WPS_PRINTF("\n");
#endif
			WPS_MEM_CPY(tmp_credential.Cre_MACAddress, p+4, E_MACAddress_Length);
			p += 2+2+E_MACAddress_Length;
		}
		else {
			WPS_PRINTF("Enrollee: Credential format is invalid.\n");
			return;
		}

		//
		// Optional elemnet: EAP Type
		//
		if (WPS_get_word(p) == WPS_h2n16(E_EAPType_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) <= E_EAPType_MaxLength) {
			DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tEAP Type:\t\t");
			for (i=0; i<DataLen; i++) {
				WPS_PRINTF("\t%x", *(p+4+i));
			}
			WPS_PRINTF("\n");
#endif
			p += 2+2+DataLen;
		}

		//
		// Optional elemnet: EAP Identity
		//
		if (WPS_get_word(p) == WPS_h2n16(E_EAPIdentity_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) <= E_EAPIdentity_MaxLength) {
			DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
			WPS_PRINTF("\tEAP Identity:\t\t");
			for (i=0; i<DataLen; i++) {
				WPS_PRINTF("\t%x", *(p+4+i));
			}
			WPS_PRINTF("\n");
#endif
			p += 2+2+DataLen;
		}

		//
		// Optional elemnet: Key Provided Automatically
		//
		if (WPS_get_word(p) == WPS_h2n16(E_KeyProvidedAutomatically_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) == E_KeyProvidedAutomatically_Length) {
#if ENROLLEE_DEBUG
			if (WPS_BOOL_LENGTH == 4) {
				WPS_PRINTF("\tKey Provided Automatically:\t%x\n",
				           WPS_get_dword(p+4));
			}
			else if (WPS_BOOL_LENGTH == 2) {
				WPS_PRINTF("\tKey Provided Automatically:\t%x\n", WPS_get_word(p+4));
			}
			else /* 1 byte */
			{
				WPS_PRINTF("\tKey Provided Automatically:\t%x\n", *(p+4));
			}
#endif
			p += 2+2+E_KeyProvidedAutomatically_Length;
		}

		//
		// Optional elemnet: 802.1X Enabled
		//
		if (WPS_get_word(p) == WPS_h2n16(E_8021xEnabled_ID)
		    && WPS_n2h16(WPS_get_word(p+2)) == E_8021xEnabled_Length) {
#if ENROLLEE_DEBUG
			if (WPS_BOOL_LENGTH == 4) {
				WPS_PRINTF("\t802.1X Enabled:\t%x\n", WPS_get_dword(p+4));
			}
			else if (WPS_BOOL_LENGTH == 2) {
				WPS_PRINTF("\t802.1X Enabled:\t%x\n", WPS_get_word(p+4));
			}
			else /* 1 byte */
			{
				WPS_PRINTF("\t802.1X Enabled:\t%x\n", *(p+4));
			}
#endif
			p += 2+2+E_8021xEnabled_Length;
		}

		if (tmp_credential.Cre_SSID_Length == enrollee->Current_SSID_Length &&
			WPS_MEM_CMP(tmp_credential.Cre_SSID, enrollee->Current_SSID, tmp_credential.Cre_SSID_Length) == 0) {
			enrollee->credential = tmp_credential;
			WPS_PRINTF("Credential selected!!!\n");
		}
		
#if ENROLLEE_DEBUG
		WPS_PRINTF("----------------------------------------------------------\n\n");
#endif
		p = CredentialStart+2+2+CredentialDataLen;

	}

	
	//
	// Optional elemnet: New Password
	//
	if (WPS_get_word(p) == WPS_h2n16(E_NewPassword_ID)
	    && WPS_n2h16(WPS_get_word(p+2)) <= E_NewPassword_MaxLength) {
		DataLen = WPS_n2h16(WPS_get_word(p+2));
#if ENROLLEE_DEBUG
		WPS_PRINTF("\tNew Password:\t\t");
		for (i=0; i<DataLen; i++) {
			WPS_PRINTF("\t%x", *(p+4+i));
		}
		WPS_PRINTF("\n");
#endif
		p += 2+2+DataLen;
	}

	//
	// Optional elemnet: Device Password ID
	//
	if (WPS_get_word(p) == WPS_h2n16(E_DevicePasswordID_ID)
	    && WPS_n2h16(WPS_get_word(p+2)) == E_DevicePasswordID_Length) {
#if ENROLLEE_DEBUG
		WPS_PRINTF("\tDevice Password ID:\t%x\n", WPS_n2h16(WPS_get_word(p+4)));
#endif
		p += 2+2+E_DevicePasswordID_Length;
	}
}

//
// Parameters:
//     DataToEncrypt: a set of Simple Config TLV attributes excluding the Key Wrap Authenticator attribute
//     Output: the point of target buffer to put the Encrypted Settings attribute
// Return values:
//     0: Successful.
//     -1: Failed to build the Encrypted Settings attribute.
//
WPS_s32 wps_enrol_build_enc_set(struct enrollee *enrollee, const WPS_u8 *DataToEncrypt, WPS_s32 DataLen, WPS_u8 *Output, WPS_s32 OutputBuffLen)
{
	WPS_s16 AES_Input_Length = DataLen+2+2+E_KeyWrapAuthenticator_Length+16;

	if (OutputBuffLen < (4+16+AES_Input_Length))
	{
		WPS_PRINTF("BuildEncryptedSettings(): Output buffer is too small!\n");
		return -1;
	}

	WPS_set_word(Output, WPS_h2n16(E_EncryptedSettings_ID));
	WPS_set_word(Output+2, WPS_h2n16(16+AES_Input_Length));
	WPS_u8 *IV = Output+4;
	WPS_Rand(IV, 16);

	WPS_u8 *temp = (WPS_u8 *)WPS_MALLOC(AES_Input_Length);
	WPS_MEM_CPY(temp, DataToEncrypt, DataLen);

	WPS_u8 HMAC_Output[32];
	WPS_HMAC_Sha256(enrollee->AuthKey, 32, temp, DataLen, HMAC_Output, 32);

	WPS_set_word((temp+DataLen), WPS_h2n16(E_KeyWrapAuthenticator_ID));
	WPS_set_word((temp+DataLen+2), WPS_h2n16(E_KeyWrapAuthenticator_Length));
	WPS_MEM_CPY(temp+DataLen+2+2, HMAC_Output, E_KeyWrapAuthenticator_Length);
	WPS_MEM_FILL(temp+DataLen+2+2+E_KeyWrapAuthenticator_Length, 0x10, 16);

	WPS_u8 IV_temp[16];
	WPS_MEM_CPY(IV_temp, IV, 16);

	WPS_AES_CBC_Encrypt(enrollee->KeyWrapKey, 16, IV_temp, 16, temp, AES_Input_Length, Output+4+16, AES_Input_Length);

	WPS_MFREE(temp);

	return 0;
}

//
// Parameters:
//     Input: the point of the input Encrypted Settings attribute to be analyzed
//     Output: the point of target buffer to put the decrypted result
// Return values:
//     0: Analyzed successfully, the decrypted result is copied to Output buffer.
//     -1: HMAC-SHA256 checksum failed.
//
WPS_s32 wps_enrol_analyze_enc_set(struct enrollee *enrollee, const WPS_u8 *Input, WPS_s32 InputLen, WPS_u8 *Output, WPS_s32 OutputBuffLen)

⌨️ 快捷键说明

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