summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/rtl8723as/core/rtw_security.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rtl8723as/core/rtw_security.c')
-rwxr-xr-xdrivers/net/wireless/rtl8723as/core/rtw_security.c325
1 files changed, 280 insertions, 45 deletions
diff --git a/drivers/net/wireless/rtl8723as/core/rtw_security.c b/drivers/net/wireless/rtl8723as/core/rtw_security.c
index 4a3b20a9caed..68dfafb18de5 100755
--- a/drivers/net/wireless/rtl8723as/core/rtw_security.c
+++ b/drivers/net/wireless/rtl8723as/core/rtw_security.c
@@ -212,7 +212,7 @@ _func_enter_;
length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
- *((unsigned long *)crc)=cpu_to_le32(getcrc32(payload,length));
+ *((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));
arcfour_init(&mycontext, wepkey,3+keylength);
arcfour_encrypt(&mycontext, payload, payload, length);
@@ -222,7 +222,7 @@ _func_enter_;
else
{
length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
- *((unsigned long *)crc)=cpu_to_le32(getcrc32(payload,length));
+ *((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));
arcfour_init(&mycontext, wepkey,3+keylength);
arcfour_encrypt(&mycontext, payload, payload, length);
arcfour_encrypt(&mycontext, payload+length, crc, 4);
@@ -275,7 +275,7 @@ _func_enter_;
arcfour_encrypt(&mycontext, payload, payload, length);
//calculate icv and compare the icv
- *((unsigned long *)crc)=le32_to_cpu(getcrc32(payload,length-4));
+ *((u32 *)crc)=le32_to_cpu(getcrc32(payload,length-4));
if(crc[3]!=payload[length-1] || crc[2]!=payload[length-2] || crc[1]!=payload[length-3] || crc[0]!=payload[length-4])
{
@@ -801,12 +801,42 @@ _func_enter_;
if(IS_MCAST(prxattrib->ra))
{
+ static u32 start = 0;
+ static u32 no_gkey_bc_cnt = 0;
+ static u32 no_gkey_mc_cnt = 0;
+
if(psecuritypriv->binstallGrpkey==_FALSE)
{
- res=_FAIL;
- DBG_8192C("%s:rx bc/mc packets,but didn't install group key!!!!!!!!!!\n",__FUNCTION__);
+ res=_FAIL;
+
+ if (start == 0)
+ start = rtw_get_current_time();
+
+ if (is_broadcast_mac_addr(prxattrib->ra))
+ no_gkey_bc_cnt++;
+ else
+ no_gkey_mc_cnt++;
+
+ if (rtw_get_passing_time_ms(start) > 1000) {
+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+ }
+ start = rtw_get_current_time();
+ no_gkey_bc_cnt = 0;
+ no_gkey_mc_cnt = 0;
+ }
goto exit;
}
+
+ if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+ DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+ FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+ }
+ start = 0;
+ no_gkey_bc_cnt = 0;
+ no_gkey_mc_cnt = 0;
+
//DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n");
//prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
@@ -916,11 +946,13 @@ static void construct_mic_iv(
sint a4_exists,
u8 *mpdu,
uint payload_length,
- u8 * pn_vector);
+ u8 * pn_vector,
+ uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
static void construct_mic_header1(
u8 *mic_header1,
sint header_length,
- u8 *mpdu);
+ u8 *mpdu,
+ uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
static void construct_mic_header2(
u8 *mic_header2,
u8 *mpdu,
@@ -932,7 +964,8 @@ static void construct_ctr_preload(
sint qc_exists,
u8 *mpdu,
u8 *pn_vector,
- sint c);
+ sint c,
+ uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
static void xor_128(u8 *a, u8 *b, u8 *out);
static void xor_32(u8 *a, u8 *b, u8 *out);
static u8 sbox(u8 a);
@@ -1152,6 +1185,8 @@ _func_exit_;
/************************************************/
/* construct_mic_iv() */
/* Builds the MIC IV from header fields and PN */
+/* Baron think the function is construct CCM */
+/* nonce */
/************************************************/
static void construct_mic_iv(
u8 *mic_iv,
@@ -1159,7 +1194,8 @@ static void construct_mic_iv(
sint a4_exists,
u8 *mpdu,
uint payload_length,
- u8 *pn_vector
+ u8 *pn_vector,
+ uint frtype// add for CONFIG_IEEE80211W, none 11w also can use
)
{
sint i;
@@ -1168,6 +1204,11 @@ _func_enter_;
if (qc_exists && a4_exists) mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
if (qc_exists && !a4_exists) mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
if (!qc_exists) mic_iv[1] = 0x00;
+#ifdef CONFIG_IEEE80211W
+ //802.11w management frame should set management bit(4)
+ if(frtype == WIFI_MGT_TYPE)
+ mic_iv[1] |= BIT(4);
+#endif //CONFIG_IEEE80211W
for (i = 2; i < 8; i++)
mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
#ifdef CONSISTENT_PN_ORDER
@@ -1187,17 +1228,26 @@ _func_exit_;
/* construct_mic_header1() */
/* Builds the first MIC header block from */
/* header fields. */
+/* Build AAD SC,A1,A2 */
/************************************************/
static void construct_mic_header1(
u8 *mic_header1,
sint header_length,
- u8 *mpdu
+ u8 *mpdu,
+ uint frtype// add for CONFIG_IEEE80211W, none 11w also can use
)
{
_func_enter_;
mic_header1[0] = (u8)((header_length - 2) / 256);
mic_header1[1] = (u8)((header_length - 2) % 256);
- mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+#ifdef CONFIG_IEEE80211W
+ //802.11w management frame don't AND subtype bits 4,5,6 of frame control field
+ if(frtype == WIFI_MGT_TYPE)
+ mic_header1[2] = mpdu[0]; /* Mute CF poll & CF ack bits */
+ else
+#endif //CONFIG_IEEE80211W
+ mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
+
mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */
mic_header1[4] = mpdu[4]; /* A1 */
mic_header1[5] = mpdu[5];
@@ -1271,6 +1321,8 @@ _func_exit_;
/* construct_mic_header2() */
/* Builds the last MIC header block from */
/* header fields. */
+/* Baron think the function is construct CCM */
+/* nonce */
/************************************************/
static void construct_ctr_preload(
u8 *ctr_preload,
@@ -1278,20 +1330,25 @@ static void construct_ctr_preload(
sint qc_exists,
u8 *mpdu,
u8 *pn_vector,
- sint c
+ sint c,
+ uint frtype // add for CONFIG_IEEE80211W, none 11w also can use
)
{
sint i = 0;
_func_enter_;
for (i=0; i<16; i++) ctr_preload[i] = 0x00;
i = 0;
-
+
ctr_preload[0] = 0x01; /* flag */
if (qc_exists && a4_exists)
ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */
if (qc_exists && !a4_exists)
ctr_preload[1] = mpdu[24] & 0x0f;
-
+#ifdef CONFIG_IEEE80211W
+ //802.11w management frame should set management bit(4)
+ if(frtype == WIFI_MGT_TYPE)
+ ctr_preload[1] |= BIT(4);
+#endif //CONFIG_IEEE80211W
for (i = 2; i < 8; i++)
ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
#ifdef CONSISTENT_PN_ORDER
@@ -1363,9 +1420,9 @@ _func_enter_;
a4_exists = 1;
if (
- (frtype == WIFI_DATA_CFACK) ||
- (frtype == WIFI_DATA_CFPOLL)||
- (frtype == WIFI_DATA_CFACKPOLL))
+ ((frtype|frsubtype) == WIFI_DATA_CFACK) ||
+ ((frtype|frsubtype) == WIFI_DATA_CFPOLL)||
+ ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL))
{
qc_exists = 1;
if(hdrlen != WLAN_HDR_A3_QOS_LEN){
@@ -1373,11 +1430,12 @@ _func_enter_;
hdrlen += 2;
}
}
- else if (
- (frsubtype == 0x08) ||
+ // add for CONFIG_IEEE80211W, none 11w also can use
+ else if ((frtype == WIFI_DATA) &&
+ ((frsubtype == 0x08) ||
(frsubtype == 0x09)||
(frsubtype == 0x0a)||
- (frsubtype == 0x0b))
+ (frsubtype == 0x0b)))
{
if(hdrlen != WLAN_HDR_A3_QOS_LEN){
@@ -1401,13 +1459,15 @@ _func_enter_;
a4_exists,
pframe, //message,
plen,
- pn_vector
+ pn_vector,
+ frtype // add for CONFIG_IEEE80211W, none 11w also can use
);
construct_mic_header1(
mic_header1,
hdrlen,
- pframe //message
+ pframe, //message
+ frtype // add for CONFIG_IEEE80211W, none 11w also can use
);
construct_mic_header2(
mic_header2,
@@ -1466,7 +1526,8 @@ _func_enter_;
qc_exists,
pframe, //message,
pn_vector,
- i+1);
+ i+1,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);//bitwise_xor(aes_out, &message[payload_index], chain_buffer);
for (j=0; j<16;j++) pframe[payload_index++] = chain_buffer[j];//for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j];
@@ -1480,7 +1541,8 @@ _func_enter_;
qc_exists,
pframe, //message,
pn_vector,
- num_blocks+1);
+ num_blocks+1,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
@@ -1499,7 +1561,8 @@ _func_enter_;
qc_exists,
pframe, //message,
pn_vector,
- 0);
+ 0,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
for (j = 0; j < 8; j++)
@@ -1566,7 +1629,7 @@ _func_enter_;
{
DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] );
- }
+ }
if (stainfo!=NULL){
@@ -1671,7 +1734,7 @@ _func_enter_;
//start to decrypt the payload
- num_blocks = (plen-8) / 16; //(plen including llc, payload_length and mic )
+ num_blocks = (plen-8) / 16; //(plen including LLC, payload_length and mic )
payload_remainder = (plen-8) % 16;
@@ -1688,21 +1751,21 @@ _func_enter_;
a4_exists = 1;
if (
- (frtype == WIFI_DATA_CFACK) ||
- (frtype == WIFI_DATA_CFPOLL)||
- (frtype == WIFI_DATA_CFACKPOLL))
+ ((frtype|frsubtype) == WIFI_DATA_CFACK) ||
+ ((frtype|frsubtype) == WIFI_DATA_CFPOLL)||
+ ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL))
{
qc_exists = 1;
if(hdrlen != WLAN_HDR_A3_QOS_LEN){
hdrlen += 2;
}
- }
- else if (
- (frsubtype == 0x08) ||
+ }//only for data packet . add for CONFIG_IEEE80211W, none 11w also can use
+ else if ((frtype == WIFI_DATA) &&
+ ((frsubtype == 0x08) ||
(frsubtype == 0x09)||
(frsubtype == 0x0a)||
- (frsubtype == 0x0b))
+ (frsubtype == 0x0b)))
{
if(hdrlen != WLAN_HDR_A3_QOS_LEN){
@@ -1726,7 +1789,8 @@ _func_enter_;
qc_exists,
pframe,
pn_vector,
- i+1
+ i+1,
+ frtype
);
aes128k128d(key, ctr_preload, aes_out);
@@ -1743,7 +1807,8 @@ _func_enter_;
qc_exists,
pframe,
pn_vector,
- num_blocks+1
+ num_blocks+1,
+ frtype // add for CONFIG_IEEE80211W, none 11w also can use
);
for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
@@ -1776,13 +1841,15 @@ _func_enter_;
a4_exists,
message,
plen-8,
- pn_vector
+ pn_vector,
+ frtype // add for CONFIG_IEEE80211W, none 11w also can use
);
construct_mic_header1(
mic_header1,
hdrlen,
- message
+ message,
+ frtype // add for CONFIG_IEEE80211W, none 11w also can use
);
construct_mic_header2(
mic_header2,
@@ -1841,7 +1908,8 @@ _func_enter_;
qc_exists,
message,
pn_vector,
- i+1);
+ i+1,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
aes128k128d(key, ctr_preload, aes_out);
bitwise_xor(aes_out, &message[payload_index], chain_buffer);
for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j];
@@ -1855,7 +1923,8 @@ _func_enter_;
qc_exists,
message,
pn_vector,
- num_blocks+1);
+ num_blocks+1,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
for (j = 0; j < payload_remainder; j++)
@@ -1874,7 +1943,8 @@ _func_enter_;
qc_exists,
message,
pn_vector,
- 0);
+ 0,
+ frtype); // add for CONFIG_IEEE80211W, none 11w also can use
for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
for (j = 0; j < 8; j++)
@@ -1952,9 +2022,31 @@ _func_enter_;
{
prwskey=&stainfo->dot118021x_UncstKey.skey[0];
}
-
+
length= ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
-
+ /*// add for CONFIG_IEEE80211W, debug
+ if(0)
+ printk("@@@@@@@@@@@@@@@@@@ length=%d, prxattrib->hdrlen=%d, prxattrib->pkt_len=%d \n"
+ , length, prxattrib->hdrlen, prxattrib->pkt_len);
+ if(0)
+ {
+ int no;
+ //test print PSK
+ printk("PSK key below:\n");
+ for(no=0;no<16;no++)
+ printk(" %02x ", prwskey[no]);
+ printk("\n");
+ }
+ if(0)
+ {
+ int no;
+ //test print PSK
+ printk("frame:\n");
+ for(no=0;no<prxattrib->pkt_len;no++)
+ printk(" %02x ", pframe[no]);
+ printk("\n");
+ }*/
+
res= aes_decipher(prwskey,prxattrib->hdrlen,pframe, length);
@@ -1969,6 +2061,109 @@ _func_exit_;
exit:
return res;
}
+
+#ifdef CONFIG_IEEE80211W
+u32 rtw_BIP_verify(_adapter *padapter, u8 *precvframe)
+{
+ struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+ u8 *pframe;
+ u8 *BIP_AAD, *p;
+ u32 res=_FAIL;
+ uint len, ori_len;
+ struct rtw_ieee80211_hdr *pwlanhdr;
+ u8 mic[16];
+ struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+ ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
+ BIP_AAD = rtw_zmalloc(ori_len);
+
+ if(BIP_AAD == NULL)
+ {
+ DBG_871X("BIP AAD allocate fail\n");
+ return _FAIL;
+ }
+ //PKT start
+ pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+ //mapping to wlan header
+ pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+ //save the frame body + MME
+ _rtw_memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN);
+ //find MME IE pointer
+ p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN);
+ //Baron
+ if(p)
+ {
+ u16 keyid=0;
+ u64 temp_ipn=0;
+ //save packet number
+ _rtw_memcpy(&temp_ipn, p+4, 6);
+ temp_ipn = le64_to_cpu(temp_ipn);
+ //BIP packet number should bigger than previous BIP packet
+ if(temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx)
+ {
+ DBG_871X("replay BIP packet\n");
+ goto BIP_exit;
+ }
+ //copy key index
+ _rtw_memcpy(&keyid, p+2, 2);
+ keyid = le16_to_cpu(keyid);
+ if(keyid != padapter->securitypriv.dot11wBIPKeyid)
+ {
+ DBG_871X("BIP key index error!\n");
+ goto BIP_exit;
+ }
+ //clear the MIC field of MME to zero
+ _rtw_memset(p+2+len-8, 0, 8);
+
+ //conscruct AAD, copy frame control field
+ _rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2);
+ ClearRetry(BIP_AAD);
+ ClearPwrMgt(BIP_AAD);
+ ClearMData(BIP_AAD);
+ //conscruct AAD, copy address 1 to address 3
+ _rtw_memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
+
+ if(omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
+ , BIP_AAD, ori_len, mic))
+ goto BIP_exit;
+
+ /*//management packet content
+ {
+ int pp;
+ DBG_871X("pkt: ");
+ for(pp=0;pp< pattrib->pkt_len; pp++)
+ printk(" %02x ", pframe[pp]);
+ DBG_871X("\n");
+ //BIP AAD + management frame body + MME(MIC is zero)
+ DBG_871X("AAD+PKT: ");
+ for(pp=0;pp< ori_len; pp++)
+ DBG_871X(" %02x ", BIP_AAD[pp]);
+ DBG_871X("\n");
+ //show the MIC result
+ DBG_871X("mic: ");
+ for(pp=0;pp<16; pp++)
+ DBG_871X(" %02x ", mic[pp]);
+ DBG_871X("\n");
+ }
+ */
+ //MIC field should be last 8 bytes of packet (packet without FCS)
+ if(_rtw_memcmp(mic, pframe+pattrib->pkt_len-8, 8))
+ {
+ pmlmeext->mgnt_80211w_IPN_rx = temp_ipn;
+ res=_SUCCESS;
+ }
+ else
+ DBG_871X("BIP MIC error!\n");
+
+ }
+ else
+ res = RTW_RX_HANDLED;
+BIP_exit:
+
+ rtw_mfree(BIP_AAD, ori_len);
+ return res;
+}
+#endif //CONFIG_IEEE80211W
+
#ifndef PLATFORM_FREEBSD
/* compress 512-bits */
static int sha256_compress(struct sha256_state *md, unsigned char *buf)
@@ -2676,8 +2871,8 @@ static int omac1_aes_128_vector(u8 *key, size_t num_elem,
* This is a mode for using block cipher (AES in this case) for authentication.
* OMAC1 was standardized with the name CMAC by NIST in a Special Publication
* (SP) 800-38B.
- */
-static int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
+ */ //modify for CONFIG_IEEE80211W
+int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
{
return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
}
@@ -2891,3 +3086,43 @@ _func_exit_;
}
+/* Restore HW wep key setting according to key_mask */
+void rtw_sec_restore_wep_key(_adapter *adapter)
+{
+ struct security_priv* securitypriv=&(adapter->securitypriv);
+ sint keyid;
+
+ if((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) {
+ for(keyid=0;keyid<4;keyid++){
+ if(securitypriv->key_mask & BIT(keyid)){
+ if(keyid == securitypriv->dot11PrivacyKeyIndex)
+ rtw_set_key(adapter,securitypriv, keyid, 1, _TRUE);
+ else
+ rtw_set_key(adapter,securitypriv, keyid, 0, _TRUE);
+ }
+ }
+ }
+}
+
+u8 rtw_handle_tkip_countermeasure(_adapter* adapter, const char *caller)
+{
+ struct security_priv* securitypriv=&(adapter->securitypriv);
+ u8 status = _SUCCESS;
+
+ if (securitypriv->btkip_countermeasure == _TRUE) {
+ u32 passing_ms = rtw_get_passing_time_ms(securitypriv->btkip_countermeasure_time);
+ if (passing_ms > 60*1000) {
+ DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds > 60s \n",
+ caller, ADPT_ARG(adapter), passing_ms/1000);
+ securitypriv->btkip_countermeasure = _FALSE;
+ securitypriv->btkip_countermeasure_time = 0;
+ } else {
+ DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds < 60s \n",
+ caller, ADPT_ARG(adapter), passing_ms/1000);
+ status = _FAIL;
+ }
+ }
+
+ return status;
+}
+