1391 lines
38 KiB
C
1391 lines
38 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:
|
|
wapi.c
|
|
|
|
Abstract:
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- ---------- ----------------------------------------------
|
|
Albert 2008-4-3 Supoort WAPI protocol
|
|
*/
|
|
/*#include <linux/stdio.h> */
|
|
/*#include <linux/stdlib.h> */
|
|
/*#include <linux/string.h> */
|
|
/*#include <linux/time.h> */
|
|
|
|
#ifdef WAPI_SUPPORT
|
|
|
|
#include "rt_config.h"
|
|
|
|
/* WAPI AKM OUI */
|
|
UCHAR OUI_WAI_CERT_AKM[4] = {0x00, 0x14, 0x72, 0x01};
|
|
UCHAR OUI_WAI_PSK_AKM[4] = {0x00, 0x14, 0x72, 0x02};
|
|
|
|
/* WAPI CIPHER OUI */
|
|
UCHAR OUI_WPI_CIPHER_SMS4[4] = {0x00, 0x14, 0x72, 0x01};
|
|
|
|
UCHAR WAPI_TYPE[] = {0x88, 0xb4};
|
|
|
|
/* IV default value */
|
|
UCHAR AE_BCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
|
|
0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
|
|
UCHAR ASUE_UCAST_PN[LEN_WAPI_TSC] = {0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
|
|
0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
|
|
UCHAR AE_UCAST_PN[LEN_WAPI_TSC] = {0x37, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c,
|
|
0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c, 0x36, 0x5c};
|
|
|
|
BUILD_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec);
|
|
BUILD_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec);
|
|
|
|
static void kd_hmac_sha256(
|
|
unsigned char *key,
|
|
unsigned int key_len,
|
|
unsigned char *text,
|
|
unsigned int text_len,
|
|
unsigned char *output,
|
|
unsigned int output_len)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; output_len/SHA256_DIGEST_SIZE; i++, output_len -= SHA256_DIGEST_SIZE)
|
|
{
|
|
RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], SHA256_DIGEST_SIZE);
|
|
text = &output[i*SHA256_DIGEST_SIZE];
|
|
text_len = SHA256_DIGEST_SIZE;
|
|
}
|
|
|
|
if (output_len > 0)
|
|
RT_HMAC_SHA256(key, key_len, text, text_len, &output[i*SHA256_DIGEST_SIZE], output_len);
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Build WAPI IE in RSN-IE.
|
|
It only shall be called by RTMPMakeRSNIE.
|
|
|
|
Arguments:
|
|
pAd - pointer to our pAdapter context
|
|
AuthMode - indicate the authentication mode
|
|
WepStatus - indicate the encryption type
|
|
|
|
Return Value:
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
VOID RTMPInsertWapiIe(
|
|
IN UINT AuthMode,
|
|
IN UINT WepStatus,
|
|
OUT PUCHAR pWIe,
|
|
OUT UCHAR *w_len)
|
|
{
|
|
WAPIIE *pWapiHdr = (WAPIIE*)pWIe;
|
|
WAPIIE_UCAST *pWIE_ucast;
|
|
WAPIIE_MCAST *pWIE_mcast;
|
|
|
|
*w_len = 0;
|
|
|
|
/* Assign the verson as 1 */
|
|
pWapiHdr->version = 1;
|
|
|
|
/* Set the AKM count and suite */
|
|
pWapiHdr->acount = 1;
|
|
switch (AuthMode)
|
|
{
|
|
case Ndis802_11AuthModeWAICERT:
|
|
NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_CERT_AKM, 4);
|
|
break;
|
|
|
|
case Ndis802_11AuthModeWAIPSK:
|
|
NdisMoveMemory(pWapiHdr->auth[0].oui, OUI_WAI_PSK_AKM, 4);
|
|
break;
|
|
}
|
|
|
|
/* swap for big-endian platform */
|
|
pWapiHdr->version = cpu2le16(pWapiHdr->version);
|
|
pWapiHdr->acount = cpu2le16(pWapiHdr->acount);
|
|
|
|
/* update current length */
|
|
(*w_len) += sizeof(WAPIIE);
|
|
|
|
/* Set the unicast cipher and count */
|
|
pWIE_ucast = (WAPIIE_UCAST*)(pWIe + (*w_len));
|
|
pWIE_ucast->ucount = 1;
|
|
NdisMoveMemory(pWIE_ucast->ucast[0].oui, OUI_WPI_CIPHER_SMS4, 4);
|
|
|
|
/* swap for big-endian platform */
|
|
pWIE_ucast->ucount = cpu2le16(pWIE_ucast->ucount);
|
|
|
|
/* update current length */
|
|
(*w_len) += sizeof(WAPIIE_UCAST);
|
|
|
|
/* Set the multicast cipher and capability */
|
|
pWIE_mcast = (WAPIIE_MCAST*)(pWIe + (*w_len));
|
|
NdisMoveMemory(pWIE_mcast->mcast, OUI_WPI_CIPHER_SMS4, 4);
|
|
pWIE_mcast->capability = 0; /* Todo AlbertY - support pre-authentication */
|
|
|
|
/* update current length */
|
|
(*w_len) += sizeof(WAPIIE_MCAST);
|
|
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Check whether the received frame is WAPI frame.
|
|
|
|
Arguments:
|
|
pAd - pointer to our pAdapter context
|
|
pData - the received frame
|
|
DataByteCount - the received frame's length
|
|
|
|
Return:
|
|
TRUE - This frame is WAPI frame
|
|
FALSE - otherwise
|
|
==========================================================================
|
|
*/
|
|
BOOLEAN RTMPCheckWAIframe(
|
|
IN PUCHAR pData,
|
|
IN ULONG DataByteCount)
|
|
{
|
|
if(DataByteCount < (LENGTH_802_1_H + LENGTH_WAI_H))
|
|
return FALSE;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
DBGPRINT(RT_DEBUG_INFO, ("RTMPCheckWAIframe ===> \n"));
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
/* Skip LLC header */
|
|
if (NdisEqualMemory(SNAP_802_1H, pData, 6))
|
|
{
|
|
pData += 6;
|
|
}
|
|
/* Skip 2-bytes EAPoL type */
|
|
if (NdisEqualMemory(WAPI_TYPE, pData, 2))
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, ("--> Receive a WAI frame \n"));
|
|
pData += 2;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Check whether the cipher is SMS4.
|
|
|
|
Arguments:
|
|
pAd - pointer to our pAdapter context
|
|
apidx - interface index
|
|
|
|
Return:
|
|
TRUE - The cipher is SMS4
|
|
FALSE - otherwise
|
|
==========================================================================
|
|
*/
|
|
BOOLEAN RTMPIsWapiCipher(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR apidx)
|
|
{
|
|
NDIS_802_11_ENCRYPTION_STATUS cipher_mode = Ndis802_11EncryptionDisabled;
|
|
|
|
/* Currently, WAPI only support MBSS */
|
|
if (apidx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM)
|
|
return FALSE;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
if (apidx < MAX_MBSSID_NUM(pAd))
|
|
cipher_mode = pAd->ApCfg.MBSSID[apidx].wdev.WepStatus;
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
cipher_mode = pAd->StaCfg.wdev.WepStatus;
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
if (cipher_mode == Ndis802_11EncryptionSMS4Enabled)
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Insert the WPI-SMS4 IV header
|
|
|
|
+-------+------+-------------+
|
|
| KeyId | resv | sequence PN |
|
|
+-------+------+-------------+
|
|
|
|
Arguments:
|
|
|
|
Return:
|
|
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPConstructWPIIVHdr(
|
|
IN UCHAR key_id,
|
|
IN UCHAR *tx_iv,
|
|
OUT UCHAR *iv_hdr)
|
|
{
|
|
#if 1
|
|
iv_hdr[0] = key_id;
|
|
iv_hdr[1] = 0x00;
|
|
|
|
NdisMoveMemory(&iv_hdr[2], tx_iv, LEN_WAPI_TSC);
|
|
#else
|
|
ULONG TempLen = 0;
|
|
UCHAR res_byte = 0x00;
|
|
|
|
MakeOutgoingFrame( pFrameBuf, &TempLen,
|
|
1, &key_id, /* key index */
|
|
1, &res_byte, /* reserve byte */
|
|
LEN_WAPI_TSC, tx_iv,
|
|
END_OF_ARGS);
|
|
return TempLen;
|
|
#endif
|
|
}
|
|
|
|
VOID RTMPDeriveWapiGTK(
|
|
IN PUCHAR nmk,
|
|
OUT PUCHAR gtk_ptr)
|
|
{
|
|
const char group_context[100] = "multicast or station key expansion for station unicast and multicast and broadcast";
|
|
|
|
NdisZeroMemory(gtk_ptr, 32);
|
|
kd_hmac_sha256(nmk,
|
|
16,
|
|
(UCHAR *)group_context,
|
|
strlen(group_context),
|
|
gtk_ptr,
|
|
32);
|
|
}
|
|
|
|
VOID RT_SMS4_TEST(
|
|
IN UINT8 test)
|
|
{
|
|
CIPHER_KEY CipherKey;
|
|
UINT16 data_len;
|
|
UINT8 rcvd_data[50];
|
|
UINT8 mac_hdr_qos[] = {0x88, 0x42, 0x00, 0x00, 0x08, 0xda, 0x75, 0x84,
|
|
0xd0, 0xcc, 0x27, 0xe8, 0x72, 0xaa, 0x2c, 0xb9,
|
|
0x6b, 0xbb, 0xea, 0x35, 0xa4, 0x20, 0x1e, 0xd2,
|
|
0xcf, 0x14};
|
|
|
|
UINT8 payload_qos[] = {0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00};
|
|
UINT8 pn[] = {0x98, 0xba, 0xdc, 0xfe, 0x10, 0x32, 0x54, 0x76,
|
|
0x67, 0x45, 0x23, 0x01, 0xef, 0xcd, 0xab, 0x89};
|
|
UINT8 key[] = {0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe,
|
|
0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
|
|
0xef, 0xcd, 0xab, 0x89, 0x67, 0x45, 0x23, 0x01,
|
|
0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe};
|
|
#if 0
|
|
UINT8 pn_inv[] = {0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67,
|
|
0x76, 0x54, 0x32, 0x10, 0xfe, 0xdc, 0xba, 0x98};
|
|
UINT8 payload[] = {0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00};
|
|
UINT8 mac_hdr[] = {0x08, 0x42, 0x00, 0x00, 0x08, 0xda, 0x75, 0x84,
|
|
0xd0, 0xcc, 0x27, 0xe8, 0x72, 0xaa, 0x2c, 0xb9,
|
|
0x6b, 0xbb, 0xea, 0x35, 0xa4, 0x20, 0x1e, 0xd2};
|
|
#endif
|
|
|
|
RTMPSoftEncryptSMS4(mac_hdr_qos,
|
|
payload_qos,
|
|
1,
|
|
1,
|
|
key,
|
|
pn);
|
|
|
|
hex_dump("encrypted payload", payload_qos, 17);
|
|
|
|
#if 1
|
|
NdisZeroMemory(&CipherKey, sizeof(CIPHER_KEY));
|
|
NdisMoveMemory(CipherKey.Key, key, 16);
|
|
NdisMoveMemory(CipherKey.TxMic, &key[16], 8);
|
|
NdisMoveMemory(CipherKey.RxMic, &key[24], 8);
|
|
CipherKey.KeyLen = 16;
|
|
|
|
|
|
NdisZeroMemory(rcvd_data, 50);
|
|
rcvd_data[0] = 1;
|
|
data_len = 2;
|
|
NdisMoveMemory(&rcvd_data[data_len], pn, 16);
|
|
data_len += 16;
|
|
NdisMoveMemory(&rcvd_data[data_len], payload_qos, 17);
|
|
data_len += 17;
|
|
|
|
|
|
if (RTMPSoftDecryptSMS4(mac_hdr_qos,
|
|
FALSE,
|
|
&CipherKey,
|
|
rcvd_data,
|
|
&data_len) == 0)
|
|
hex_dump("decrypted payload", rcvd_data, data_len);
|
|
else
|
|
printk("decrypted fail\n");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
In kernel mode read parameters from file
|
|
|
|
Arguments:
|
|
src the location of the file.
|
|
dest put the parameters to the destination.
|
|
Length size to read.
|
|
|
|
Return Value:
|
|
None
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
void rtmp_read_wapi_parms_from_file(
|
|
IN PRTMP_ADAPTER pAd,
|
|
RTMP_STRING *tmpbuf,
|
|
RTMP_STRING *buffer)
|
|
{
|
|
UINT32 ip_addr;
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
INT apidx = 0;
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
RTMP_STRING tok_str[32];
|
|
INT idx;
|
|
|
|
PCOMMON_WAPI_INFO pInfo = &pAd->CommonCfg.comm_wapi_info;
|
|
|
|
/* wapi interface name */
|
|
if (RTMPGetKeyParameter("Wapiifname", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->wapi_ifname, tmpbuf, strlen(tmpbuf));
|
|
pInfo->wapi_ifname_len = strlen(tmpbuf);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Wapiifname=%s, len=%d\n",
|
|
pInfo->wapi_ifname,
|
|
pInfo->wapi_ifname_len));
|
|
}
|
|
}
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
/* WapiPreAuthifname - Not implement yet */
|
|
if (RTMPGetKeyParameter("WapiPreAuthifname", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->preauth_ifname, tmpbuf, strlen(tmpbuf));
|
|
pInfo->preauth_ifname_len = strlen(tmpbuf);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiPreAuthifname=%s, len=%d\n",
|
|
pInfo->preauth_ifname,
|
|
pInfo->preauth_ifname_len));
|
|
}
|
|
}
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
/* WapiAsCertPath */
|
|
if (RTMPGetKeyParameter("WapiAsCertPath", tmpbuf, 128, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->as_cert_path[0], tmpbuf, strlen(tmpbuf));
|
|
pInfo->as_cert_path_len[0] = strlen(tmpbuf);
|
|
pInfo->as_cert_no = 1;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath=%s, len=%d\n",
|
|
pInfo->as_cert_path[0],
|
|
pInfo->as_cert_path_len[0]));
|
|
}
|
|
}
|
|
|
|
/* WapiAsCertPath2 ~ WapiAsCertPath10 */
|
|
for (idx = 1; idx < MAX_ID_NO; idx++)
|
|
{
|
|
sprintf(tok_str, "WapiAsCertPath%d", idx + 1);
|
|
|
|
if (RTMPGetKeyParameter(tok_str, tmpbuf, 128, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->as_cert_path[idx], tmpbuf, strlen(tmpbuf));
|
|
pInfo->as_cert_path_len[idx] = strlen(tmpbuf);
|
|
pInfo->as_cert_no++;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiAsCertPath%d=%s, len=%d\n",
|
|
idx+1,
|
|
pInfo->as_cert_path[idx],
|
|
pInfo->as_cert_path_len[idx]));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* WapiCaCertPath */
|
|
if (RTMPGetKeyParameter("WapiCaCertPath", tmpbuf, 128, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->ca_cert_path, tmpbuf, strlen(tmpbuf));
|
|
pInfo->ca_cert_path_len = strlen(tmpbuf);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiCaCertPath=%s, len=%d\n",
|
|
pInfo->ca_cert_path,
|
|
pInfo->ca_cert_path_len));
|
|
}
|
|
}
|
|
|
|
/* WapiUserCertPath */
|
|
if (RTMPGetKeyParameter("WapiUserCertPath", tmpbuf, 128, buffer, TRUE))
|
|
{
|
|
if (strlen(tmpbuf) > 0)
|
|
{
|
|
NdisMoveMemory(pInfo->user_cert_path, tmpbuf, strlen(tmpbuf));
|
|
pInfo->user_cert_path_len = strlen(tmpbuf);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiUserCertPath=%s, len=%d\n",
|
|
pInfo->user_cert_path,
|
|
pInfo->user_cert_path_len));
|
|
}
|
|
}
|
|
|
|
/* WapiAsIpAddr */
|
|
if (RTMPGetKeyParameter("WapiAsIpAddr", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
if (rtinet_aton(tmpbuf, &ip_addr))
|
|
{
|
|
pInfo->wapi_as_ip = ip_addr;
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiAsIpAddr=%s(%x)\n", tmpbuf, pInfo->wapi_as_ip));
|
|
}
|
|
}
|
|
|
|
/* WapiAsPort */
|
|
if (RTMPGetKeyParameter("WapiAsPort", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
pInfo->wapi_as_port = simple_strtol(tmpbuf, 0, 10);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiAsPort=%d\n", pInfo->wapi_as_port));
|
|
}
|
|
|
|
/* WapiUskRekeyMethod */
|
|
if (RTMPGetKeyParameter("WapiUskRekeyMethod", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0))
|
|
pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_TIME;
|
|
else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0))
|
|
pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_PKT;
|
|
else
|
|
pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyMethod=%d\n", pAd->CommonCfg.wapi_usk_rekey_method));
|
|
}
|
|
|
|
/* WapiUskRekeyThreshold */
|
|
if (RTMPGetKeyParameter("WapiUskRekeyThreshold", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
pAd->CommonCfg.wapi_usk_rekey_threshold = simple_strtol(tmpbuf, 0, 10);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiUskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_usk_rekey_threshold));
|
|
}
|
|
|
|
/* WapiMskRekeyMethod */
|
|
if (RTMPGetKeyParameter("WapiMskRekeyMethod", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
if ((strcmp(tmpbuf, "TIME") == 0) || (strcmp(tmpbuf, "time") == 0))
|
|
pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_TIME;
|
|
else if ((strcmp(tmpbuf, "PKT") == 0) || (strcmp(tmpbuf, "pkt") == 0))
|
|
pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_PKT;
|
|
else
|
|
pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyMethod=%d\n", pAd->CommonCfg.wapi_msk_rekey_method));
|
|
}
|
|
|
|
/* WapiMskRekeyThreshold */
|
|
if (RTMPGetKeyParameter("WapiMskRekeyThreshold", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
pAd->CommonCfg.wapi_msk_rekey_threshold = simple_strtol(tmpbuf, 0, 10);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiMskRekeyThreshold=%d\n", pAd->CommonCfg.wapi_msk_rekey_threshold));
|
|
}
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
RTMP_STRING tok_str[16];
|
|
|
|
/* WapiPskX */
|
|
for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
|
|
{
|
|
snprintf(tok_str, sizeof(tok_str), "WapiPsk%d", apidx + 1);
|
|
|
|
NdisZeroMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, 64);
|
|
pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = 0;
|
|
if(RTMPGetKeyParameter(tok_str, tmpbuf, 65, buffer, FALSE))
|
|
{
|
|
if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64)
|
|
{
|
|
NdisMoveMemory(pAd->ApCfg.MBSSID[apidx].WAPIPassPhrase, tmpbuf, strlen(tmpbuf));
|
|
pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen = strlen(tmpbuf);
|
|
DBGPRINT(RT_DEBUG_TRACE, ("IF(ra%d) WapiPsk=(%s), len=%d\n", apidx, tmpbuf, strlen(tmpbuf)));
|
|
}
|
|
else
|
|
{
|
|
if (pAd->ApCfg.MBSSID[apidx].wdev.AuthMode == Ndis802_11AuthModeWAIPSK)
|
|
{
|
|
pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen;
|
|
pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled;
|
|
}
|
|
DBGPRINT(RT_DEBUG_ERROR, ("IF(ra%d) The length of WAPI PSKPassPhrase is invalid(len=%d). \n", apidx, strlen(tmpbuf)));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
/* WapiPsk */
|
|
if (RTMPGetKeyParameter("WapiPsk", tmpbuf, 512, buffer, FALSE))
|
|
{
|
|
NdisZeroMemory(pAd->StaCfg.WAPIPassPhrase, 64);
|
|
pAd->StaCfg.WAPIPassPhraseLen = 0;
|
|
if (strlen(tmpbuf) >= 8 && strlen(tmpbuf) <= 64)
|
|
{
|
|
NdisMoveMemory(pAd->StaCfg.WAPIPassPhrase, tmpbuf, strlen(tmpbuf));
|
|
pAd->StaCfg.WAPIPassPhraseLen = strlen(tmpbuf);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiPsk=(%s), len=%d\n", tmpbuf, strlen(tmpbuf)));
|
|
}
|
|
else
|
|
{
|
|
if (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAIPSK)
|
|
{
|
|
pAd->StaCfg.wdev.AuthMode = Ndis802_11AuthModeOpen;
|
|
pAd->StaCfg.wdev.WepStatus = Ndis802_11EncryptionDisabled;
|
|
}
|
|
DBGPRINT(RT_DEBUG_ERROR, ("The length of WAPI PSKPassPhrase is invalid(len=%d). \n", strlen(tmpbuf)));
|
|
}
|
|
}
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
/* WapiPskType */
|
|
if (RTMPGetKeyParameter("WapiPskType", tmpbuf, 32, buffer, TRUE))
|
|
{
|
|
INT err;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
RTMP_STRING *macptr;
|
|
|
|
for (apidx = 0, macptr = rstrtok(tmpbuf,";"); macptr; macptr = rstrtok(NULL,";"), apidx++)
|
|
{
|
|
err = 0;
|
|
|
|
if (apidx >= pAd->ApCfg.BssidNum)
|
|
break;
|
|
|
|
/* HEX */
|
|
if(simple_strtol(macptr, 0, 10) == 0)
|
|
{
|
|
pAd->ApCfg.MBSSID[apidx].WapiPskType = HEX_MODE;
|
|
|
|
if (pAd->ApCfg.MBSSID[apidx].WAPIPassPhraseLen % 2 != 0)
|
|
{
|
|
err = 1;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("I/F(ra%d) The WAPI-PSK key length MUST be even in Hex mode\n", apidx));
|
|
}
|
|
}
|
|
/* ASCII */
|
|
else
|
|
{
|
|
pAd->ApCfg.MBSSID[apidx].WapiPskType = ASCII_MODE;
|
|
}
|
|
|
|
if (err)
|
|
{
|
|
pAd->ApCfg.MBSSID[apidx].wdev.AuthMode = Ndis802_11AuthModeOpen;
|
|
pAd->ApCfg.MBSSID[apidx].wdev.WepStatus = Ndis802_11EncryptionDisabled;
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_TRACE, ("I/F(ra%d) WapiPskType=%s\n", apidx, (pAd->ApCfg.MBSSID[apidx].WapiPskType == HEX_MODE) ? "HEX" : "ASCII"));
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
err = 0;
|
|
|
|
/* HEX */
|
|
if(simple_strtol(tmpbuf, 0, 10) == 0)
|
|
{
|
|
pAd->StaCfg.WapiPskType = HEX_MODE;
|
|
|
|
if (pAd->StaCfg.WAPIPassPhraseLen % 2 != 0)
|
|
{
|
|
err = 1;
|
|
DBGPRINT(RT_DEBUG_ERROR, ("The WAPI-PSK key length MUST be even in Hex mode\n"));
|
|
}
|
|
}
|
|
/* ASCII */
|
|
else
|
|
{
|
|
pAd->StaCfg.WapiPskType = ASCII_MODE;
|
|
}
|
|
|
|
if (err)
|
|
{
|
|
pAd->StaCfg.wdev.AuthMode = Ndis802_11AuthModeOpen;
|
|
pAd->StaCfg.wdev.WepStatus = Ndis802_11EncryptionDisabled;
|
|
}
|
|
else
|
|
DBGPRINT(RT_DEBUG_TRACE, ("WapiPskType=%s\n", (pAd->StaCfg.WapiPskType == HEX_MODE) ? "HEX" : "ASCII"));
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
}
|
|
|
|
/* Sanity check - USK rekey parameter */
|
|
if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_DISABLE ||
|
|
pAd->CommonCfg.wapi_usk_rekey_threshold == 0)
|
|
{
|
|
pAd->CommonCfg.wapi_usk_rekey_method = REKEY_METHOD_DISABLE;
|
|
pAd->CommonCfg.wapi_usk_rekey_threshold = 0;
|
|
}
|
|
|
|
/* Sanity check - MSK rekey parameter */
|
|
if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_DISABLE ||
|
|
pAd->CommonCfg.wapi_msk_rekey_threshold == 0)
|
|
{
|
|
pAd->CommonCfg.wapi_msk_rekey_method = REKEY_METHOD_DISABLE;
|
|
pAd->CommonCfg.wapi_msk_rekey_threshold = 0;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
It only shall be queried by wapi daemon for querying the related
|
|
configuration. This routine process the WAPI configuration for per BSS.
|
|
|
|
==========================================================================
|
|
*/
|
|
static VOID RTMPQueryWapiConfPerBss(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PWAPI_CONF wapi_conf_ptr,
|
|
IN UCHAR apidx)
|
|
{
|
|
PMBSS_WAPI_INFO pConf = &wapi_conf_ptr->mbss_wapi_info[apidx];
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
BSS_STRUCT *pMbss = &pAd->ApCfg.MBSSID[apidx];
|
|
|
|
if (pMbss->wdev.if_dev != NULL)
|
|
{
|
|
PNET_DEV dev = pMbss->wdev.if_dev;
|
|
|
|
NdisMoveMemory(pConf->ifname, RtmpOsGetNetDevName(dev), strlen(RtmpOsGetNetDevName(dev)));
|
|
pConf->ifname_len = strlen(RtmpOsGetNetDevName(dev));
|
|
}
|
|
else
|
|
{
|
|
RTMP_STRING slot_name[IFNAMSIZ];
|
|
|
|
snprintf(slot_name, sizeof(slot_name), "ra%d", apidx);
|
|
NdisMoveMemory(pConf->ifname, slot_name, strlen(slot_name));
|
|
pConf->ifname_len = strlen(slot_name);
|
|
}
|
|
|
|
/* Decide the authentication mode */
|
|
if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAICERT)
|
|
pConf->auth_mode = WAPI_AUTH_CERT;
|
|
else if (pMbss->wdev.AuthMode == Ndis802_11AuthModeWAIPSK)
|
|
pConf->auth_mode = WAPI_AUTH_PSK;
|
|
else
|
|
pConf->auth_mode = WAPI_AUTH_DISABLE;
|
|
|
|
/* Fill in WAI pre-shared key */
|
|
if (pMbss->WAPIPassPhraseLen > 0)
|
|
{
|
|
if (pMbss->WapiPskType == HEX_MODE)
|
|
{
|
|
pConf->psk_len = pMbss->WAPIPassPhraseLen / 2;
|
|
AtoH((RTMP_STRING *) pMbss->WAPIPassPhrase, (PUCHAR) pConf->psk, pConf->psk_len);
|
|
}
|
|
else
|
|
{
|
|
pConf->psk_len = pMbss->WAPIPassPhraseLen;
|
|
NdisMoveMemory(pConf->psk, pMbss->WAPIPassPhrase, pConf->psk_len);
|
|
}
|
|
}
|
|
|
|
/* Fill in WIE */
|
|
if (pMbss->RSNIE_Len[0] > 0)
|
|
{
|
|
pConf->wie_len = pMbss->RSNIE_Len[0] + 2;
|
|
|
|
pConf->wie[0] = IE_WAPI;
|
|
pConf->wie[1] = pMbss->RSNIE_Len[0];
|
|
NdisMoveMemory(&pConf->wie[2], pMbss->RSN_IE[0], pMbss->RSNIE_Len[0]);
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
NdisMoveMemory(pConf->ifname, pAd->StaCfg.dev_name, strlen((RTMP_STRING *) pAd->StaCfg.dev_name));
|
|
pConf->ifname_len = strlen((RTMP_STRING *) pAd->StaCfg.dev_name);
|
|
|
|
/* Decide the authentication mode */
|
|
if (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAICERT)
|
|
pConf->auth_mode = WAPI_AUTH_CERT;
|
|
else if (pAd->StaCfg.wdev.AuthMode == Ndis802_11AuthModeWAIPSK)
|
|
pConf->auth_mode = WAPI_AUTH_PSK;
|
|
else
|
|
pConf->auth_mode = WAPI_AUTH_DISABLE;
|
|
|
|
/* Fill in WAI pre-shared key */
|
|
if (pAd->StaCfg.WAPIPassPhraseLen > 0)
|
|
{
|
|
if (pAd->StaCfg.WapiPskType == HEX_MODE)
|
|
{
|
|
pConf->psk_len = pAd->StaCfg.WAPIPassPhraseLen / 2;
|
|
AtoH((RTMP_STRING *) pAd->StaCfg.WAPIPassPhrase, (PUCHAR) pConf->psk, pConf->psk_len);
|
|
}
|
|
else
|
|
{
|
|
pConf->psk_len = pAd->StaCfg.WAPIPassPhraseLen;
|
|
NdisMoveMemory(pConf->psk, pAd->StaCfg.WAPIPassPhrase, pConf->psk_len);
|
|
}
|
|
}
|
|
|
|
RTMPMakeRSNIE(pAd, pAd->StaCfg.wdev.AuthMode, pAd->StaCfg.wdev.WepStatus, BSS0);
|
|
/* Fill in WIE */
|
|
if (pAd->StaCfg.RSNIE_Len > 0)
|
|
{
|
|
pConf->wie_len = pAd->StaCfg.RSNIE_Len + 2;
|
|
|
|
pConf->wie[0] = IE_WAPI;
|
|
pConf->wie[1] = pAd->StaCfg.RSNIE_Len;
|
|
NdisMoveMemory(&pConf->wie[2], pAd->StaCfg.RSN_IE, pAd->StaCfg.RSNIE_Len);
|
|
}
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
It only shall be queried by wapi daemon for querying the related
|
|
configuration.
|
|
Arguments:
|
|
pAd Pointer to our adapter
|
|
wrq Pointer to the ioctl argument
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPIoctlQueryWapiConf(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN RTMP_IOCTL_INPUT_STRUCT *wrq)
|
|
{
|
|
UCHAR apidx;
|
|
UCHAR *buf = NULL;
|
|
PWAPI_CONF pConf;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("RTMPIoctlQueryWapiConf==>\n"));
|
|
|
|
/* Allocate memory for WAPI configuration */
|
|
os_alloc_mem(NULL, (PUCHAR *)&buf, sizeof(WAPI_CONF));
|
|
|
|
if (buf == NULL)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: allocate memory fail\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
pConf = (PWAPI_CONF)buf;
|
|
|
|
NdisZeroMemory((PUCHAR)pConf, sizeof(WAPI_CONF));
|
|
|
|
/* get MBSS number */
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
pConf->mbss_num = pAd->ApCfg.BssidNum;
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
pConf->mbss_num = 1;
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
/* Set common configuration */
|
|
NdisMoveMemory(&pConf->comm_wapi_info, &pAd->CommonCfg.comm_wapi_info, sizeof(COMMON_WAPI_INFO));
|
|
|
|
for (apidx = 0; apidx < pConf->mbss_num; apidx++)
|
|
{
|
|
RTMPQueryWapiConfPerBss(pAd, pConf, apidx);
|
|
}
|
|
|
|
wrq->u.data.length = sizeof(WAPI_CONF);
|
|
if (copy_to_user(wrq->u.data.pointer, pConf, wrq->u.data.length))
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s: copy_to_user() fail\n", __FUNCTION__));
|
|
}
|
|
|
|
os_free_mem(NULL, buf);
|
|
}
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Timer execution function for periodically updating WAPI key.
|
|
Return:
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPWapiUskRekeyPeriodicExec(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
UINT32 tmp_cnt = 0;
|
|
PMAC_TABLE_ENTRY pEntry = (PMAC_TABLE_ENTRY)FunctionContext;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)pEntry->pAd;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
DBGPRINT(RT_DEBUG_INFO, ("RTMPWapiUskRekeyPeriodicExec ==>> \n"));
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_TIME)
|
|
{
|
|
tmp_cnt = (++pEntry->wapi_usk_rekey_cnt);
|
|
}
|
|
else if (pAd->CommonCfg.wapi_usk_rekey_method == REKEY_METHOD_PKT)
|
|
{
|
|
/* the unit is 1K packets */
|
|
tmp_cnt = pEntry->wapi_usk_rekey_cnt/1000;
|
|
}
|
|
else
|
|
return;
|
|
|
|
/* Trigger rekey procedure */
|
|
if (tmp_cnt > pAd->CommonCfg.wapi_usk_rekey_threshold)
|
|
{
|
|
pEntry->wapi_usk_rekey_cnt = 0;
|
|
WAPI_InternalCmdAction(pAd,
|
|
pEntry->AuthMode,
|
|
pEntry->func_tb_idx,
|
|
pEntry->Addr,
|
|
WAI_MLME_UPDATE_USK);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
==========================================================================
|
|
Description:
|
|
Timer execution function for periodically updating WAPI key.
|
|
Return:
|
|
==========================================================================
|
|
*/
|
|
VOID RTMPWapiMskRekeyPeriodicExec(
|
|
IN PVOID SystemSpecific1,
|
|
IN PVOID FunctionContext,
|
|
IN PVOID SystemSpecific2,
|
|
IN PVOID SystemSpecific3)
|
|
{
|
|
UINT i;
|
|
UINT32 tmp_cnt = 0;
|
|
PRTMP_ADAPTER pAd = (PRTMP_ADAPTER)FunctionContext;
|
|
|
|
#ifdef RELEASE_EXCLUDE
|
|
DBGPRINT(RT_DEBUG_INFO, ("RTMPWapiMskRekeyPeriodicExec ==>> \n"));
|
|
#endif /* RELEASE_EXCLUDE */
|
|
|
|
/* if no any WAPI STA associated, don't do anything. */
|
|
if (pAd->MacTab.fAnyWapiStation == FALSE)
|
|
return;
|
|
|
|
/* increase counter for TIME method */
|
|
if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_TIME)
|
|
{
|
|
tmp_cnt = (++pAd->CommonCfg.wapi_msk_rekey_cnt);
|
|
}
|
|
else if (pAd->CommonCfg.wapi_msk_rekey_method == REKEY_METHOD_PKT)
|
|
{
|
|
/* the unit is 1K packets */
|
|
tmp_cnt = pAd->CommonCfg.wapi_msk_rekey_cnt/1000;
|
|
}
|
|
else
|
|
return;
|
|
|
|
if (tmp_cnt > pAd->CommonCfg.wapi_msk_rekey_threshold)
|
|
{
|
|
pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
|
|
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
INT apidx = 0;
|
|
UINT cnt;
|
|
|
|
for (apidx = 0; apidx < pAd->ApCfg.BssidNum; apidx++)
|
|
{
|
|
UINT m_wcid;
|
|
|
|
pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId = pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId == 0 ? 1 : 0;
|
|
inc_iv_byte(pAd->ApCfg.MBSSID[apidx].key_announce_flag, LEN_WAPI_TSC, 1);
|
|
|
|
/* Generate NMK randomly */
|
|
for (cnt = 0; cnt < 16; cnt++)
|
|
pAd->ApCfg.MBSSID[apidx].NMK[cnt] = RandomByte(pAd);
|
|
|
|
RTMPDeriveWapiGTK(pAd->ApCfg.MBSSID[apidx].NMK, pAd->ApCfg.MBSSID[apidx].GTK);
|
|
|
|
GET_GroupKey_WCID(pAd, m_wcid, apidx);
|
|
/* Install Shared key */
|
|
WAPIInstallSharedKey(pAd,
|
|
pAd->ApCfg.MBSSID[apidx].wdev.GroupKeyWepStatus,
|
|
apidx,
|
|
pAd->ApCfg.MBSSID[apidx].wdev.DefaultKeyId,
|
|
m_wcid,
|
|
pAd->ApCfg.MBSSID[apidx].GTK);
|
|
}
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
/* Todo for Adhoc mode */
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
|
|
for (i = 0; i < MAX_LEN_OF_MAC_TABLE; i++)
|
|
{
|
|
MAC_TABLE_ENTRY *pEntry;
|
|
STA_TR_ENTRY *tr_entry = NULL;
|
|
|
|
pEntry = &pAd->MacTab.Content[i];
|
|
tr_entry = &pAd->MacTab.tr_entry[i];
|
|
if (IS_ENTRY_CLIENT(pEntry) &&
|
|
(pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled) &&
|
|
(tr_entry->PortSecured == WPA_802_1X_PORT_SECURED))
|
|
{
|
|
WAPI_InternalCmdAction(pAd,
|
|
pEntry->AuthMode,
|
|
pEntry->func_tb_idx,
|
|
pEntry->Addr,
|
|
WAI_MLME_UPDATE_MSK);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID RTMPInitWapiRekeyTimerAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMAC_TABLE_ENTRY pEntry)
|
|
{
|
|
if (pEntry)
|
|
{
|
|
DBGPRINT(RT_DEBUG_TRACE, (" RTMPInitWapiRekeyTimerAction : WAPI USK rekey timer (wcid-%d) \n", pEntry->wcid));
|
|
RTMPInitTimer(pAd, &pEntry->WapiUskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiUskRekeyPeriodicExec), pEntry, TRUE);
|
|
pEntry->WapiUskRekeyTimerRunning = FALSE;
|
|
}
|
|
else
|
|
{
|
|
RTMPInitTimer(pAd, &pAd->CommonCfg.WapiMskRekeyTimer, GET_TIMER_FUNCTION(RTMPWapiMskRekeyPeriodicExec), pAd, TRUE);
|
|
pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE;
|
|
}
|
|
}
|
|
|
|
VOID RTMPStartWapiRekeyTimerAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMAC_TABLE_ENTRY pEntry)
|
|
{
|
|
if (pEntry)
|
|
{
|
|
if ((pAd->CommonCfg.wapi_usk_rekey_method != REKEY_METHOD_DISABLE) &&
|
|
(pAd->CommonCfg.wapi_usk_rekey_threshold > 0))
|
|
{
|
|
/* Regularly check the timer */
|
|
if (pEntry->WapiUskRekeyTimerRunning == FALSE)
|
|
{
|
|
RTMPSetTimer(&pEntry->WapiUskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV);
|
|
|
|
pEntry->WapiUskRekeyTimerRunning = TRUE;
|
|
pEntry->wapi_usk_rekey_cnt = 0;
|
|
DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI USK rekey timer is started (%d) \n", pAd->CommonCfg.wapi_usk_rekey_threshold));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((pAd->CommonCfg.wapi_msk_rekey_method != REKEY_METHOD_DISABLE) &&
|
|
(pAd->CommonCfg.wapi_msk_rekey_threshold > 0))
|
|
{
|
|
/* Regularly check the timer */
|
|
if (pAd->CommonCfg.WapiMskRekeyTimerRunning == FALSE)
|
|
{
|
|
RTMPSetTimer(&pAd->CommonCfg.WapiMskRekeyTimer, WAPI_KEY_UPDATE_EXEC_INTV);
|
|
|
|
pAd->CommonCfg.WapiMskRekeyTimerRunning = TRUE;
|
|
pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
|
|
DBGPRINT(RT_DEBUG_TRACE, (" RTMPStartWapiRekeyTimerAction : WAPI MSK rekey timer is started \n"));
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
VOID RTMPCancelWapiRekeyTimerAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN PMAC_TABLE_ENTRY pEntry)
|
|
{
|
|
if(pEntry)
|
|
{
|
|
if (pEntry->WapiUskRekeyTimerRunning == TRUE)
|
|
{
|
|
BOOLEAN Cancelled;
|
|
|
|
RTMPCancelTimer(&pEntry->WapiUskRekeyTimer, &Cancelled);
|
|
pEntry->wapi_usk_rekey_cnt = 0;
|
|
pEntry->WapiUskRekeyTimerRunning = FALSE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (pAd->CommonCfg.WapiMskRekeyTimerRunning == TRUE)
|
|
{
|
|
BOOLEAN Cancelled;
|
|
|
|
RTMPCancelTimer(&pAd->CommonCfg.WapiMskRekeyTimer, &Cancelled);
|
|
pAd->CommonCfg.wapi_msk_rekey_cnt = 0;
|
|
pAd->CommonCfg.WapiMskRekeyTimerRunning = FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
========================================================================
|
|
|
|
Routine Description:
|
|
Prepare a L2 frame to wapi daemon to trigger WAPI state machine
|
|
|
|
Arguments:
|
|
pAd - pointer to our pAdapter context
|
|
|
|
Return Value:
|
|
|
|
Note:
|
|
|
|
========================================================================
|
|
*/
|
|
BOOLEAN WAPI_InternalCmdAction(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UCHAR AuthMode,
|
|
IN UCHAR apidx,
|
|
IN PUCHAR pAddr,
|
|
IN UCHAR flag)
|
|
{
|
|
// TODO: shiang-usw, fix me for pEntry->apidx to func_tb_idx
|
|
if ((AuthMode == Ndis802_11AuthModeWAICERT) ||
|
|
(AuthMode == Ndis802_11AuthModeWAIPSK))
|
|
{
|
|
UCHAR WAPI_IE[] = {0x88, 0xb4};
|
|
UINT8 frame_len = LENGTH_802_3 + 12; /* 12 indicates the WAPI internal command length */
|
|
UCHAR FrameBuf[frame_len];
|
|
UINT8 offset = 0;
|
|
|
|
/* Init the frame buffer */
|
|
NdisZeroMemory(FrameBuf, frame_len);
|
|
|
|
/* Prepare the 802.3 header */
|
|
#ifdef CONFIG_AP_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_AP(pAd)
|
|
{
|
|
MAKE_802_3_HEADER(FrameBuf, pAd->ApCfg.MBSSID[apidx].wdev.bssid, pAddr, WAPI_IE);
|
|
}
|
|
#endif /* CONFIG_AP_SUPPORT */
|
|
#ifdef CONFIG_STA_SUPPORT
|
|
IF_DEV_CONFIG_OPMODE_ON_STA(pAd)
|
|
{
|
|
MAKE_802_3_HEADER(FrameBuf, pAd->CurrentAddress, pAddr, WAPI_IE);
|
|
}
|
|
#endif /* CONFIG_STA_SUPPORT */
|
|
offset += LENGTH_802_3;
|
|
|
|
/* Prepare the specific WAPI header */
|
|
NdisMoveMemory(&FrameBuf[offset], RALINK_OUI, 3);
|
|
offset += 3;
|
|
|
|
/* Set the state of this command */
|
|
FrameBuf[offset] = flag;
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("Trigger WAPI for this sta(%02x:%02x:%02x:%02x:%02x:%02x)\n", PRINT_MAC(pAddr)));
|
|
|
|
/* Report to upper layer */
|
|
if (RTMP_L2_FRAME_TX_ACTION(pAd, apidx, FrameBuf, frame_len) == FALSE)
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID RTMPGetWapiTxTscFromAsic(
|
|
IN PRTMP_ADAPTER pAd,
|
|
IN UINT Wcid,
|
|
OUT UCHAR *tx_tsc)
|
|
{
|
|
USHORT offset;
|
|
int i;
|
|
|
|
if (IS_HW_WAPI_SUPPORT(pAd))
|
|
{
|
|
UINT32 iveiv_tb_base = 0, iveiv_tb_size = 0;
|
|
UINT32 wapi_pn_base = 0, wapi_pn_size = 0;
|
|
|
|
#ifdef RLT_MAC
|
|
if (pAd->chipCap.hif_type == HIF_RLT) {
|
|
iveiv_tb_base = RLT_MAC_IVEIV_TABLE_BASE;
|
|
iveiv_tb_size = RLT_HW_IVEIV_ENTRY_SIZE;
|
|
wapi_pn_base = RLT_WAPI_PN_TABLE_BASE;
|
|
wapi_pn_size = RLT_WAPI_PN_ENTRY_SIZE;
|
|
}
|
|
#endif /* RLT_MAC */
|
|
|
|
#ifdef RTMP_MAC
|
|
if (pAd->chipCap.hif_type == HIF_RTMP) {
|
|
iveiv_tb_base = MAC_IVEIV_TABLE_BASE;
|
|
iveiv_tb_size = HW_IVEIV_ENTRY_SIZE;
|
|
wapi_pn_base = WAPI_PN_TABLE_BASE;
|
|
wapi_pn_size = WAPI_PN_ENTRY_SIZE;
|
|
}
|
|
#endif /* RTMP_MAC */
|
|
|
|
NdisZeroMemory(tx_tsc, LEN_WAPI_TSC);
|
|
|
|
/* Read IVEIV from Asic */
|
|
offset = iveiv_tb_base + (Wcid * iveiv_tb_size);
|
|
for (i=0 ; i < iveiv_tb_size; i++)
|
|
RTMP_IO_READ8(pAd, offset+i, &tx_tsc[i]);
|
|
|
|
/* Read WAPI PM from Asic */
|
|
offset = wapi_pn_base + (Wcid * wapi_pn_size);
|
|
for (i=0 ; i < wapi_pn_size; i++)
|
|
RTMP_IO_READ8(pAd, offset+i, &tx_tsc[iveiv_tb_size + i]);
|
|
|
|
DBGPRINT(RT_DEBUG_TRACE, ("%s : WCID(%d) offset(%u)", __FUNCTION__, Wcid,offset));
|
|
hex_dump("TxTsc", tx_tsc, LEN_WAPI_TSC);
|
|
}
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_WARN, ("%s : Not support HW_WAPI_PN_TABLE\n",
|
|
__FUNCTION__));
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID WAPIInstallPairwiseKey(
|
|
PRTMP_ADAPTER pAd,
|
|
PMAC_TABLE_ENTRY pEntry,
|
|
BOOLEAN bAE)
|
|
{
|
|
PCIPHER_KEY pKey;
|
|
|
|
pKey = &pEntry->PairwiseKey;
|
|
NdisZeroMemory(pKey, sizeof(CIPHER_KEY));
|
|
|
|
/* Assign the pairwise cipher algorithm */
|
|
if (pEntry->WepStatus == Ndis802_11EncryptionSMS4Enabled)
|
|
pKey->CipherAlg = CIPHER_SMS4;
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (wcid-%d)\n",
|
|
__FUNCTION__, pEntry->wcid));
|
|
return;
|
|
}
|
|
|
|
/* Prepare pair-wise key material */
|
|
pKey->KeyLen = LEN_TK;
|
|
NdisMoveMemory(pKey->Key, &pEntry->PTK[0], 16);
|
|
NdisMoveMemory(pKey->TxMic, &pEntry->PTK[16], 8);
|
|
NdisMoveMemory(pKey->RxMic, &pEntry->PTK[24], 8);
|
|
|
|
/* Initial TSC for unicast */
|
|
if (bAE)
|
|
NdisMoveMemory(pKey->TxTsc, AE_UCAST_PN, LEN_WAPI_TSC);
|
|
else
|
|
NdisMoveMemory(pKey->TxTsc, ASUE_UCAST_PN, LEN_WAPI_TSC);
|
|
NdisZeroMemory(pKey->RxTsc, LEN_WAPI_TSC);
|
|
|
|
/* HW_WAPI is supported in RT3883 or later */
|
|
if (IS_HW_WAPI_SUPPORT(pAd))
|
|
{
|
|
UINT32 CONST_WAPI_PN = 0x5C365C36;
|
|
|
|
/* Set unicast packet's PN to Asic. */
|
|
if (bAE)
|
|
AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN + 1, CONST_WAPI_PN);
|
|
else
|
|
AsicUpdateWCIDIVEIV(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN);
|
|
AsicUpdateWAPIPN(pAd, pEntry->wcid, CONST_WAPI_PN, CONST_WAPI_PN);
|
|
|
|
/* Add Pair-wise key to Asic */
|
|
AsicAddPairwiseKeyEntry(
|
|
pAd,
|
|
(UCHAR)pEntry->wcid,
|
|
&pEntry->PairwiseKey);
|
|
|
|
/* update WCID attribute table and IVEIV table for this entry */
|
|
AsicUpdateWcidAttributeEntry(
|
|
pAd,
|
|
pEntry->func_tb_idx,
|
|
pEntry->usk_id,
|
|
pEntry->PairwiseKey.CipherAlg,
|
|
(UCHAR)pEntry->wcid,
|
|
PAIRWISEKEYTABLE);
|
|
|
|
#ifdef MT_MAC
|
|
if (pAd->chipCap.hif_type == HIF_MT)
|
|
CmdProcAddRemoveKey(pAd, 0, pEntry->func_tb_idx, 0, pEntry->wcid, PAIRWISEKEYTABLE, &pEntry->PairwiseKey, pEntry->Addr);
|
|
#endif /* MT_MAC */
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID WAPIInstallSharedKey(
|
|
PRTMP_ADAPTER pAd,
|
|
UINT8 GroupCipher,
|
|
UINT8 BssIdx,
|
|
UINT8 KeyIdx,
|
|
UINT8 Wcid,
|
|
PUINT8 pGtk)
|
|
{
|
|
UINT32 CONST_WAPI_PN = 0x5C365C36;
|
|
PCIPHER_KEY pSharedKey;
|
|
|
|
if (BssIdx >= MAX_MBSSID_NUM(pAd) + MAX_P2P_NUM)
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : The BSS-index(%d) is out of range for MBSSID link. \n",
|
|
__FUNCTION__, BssIdx));
|
|
return;
|
|
}
|
|
|
|
pSharedKey = &pAd->SharedKey[BssIdx][KeyIdx];
|
|
NdisZeroMemory(pSharedKey, sizeof(CIPHER_KEY));
|
|
|
|
if (GroupCipher == Ndis802_11EncryptionSMS4Enabled)
|
|
pSharedKey->CipherAlg = CIPHER_SMS4;
|
|
else
|
|
{
|
|
DBGPRINT(RT_DEBUG_ERROR, ("%s : fails (IF/ra%d) \n",
|
|
__FUNCTION__, BssIdx));
|
|
return;
|
|
}
|
|
|
|
/* Assign key material into SW key table */
|
|
pSharedKey->KeyLen = LEN_TK;
|
|
NdisMoveMemory(pSharedKey->Key, pGtk, LEN_TK);
|
|
NdisMoveMemory(pSharedKey->TxMic, pGtk + 16, LEN_TKIP_MIC);
|
|
NdisMoveMemory(pSharedKey->RxMic, pGtk + 24, LEN_TKIP_MIC);
|
|
|
|
/* Initial TSC for B/Mcast */
|
|
NdisMoveMemory(pSharedKey->TxTsc, AE_BCAST_PN, LEN_WAPI_TSC);
|
|
NdisZeroMemory(pSharedKey->RxTsc, LEN_WAPI_TSC);
|
|
|
|
/* HW_WAPI is supported in RT3883 or later */
|
|
if (IS_HW_WAPI_SUPPORT(pAd))
|
|
{
|
|
/* Install Group Key to MAC ASIC */
|
|
AsicAddSharedKeyEntry(
|
|
pAd,
|
|
BssIdx,
|
|
KeyIdx,
|
|
pSharedKey);
|
|
|
|
/* When Wcid isn't zero, it means that this is a Authenticator Role.
|
|
Only Authenticator entity needs to set HW IE/EIV table (0x6000),
|
|
WAPI PN table (0x7800)
|
|
and WCID attribute table (0x6800) for group key. */
|
|
if (Wcid != 0)
|
|
{
|
|
/* Set 16-bytes PN to Asic. */
|
|
AsicUpdateWCIDIVEIV(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN);
|
|
AsicUpdateWAPIPN(pAd, Wcid, CONST_WAPI_PN, CONST_WAPI_PN);
|
|
|
|
/* update Group key information to ASIC */
|
|
AsicUpdateWcidAttributeEntry(
|
|
pAd,
|
|
BssIdx,
|
|
KeyIdx,
|
|
pSharedKey->CipherAlg,
|
|
Wcid,
|
|
SHAREDKEYTABLE);
|
|
}
|
|
|
|
#ifdef MT_MAC
|
|
if (pAd->chipCap.hif_type == HIF_MT)
|
|
CmdProcAddRemoveKey(pAd, 0, BssIdx, KeyIdx, Wcid, SHAREDKEYTABLE, pSharedKey, BROADCAST_ADDR);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
#endif /* WAPI_SUPPORT */
|
|
|