4801 lines
150 KiB
C
4801 lines
150 KiB
C
/*
|
||
***************************************************************************
|
||
* Ralink Tech Inc.
|
||
* 4F, No. 2 Technology 5th Rd.
|
||
* Science-based Industrial Park
|
||
* Hsin-chu, Taiwan, R.O.C.
|
||
*
|
||
* (c) Copyright 2002-2006, Ralink Technology, Inc.
|
||
*
|
||
* All rights reserved. Ralink's source code is an unpublished work and the
|
||
* use of a copyright notice does not imply otherwise. This source code
|
||
* contains confidential trade secret material of Ralink Tech. Any attemp
|
||
* or participation in deciphering, decoding, reverse engineering or in any
|
||
* way altering the source code is stricitly prohibited, unless the prior
|
||
* written consent of Ralink Technology, Inc. is obtained.
|
||
***************************************************************************
|
||
|
||
Module Name:
|
||
wsc.c
|
||
|
||
Abstract:
|
||
|
||
Revision History:
|
||
Who When What
|
||
-------- ---------- ----------------------------------------------
|
||
Paul Lin 06-08-08 Initial
|
||
JuemingChen 06-10-30 Do modifications and Add APIs for AP
|
||
*/
|
||
|
||
#include "rt_config.h"
|
||
|
||
#ifdef WSC_INCLUDED
|
||
#include "wsc_tlv.h"
|
||
|
||
static UCHAR Wsc_Personal_String[] = "Wi-Fi Easy and Secure Key Derivation";
|
||
|
||
#define IV_ENCR_DATA_LEN_512 512
|
||
#define IV_ENCR_DATA_LEN_144 144
|
||
|
||
#define WSC_TLV_ENT(TLV_PARA) (0x00ff & TLV_PARA)
|
||
#define WSC_TLV_BYTE1(TLV_PARA) (0x000f & TLV_PARA)
|
||
#define WSC_TLV_BYTE2(TLV_PARA) (0x000f & (TLV_PARA >> 4))
|
||
|
||
/* Global reusable buffer */
|
||
static WSC_TLV_0B wsc_tlv_0b[]=
|
||
{
|
||
{/*0,*/0},
|
||
/*AP Channel*/ {/*0x1001,*/ 2}, /* WSC_ID_AP_CHANNEL */
|
||
/*Association State*/ {/*0x1002,*/ 2}, /* WSC_ID_ASSOC_STATE */
|
||
/*Authentication Type*/ {/*0x1003,*/ 2}, /* WSC_ID_AUTH_TYPE */
|
||
/*Authentication Type Flags*/ {/*0x1004,*/ 2}, /* WSC_ID_AUTH_TYPE_FLAGS */
|
||
/*Authenticator*/ {/*0x1005,*/ 8}, /* WSC_ID_AUTHENTICATOR */
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
/*Config Methods*/ {/*0x1008,*/ 2}, /* WSC_ID_CONFIG_METHODS */
|
||
/*Configuration Error*/ {/*0x1009,*/ 2}, /* WSC_ID_CONFIG_ERROR */
|
||
/*Confirmation URL4*/ {/*0x100A,*/ 0x40}, /* <= 64B WSC_ID_CONF_URL4 */
|
||
/*Confirmation URL6*/ {/*0x100B,*/ 0x4C}, /* <= 76B WSC_ID_CONF_URL6 */
|
||
/*Connection Type*/ {/*0x100C,*/ 1}, /* WSC_ID_CONN_TYPE */
|
||
/*Connection Type Flags*/ {/*0x100D,*/ 1}, /* WSC_ID_CONN_TYPE_FLAGS */
|
||
/*Credential*/ {/*0x100E,*/ 0xff}, /* WSC_ID_CREDENTIAL */
|
||
/*Encryption Type*/ {/*0x100F,*/ 2}, /* WSC_ID_ENCR_TYPE */
|
||
/*Encryption Type Flags*/ {/*0x1010,*/ 2}, /* WSC_ID_ENCR_TYPE_FLAGS */
|
||
/*Device Name*/ {/*0x1011,*/ 0x20}, /* <= 32B WSC_ID_DEVICE_NAME */
|
||
/*Device Password ID*/ {/*0x1012,*/ 2}, /* WSC_ID_DEVICE_PWD_ID */
|
||
{/*0,*/0},
|
||
/*E-Hash1*/ {/*0x1014,*/ 32}, /* WSC_ID_E_HASH1 */
|
||
/*E-Hash2*/ {/*0x1015,*/ 32}, /* WSC_ID_E_HASH2 */
|
||
/*E-SNonce1*/ {/*0x1016,*/ 16}, /* WSC_ID_E_SNONCE1 */
|
||
/*E-SNonce2*/ {/*0x1017,*/ 16}, /* WSC_ID_E_SNONCE2 */
|
||
/*Encrypted Settings*/ {/*0x1018,*/ 0xff}, /* WSC_ID_ENCR_SETTINGS */
|
||
{/*0,*/0},
|
||
/*Enrollee Nonce*/ {/*0x101A,*/ 16}, /* WSC_ID_ENROLLEE_NONCE */
|
||
/*Feature_ID*/ {/*0x101B,*/ 4}, /* WSC_ID_FEATURE_ID */
|
||
/*Identity*/ {/*0x101C,*/ 0x50}, /* <= 80B WSC_ID_IDENTITY */
|
||
{/*0,*/0}, /* WSC_ID_IDENTITY_PROOF */
|
||
/*Key Wrap Authenticator*/ {/*0x101E,*/ 8}, /* WSC_ID_KEY_WRAP_AUTH */
|
||
/*Key Identifier*/ {/*0x101F,*/ 16}, /* WSC_ID_KEY_IDENTIFIER */
|
||
/*MAC Address*/ {/*0x1020,*/ 6}, /* WSC_ID_MAC_ADDR */
|
||
/*Manufacturer*/ {/*0x1021,*/ 0x40}, /* <= 64B WSC_ID_MANUFACTURER */
|
||
/*Message Type*/ {/*0x1022,*/ 1}, /* WSC_ID_MSG_TYPE */
|
||
/*Model Name*/ {/*0x1023,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NAME */
|
||
/*Model Number*/ {/*0x1024,*/ 0x20}, /* <= 32B WSC_ID_MODEL_NUMBER */
|
||
{/*0,*/0},
|
||
/*Network Index*/ {/*0x1026,*/ 1}, /* WSC_ID_NW_INDEX */
|
||
|
||
/*
|
||
Windows 7 WCN test only accept Len of Network Key item in credentail is zero
|
||
when auth type of AP is OPEN/NONE
|
||
*/
|
||
/*Network Key*/ {/*0x1027,*/ 0}, /* <= 64B WSC_ID_NW_KEY */
|
||
|
||
/*Network Key Index*/ {/*0x1028,*/ 1}, /* WSC_ID_NW_KEY_INDEX */
|
||
/*New Device Name*/ {/*0x1029,*/ 0x20}, /* <= 32B WSC_ID_NEW_DEVICE_NAME */
|
||
/*New Password*/ {/*0x102A,*/ 0x40}, /* <= 64B WSC_ID_NEW_PWD */
|
||
{/*0,*/0},
|
||
/*OOB Device Password*/ {/*0x102C,*/ 0x3A}, /* <= 58B WSC_ID_OOB_DEV_PWD */
|
||
/*OS Version*/ {/*0x102D,*/ 4}, /* WSC_ID_OS_VERSION */
|
||
{/*0,*/0},
|
||
/*Power Level*/ {/*0x102F,*/ 1}, /* WSC_ID_POWER_LEVEL */
|
||
/*PSK Current*/ {/*0x1030,*/ 1}, /* WSC_ID_PSK_CURRENT */
|
||
/*PSK Max*/ {/*0x1031,*/ 1}, /* WSC_ID_PSK_MAX */
|
||
/*Public Key*/ {/*0x1032,*/ 192}, /* WSC_ID_PUBLIC_KEY */
|
||
/*Radio Enabled*/ {/*0x1033,*/ 1}, /* WSC_ID_RADIO_ENABLED */
|
||
/*Reboot*/ {/*0x1034,*/ 1}, /* WSC_ID_REBOOT */
|
||
/*Registrar Current*/ {/*0x1035,*/ 1}, /* WSC_ID_REGISTRAR_CURRENT */
|
||
/*Registrar Established*/ {/*0x1036,*/ 1}, /* WSC_ID_REGISTRAR_ESTBLSHD */
|
||
{/*0,*/0}, /* WSC_ID_REGISTRAR_LIST */
|
||
/*Registrar Max*/ {/*0x1038,*/ 1}, /* WSC_ID_REGISTRAR_MAX */
|
||
/*Registrar Nonce*/ {/*0x1039,*/ 16}, /* WSC_ID_REGISTRAR_NONCE */
|
||
/*Request Type*/ {/*0x103A,*/ 1}, /* WSC_ID_REQ_TYPE */
|
||
/*Response Type*/ {/*0x103B,*/ 1}, /* WSC_ID_RESP_TYPE */
|
||
/*RF Bands*/ {/*0x103C,*/ 1}, /* WSC_ID_RF_BAND */
|
||
/*R-Hash1*/ {/*0x103D,*/ 32}, /* WSC_ID_R_HASH1 */
|
||
/*R-Hash2*/ {/*0x103E,*/ 32}, /* WSC_ID_R_HASH2 */
|
||
/*R-SNonce1*/ {/*0x103F,*/ 16}, /* WSC_ID_R_SNONCE1 */
|
||
/*R-SNonce2*/ {/*0x1040,*/ 16}, /* WSC_ID_R_SNONCE2 */
|
||
/*Selected Registrar*/ {/*0x1041,*/ 1}, /* WSC_ID_SEL_REGISTRAR */
|
||
/*Serial Number*/ {/*0x1042,*/ 0x20}, /* <= 32B WSC_ID_SERIAL_NUM */
|
||
{/*0,*/0},
|
||
/*Simple Config State*/ {/*0x1044,*/ 1}, /* WSC_ID_SC_STATE */
|
||
/*SSID*/ {/*0x1045,*/ 0x20}, /* <= 32B WSC_ID_SSID */
|
||
/*Total Networks*/ {/*0x1046,*/ 1}, /* WSC_ID_TOT_NETWORKS */
|
||
/*UUID-E*/ {/*0x1047,*/ 16}, /* WSC_ID_UUID_E */
|
||
/*UUID-R*/ {/*0x1048,*/ 16}, /* WSC_ID_UUID_R */
|
||
/*WPS Vendor Extension*/ {/*0x1049,*/ 0x400}, /* WSC_ID_VENDOR_EXT */
|
||
/*Version*/ {/*0x104A,*/ 1}, /* WSC_ID_VERSION */
|
||
/*X.509 Certificate Request*/ {/*0x104B,*/ 0xff}, /* WSC_ID_X509_CERT_REQ */
|
||
/*X.509 Certificate*/ {/*0x104C,*/ 0xff}, /* WSC_ID_X509_CERT */
|
||
/*EAP Identity*/ {/*0x104D,*/ 0x40}, /* <= 64B WSC_ID_EAP_IDENTITY */
|
||
/*Message Counter*/ {/*0x104E,*/ 8}, /* WSC_ID_MSG_COUNTER */
|
||
/*Public Key Hash*/ {/*0x104F,*/ 20}, /* WSC_ID_PUBKEY_HASH */
|
||
/*Rekey Key*/ {/*0x1050,*/ 32}, /* WSC_ID_REKEY_KEY */
|
||
/*Key Lifetime*/ {/*0x1051,*/ 4}, /* WSC_ID_KEY_LIFETIME */
|
||
/*Permitted Config Methods*/ {/*0x1052,*/ 2}, /* WSC_ID_PERM_CFG_METHODS */
|
||
/*Selected Registrar Config Method*/{/*0x1053,*/ 2}, /* WSC_ID_SEL_REG_CFG_METHODS */
|
||
/*Primary Device Type*/ {/*0x1054,*/ 8}, /* WSC_ID_PRIM_DEV_TYPE */
|
||
{/*0,*/0}, /* WSC_ID_SEC_DEV_TYPE_LIST */
|
||
/*Portable Device*/ {/*0x1056,*/ 1}, /* WSC_ID_PORTABLE_DEVICE */
|
||
/*AP Setup Locked*/ {/*0x1057,*/ 1}, /* WSC_ID_AP_SETUP_LOCKED */
|
||
{/*0,*/0}, /* WSC_ID_APP_LIST */
|
||
/*EAP Type*/ {/*0x1059,*/ 0x08}, /* <= 8B WSC_ID_EAP_TYPE */
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
/*Initialization Vector*/ {/*0x1060,*/ 32}, /* WSC_ID_INIT_VECTOR */
|
||
/*Key Provided Automatically*/ {/*0x1061,*/ 1}, /* WSC_ID_KEY_PROVIDED_AUTO */
|
||
/*802.1X Enabled*/ {/*0x1062,*/ 1}, /* WSC_ID_8021X_ENABLED */
|
||
#ifdef IWSC_SUPPORT
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0},
|
||
{/*0,*/0}, //A
|
||
{/*0,*/0}, //B
|
||
{/*0,*/0}, //C
|
||
/*Entry Acceptable (only for IBSS)*/ {/*0x106D,*/ 1}, //WSC_ID_ENTRY_ACCEPTABLE
|
||
/*Registration Ready (only for IBSS)*/{/*0x106E,*/ 1}, //WSC_ID_REGISTRATON_READY
|
||
/*Registrar IPv4 Address (only for IBSS)*/{/*0x106F,*/ 4}, //WSC_ID_REGISTRAR_IPV4
|
||
/*IPv4 Subnet Mask (only for IBSS)*/{/*0x1070,*/ 4}, //WSC_ID_IPV4_SUBMASK
|
||
/*Enrollee IPv4 Address (only for IBSS)*/{/*0x1071,*/ 4}, //WSC_ID_ENROLLEE_IPV4
|
||
/*Available IPv4 Submask List (only for IBSS)*/{/*0x1072,*/ 0}, //WSC_ID_IPV4_SUBMASK_LIST (N*4B)
|
||
/*IP Address Configuration Methods (only for IBSS)*/{/*0x1073,*/ 2},//WSC_ID_IP_ADDR_CONF_METHOD
|
||
#endif // IWSC_SUPPORT //
|
||
/*<Reserved for WFA> 0x106F <20>V 0x1FFF*/
|
||
/*<Unavailable> 0x000 <20>V 0x0FFF,0x2000 <20>V 0xFFFF*/
|
||
};
|
||
|
||
extern UINT8 WPS_DH_G_VALUE[1];
|
||
extern UINT8 WPS_DH_P_VALUE[192];
|
||
|
||
int AppendWSCTLV(USHORT index, OUT UCHAR * obuf, IN UCHAR * ibuf, IN USHORT varlen)
|
||
{
|
||
USHORT len, dataLen, tag = cpu2be16(index);
|
||
|
||
/*
|
||
The max len of WPS Vendor Extension is 1024B
|
||
*/
|
||
dataLen = ( varlen != (USHORT)0 ) ? varlen : wsc_tlv_0b[WSC_TLV_ENT(index)].len;
|
||
|
||
NdisMoveMemory(obuf, &tag, 2);
|
||
len = cpu2be16(dataLen);
|
||
memcpy(obuf + 2, &len, 2);
|
||
if (dataLen != 0)
|
||
memcpy(obuf + 4, ibuf, dataLen);
|
||
return (dataLen + 4);
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process elements encryption settings
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
1. Recv M4 M5 M6 M7
|
||
|
||
========================================================================
|
||
*/
|
||
static VOID WscParseEncrSettings(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PUCHAR pPlainData,
|
||
IN INT PlainLength,
|
||
IN PWSC_CTRL pWscControl)
|
||
{
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
/* Point to M7 Profile */
|
||
PWSC_PROFILE pProfile = (PWSC_PROFILE) &pAdapter->StaCfg.WscControl.WscM7Profile;
|
||
UCHAR *pTmp;
|
||
USHORT Idx = 0, tmpVal = 0;
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
USHORT WscType, WscLen, HmacLen;
|
||
PUCHAR pData;
|
||
UCHAR Hmac[8]={0}, Temp[32];
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
|
||
HmacLen = (USHORT)(PlainLength - 12);
|
||
pData = pPlainData;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (PlainLength > 4)
|
||
{
|
||
WSC_IE TLV_Encr;
|
||
memcpy((UINT8 *)&TLV_Encr, pData, 4);
|
||
WscType = be2cpu16(TLV_Encr.Type);
|
||
WscLen = be2cpu16(TLV_Encr.Length);
|
||
pData += 4;
|
||
PlainLength -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_E_SNONCE1:
|
||
/* for verification with our enrollee nonce */
|
||
NdisMoveMemory(pReg->Es1, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_E_SNONCE2:
|
||
/* for verification with our enrollee nonce */
|
||
NdisMoveMemory(pReg->Es2, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_R_SNONCE1:
|
||
/* for verification with our enrollee nonce */
|
||
NdisMoveMemory(pReg->Rs1, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_R_SNONCE2:
|
||
/* for verification with our enrollee nonce */
|
||
NdisMoveMemory(pReg->Rs2, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_KEY_WRAP_AUTH:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
break;
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
/* */
|
||
/* Parse AP Settings in M7 if the peer is configured AP. */
|
||
/* */
|
||
case WSC_ID_SSID:
|
||
/* Find the exact length of SSID without null terminator */
|
||
pTmp = pData;
|
||
for (Idx = 0; Idx < WscLen; Idx++)
|
||
{
|
||
if (*(pTmp++) == 0x0)
|
||
break;
|
||
}
|
||
pProfile->Profile[0].SSID.SsidLength = Idx;
|
||
RTMPZeroMemory(pProfile->Profile[0].SSID.Ssid, NDIS_802_11_LENGTH_SSID);
|
||
RTMPMoveMemory(pProfile->Profile[0].SSID.Ssid, pData, pProfile->Profile[0].SSID.SsidLength);
|
||
/* Svae the total number, always get the first profile */
|
||
pProfile->ProfileCnt = 1;
|
||
break;
|
||
|
||
case WSC_ID_MAC_ADDR:
|
||
if (!MAC_ADDR_EQUAL(pData, pAdapter->StaCfg.WscControl.RegData.SelfInfo.MacAddr))
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Enrollee macAddr not match\n"));
|
||
RTMPMoveMemory(pProfile->Profile[0].MacAddr, pData, 6);
|
||
break;
|
||
|
||
case WSC_ID_AUTH_TYPE:
|
||
tmpVal = get_unaligned((PUSHORT) pData);
|
||
pProfile->Profile[0].AuthType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */
|
||
break;
|
||
|
||
case WSC_ID_ENCR_TYPE:
|
||
tmpVal = get_unaligned((PUSHORT) pData);
|
||
pProfile->Profile[0].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData)); */
|
||
break;
|
||
|
||
case WSC_ID_NW_KEY_INDEX:
|
||
/* Netork Key Index: 1 ~ 4 */
|
||
pProfile->Profile[0].KeyIndex = (*pData);
|
||
break;
|
||
|
||
case WSC_ID_NW_KEY:
|
||
if (WscLen == 0)
|
||
break;
|
||
pProfile->Profile[0].KeyLength = WscLen;
|
||
RTMPMoveMemory(pProfile->Profile[0].Key, pData, pProfile->Profile[0].KeyLength);
|
||
break;
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscParseEncrSettings --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
PlainLength -= WscLen;
|
||
}
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pPlainData, HmacLen, Temp, SHA256_DIGEST_SIZE);
|
||
|
||
if (RTMPEqualMemory(Hmac, Temp, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("WscParseEncrSettings --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Temp[0])), (UINT)cpu2be32(*((PUINT) &Temp[4]))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
}
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process credentials within AP encryption settings
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
1. Recv M8
|
||
|
||
========================================================================
|
||
*/
|
||
BOOLEAN WscProcessCredential(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PUCHAR pPlainData,
|
||
IN INT PlainLength,
|
||
IN PWSC_CTRL pWscControl)
|
||
{
|
||
USHORT WscType, WscLen, Cnt = 0, CurrentIdx=0, Idx, tmpVal = 0;
|
||
PUCHAR pData, pTmp;
|
||
PWSC_PROFILE pProfile;
|
||
#ifdef WSC_V2_SUPPORT
|
||
BOOLEAN bReject = FALSE;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
#ifdef IWSC_SUPPORT
|
||
UINT32 IPv4Addr = 0, IPv4SubMask = 0;
|
||
PIWSC_INFO pIWscInfo = &pAdapter->StaCfg.IWscInfo;
|
||
#endif /* IWSC_SUPPORT */
|
||
|
||
pData = pPlainData;
|
||
|
||
/* Cleanup Old contents */
|
||
NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE));
|
||
|
||
pProfile = (PWSC_PROFILE) &pWscControl->WscProfile;
|
||
/*CurrentIdx = pWscControl->EntryIfIdx; */
|
||
|
||
/* Init Profile number */
|
||
Cnt = 0;
|
||
|
||
hex_dump("WscProcessCredential - PlainData", pPlainData, PlainLength);
|
||
/* Start to process WSC IEs within credential */
|
||
while (PlainLength > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
PlainLength -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_NW_INDEX:
|
||
/* A new profile, add the cnt and save to database */
|
||
CurrentIdx = Cnt; /* since the index start from 0, we have to minus 1 */
|
||
Cnt++;
|
||
break;
|
||
|
||
case WSC_ID_SSID:
|
||
/* Find the exact length of SSID without null terminator */
|
||
pTmp = pData;
|
||
for (Idx = 0; Idx < WscLen; Idx++)
|
||
{
|
||
if (*(pTmp++) == 0x0)
|
||
break;
|
||
}
|
||
pProfile->Profile[CurrentIdx].SSID.SsidLength = Idx;
|
||
if (RTMPCheckStrPrintAble((CHAR *)pData, Idx) || (pWscControl->bCheckMultiByte == FALSE))
|
||
NdisMoveMemory(pProfile->Profile[CurrentIdx].SSID.Ssid, pData, pProfile->Profile[CurrentIdx].SSID.SsidLength);
|
||
else
|
||
return FALSE;
|
||
break;
|
||
|
||
case WSC_ID_AUTH_TYPE:
|
||
tmpVal = get_unaligned((PUSHORT) pData);
|
||
pProfile->Profile[CurrentIdx].AuthType = cpu2be16(tmpVal); /*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.AuthTypeFlags */
|
||
break;
|
||
|
||
case WSC_ID_ENCR_TYPE:
|
||
tmpVal = get_unaligned((PUSHORT) pData);
|
||
pProfile->Profile[CurrentIdx].EncrType = cpu2be16(tmpVal);/*cpu2be16(*((PUSHORT) pData));//(UINT8 *)&pReg->RegistrarInfo.EncrTypeFlags */
|
||
break;
|
||
|
||
case WSC_ID_NW_KEY_INDEX:
|
||
/* Netork Key Index: 1 ~ 4 */
|
||
pProfile->Profile[CurrentIdx].KeyIndex = (*pData);
|
||
break;
|
||
|
||
case WSC_ID_NW_KEY:
|
||
if (WscLen == 0)
|
||
break;
|
||
|
||
if (RTMPCheckStrPrintAble((CHAR *)pData, WscLen) || (pWscControl->bCheckMultiByte == FALSE))
|
||
{
|
||
pProfile->Profile[CurrentIdx].KeyLength = WscLen;
|
||
NdisMoveMemory(pProfile->Profile[CurrentIdx].Key, pData, pProfile->Profile[CurrentIdx].KeyLength);
|
||
}
|
||
else
|
||
return FALSE;
|
||
break;
|
||
|
||
case WSC_ID_MAC_ADDR:
|
||
/*
|
||
Some AP (ex. Buffalo WHR-G300N WPS AP) would change BSSID during WPS processing.
|
||
STA shall not change MacAddr of credential form AP.
|
||
*/
|
||
RTMPMoveMemory(pProfile->Profile[CurrentIdx].MacAddr, pData, MAC_ADDR_LEN);
|
||
break;
|
||
|
||
case WSC_ID_KEY_WRAP_AUTH:
|
||
/* Not used here, since we already verify it at decryption */
|
||
break;
|
||
|
||
case WSC_ID_CREDENTIAL:
|
||
/* Credential IE, The WscLen include all length within profile, we need to modify it */
|
||
/* to be able to parse all profile fields */
|
||
WscLen = 0;
|
||
break;
|
||
|
||
#ifdef IWSC_SUPPORT
|
||
case WSC_ID_IP_ADDR_CONF_METHOD:
|
||
tmpVal = get_unaligned((PUSHORT) pData);
|
||
pProfile->Profile[CurrentIdx].IpConfigMethod = be2cpu16(tmpVal);
|
||
break;
|
||
case WSC_ID_REGISTRAR_IPV4:
|
||
IPv4Addr = get_unaligned((PUINT32) pData);
|
||
pProfile->Profile[CurrentIdx].RegIpv4Addr = be2cpu32(IPv4Addr);
|
||
if (CurrentIdx == 0)
|
||
pIWscInfo->RegIpv4Addr = pProfile->Profile[CurrentIdx].RegIpv4Addr;
|
||
pIWscInfo->RegDepth = 1;
|
||
pIWscInfo->IpDevCount = 0;
|
||
break;
|
||
case WSC_ID_IPV4_SUBMASK:
|
||
IPv4SubMask = get_unaligned((PUINT32) pData);
|
||
pProfile->Profile[CurrentIdx].Ipv4SubMask = be2cpu32(IPv4SubMask);
|
||
if (pProfile->Profile[CurrentIdx].Ipv4SubMask!= IWSC_DEFAULT_IPV4_SUBMASK)
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> different IPv4 subnet mask (=0x%08x)\n",
|
||
pProfile->Profile[CurrentIdx].Ipv4SubMask));
|
||
break;
|
||
case WSC_ID_ENROLLEE_IPV4:
|
||
IPv4Addr = get_unaligned((PUINT32) pData);
|
||
pProfile->Profile[CurrentIdx].EnrIpv4Addr = be2cpu32(IPv4Addr);
|
||
if (CurrentIdx == 0)
|
||
pIWscInfo->SelfIpv4Addr = pProfile->Profile[CurrentIdx].EnrIpv4Addr;
|
||
break;
|
||
case WSC_ID_IPV4_SUBMASK_LIST:
|
||
NdisZeroMemory(&pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[0], sizeof(pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList));
|
||
if ((WscLen == 0) ||
|
||
(WscLen == 4) ||
|
||
((WscLen%4) != 0))
|
||
{
|
||
pIWscInfo->AvaSubMaskListCount = 0;
|
||
pIWscInfo->bAssignWscIPv4 = FALSE;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> WscLen = %d, set AvaSubMaskListCount to be 0\n", WscLen));
|
||
}
|
||
else
|
||
{
|
||
UINT8 i = 0, AvaSubMaskListCount;
|
||
|
||
AvaSubMaskListCount = (UINT8)((WscLen/4) - 1);
|
||
for (i = 0; i < AvaSubMaskListCount; i++)
|
||
{
|
||
pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[i] = be2cpu32(get_unaligned((PUINT32) (pData + i + 1)));
|
||
}
|
||
|
||
pIWscInfo->bAssignWscIPv4 = TRUE;
|
||
if (CurrentIdx == 0)
|
||
{
|
||
pIWscInfo->CurrentIpRange = be2cpu32(get_unaligned((PUINT32) pData));
|
||
pIWscInfo->AvaSubMaskListCount = (UINT8)AvaSubMaskListCount;
|
||
NdisZeroMemory(pIWscInfo->AvaSubMaskList, sizeof(pIWscInfo->AvaSubMaskList));
|
||
NdisMoveMemory( &pIWscInfo->AvaSubMaskList[0],
|
||
&pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[0],
|
||
sizeof(pIWscInfo->AvaSubMaskList));
|
||
}
|
||
pProfile->Profile[CurrentIdx].AvaIpv4SubmaskList[AvaSubMaskListCount] = pIWscInfo->CurrentIpRange;
|
||
}
|
||
break;
|
||
#endif /* IWSC_SUPPORT */
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
PlainLength -= WscLen;
|
||
}
|
||
|
||
/* Svae the total number */
|
||
pProfile->ProfileCnt = (UINT)Cnt;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/*
|
||
Check all credentials
|
||
*/
|
||
for (Idx = 0; Idx < pProfile->ProfileCnt; Idx++)
|
||
{
|
||
PWSC_CREDENTIAL pCredential = &pProfile->Profile[Idx];
|
||
/*if ((pCredential->EncrType != WSC_ENCRTYPE_WEP) && (pCredential->EncrType != WSC_ENCRTYPE_TKIP)) */
|
||
if (pCredential->EncrType == WSC_ENCRTYPE_WEP)
|
||
{
|
||
bReject = TRUE;
|
||
/* Cleanup contents */
|
||
NdisZeroMemory(&pWscControl->WscProfile, sizeof(WSC_PROFILE));
|
||
}
|
||
}
|
||
|
||
if (bReject)
|
||
return FALSE;
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WscProcessCredential --> %d profile retrieved from credential\n", Cnt));
|
||
return TRUE;
|
||
}
|
||
|
||
/* return 0 to success ,1 to failed */
|
||
int WscDeriveKey (
|
||
unsigned char *kdk, unsigned int kdk_len,
|
||
unsigned char *prsnlString, unsigned int str_len,
|
||
unsigned char *key, unsigned int keyBits )
|
||
{
|
||
unsigned int i = 0, iterations = 0;
|
||
unsigned char input[64], output[128]={0};
|
||
unsigned char hmac[32];
|
||
unsigned int temp;
|
||
|
||
#ifdef RELEASE_EXCLUDE
|
||
DBGPRINT(RT_DEBUG_INFO, ("WscDeriveKey: Deriving a key of %d bits\n", keyBits));
|
||
#endif /* RELEASE_EXCLUDE */
|
||
iterations = ((keyBits/8) + 32 - 1)/32;
|
||
|
||
/*Prepare the input buffer. During the iterations, we need only replace the */
|
||
/*value of i at the start of the buffer. */
|
||
temp = cpu2be32(i);
|
||
memcpy(input, &temp, 4);
|
||
memcpy(input+4, prsnlString, str_len);
|
||
|
||
temp = cpu2be32(keyBits);
|
||
memcpy(input+4+str_len, &temp, 4);
|
||
|
||
for(i = 0; i < iterations; i++)
|
||
{
|
||
/*Set the current value of i at the start of the input buffer */
|
||
temp = cpu2be32(i+1); /*i should start at 1 */
|
||
memcpy(input,&temp,4);
|
||
RT_HMAC_SHA256(kdk, kdk_len, input, 4+str_len+4, hmac, SHA256_DIGEST_SIZE);
|
||
memcpy(output+i*32, hmac, 32);
|
||
}
|
||
|
||
/*Sanity check */
|
||
if(keyBits/8 > (32*iterations))
|
||
{
|
||
#ifdef RELEASE_EXCLUDE
|
||
DBGPRINT(RT_DEBUG_INFO, ("WscDeriveKey: Key derivation generated less bits "
|
||
"than asked\n"));
|
||
#endif /* RELEASE_EXCLUDE */
|
||
|
||
return 1; /*failed */
|
||
}
|
||
|
||
memcpy(key, output, 80);
|
||
|
||
return 0; /*success */
|
||
|
||
}
|
||
|
||
VOID WscGenPSK1(
|
||
PRTMP_ADAPTER pAd,
|
||
PWSC_CTRL pWscCtrl,
|
||
UCHAR *pPSK1)
|
||
{
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData;
|
||
PUCHAR pTempPsk = NULL;
|
||
#ifdef WSC_NFC_SUPPORT
|
||
PUCHAR pTempPasswd = NULL;
|
||
UCHAR idx;
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE);
|
||
if (pTempPsk == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__));
|
||
return;
|
||
}
|
||
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscCtrl->bTriggerByNFC)
|
||
{
|
||
hex_dump("WscGenPSK1 1 - NfcPasswd", &pWscCtrl->NfcPasswd[0], pWscCtrl->NfcPasswdLen/2);
|
||
hex_dump("WscGenPSK1 - pReg->AuthKey", pReg->AuthKey, 32);
|
||
os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen);
|
||
if (pTempPasswd)
|
||
{
|
||
NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen);
|
||
if (pWscCtrl->NfcPasswdCaculate == 2)
|
||
{
|
||
for (idx = 0; idx < (pWscCtrl->NfcPasswdLen/2); idx++)
|
||
sprintf((RTMP_STRING *) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]);
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
else
|
||
{
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pWscCtrl->NfcPasswd, pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
os_free_mem(NULL, pTempPasswd);
|
||
}
|
||
}
|
||
else
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
{
|
||
printk("sn - PinCodeLen = %d\n", pReg->PinCodeLen); //snowpin test
|
||
hex_dump("WscGenPSK1: PIN", pReg->PIN, 8); //snowpin test
|
||
// Generate PSK1
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 2, pTempPsk, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[0], 4, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
NdisMoveMemory(pPSK1, pTempPsk, SHA256_DIGEST_SIZE);
|
||
os_free_mem(NULL, pTempPsk);
|
||
}
|
||
|
||
VOID WscGenPSK2(
|
||
PRTMP_ADAPTER pAd,
|
||
PWSC_CTRL pWscCtrl,
|
||
UCHAR *pPSK2)
|
||
{
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscCtrl->RegData;
|
||
PUCHAR pTempPsk = NULL;
|
||
#ifdef WSC_NFC_SUPPORT
|
||
PUCHAR pTempPasswd = NULL;
|
||
UCHAR idx;
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
os_alloc_mem(NULL, &pTempPsk, SHA256_DIGEST_SIZE);
|
||
if (pTempPsk == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s - pTempPsk alloc failed.", __FUNCTION__));
|
||
return;
|
||
}
|
||
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscCtrl->bTriggerByNFC)
|
||
{
|
||
hex_dump("WscGenPSK2 1 - NfcPasswd", &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2);
|
||
hex_dump("WscGenPSK2 - pReg->AuthKey", pReg->AuthKey, 32);
|
||
os_alloc_mem(NULL, &pTempPasswd, pWscCtrl->NfcPasswdLen);
|
||
if (pTempPasswd)
|
||
{
|
||
NdisZeroMemory(pTempPasswd, pWscCtrl->NfcPasswdLen);
|
||
if (pWscCtrl->NfcPasswdCaculate == 2)
|
||
{
|
||
for (idx = (pWscCtrl->NfcPasswdLen/2); idx < pWscCtrl->NfcPasswdLen; idx++)
|
||
sprintf((RTMP_STRING *) pTempPasswd, "%s%02X", pTempPasswd, pWscCtrl->NfcPasswd[idx]);
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pTempPasswd, pWscCtrl->NfcPasswdLen, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
else
|
||
{
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pWscCtrl->NfcPasswd[pWscCtrl->NfcPasswdLen/2], pWscCtrl->NfcPasswdLen/2, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
os_free_mem(NULL, pTempPasswd);
|
||
}
|
||
}
|
||
else
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
{
|
||
// Generate PSK2
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, pTempPsk, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, pTempPsk, SHA256_DIGEST_SIZE);
|
||
}
|
||
NdisMoveMemory(pPSK2, pTempPsk, SHA256_DIGEST_SIZE);
|
||
os_free_mem(NULL, pTempPsk);
|
||
}
|
||
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M1 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx EAP-Req(ID)
|
||
1. Change the correct parameters
|
||
2. Build M1
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM1(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[1];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
INT idx;
|
||
USHORT ConfigError = 0, ConfigMethods = 0;
|
||
#ifdef STA_EASY_CONFIG_SETUP
|
||
UCHAR VendorExt[32] = {0};
|
||
#endif /* STA_EASY_CONFIG_SETUP */
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
UCHAR CurOpMode = 0xFF;
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
CurOpMode = STA_MODE;
|
||
#ifdef P2P_SUPPORT
|
||
if (pWscControl->EntryIfIdx != BSS0)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* P2P_SUPPORT */
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
// Enrollee 16 byte E-S1 generation
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->Es1[idx] = RandomByte(pAdapter);
|
||
}
|
||
|
||
// Enrollee 16 byte E-S2 generation
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->Es2[idx] = RandomByte(pAdapter);
|
||
}
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M1 */
|
||
TB[0] = WSC_ID_MESSAGE_M1;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. UUID_E, last 6 bytes use MAC */
|
||
/*templen = AppendWSCTLV(WSC_ID_UUID_E, pData, pReg->EnrolleeInfo.Uuid, 0); */
|
||
templen = AppendWSCTLV(WSC_ID_UUID_E, pData, &pWscControl->Wsc_Uuid_E[0], 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. MAC address */
|
||
templen = AppendWSCTLV(WSC_ID_MAC_ADDR, pData, pReg->SelfInfo.MacAddr, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Enrollee Nonce, first generate and save to Wsc Control Block */
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->SelfNonce[idx] = RandomByte(pAdapter);
|
||
pReg->EnrolleeNonce[idx] = pReg->SelfNonce[idx];
|
||
}
|
||
/* 5. Enrollee Nonce, first generate and save to Wsc Control Block */
|
||
NdisMoveMemory(pReg->EnrolleeNonce, pReg->SelfNonce, 16);
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->SelfNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 6. Public Key, 192 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pke, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 7. Authentication Type Flags */
|
||
templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 8. Encryption Type Flags */
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 9. Connection Type Flag ESS */
|
||
templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*10. Config Method */
|
||
/*pReg->SelfInfo.ConfigMethods = cpu2be16(pWscControl->WscConfigMethods);*/
|
||
ConfigMethods = pWscControl->WscConfigMethods;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/*
|
||
AP MUST NOT support using PBC to add an external Registrar
|
||
*/
|
||
if (CurOpMode == AP_MODE)
|
||
{
|
||
ConfigMethods = (pWscControl->WscConfigMethods & 0x210F);
|
||
}
|
||
|
||
#ifdef IWSC_SUPPORT
|
||
if ((pWscControl->WscMode == WSC_PIN_MODE) &&
|
||
(pAdapter->StaCfg.BssType == BSS_ADHOC))
|
||
{
|
||
if (pAdapter->StaCfg.IWscInfo.bLimitedUI)
|
||
{
|
||
ConfigMethods &= (~WSC_CONFMET_KEYPAD);
|
||
}
|
||
else
|
||
{
|
||
ConfigMethods |= WSC_CONFMET_KEYPAD;
|
||
}
|
||
}
|
||
#endif /* IWSC_SUPPORT */
|
||
}
|
||
else
|
||
#endif /* WSC_V2_SUPPORT */
|
||
{
|
||
/*
|
||
WSC 1.0 WCN logo testing has AP PBC Enrollee testing item.
|
||
We cannot remove PBC capability here.
|
||
*/
|
||
ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF);
|
||
}
|
||
|
||
ConfigMethods = cpu2be16(ConfigMethods);
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*11. Simple Config State (Not Configured) */
|
||
if (CurOpMode == AP_MODE)
|
||
pReg->SelfInfo.ScState = pWscControl->WscConfStatus;
|
||
templen = AppendWSCTLV(WSC_ID_SC_STATE, pData, (UINT8 *)&pReg->SelfInfo.ScState, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*12. Manufacture */
|
||
templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((RTMP_STRING *) pReg->SelfInfo.Manufacturer));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*13. Model Name */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*14. Model Number */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*15. Serial Number */
|
||
templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) pReg->SelfInfo.SerialNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*16. Primary Device Type */
|
||
templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*17. Device Name */
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((RTMP_STRING *) pReg->SelfInfo.DeviceName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*18. RF Band */
|
||
templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*19. Associate state (Not associated) */
|
||
templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*20. Device Password ID */
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC)
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->NfcPasswdID, 0);
|
||
}
|
||
else
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*21. Configure Error */
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/*22. OS Version Not associated) */
|
||
templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
#ifdef STA_EASY_CONFIG_SETUP
|
||
if ((CurOpMode == STA_MODE) &&
|
||
(pAdapter->StaCfg.EasyConfigInfo.bRaAutoWpsAp) &&
|
||
(!pWscControl->bWscTrigger))
|
||
{
|
||
/*WPS Vendor Extension */
|
||
NdisMoveMemory(VendorExt, RALINK_OUI, 3);
|
||
NdisMoveMemory(VendorExt + 3, pAdapter->StaCfg.EasyConfigInfo.WpsEncryptPIN, 12);
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT, pData, (UINT8 *)VendorExt, 15);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* STA_EASY_CONFIG_SETUP */
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscControl->WscV2Info.bEnableWpsV2 && pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1 - bUPnPMsgTimerRunning = %d, pWscControl->WscUseUPnP = %d, pWscControl->EapMsgRunning = %d\n",
|
||
pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning,
|
||
pWscControl->WscUseUPnP,
|
||
pWscControl->EapMsgRunning));
|
||
|
||
/* Fixed WCN vista logo 2 registrar test item issue. */
|
||
/* Also prevent that WCN GetDeviceInfo disturbs EAP processing. */
|
||
if (pWscControl->WscUPnPNodeInfo.bUPnPMsgTimerRunning ||
|
||
(pWscControl->WscUseUPnP && pWscControl->EapMsgRunning))
|
||
;
|
||
else
|
||
{
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
}
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM1.\n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M2 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M1
|
||
1. Change the correct parameters
|
||
2. Build M2
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM2(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
#ifdef WSC_NFC_SUPPORT
|
||
UCHAR TB[256];
|
||
#else
|
||
UCHAR TB[1];
|
||
#endif
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg;
|
||
UCHAR DHKey[32], KDK[32], KdkInput[38], KdfKey[80];
|
||
INT DH_Len;
|
||
INT HmacLen = 0;
|
||
INT idx;
|
||
USHORT ConfigMethods;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
|
||
// Enrollee 16 byte E-S1 generation
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->Es1[idx] = RandomByte(pAdapter);
|
||
}
|
||
|
||
// Enrollee 16 byte E-S2 generation
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->Es2[idx] = RandomByte(pAdapter);
|
||
}
|
||
|
||
DH_Len = sizeof(pReg->SecretKey);
|
||
RT_DH_SecretKey_Generate (
|
||
pReg->Pke, sizeof(pReg->Pke),
|
||
WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
|
||
pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom),
|
||
pReg->SecretKey, (UINT *) &DH_Len);
|
||
RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]);
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M2 */
|
||
TB[0] = WSC_ID_MESSAGE_M2;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* fixed config Windows 7 issue */
|
||
/* Enrollee Nonce, first generate and save to Wsc Control Block */
|
||
for (idx = 0; idx < 16; idx++)
|
||
{
|
||
pReg->SelfNonce[idx] = RandomByte(pAdapter);
|
||
pReg->RegistrarNonce[idx] = pReg->SelfNonce[idx];
|
||
}
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* UUID, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Publikc Key */
|
||
templen = AppendWSCTLV(WSC_ID_PUBLIC_KEY, pData, pReg->Pkr, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Authentication Type Flags */
|
||
templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Encrypt Type */
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Connection Type */
|
||
templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Config Method */
|
||
ConfigMethods = pWscControl->WscConfigMethods;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/*
|
||
In WPS 2.0.0
|
||
In Test Item 4.1.1 ,Step 13
|
||
On the sniffer device, verify that the M2 message that the APUT sends includes
|
||
the Configuration Methods attribute. The Configuration Methods attribute in the
|
||
WSC IE must reflect the correct configuration methods that the Internal Registrar
|
||
supports.
|
||
*/
|
||
#ifdef IWSC_SUPPORT
|
||
if (pAdapter->StaCfg.BssType == BSS_ADHOC)
|
||
{
|
||
if (pAdapter->StaCfg.IWscInfo.bLimitedUI)
|
||
{
|
||
ConfigMethods &= (~WSC_CONFMET_KEYPAD);
|
||
}
|
||
else
|
||
{
|
||
ConfigMethods |= WSC_CONFMET_KEYPAD;
|
||
}
|
||
}
|
||
#endif /* IWSC_SUPPORT */
|
||
}
|
||
else
|
||
{
|
||
ConfigMethods = (pWscControl->WscConfigMethods & 0x00FF);
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
ConfigMethods = cpu2be16(ConfigMethods);
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&ConfigMethods, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Manufacture Name */
|
||
templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((RTMP_STRING *) pReg->SelfInfo.Manufacturer));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Model Name */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Model Number */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Serial Number */
|
||
templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) pReg->SelfInfo.SerialNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Prime Device Type */
|
||
templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Device Name */
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((RTMP_STRING *) pReg->SelfInfo.DeviceName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* RF Band */
|
||
templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Assoc State */
|
||
templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Config Error */
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Device Password ID */
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC)
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pWscControl->PeerNfcPasswdID, 0);
|
||
}
|
||
else
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_PWD_ID, pData, (UINT8 *)&pReg->SelfInfo.DevPwdId, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* OS Version */
|
||
templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* Create KDK input data */
|
||
NdisMoveMemory(&KdkInput[0], &pReg->EnrolleeNonce[0], 16);
|
||
NdisMoveMemory(&KdkInput[16], &pReg->PeerInfo.MacAddr[0], 6);
|
||
NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16);
|
||
|
||
/* Generate the KDK */
|
||
RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE);
|
||
|
||
/* KDF */
|
||
WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640);
|
||
|
||
/* Assign Key from KDF */
|
||
NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32);
|
||
NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16);
|
||
NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32);
|
||
|
||
#ifdef WSC_NFC_SUPPORT
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER)
|
||
{
|
||
PWSC_CREDENTIAL pCredential = NULL;
|
||
INT CerLen = 0, PlainLen = 0, EncrLen;
|
||
USHORT AuthType = 0;
|
||
USHORT EncrType = 0;
|
||
UCHAR Plain[300], *IV_EncrData;
|
||
|
||
IV_EncrData = kmalloc(512, MEM_ALLOC_FLAG);
|
||
if(IV_EncrData)
|
||
{
|
||
WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile);
|
||
pCredential = &pAdapter->ApCfg.MBSSID[0].WscControl.WscProfile.Profile[0];
|
||
|
||
// 4a. Encrypted R-S1
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0);
|
||
|
||
AuthType = cpu2be16(pCredential->AuthType);
|
||
EncrType = cpu2be16(pCredential->EncrType);
|
||
CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
|
||
CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength);
|
||
CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], pCredential->MacAddr, 0);
|
||
|
||
// Prepare plain text
|
||
// Reguired attribute item in M8 if Enrollee is STA.
|
||
if (pAdapter->OpMode == OPMODE_AP)
|
||
PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen);
|
||
|
||
// Generate HMAC
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
// 4b. Encrypted Settings
|
||
// Encrypt data
|
||
EncrLen = sizeof(IV_EncrData) - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);//IVLen + EncrLen
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
kfree(IV_EncrData);
|
||
}
|
||
}
|
||
#endif // CONFIG_AP_SUPPORT //
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
/* 22. Hmac */
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2.\n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M2D Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M1 process Error
|
||
1. Change the correct parameters
|
||
2. Build M2D
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM2D(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[1];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M2D */
|
||
TB[0] = WSC_ID_MESSAGE_M2D;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->SelfNonce, 0);
|
||
/*templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0); */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* UUID, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_UUID_R, pData, pReg->SelfInfo.Uuid, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
|
||
/* 7. Authentication Type Flags */
|
||
templen = AppendWSCTLV(WSC_ID_AUTH_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.AuthTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Encrypt Type */
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.EncrTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Connection Type */
|
||
templen = AppendWSCTLV(WSC_ID_CONN_TYPE_FLAGS, pData, (UINT8 *)&pReg->SelfInfo.ConnTypeFlags, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Config Methods */
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_METHODS, pData, (UINT8 *)&pReg->SelfInfo.ConfigMethods, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Manufacturer Name */
|
||
templen = AppendWSCTLV(WSC_ID_MANUFACTURER, pData, pReg->SelfInfo.Manufacturer, strlen((RTMP_STRING *) pReg->SelfInfo.Manufacturer));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Model Name */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NAME, pData, pReg->SelfInfo.ModelName, strlen((RTMP_STRING *) pReg->SelfInfo.ModelName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Model Number */
|
||
templen = AppendWSCTLV(WSC_ID_MODEL_NUMBER, pData, pReg->SelfInfo.ModelNumber, strlen((RTMP_STRING *) pReg->SelfInfo.ModelNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Serial Number */
|
||
templen = AppendWSCTLV(WSC_ID_SERIAL_NUM, pData, pReg->SelfInfo.SerialNumber, strlen((RTMP_STRING *) pReg->SelfInfo.SerialNumber));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Prime Device Type */
|
||
templen = AppendWSCTLV(WSC_ID_PRIM_DEV_TYPE, pData, pReg->SelfInfo.PriDeviceType, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Device Name */
|
||
templen = AppendWSCTLV(WSC_ID_DEVICE_NAME, pData, pReg->SelfInfo.DeviceName, strlen((RTMP_STRING *) pReg->SelfInfo.DeviceName));
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* RF Band */
|
||
templen = AppendWSCTLV(WSC_ID_RF_BAND, pData, (UINT8 *)&pReg->SelfInfo.RfBand, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Assoc State */
|
||
templen = AppendWSCTLV(WSC_ID_ASSOC_STATE, pData, (UINT8 *)&pReg->SelfInfo.AssocState, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Config Error */
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&pReg->SelfInfo.ConfigError, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* OS Version */
|
||
templen = AppendWSCTLV(WSC_ID_OS_VERSION, pData, (UINT8 *)&pReg->SelfInfo.OsVersion, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM2D.\n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M3 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M2
|
||
1. Change the correct parameters
|
||
2. Build M3
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM3(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[32];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg = NULL;
|
||
INT HmacLen;
|
||
UCHAR *pHash=NULL;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&pHash, 512);
|
||
if(NULL == pHash)
|
||
return Len;
|
||
pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M3 */
|
||
TB[0] = WSC_ID_MESSAGE_M3;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. E-Hash1 */
|
||
/* */
|
||
/* Generate PSK1 */
|
||
#if 1
|
||
WscGenPSK1(pAdapter, pWscControl, &TB[0]);
|
||
#else
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE);
|
||
#endif
|
||
|
||
/* Copy first 16 bytes to PSK1 */
|
||
NdisMoveMemory(pReg->Psk1, TB, 16);
|
||
|
||
hex_dump("Es1", pReg->Es1, 16);
|
||
hex_dump("Es2", pReg->Es2, 16);
|
||
|
||
/* Create input for E-Hash1 */
|
||
NdisMoveMemory(pHash, pReg->Es1, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate E-Hash1 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash1, SHA256_DIGEST_SIZE);
|
||
|
||
templen = AppendWSCTLV(WSC_ID_E_HASH1, pData, pReg->EHash1, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 5. E-Hash2 */
|
||
/* */
|
||
/* Generate PSK2 */
|
||
#if 1
|
||
WscGenPSK2(pAdapter, pWscControl, &TB[0]);
|
||
#else
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE);
|
||
#endif
|
||
/* Copy first 16 bytes to PSK2 */
|
||
NdisMoveMemory(pReg->Psk2, TB, 16);
|
||
|
||
/* Create input for E-Hash2 */
|
||
NdisMoveMemory(pHash, pReg->Es2, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate E-Hash2 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->EHash2, SHA256_DIGEST_SIZE);
|
||
|
||
templen = AppendWSCTLV(WSC_ID_E_HASH2, pData, pReg->EHash2, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Generate authenticator
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
if(pHash)
|
||
os_free_mem(NULL, pHash);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM3 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M4 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M3
|
||
1. Change the correct parameters
|
||
2. Build M4
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM4(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[32];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
INT HmacLen;
|
||
UCHAR KDK[32];
|
||
UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
|
||
UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
|
||
INT PlainLen = 0, EncrLen;
|
||
UCHAR *pHash=NULL;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&pHash, 512);
|
||
if(NULL == pHash)
|
||
return Len;
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144);
|
||
if (IV_EncrData == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
|
||
goto LabelErr;
|
||
}
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M4 */
|
||
TB[0] = WSC_ID_MESSAGE_M4;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. R-Hash1 */
|
||
/* */
|
||
/* Generate PSK1 */
|
||
#if 1
|
||
WscGenPSK1(pAdapter, pWscControl, &TB[0]);
|
||
#else
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 2, TB, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pReg->PIN, 4, TB, SHA256_DIGEST_SIZE);
|
||
#endif
|
||
|
||
/* Copy first 16 bytes to PSK1 */
|
||
NdisMoveMemory(pReg->Psk1, TB, 16);
|
||
|
||
hex_dump("Es1", pReg->Es1, 16);
|
||
hex_dump("Es2", pReg->Es2, 16);
|
||
/* Create input for R-Hash1 */
|
||
NdisMoveMemory(pHash, pReg->Es1, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate R-Hash1 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash1, SHA256_DIGEST_SIZE);
|
||
|
||
templen = AppendWSCTLV(WSC_ID_R_HASH1, pData, pReg->RHash1, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 5. R-Hash2 */
|
||
/* */
|
||
/* Generate PSK2 */
|
||
#if 1
|
||
WscGenPSK2(pAdapter, pWscControl, &TB[0]);
|
||
#else
|
||
if (pReg->PinCodeLen == 4)
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[2], 2, TB, SHA256_DIGEST_SIZE);
|
||
else
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &pReg->PIN[4], 4, TB, SHA256_DIGEST_SIZE);
|
||
#endif
|
||
|
||
/* Copy first 16 bytes to PSK2 */
|
||
NdisMoveMemory(pReg->Psk2, TB, 16);
|
||
|
||
/* Create input for R-Hash2 */
|
||
NdisMoveMemory(pHash, pReg->Es2, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate R-Hash2 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, pReg->RHash2, SHA256_DIGEST_SIZE);
|
||
|
||
templen = AppendWSCTLV(WSC_ID_R_HASH2, pData, pReg->RHash2, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 6a. Encrypted R-S1 */
|
||
/* Prepare plain text */
|
||
PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE1, &Plain[0], pReg->Es1, 0);
|
||
|
||
/* Generate HMAC */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
/* 6b. Encrypted Settings */
|
||
/* Encrypt data */
|
||
EncrLen = IV_ENCR_DATA_LEN_144 - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
We have to exclude last 12 bytes from last receive since it's authenticator value
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
LabelErr:
|
||
if(pHash)
|
||
os_free_mem(NULL, pHash);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
|
||
if (IV_EncrData != NULL)
|
||
os_free_mem(NULL, IV_EncrData);
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM4 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M5 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M4
|
||
1. Change the correct parameters
|
||
2. Build M5
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM5(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[32];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
PUCHAR pAuth;
|
||
INT HmacLen;
|
||
UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
|
||
UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
|
||
INT PlainLen=0, EncrLen;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* allocate memory */
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_144);
|
||
if (IV_EncrData == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
|
||
return 0;
|
||
}
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M5 */
|
||
TB[0] = WSC_ID_MESSAGE_M5;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4a. Encrypted E-S1 */
|
||
/* Prepare plain text */
|
||
PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE1, &Plain[0], pReg->Es1, 0);
|
||
|
||
/* Generate HMAC */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
/* 4b. Encrypted Settings */
|
||
/* Encrypt data */
|
||
EncrLen = IV_ENCR_DATA_LEN_144 - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Generate authenticator
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
|
||
if (IV_EncrData != NULL)
|
||
os_free_mem(NULL, IV_EncrData);
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM5 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M6 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M5
|
||
1. Change the correct parameters
|
||
2. Build M6
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM6(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[32];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
INT HmacLen;
|
||
UCHAR KDK[32];
|
||
UCHAR Plain[128]; /*, IV_EncrData[144];//IV len 16,EncrData len 128 */
|
||
UCHAR *IV_EncrData = NULL;/*IV len 16,EncrData len 128 */
|
||
INT PlainLen = 0, EncrLen;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
|
||
/* allocate memory */
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, 144);
|
||
if (IV_EncrData == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
|
||
return 0;
|
||
}
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M6 */
|
||
TB[0] = WSC_ID_MESSAGE_M6;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4a. Encrypted R-S2 */
|
||
/* Prepare plain text */
|
||
PlainLen += AppendWSCTLV(WSC_ID_R_SNONCE2, &Plain[0], pReg->Es2, 0);
|
||
|
||
/* Generate HMAC */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
/* 4b. Encrypted Settings */
|
||
/* Encrypt data */
|
||
EncrLen = IV_ENCR_DATA_LEN_144 - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, &IV_EncrData[0], 16 + EncrLen);/*IVLen + EncrLen */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
We have to exclude last 12 bytes from last receive since it's authenticator value
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
|
||
if (IV_EncrData != NULL)
|
||
os_free_mem(NULL, IV_EncrData);
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM6 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M7 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M6
|
||
1. Change the correct parameters
|
||
2. Build M7
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM7(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[32];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
INT HmacLen;
|
||
UCHAR Plain[256], *IV_EncrData=NULL;/*IV len 16 ,EncrData len */
|
||
INT PlainLen=0, EncrLen;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
UCHAR CurOpMode = 0xFF;
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512);
|
||
if(NULL == IV_EncrData)
|
||
return 0;
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
CurOpMode = STA_MODE;
|
||
#ifdef P2P_SUPPORT
|
||
if (pWscControl->EntryIfIdx != BSS0)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* P2P_SUPPORT */
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M7 */
|
||
TB[0] = WSC_ID_MESSAGE_M7;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4a. Encrypted E-S2 */
|
||
/* Prepare plain text */
|
||
PlainLen += AppendWSCTLV(WSC_ID_E_SNONCE2, &Plain[0], pReg->Es2, 0);
|
||
|
||
/* Marvell WPS AP doesn't accept STA includes profile in M7. 20070604 */
|
||
if ((CurOpMode == AP_MODE) &&
|
||
(pWscControl->EntryIfIdx < MIN_NET_DEVICE_FOR_APCLI))
|
||
{
|
||
USHORT authType;
|
||
USHORT encyType;
|
||
PWSC_CREDENTIAL pCredential = &pWscControl->WscProfile.Profile[0];
|
||
WscCreateProfileFromCfg(pAdapter, ENROLLEE_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile);
|
||
|
||
authType = pCredential->AuthType;
|
||
encyType = pCredential->EncrType;
|
||
/*
|
||
Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType.
|
||
We need to check STA is WSC 1.0 or WSC 2.0 here.
|
||
If STA is WSC 1.0, re-assign authType and encyType.
|
||
*/
|
||
if (pWscControl->RegData.PeerInfo.Version2 == 0)
|
||
{
|
||
if (authType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK))
|
||
authType = WSC_AUTHTYPE_WPA2PSK;
|
||
if (encyType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
|
||
encyType = WSC_ENCRTYPE_AES;
|
||
}
|
||
authType = cpu2be16(authType);
|
||
encyType = cpu2be16(encyType);
|
||
PlainLen += AppendWSCTLV(WSC_ID_SSID, &Plain[PlainLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
|
||
PlainLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &Plain[PlainLen], pCredential->MacAddr, 0);
|
||
PlainLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &Plain[PlainLen], (UINT8 *)&authType, 0);
|
||
PlainLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &Plain[PlainLen], (UINT8 *)&encyType, 0);
|
||
PlainLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &Plain[PlainLen], &pCredential->KeyIndex, 0);
|
||
PlainLen += AppendWSCTLV(WSC_ID_NW_KEY, &Plain[PlainLen], pCredential->Key, pCredential->KeyLength);
|
||
}
|
||
|
||
/* Generate HMAC */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
/* 4b. Encrypted Settings */
|
||
/* Encrypt data */
|
||
EncrLen = IV_ENCR_DATA_LEN_512 - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Generate authenticator
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, TB, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* Copy the content to Regdata for lasttx information */
|
||
pReg->LastTx.Length = Len;
|
||
NdisMoveMemory(pReg->LastTx.Data, pbuf, Len);
|
||
|
||
if(IV_EncrData)
|
||
os_free_mem(NULL, IV_EncrData);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM7 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Build WSC M8 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after M7
|
||
1. Change the correct parameters
|
||
2. Build M8
|
||
|
||
========================================================================
|
||
*/
|
||
int BuildMessageM8(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
/* UCHAR TB[256]; */
|
||
UCHAR *TB = NULL;
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf, pAuth;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
INT HmacLen;
|
||
UCHAR KDK[32];
|
||
UCHAR /* Plain[300], */ *IV_EncrData=NULL;/*IV len 16 ,EncrData len */
|
||
UCHAR *Plain = NULL;
|
||
INT CerLen = 0, PlainLen = 0, EncrLen;
|
||
PWSC_CREDENTIAL pCredential = NULL;
|
||
USHORT AuthType = 0;
|
||
USHORT EncrType = 0;
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
UCHAR apidx = (pWscControl->EntryIfIdx & 0x0F);
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
UCHAR CurOpMode = 0xFF;
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_EncrData, IV_ENCR_DATA_LEN_512);
|
||
if(NULL == IV_EncrData)
|
||
return 0;
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&TB, 256);
|
||
if (TB == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
|
||
goto LabelErr;
|
||
}
|
||
os_alloc_mem(NULL, (UCHAR **)&Plain, 300);
|
||
if (Plain == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: Allocate memory fail!!!\n", __FUNCTION__));
|
||
goto LabelErr;
|
||
}
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
CurOpMode = STA_MODE;
|
||
#ifdef P2P_SUPPORT
|
||
if (pWscControl->EntryIfIdx != BSS0)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* P2P_SUPPORT */
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, M8 */
|
||
TB[0] = WSC_ID_MESSAGE_M8;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
if (CurOpMode == AP_MODE)
|
||
{
|
||
WscCreateProfileFromCfg(pAdapter, REGISTRAR_ACTION | AP_MODE, pWscControl, &pWscControl->WscProfile);
|
||
pCredential = &pAdapter->ApCfg.MBSSID[apidx].WscControl.WscProfile.Profile[0];
|
||
}
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
if (CurOpMode == STA_MODE)
|
||
{
|
||
if (pAdapter->StaCfg.WscControl.WscProfile.ProfileCnt == 0 ||
|
||
(pAdapter->StaCfg.WscControl.bConfiguredAP
|
||
#ifdef WSC_V2_SUPPORT
|
||
/*
|
||
Check AP is v2 or v1, Check WscV2 Enabled or not
|
||
*/
|
||
&& !(pWscControl->WscV2Info.bForceSetAP
|
||
&& pWscControl->WscV2Info.bEnableWpsV2
|
||
&& (pWscControl->RegData.PeerInfo.Version2!= 0))
|
||
#endif /* WSC_V2_SUPPORT */
|
||
))
|
||
WscCreateProfileFromCfg(pAdapter, STA_MODE, pWscControl, &pWscControl->WscProfile);
|
||
|
||
pCredential = &pAdapter->StaCfg.WscControl.WscProfile.Profile[0];
|
||
NdisMoveMemory(pCredential->MacAddr, pAdapter->MlmeAux.Bssid, 6);
|
||
}
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
/* 4a. Encrypted R-S1 */
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_INDEX, &TB[0], (PUCHAR)"1", 0);
|
||
|
||
if (pCredential == NULL)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("%s: pWscControl == NULL!\n", __FUNCTION__));
|
||
goto LabelErr;
|
||
}
|
||
|
||
AuthType = pCredential->AuthType;
|
||
EncrType = pCredential->EncrType;
|
||
/*
|
||
Some Win7 WSC 1.0 STA has problem to receive mixed authType and encyType.
|
||
We need to check STA is WSC 1.0 or WSC 2.0 here.
|
||
If STA is WSC 1.0, re-assign authType and encyType.
|
||
*/
|
||
#if 0 /* Some Win8 WSC 2.0 STA cannot handle mixed AuthType & EncrType @2014/01/15 */
|
||
if (pWscControl->RegData.PeerInfo.Version2 == 0)
|
||
#endif
|
||
{
|
||
if (AuthType == (WSC_AUTHTYPE_WPAPSK | WSC_AUTHTYPE_WPA2PSK))
|
||
AuthType = WSC_AUTHTYPE_WPA2PSK;
|
||
if (EncrType == (WSC_ENCRTYPE_TKIP | WSC_ENCRTYPE_AES))
|
||
EncrType = WSC_ENCRTYPE_AES;
|
||
}
|
||
|
||
AuthType = cpu2be16(AuthType);
|
||
EncrType = cpu2be16(EncrType);
|
||
CerLen += AppendWSCTLV(WSC_ID_SSID, &TB[CerLen], pCredential->SSID.Ssid, pCredential->SSID.SsidLength);
|
||
CerLen += AppendWSCTLV(WSC_ID_AUTH_TYPE, &TB[CerLen], (UINT8 *)&AuthType, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_ENCR_TYPE, &TB[CerLen], (UINT8 *)&EncrType, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_KEY_INDEX, &TB[CerLen], &pCredential->KeyIndex, 0);
|
||
CerLen += AppendWSCTLV(WSC_ID_NW_KEY, &TB[CerLen], pCredential->Key, pCredential->KeyLength);
|
||
CerLen += AppendWSCTLV(WSC_ID_MAC_ADDR, &TB[CerLen], pCredential->MacAddr, 0);
|
||
|
||
/* Prepare plain text */
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
if ((CurOpMode == STA_MODE) && (pAdapter->StaCfg.BssType == BSS_INFRA))
|
||
{
|
||
/* If Enrollee is AP, CREDENTIAL isn't needed in M8. */
|
||
PlainLen = CerLen;
|
||
NdisMoveMemory(Plain, TB, CerLen);
|
||
}
|
||
else
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
if ((CurOpMode == AP_MODE)
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
|| ((CurOpMode == STA_MODE) && (pAdapter->StaCfg.BssType == BSS_ADHOC))
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
)
|
||
{
|
||
#ifdef IWSC_SUPPORT
|
||
USHORT tmpVal = 0;
|
||
UINT32 tmpUint32 = 0;
|
||
#endif /* IWSC_SUPPORT */
|
||
/* Reguired attribute item in M8 if Enrollee is STA. */
|
||
PlainLen += AppendWSCTLV(WSC_ID_CREDENTIAL, &Plain[0], TB, CerLen);
|
||
#ifdef IWSC_SUPPORT
|
||
// TODO: Need to check the total length, we need to alarm if total length exceeds the size of Plain. snowpin 2011/05/16
|
||
|
||
if (IWSC_IpContentForCredential(pAdapter))
|
||
{
|
||
PIWSC_INFO pIWscInfo = &pAdapter->StaCfg.IWscInfo;
|
||
UINT32 *pIpv4SubMaskList = NULL;
|
||
USHORT Ipv4SubMaskListSize = 0;
|
||
|
||
if (pIWscInfo->AvaSubMaskListCount != 0)
|
||
{
|
||
Ipv4SubMaskListSize = sizeof(UINT32)*pIWscInfo->AvaSubMaskListCount;
|
||
os_alloc_mem(NULL, (UCHAR **) &pIpv4SubMaskList, Ipv4SubMaskListSize);
|
||
if (pIWscInfo->AvaSubMaskListCount == 3)
|
||
{
|
||
*pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]);
|
||
*(pIpv4SubMaskList+1) = cpu2be32(pIWscInfo->AvaSubMaskList[1]);
|
||
*(pIpv4SubMaskList+2) = cpu2be32(pIWscInfo->AvaSubMaskList[2]);
|
||
}
|
||
else if (pIWscInfo->AvaSubMaskListCount == 2)
|
||
{
|
||
*pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]);
|
||
*(pIpv4SubMaskList+1) = cpu2be32(pIWscInfo->AvaSubMaskList[1]);
|
||
}
|
||
else if (pIWscInfo->AvaSubMaskListCount == 1)
|
||
*pIpv4SubMaskList = cpu2be32(pIWscInfo->AvaSubMaskList[0]);
|
||
pIWscInfo->AvaSubMaskListCount--;
|
||
}
|
||
|
||
tmpVal = cpu2be16(pIWscInfo->IpMethod);
|
||
PlainLen += AppendWSCTLV(WSC_ID_IP_ADDR_CONF_METHOD,
|
||
&Plain[PlainLen],
|
||
&tmpVal, 0);
|
||
|
||
pCredential->RegIpv4Addr = pIWscInfo->SelfIpv4Addr;
|
||
tmpUint32 = cpu2be32(pIWscInfo->SelfIpv4Addr);
|
||
PlainLen += AppendWSCTLV(WSC_ID_REGISTRAR_IPV4,
|
||
&Plain[PlainLen],
|
||
(UCHAR *)&tmpUint32, 0);
|
||
|
||
tmpUint32 = cpu2be32(pIWscInfo->Ipv4SubMask);
|
||
PlainLen += AppendWSCTLV(WSC_ID_IPV4_SUBMASK,
|
||
&Plain[PlainLen],
|
||
(UCHAR *)&tmpUint32, 0);
|
||
|
||
pCredential->EnrIpv4Addr = pIWscInfo->PeerIpv4Addr;
|
||
tmpUint32 = cpu2be32(pIWscInfo->PeerIpv4Addr);
|
||
PlainLen += AppendWSCTLV(WSC_ID_ENROLLEE_IPV4,
|
||
&Plain[PlainLen],
|
||
(UCHAR *)&tmpUint32, 0);
|
||
|
||
if (pIpv4SubMaskList
|
||
#ifdef IWSC_TEST_SUPPORT
|
||
&& (pIWscInfo->bEmptySubmaskList == FALSE)
|
||
#endif /* IWSC_TEST_SUPPORT */
|
||
)
|
||
{
|
||
PlainLen += AppendWSCTLV(WSC_ID_IPV4_SUBMASK_LIST,
|
||
&Plain[PlainLen],
|
||
(UCHAR *)pIpv4SubMaskList, Ipv4SubMaskListSize);
|
||
}
|
||
|
||
if (pIpv4SubMaskList)
|
||
os_free_mem(NULL, pIpv4SubMaskList);
|
||
}
|
||
#endif // IWSC_SUPPORT //
|
||
}
|
||
|
||
/* Generate HMAC */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, &Plain[0], PlainLen, TB, SHA256_DIGEST_SIZE);
|
||
PlainLen += AppendWSCTLV(WSC_ID_KEY_WRAP_AUTH, &Plain[PlainLen], TB, 0);
|
||
|
||
/* 4b. Encrypted Settings */
|
||
/* Encrypt data */
|
||
EncrLen = IV_ENCR_DATA_LEN_512 - 16;
|
||
AES_CBC_Encrypt(Plain, PlainLen,pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),&IV_EncrData[0], 16, (UINT8 *) &IV_EncrData[16], (UINT *) &EncrLen);
|
||
templen = AppendWSCTLV(WSC_ID_ENCR_SETTINGS, pData, IV_EncrData, 16 + EncrLen);/*IVLen + EncrLen */
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef DPA_T
|
||
/* Vendor Extension */
|
||
if ((pWscControl->WpsVendorExt[0].Length > 0) &&
|
||
(pWscControl->WpsVendorExt[0].Length <= 1024))
|
||
{
|
||
templen = AppendWSCTLV(WSC_ID_VENDOR_EXT,
|
||
pData,
|
||
(UINT8 *)pWscControl->WpsVendorExt[0].pData,
|
||
pWscControl->WpsVendorExt[0].Length);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
#endif /* DPA_T */
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/*
|
||
Combine last TX & RX message contents and validate the HMAC
|
||
We have to exclude last 12 bytes from last receive since it's authenticator value
|
||
*/
|
||
HmacLen = Len + pReg->LastRx.Length;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
pAuth = (PUCHAR) pAdapter->pHmacData;
|
||
NdisMoveMemory(pAuth, pReg->LastRx.Data, pReg->LastRx.Length);
|
||
pAuth += pReg->LastRx.Length;
|
||
NdisMoveMemory(pAuth, pbuf, Len);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
templen = AppendWSCTLV(WSC_ID_AUTHENTICATOR, pData, KDK, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
LabelErr:
|
||
if(IV_EncrData)
|
||
os_free_mem(NULL, IV_EncrData);
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
|
||
if (TB != NULL)
|
||
os_free_mem(NULL, TB);
|
||
if (Plain != NULL)
|
||
os_free_mem(NULL, Plain);
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageM8 : \n"));
|
||
return Len;
|
||
}
|
||
|
||
int BuildMessageDONE(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[1];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, WSC DONE */
|
||
TB[0] = WSC_MSG_WSC_DONE;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageDONE : \n"));
|
||
return Len;
|
||
}
|
||
|
||
int BuildMessageACK(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[1];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, WSC ACK */
|
||
TB[0] = WSC_MSG_WSC_ACK;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageACK : \n"));
|
||
return Len;
|
||
}
|
||
|
||
int BuildMessageNACK(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
OUT VOID *pbuf)
|
||
{
|
||
UCHAR TB[2];
|
||
INT Len = 0, templen = 0;
|
||
PUCHAR pData = (PUCHAR)pbuf;
|
||
PWSC_REG_DATA pReg = (PWSC_REG_DATA) &pWscControl->RegData;
|
||
USHORT ConfigError = htons(pReg->SelfInfo.ConfigError);
|
||
#ifdef WSC_V2_SUPPORT
|
||
PWSC_TLV pWscTLV = &pWscControl->WscV2Info.ExtraTlv;
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
/* 1. Version */
|
||
templen = AppendWSCTLV(WSC_ID_VERSION, pData, &pReg->SelfInfo.Version, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 2. Message Type, WSC NACK */
|
||
TB[0] = WSC_ID_MESSAGE_NACK;
|
||
templen = AppendWSCTLV(WSC_ID_MSG_TYPE, pData, TB, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 3. Enrollee Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_ENROLLEE_NONCE, pData, pReg->EnrolleeNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 4. Registrar Nonce, 16 bytes */
|
||
templen = AppendWSCTLV(WSC_ID_REGISTRAR_NONCE, pData, pReg->RegistrarNonce, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
/* 5. Error */
|
||
templen = AppendWSCTLV(WSC_ID_CONFIG_ERROR, pData, (UINT8 *)&ConfigError, 0);
|
||
pData += templen;
|
||
Len += templen;
|
||
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
/* Version2 */
|
||
WscGenV2Msg(pWscControl,
|
||
FALSE,
|
||
NULL,
|
||
0,
|
||
&pData,
|
||
&Len);
|
||
|
||
/* Extra attribute that is not defined in WSC Sepc. */
|
||
if (pWscTLV->pTlvData && pWscTLV->TlvLen)
|
||
{
|
||
templen = AppendWSCTLV(pWscTLV->TlvTag, pData, (UINT8 *)pWscTLV->pTlvData, pWscTLV->TlvLen);
|
||
pData += templen;
|
||
Len += templen;
|
||
}
|
||
}
|
||
#endif /* WSC_V2_SUPPORT */
|
||
|
||
pWscControl->WscRetryCount = 0;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("BuildMessageNACK : \n"));
|
||
return Len;
|
||
}
|
||
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M1 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M1
|
||
1. Change the correct parameters
|
||
2. Process M1
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM1(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR, DH_Len = 0, idx;
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
|
||
//CurOpMode = AP_MODE;
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
UCHAR CurOpMode = 0xFF;
|
||
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
CurOpMode = STA_MODE;
|
||
#ifdef P2P_SUPPORT
|
||
if (pWscControl->EntryIfIdx != BSS0)
|
||
CurOpMode = AP_MODE;
|
||
#endif /* P2P_SUPPORT */
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
pReg->PeerInfo.Version2 = 0;
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC)
|
||
pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_NO_ERROR;
|
||
|
||
if (pWscControl->bTriggerByNFC && pWscControl->bRegenPublicKey == 0)
|
||
; /* Do NOT need to generate EnrolleeRandom and DH public key here. */
|
||
else
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
{
|
||
|
||
DH_Len = sizeof(pReg->Pkr);
|
||
/* Enrollee 192 random bytes for DH key generation */
|
||
for (idx = 0; idx < 192; idx++)
|
||
pWscControl->RegData.EnrolleeRandom[idx] = RandomByte(pAdapter);
|
||
|
||
RT_DH_PublicKey_Generate (
|
||
WPS_DH_G_VALUE, sizeof(WPS_DH_G_VALUE),
|
||
WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
|
||
pWscControl->RegData.EnrolleeRandom, sizeof(pWscControl->RegData.EnrolleeRandom),
|
||
pReg->Pkr, (UINT *) &DH_Len);
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Re-generate public key for negative test!\n"));
|
||
pWscControl->bRegenPublicKey = 0;
|
||
}
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
}
|
||
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO));
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M1 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M1 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_UUID_E:
|
||
NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_E))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_E));
|
||
break;
|
||
|
||
case WSC_ID_MAC_ADDR:
|
||
NdisMoveMemory(pReg->PeerInfo.MacAddr, pData, WscLen);
|
||
NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerMAC, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MAC_ADDR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MAC_ADDR));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
NdisMoveMemory(pReg->EnrolleeNonce, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_PUBLIC_KEY:
|
||
/* Get Enrollee Public Key */
|
||
NdisMoveMemory(pReg->Pke, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC)
|
||
{
|
||
UCHAR HashData[SHA256_DIGEST_SIZE];
|
||
RT_SHA256(&pWscControl->RegData.Pke[0], 192, &HashData[0]);
|
||
hex_dump("public_key RAW:", &pWscControl->RegData.Pke[0], 192);
|
||
if (NdisEqualMemory(&HashData[0], &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE)
|
||
{
|
||
hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN);
|
||
hex_dump("PeerNfcPasswdHash", &pWscControl->PeerNfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN);
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Enrollee public key hash different!\n"));
|
||
pWscControl->RegData.SelfInfo.ConfigError = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH;
|
||
}
|
||
}
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
break;
|
||
|
||
case WSC_ID_AUTH_TYPE_FLAGS:
|
||
pReg->PeerInfo.AuthTypeFlags = *((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_ENCR_TYPE_FLAGS:
|
||
pReg->PeerInfo.EncrTypeFlags = *((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_CONN_TYPE_FLAGS:
|
||
pReg->PeerInfo.ConnTypeFlags = *pData;
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_METHODS:
|
||
pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
|
||
break;
|
||
|
||
case WSC_ID_SC_STATE:
|
||
pReg->PeerInfo.ScState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
if (CurOpMode == STA_MODE)
|
||
{
|
||
/* Don't overwrite the credential of M7 received from AP when this flag is TRUE in registrar mode! */
|
||
pWscControl->bConfiguredAP = (pReg->PeerInfo.ScState == WSC_SCSTATE_CONFIGURED) ? TRUE:FALSE;
|
||
}
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SC_STATE));
|
||
break;
|
||
|
||
case WSC_ID_MANUFACTURER:
|
||
NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NUMBER:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
|
||
break;
|
||
|
||
case WSC_ID_SERIAL_NUM:
|
||
NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
|
||
break;
|
||
|
||
case WSC_ID_PRIM_DEV_TYPE:
|
||
NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
|
||
NdisMoveMemory(pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
|
||
break;
|
||
|
||
case WSC_ID_RF_BAND:
|
||
pReg->PeerInfo.RfBand = *pData;
|
||
/*if() ret = WSC_ERROR_CHAN24_NOT_SUPP; */
|
||
/*if() ret = WSC_ERROR_CHAN50_NOT_SUPP; */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
|
||
break;
|
||
|
||
case WSC_ID_ASSOC_STATE:
|
||
pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_ERROR:
|
||
pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_PWD_ID:
|
||
DBGPRINT(RT_DEBUG_TRACE, (" WPS Registrar DPID %04x\n",pReg->SelfInfo.DevPwdId));
|
||
if(WSC_DEVICEPWDID_DEFAULT == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PIN\n"));
|
||
pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PIN);
|
||
}
|
||
else if(WSC_DEVICEPWDID_PUSH_BTN == get_unaligned((PUSHORT) pData))/**(PUSHORT) pData) */
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID PBC\n"));
|
||
pWscControl->RegData.SelfInfo.DevPwdId = cpu2be16(DEV_PASS_ID_PBC);
|
||
}
|
||
else
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx WPS DPID unsupport\n"));
|
||
}
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
|
||
break;
|
||
|
||
case WSC_ID_OS_VERSION:
|
||
pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);/**((PULONG) pData); */
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_VENDOR_EXT:
|
||
#ifdef EASY_CONFIG_SETUP
|
||
AutoProvisionDecodeExtData(pAdapter, (pWscControl->EntryIfIdx & 0x0F), &pWscControl->EntryAddr[0], pData);
|
||
#endif /* EASY_CONFIG_SETUP */
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
UCHAR tmp_data_len = 0;
|
||
WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Version2 = %x\n", pReg->PeerInfo.Version2));
|
||
}
|
||
#endif // WSC_V2_SUPPORT //
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM1 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M2 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M2
|
||
1. Change the correct parameters
|
||
2. Process M2
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM2(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
IN UCHAR apidx,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
|
||
UCHAR DHKey[32], KdkInput[38], KdfKey[80];
|
||
INT DH_Len;
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
//MAC_TABLE_ENTRY *pEntry = NULL;
|
||
//UCHAR CurOpMode = 0xFF;
|
||
#ifdef WSC_NFC_SUPPORT
|
||
INT EncrLen;
|
||
UCHAR *IV_DecrData=NULL;//IV len 16 ,DecrData len
|
||
BOOLEAN bWscEncrSettings=FALSE;
|
||
USHORT IV_DecrDataLen;
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
|
||
#ifdef CONFIG_AP_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_AP(pAdapter)
|
||
//CurOpMode = AP_MODE;
|
||
#endif /* CONFIG_AP_SUPPORT */
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
//CurOpMode = STA_MODE;
|
||
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
pReg->PeerInfo.Version2 = 0;
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] |= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] |= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] |= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] |= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/*pEntry =*/ MacTableLookup(pAdapter, pReg->PeerInfo.MacAddr);
|
||
|
||
NdisZeroMemory(&pWscControl->WscPeerInfo, sizeof(WSC_PEER_DEV_INFO));
|
||
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER)
|
||
{
|
||
IV_DecrData = kmalloc(1024, MEM_ALLOC_FLAG);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Allocate IV_DecrData fail @ %s\n", __FUNCTION__));
|
||
return ret;
|
||
}
|
||
}
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M2 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
/* for verification with our enrollee nonce */
|
||
if (RTMPCompareMemory(pReg->SelfNonce, pData, WscLen) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n"));
|
||
}
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_REGISTRAR_NONCE:
|
||
NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_UUID_R:
|
||
NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_UUID_R))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_UUID_R));
|
||
break;
|
||
|
||
case WSC_ID_PUBLIC_KEY:
|
||
/* Get Registrar Public Key */
|
||
NdisMoveMemory(&pReg->Pkr, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PUBLIC_KEY))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PUBLIC_KEY));
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER) /* So far no this test case. */
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("NfcModel(=%d) \n", pWscControl->NfcModel));
|
||
UCHAR HashData[SHA256_DIGEST_SIZE];
|
||
RT_SHA256(&pWscControl->RegData.Pkr[0], 192, &HashData[0]);
|
||
if (NdisEqualMemory(&HashData[0], &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN) == FALSE)
|
||
{
|
||
hex_dump("HashData", &HashData[0], NFC_DEV_PASSWD_HASH_LEN);
|
||
hex_dump("PeerNfcPasswdHash", &pWscControl->NfcPasswdHash[0], NFC_DEV_PASSWD_HASH_LEN);
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Registrar public key hash different!\n"));
|
||
ret = WSC_ERROR_PUBLIC_KEY_HASH_MISMATCH;
|
||
}
|
||
}
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
break;
|
||
|
||
case WSC_ID_AUTH_TYPE_FLAGS:
|
||
pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTH_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTH_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_ENCR_TYPE_FLAGS:
|
||
pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_CONN_TYPE_FLAGS:
|
||
pReg->PeerInfo.ConnTypeFlags = *pData;
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONN_TYPE_FLAGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONN_TYPE_FLAGS));
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_METHODS:
|
||
pReg->PeerInfo.ConfigMethods = get_unaligned((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_METHODS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_METHODS));
|
||
break;
|
||
|
||
case WSC_ID_MANUFACTURER:
|
||
NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerManufacturer, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MANUFACTURER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MANUFACTURER));
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelName, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NAME));
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NUMBER:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerModelNumber, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MODEL_NUMBER))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MODEL_NUMBER));
|
||
break;
|
||
|
||
case WSC_ID_SERIAL_NUM:
|
||
NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerSerialNumber, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_SERIAL_NUM))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_SERIAL_NUM));
|
||
break;
|
||
|
||
case WSC_ID_PRIM_DEV_TYPE:
|
||
NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_PRIM_DEV_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_PRIM_DEV_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerDeviceName, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_NAME))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_NAME));
|
||
break;
|
||
|
||
case WSC_ID_RF_BAND:
|
||
pReg->PeerInfo.RfBand = *pData;
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_RF_BAND))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_RF_BAND));
|
||
break;
|
||
|
||
case WSC_ID_ASSOC_STATE:
|
||
pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ASSOC_STATE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ASSOC_STATE));
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_ERROR:
|
||
pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_CONFIG_ERROR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_CONFIG_ERROR));
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_PWD_ID:
|
||
#if 0
|
||
/*if(pReg->SelfInfo.DevPwdId != *(PUSHORT) pData)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM2 DPID R%d E%d\n",*(PUSHORT) pData ,pReg->EnrolleeInfo.DevPwdId));
|
||
ret = WSC_ERROR_DEV_PWD_AUTH_FAIL;
|
||
Length = 0;
|
||
}*/
|
||
#endif
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_DEVICE_PWD_ID))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_DEVICE_PWD_ID));
|
||
break;
|
||
|
||
case WSC_ID_OS_VERSION:
|
||
pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG) pData);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_OS_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_OS_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
break;
|
||
|
||
case WSC_ID_VENDOR_EXT:
|
||
#ifdef WSC_V2_SUPPORT
|
||
if (pWscControl->WscV2Info.bEnableWpsV2)
|
||
{
|
||
UCHAR tmp_data_len = 0;
|
||
WscParseV2SubItem(WFA_EXT_ID_VERSION2, pData, WscLen, &pReg->PeerInfo.Version2, &tmp_data_len);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Version2 = %x\n", pReg->PeerInfo.Version2));
|
||
}
|
||
#endif // WSC_V2_SUPPORT //
|
||
break;
|
||
#ifdef WSC_NFC_SUPPORT
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
// There shall have smoe kind of length check
|
||
if (pWscControl->bTriggerByNFC && pWscControl->NfcModel == MODEL_HANDOVER)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("WSC_ID_ENCR_SETTINGS at %s\n", __FUNCTION__));
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 1024)
|
||
{
|
||
// ApEncrSetting is not enough
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
hex_dump("WSC_ID_ENCR_SETTINGS-pData", pData, WscLen);
|
||
hex_dump("WSC_ID_ENCR_SETTINGS-IV_DecrData", IV_DecrData, WscLen);
|
||
IV_DecrDataLen = WscLen;
|
||
bWscEncrSettings = TRUE;
|
||
}
|
||
break;
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
NdisMoveMemory(&pWscControl->WscPeerInfo.WscPeerMAC, &pWscControl->RegData.PeerInfo.MacAddr, 6);
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
#if 0
|
||
if(WSC_ERROR_NO_ERROR != ret)
|
||
goto out;
|
||
#endif
|
||
|
||
DH_Len = sizeof(pReg->SecretKey);
|
||
RT_DH_SecretKey_Generate (
|
||
pReg->Pkr, sizeof(pReg->Pkr),
|
||
WPS_DH_P_VALUE, sizeof(WPS_DH_P_VALUE),
|
||
pReg->EnrolleeRandom, sizeof(pReg->EnrolleeRandom),
|
||
pReg->SecretKey, (UINT *) &DH_Len);
|
||
|
||
/* Compute the DHKey based on the DH secret */
|
||
RT_SHA256(&pReg->SecretKey[0], 192, &DHKey[0]);
|
||
|
||
/* Create KDK input data */
|
||
NdisMoveMemory(&KdkInput[0], pReg->SelfNonce, 16);
|
||
|
||
NdisMoveMemory(&KdkInput[16], pReg->SelfInfo.MacAddr, 6);
|
||
|
||
NdisMoveMemory(&KdkInput[22], pReg->RegistrarNonce, 16);
|
||
|
||
/* Generate the KDK */
|
||
RT_HMAC_SHA256(DHKey, 32, KdkInput, 38, KDK, SHA256_DIGEST_SIZE);
|
||
|
||
/* KDF */
|
||
WscDeriveKey(KDK, 32, Wsc_Personal_String, (sizeof(Wsc_Personal_String) - 1), KdfKey, 640);
|
||
|
||
/* Assign Key from KDF */
|
||
NdisMoveMemory(pReg->AuthKey, &KdfKey[0], 32);
|
||
NdisMoveMemory(pReg->KeyWrapKey, &KdfKey[32], 16);
|
||
NdisMoveMemory(pReg->Emsk, &KdfKey[48], 32);
|
||
|
||
#ifdef WSC_NFC_SUPPORT
|
||
if (pWscControl->bTriggerByNFC && bWscEncrSettings && pWscControl->NfcModel == MODEL_HANDOVER)
|
||
{
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (IV_DecrDataLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M2 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
// Parse encryption settings
|
||
if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE)
|
||
{
|
||
return WSC_ERROR_SETUP_LOCKED;
|
||
}
|
||
}
|
||
#endif /* WSC_NFC_SUPPORT */
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM2 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
|
||
/* out : */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M2D Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - rewrite buffer
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M2D
|
||
1. Change the correct parameters
|
||
2. Process M2D
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM2D(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen;
|
||
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M2D != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
/* for verification with our enrollee nonce */
|
||
if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M2 Compare enrollee nonce mismatched \n"));
|
||
}
|
||
break;
|
||
|
||
case WSC_ID_REGISTRAR_NONCE:
|
||
NdisMoveMemory(pReg->RegistrarNonce, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_UUID_R:
|
||
NdisMoveMemory(pReg->PeerInfo.Uuid, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_PUBLIC_KEY:
|
||
/* There shall be no Public transmitted in M2D */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Receive WSC_ID_PUBLIC_KEY!! werid!\n"));
|
||
break;
|
||
|
||
case WSC_ID_AUTH_TYPE_FLAGS:
|
||
pReg->PeerInfo.AuthTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
break;
|
||
|
||
case WSC_ID_ENCR_TYPE_FLAGS:
|
||
pReg->PeerInfo.EncrTypeFlags = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
break;
|
||
|
||
case WSC_ID_CONN_TYPE_FLAGS:
|
||
pReg->PeerInfo.ConnTypeFlags = *pData;
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_METHODS:
|
||
pReg->PeerInfo.ConfigMethods = be2cpu16(get_unaligned((PUSHORT) pData));/*be2cpu16(*((PUSHORT) pData)); */
|
||
break;
|
||
|
||
case WSC_ID_MANUFACTURER:
|
||
NdisMoveMemory(&pReg->PeerInfo.Manufacturer, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelName, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_MODEL_NUMBER:
|
||
NdisMoveMemory(&pReg->PeerInfo.ModelNumber, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_SERIAL_NUM:
|
||
NdisMoveMemory(&pReg->PeerInfo.SerialNumber, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_PRIM_DEV_TYPE:
|
||
NdisMoveMemory(&pReg->PeerInfo.PriDeviceType, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_NAME:
|
||
NdisMoveMemory(&pReg->PeerInfo.DeviceName, pData, WscLen);
|
||
break;
|
||
|
||
case WSC_ID_RF_BAND:
|
||
pReg->PeerInfo.RfBand = *pData;
|
||
break;
|
||
|
||
case WSC_ID_ASSOC_STATE:
|
||
pReg->PeerInfo.AssocState = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
break;
|
||
|
||
case WSC_ID_CONFIG_ERROR:
|
||
pReg->PeerInfo.ConfigError = get_unaligned((PUSHORT) pData);/**((PUSHORT) pData); */
|
||
break;
|
||
|
||
case WSC_ID_DEVICE_PWD_ID:
|
||
break;
|
||
|
||
case WSC_ID_OS_VERSION:
|
||
pReg->PeerInfo.OsVersion = get_unalignedlong((PULONG)pData);
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
/* No authenticator in M2D */
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM2D : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M3 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M3
|
||
1. Change the correct parameters
|
||
2. Process M3
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM3(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M3 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M3 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_REGISTRAR_NONCE:
|
||
/* for verification with our Registrar nonce */
|
||
if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M3 Compare Registrar nonce mismatched \n"));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_E_HASH1:
|
||
NdisMoveMemory(&pReg->EHash1[0], pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH1));
|
||
break;
|
||
|
||
case WSC_ID_E_HASH2:
|
||
NdisMoveMemory(&pReg->EHash2[0], pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_E_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_E_HASH2));
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM3 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM3 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M4 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M4
|
||
1. Change the correct parameters
|
||
2. Process M4
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM4(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32];
|
||
INT EncrLen;
|
||
PUCHAR pData = NULL;
|
||
UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
|
||
UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] |= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
return ret;
|
||
}
|
||
pHash = IV_DecrData;
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M4 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
/* for verification with our enrollee nonce */
|
||
if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M4 Compare enrollee nonce mismatched \n"));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_R_HASH1:
|
||
NdisMoveMemory(&pReg->RHash1, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH1))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH1));
|
||
break;
|
||
|
||
case WSC_ID_R_HASH2:
|
||
NdisMoveMemory(&pReg->RHash2, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_R_HASH2))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_R_HASH2));
|
||
break;
|
||
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
/* There shall have smoe kind of length check */
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 512)
|
||
{
|
||
/* ApEncrSetting is not enough */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M4 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
/* Parse encryption settings */
|
||
WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Verify R-Hash1 */
|
||
/* Create input for R-Hash1 */
|
||
NdisMoveMemory(pHash, pReg->Rs1, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate R-Hash1 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE);
|
||
|
||
if (RTMPCompareMemory(pReg->RHash1, RHash, 32) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> RHash1 not matched\n"));
|
||
ret = WSC_ERROR_DEV_PWD_AUTH_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM4 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
out :
|
||
if(IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M5 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M5
|
||
1. Change the correct parameters
|
||
2. Process M5
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM5(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], EHash[32];
|
||
INT EncrLen;
|
||
PUCHAR pData = NULL;
|
||
UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
|
||
UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
return ret;
|
||
}
|
||
pHash = IV_DecrData;
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M5 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_REGISTRAR_NONCE:
|
||
/* for verification with our Registrar nonce */
|
||
if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n"));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_REGISTRAR_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_REGISTRAR_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
/* There shall have smoe kind of length check */
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 512)
|
||
{
|
||
/* ApEncrSetting is not enough */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M5 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
/* Parse encryption settings */
|
||
WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM4 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
}
|
||
|
||
/* Verify E-Hash1 */
|
||
/* Create input for E-Hash1 */
|
||
NdisMoveMemory(pHash, pReg->Es1, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk1, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate E-Hash1 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, EHash, SHA256_DIGEST_SIZE);
|
||
|
||
if (RTMPCompareMemory(pReg->EHash1, EHash, 32) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 --> EHash1 not matched\n"));
|
||
pReg->SelfInfo.ConfigError = WSC_ERROR_HASH_FAIL;
|
||
ret = WSC_ERROR_HASH_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
if (pAdapter->pHmacData)
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM5 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
out :
|
||
if(IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM5 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M6 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M6
|
||
1. Change the correct parameters
|
||
2. Process M6
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM6(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32], RHash[32];
|
||
INT EncrLen;
|
||
PUCHAR pData = NULL;
|
||
UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
|
||
UCHAR *pHash=NULL;/*Reuse IV_DecrData memory */
|
||
USHORT WscType, WscLen, FieldCheck[7]={0,0,0,0,0,0,0};
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] |= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] |= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] |= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 512);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
return ret;
|
||
}
|
||
pHash = IV_DecrData;
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = cpu2be16(TLV_Recv.Type);
|
||
WscLen = cpu2be16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_VERSION))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_VERSION));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M6 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_MSG_TYPE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_MSG_TYPE));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
/* for verification with our enrollee nonce */
|
||
if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M6 Compare enrollee nonce mismatched \n"));
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENROLLEE_NONCE))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENROLLEE_NONCE));
|
||
break;
|
||
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
/* There shall have smoe kind of length check */
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 512)
|
||
{
|
||
/* ApEncrSetting is not enough */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M6 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
/* Parse encryption settings */
|
||
WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_ENCR_SETTINGS))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_ENCR_SETTINGS));
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
FieldCheck[(WSC_TLV_BYTE2(WSC_ID_AUTHENTICATOR))] ^= (1 << WSC_TLV_BYTE1(WSC_ID_AUTHENTICATOR));
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Verify R-Hash2 */
|
||
/* Create input for R-Hash1 */
|
||
NdisMoveMemory(pHash, pReg->Rs2, 16);
|
||
NdisMoveMemory(pHash + 16, pReg->Psk2, 16);
|
||
NdisMoveMemory(pHash + 32, pReg->Pke, 192);
|
||
NdisMoveMemory(pHash + 224, pReg->Pkr, 192);
|
||
|
||
/* Generate R-Hash2 */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pHash, 416, RHash, SHA256_DIGEST_SIZE);
|
||
|
||
if (RTMPCompareMemory(pReg->RHash2, RHash, 32) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 --> RHash2 not matched\n"));
|
||
ret = WSC_ERROR_DEV_PWD_AUTH_FAIL;
|
||
goto out;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData+ pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM6 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if( FieldCheck[0] || FieldCheck[1] || FieldCheck[2] || FieldCheck[3] || FieldCheck[4] || FieldCheck[5] || FieldCheck[6] )
|
||
ret = WSC_ERROR_WANTING_FIELD;
|
||
out:
|
||
if(IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM6 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M7 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M7
|
||
1. Change the correct parameters
|
||
2. Process M7
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM7(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN PWSC_CTRL pWscControl,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
OUT PWSC_REG_DATA pReg)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
|
||
INT EncrLen;
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen;
|
||
UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
return ret;
|
||
}
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M2 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M7 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_REGISTRAR_NONCE:
|
||
/* for verification with our Registrar nonce */
|
||
if (RTMPCompareMemory(pReg->RegistrarNonce, pData, WscLen) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M5 Compare Registrar nonce mismatched \n"));
|
||
}
|
||
break;
|
||
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
/* There shall have smoe kind of length check */
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 1024)
|
||
{
|
||
/* ApEncrSetting is not enough */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M7 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
#ifdef CONFIG_STA_SUPPORT
|
||
IF_DEV_CONFIG_OPMODE_ON_STA(pAdapter)
|
||
{
|
||
/* Cleanup Old M7 Profile contents */
|
||
RTMPZeroMemory(&pAdapter->StaCfg.WscControl.WscM7Profile, sizeof(WSC_PROFILE));
|
||
}
|
||
#endif /* CONFIG_STA_SUPPORT */
|
||
|
||
/* Parse encryption settings */
|
||
WscParseEncrSettings(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl);
|
||
|
||
#ifdef DPA_T
|
||
if (pAdapter->StaCfg.bPriorityCtrl)
|
||
{
|
||
WscSortProfile(pAdapter, pWscControl);
|
||
}
|
||
#endif /* DPA_T */
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM7 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if(IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM7 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
/*
|
||
========================================================================
|
||
|
||
Routine Description:
|
||
Process WSC M8 Message
|
||
|
||
Arguments:
|
||
pAdapter - NIC Adapter pointer
|
||
pbuf - recv buffer
|
||
Length - recv Length
|
||
|
||
Return Value:
|
||
None
|
||
|
||
IRQL = DISPATCH_LEVEL
|
||
|
||
Note:
|
||
Actions after Rx M8
|
||
1. Change the correct parameters
|
||
2. Process M8
|
||
|
||
========================================================================
|
||
*/
|
||
int ProcessMessageM8(
|
||
IN PRTMP_ADAPTER pAdapter,
|
||
IN VOID *precv,
|
||
IN INT Length,
|
||
IN PWSC_CTRL pWscControl)
|
||
{
|
||
int ret = WSC_ERROR_NO_ERROR;
|
||
INT HmacLen;
|
||
UCHAR Hmac[8] = { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff }, KDK[32];
|
||
INT EncrLen;
|
||
PUCHAR pData = NULL;
|
||
USHORT WscType, WscLen;
|
||
UCHAR *IV_DecrData=NULL;/*IV len 16 ,DecrData len */
|
||
PWSC_REG_DATA pReg = &pWscControl->RegData;
|
||
|
||
RTMPZeroMemory(KDK, 32);
|
||
os_alloc_mem(NULL, (UCHAR **)&IV_DecrData, 1024);
|
||
if(NULL == IV_DecrData)
|
||
{
|
||
ret = WSC_ERROR_CAN_NOT_ALLOCMEM;
|
||
return ret;
|
||
}
|
||
/* Copy the content to Regdata for lastRx information */
|
||
/* Length must include authenticator IE size */
|
||
pReg->LastRx.Length = Length;
|
||
NdisMoveMemory(pReg->LastRx.Data, precv, Length);
|
||
pData = pReg->LastRx.Data;
|
||
|
||
/* Start to process WSC IEs */
|
||
while (Length > 4)
|
||
{
|
||
WSC_IE TLV_Recv;
|
||
memcpy((UINT8 *)&TLV_Recv, pData, 4);
|
||
WscType = be2cpu16(TLV_Recv.Type);
|
||
WscLen = be2cpu16(TLV_Recv.Length);
|
||
pData += 4;
|
||
Length -= 4;
|
||
|
||
/* Parse M8 WSC type and store to RegData structure */
|
||
switch (WscType)
|
||
{
|
||
case WSC_ID_VERSION:
|
||
if(pReg->SelfInfo.Version != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Version mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_MSG_TYPE:
|
||
if(WSC_ID_MESSAGE_M8 != *pData)
|
||
DBGPRINT(RT_DEBUG_ERROR, ("Rx WPS Message Type mismatched %02x\n",*pData));
|
||
break;
|
||
|
||
case WSC_ID_ENROLLEE_NONCE:
|
||
/* for verification with our enrollee nonce */
|
||
if (RTMPCompareMemory(pReg->EnrolleeNonce, pData, WscLen) != 0)
|
||
{
|
||
DBGPRINT(RT_DEBUG_TRACE, ("Rx M8 Compare enrollee nonce mismatched \n"));
|
||
}
|
||
break;
|
||
|
||
case WSC_ID_ENCR_SETTINGS:
|
||
/* There shall have smoe kind of length check */
|
||
if (WscLen <= 16)
|
||
break;
|
||
if (WscLen > 1024)
|
||
{
|
||
/* ApEncrSetting is not enough */
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ApEncrSettings array size is not enough, require %d\n", WscLen));
|
||
break;
|
||
}
|
||
NdisMoveMemory(IV_DecrData, pData, WscLen);
|
||
EncrLen = sizeof(pReg->ApEncrSettings);
|
||
AES_CBC_Decrypt(IV_DecrData + 16, (WscLen - 16),pReg->KeyWrapKey,sizeof(pReg->KeyWrapKey),IV_DecrData, 16, (UINT8 *) pReg->ApEncrSettings, (UINT *) &EncrLen);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("M8 ApEncrSettings len = %d\n ", EncrLen));
|
||
|
||
/* Parse encryption settings */
|
||
if (WscProcessCredential(pAdapter, pReg->ApEncrSettings, EncrLen, pWscControl) == FALSE)
|
||
{
|
||
if(NULL != IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
return WSC_ERROR_SETUP_LOCKED;
|
||
}
|
||
|
||
#ifdef DPA_T
|
||
if (pAdapter->StaCfg.bPriorityCtrl)
|
||
{
|
||
WscSortProfile(pAdapter, pWscControl);
|
||
}
|
||
#endif /* DPA_T */
|
||
break;
|
||
|
||
case WSC_ID_AUTHENTICATOR:
|
||
NdisMoveMemory(Hmac, pData, WscLen);
|
||
break;
|
||
|
||
default:
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 --> Unknown IE 0x%04x\n", WscType));
|
||
break;
|
||
}
|
||
|
||
/* Offset to net WSC Ie */
|
||
pData += WscLen;
|
||
Length -= WscLen;
|
||
}
|
||
|
||
/* Combine last TX & RX message contents and validate the HMAC */
|
||
/* We have to exclude last 12 bytes from last receive since it's authenticator value */
|
||
HmacLen = pReg->LastTx.Length + pReg->LastRx.Length - 12;
|
||
if (pAdapter->pHmacData)
|
||
{
|
||
NdisMoveMemory(pAdapter->pHmacData, pReg->LastTx.Data, pReg->LastTx.Length);
|
||
NdisMoveMemory(pAdapter->pHmacData + pReg->LastTx.Length, pReg->LastRx.Data, pReg->LastRx.Length - 12);
|
||
|
||
/* Validate HMAC, reuse KDK buffer */
|
||
RT_HMAC_SHA256(pReg->AuthKey, 32, pAdapter->pHmacData, HmacLen, KDK, SHA256_DIGEST_SIZE);
|
||
}
|
||
if (RTMPEqualMemory(Hmac, KDK, 8) != 1)
|
||
{
|
||
DBGPRINT(RT_DEBUG_ERROR, ("ProcessMessageM8 --> HMAC not match\n"));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("MD --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) KDK)), (UINT)cpu2be32(*((PUINT)(KDK + 4)))));
|
||
DBGPRINT(RT_DEBUG_TRACE, ("calculated --> 0x%08x-%08x\n", (UINT)cpu2be32(*((PUINT) &Hmac[0])), (UINT)cpu2be32(*((PUINT) &Hmac[4]))));
|
||
ret = WSC_ERROR_HMAC_FAIL;
|
||
}
|
||
|
||
if(IV_DecrData)
|
||
os_free_mem(NULL, IV_DecrData);
|
||
DBGPRINT(RT_DEBUG_TRACE, ("ProcessMessageM8 : \n"));
|
||
return ret;
|
||
}
|
||
|
||
#endif /* WSC_INCLUDED */
|
||
|