158391efdSNathan Chancellor // SPDX-License-Identifier: GPL-2.0 2554c0a3aSHans de Goede /****************************************************************************** 3554c0a3aSHans de Goede * 4554c0a3aSHans de Goede * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. 5554c0a3aSHans de Goede * 6554c0a3aSHans de Goede ******************************************************************************/ 7554c0a3aSHans de Goede #define _RTW_SECURITY_C_ 8554c0a3aSHans de Goede 9554c0a3aSHans de Goede #include <drv_types.h> 10554c0a3aSHans de Goede #include <rtw_debug.h> 11554c0a3aSHans de Goede 12554c0a3aSHans de Goede static const char *_security_type_str[] = { 13554c0a3aSHans de Goede "N/A", 14554c0a3aSHans de Goede "WEP40", 15554c0a3aSHans de Goede "TKIP", 16554c0a3aSHans de Goede "TKIP_WM", 17554c0a3aSHans de Goede "AES", 18554c0a3aSHans de Goede "WEP104", 19554c0a3aSHans de Goede "SMS4", 20554c0a3aSHans de Goede "WEP_WPA", 21554c0a3aSHans de Goede "BIP", 22554c0a3aSHans de Goede }; 23554c0a3aSHans de Goede 24554c0a3aSHans de Goede const char *security_type_str(u8 value) 25554c0a3aSHans de Goede { 26554c0a3aSHans de Goede if (value <= _BIP_) 27554c0a3aSHans de Goede return _security_type_str[value]; 28554c0a3aSHans de Goede return NULL; 29554c0a3aSHans de Goede } 30554c0a3aSHans de Goede 31554c0a3aSHans de Goede #ifdef DBG_SW_SEC_CNT 32554c0a3aSHans de Goede #define WEP_SW_ENC_CNT_INC(sec, ra) \ 33554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 34554c0a3aSHans de Goede sec->wep_sw_enc_cnt_bc++; \ 35554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 36554c0a3aSHans de Goede sec->wep_sw_enc_cnt_mc++; \ 37554c0a3aSHans de Goede else \ 38554c0a3aSHans de Goede sec->wep_sw_enc_cnt_uc++; 39554c0a3aSHans de Goede 40554c0a3aSHans de Goede #define WEP_SW_DEC_CNT_INC(sec, ra) \ 41554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 42554c0a3aSHans de Goede sec->wep_sw_dec_cnt_bc++; \ 43554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 44554c0a3aSHans de Goede sec->wep_sw_dec_cnt_mc++; \ 45554c0a3aSHans de Goede else \ 46554c0a3aSHans de Goede sec->wep_sw_dec_cnt_uc++; 47554c0a3aSHans de Goede 48554c0a3aSHans de Goede #define TKIP_SW_ENC_CNT_INC(sec, ra) \ 49554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 50554c0a3aSHans de Goede sec->tkip_sw_enc_cnt_bc++; \ 51554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 52554c0a3aSHans de Goede sec->tkip_sw_enc_cnt_mc++; \ 53554c0a3aSHans de Goede else \ 54554c0a3aSHans de Goede sec->tkip_sw_enc_cnt_uc++; 55554c0a3aSHans de Goede 56554c0a3aSHans de Goede #define TKIP_SW_DEC_CNT_INC(sec, ra) \ 57554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 58554c0a3aSHans de Goede sec->tkip_sw_dec_cnt_bc++; \ 59554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 60554c0a3aSHans de Goede sec->tkip_sw_dec_cnt_mc++; \ 61554c0a3aSHans de Goede else \ 62554c0a3aSHans de Goede sec->tkip_sw_dec_cnt_uc++; 63554c0a3aSHans de Goede 64554c0a3aSHans de Goede #define AES_SW_ENC_CNT_INC(sec, ra) \ 65554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 66554c0a3aSHans de Goede sec->aes_sw_enc_cnt_bc++; \ 67554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 68554c0a3aSHans de Goede sec->aes_sw_enc_cnt_mc++; \ 69554c0a3aSHans de Goede else \ 70554c0a3aSHans de Goede sec->aes_sw_enc_cnt_uc++; 71554c0a3aSHans de Goede 72554c0a3aSHans de Goede #define AES_SW_DEC_CNT_INC(sec, ra) \ 73554c0a3aSHans de Goede if (is_broadcast_mac_addr(ra)) \ 74554c0a3aSHans de Goede sec->aes_sw_dec_cnt_bc++; \ 75554c0a3aSHans de Goede else if (is_multicast_mac_addr(ra)) \ 76554c0a3aSHans de Goede sec->aes_sw_dec_cnt_mc++; \ 77554c0a3aSHans de Goede else \ 78554c0a3aSHans de Goede sec->aes_sw_dec_cnt_uc++; 79554c0a3aSHans de Goede #else 80554c0a3aSHans de Goede #define WEP_SW_ENC_CNT_INC(sec, ra) 81554c0a3aSHans de Goede #define WEP_SW_DEC_CNT_INC(sec, ra) 82554c0a3aSHans de Goede #define TKIP_SW_ENC_CNT_INC(sec, ra) 83554c0a3aSHans de Goede #define TKIP_SW_DEC_CNT_INC(sec, ra) 84554c0a3aSHans de Goede #define AES_SW_ENC_CNT_INC(sec, ra) 85554c0a3aSHans de Goede #define AES_SW_DEC_CNT_INC(sec, ra) 86554c0a3aSHans de Goede #endif /* DBG_SW_SEC_CNT */ 87554c0a3aSHans de Goede 88554c0a3aSHans de Goede /* WEP related ===== */ 89554c0a3aSHans de Goede 90554c0a3aSHans de Goede #define CRC32_POLY 0x04c11db7 91554c0a3aSHans de Goede 92554c0a3aSHans de Goede struct arc4context { 93554c0a3aSHans de Goede u32 x; 94554c0a3aSHans de Goede u32 y; 95554c0a3aSHans de Goede u8 state[256]; 96554c0a3aSHans de Goede }; 97554c0a3aSHans de Goede 98554c0a3aSHans de Goede 99554c0a3aSHans de Goede static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len) 100554c0a3aSHans de Goede { 101554c0a3aSHans de Goede u32 t, u; 102554c0a3aSHans de Goede u32 keyindex; 103554c0a3aSHans de Goede u32 stateindex; 104554c0a3aSHans de Goede u8 *state; 105554c0a3aSHans de Goede u32 counter; 106554c0a3aSHans de Goede 107554c0a3aSHans de Goede state = parc4ctx->state; 108554c0a3aSHans de Goede parc4ctx->x = 0; 109554c0a3aSHans de Goede parc4ctx->y = 0; 110554c0a3aSHans de Goede for (counter = 0; counter < 256; counter++) 111554c0a3aSHans de Goede state[counter] = (u8)counter; 112554c0a3aSHans de Goede keyindex = 0; 113554c0a3aSHans de Goede stateindex = 0; 114554c0a3aSHans de Goede for (counter = 0; counter < 256; counter++) { 115554c0a3aSHans de Goede t = state[counter]; 116554c0a3aSHans de Goede stateindex = (stateindex + key[keyindex] + t) & 0xff; 117554c0a3aSHans de Goede u = state[stateindex]; 118554c0a3aSHans de Goede state[stateindex] = (u8)t; 119554c0a3aSHans de Goede state[counter] = (u8)u; 120554c0a3aSHans de Goede if (++keyindex >= key_len) 121554c0a3aSHans de Goede keyindex = 0; 122554c0a3aSHans de Goede } 123554c0a3aSHans de Goede } 124554c0a3aSHans de Goede 125554c0a3aSHans de Goede static u32 arcfour_byte(struct arc4context *parc4ctx) 126554c0a3aSHans de Goede { 127554c0a3aSHans de Goede u32 x; 128554c0a3aSHans de Goede u32 y; 129554c0a3aSHans de Goede u32 sx, sy; 130554c0a3aSHans de Goede u8 *state; 131554c0a3aSHans de Goede 132554c0a3aSHans de Goede state = parc4ctx->state; 133554c0a3aSHans de Goede x = (parc4ctx->x + 1) & 0xff; 134554c0a3aSHans de Goede sx = state[x]; 135554c0a3aSHans de Goede y = (sx + parc4ctx->y) & 0xff; 136554c0a3aSHans de Goede sy = state[y]; 137554c0a3aSHans de Goede parc4ctx->x = x; 138554c0a3aSHans de Goede parc4ctx->y = y; 139554c0a3aSHans de Goede state[y] = (u8)sx; 140554c0a3aSHans de Goede state[x] = (u8)sy; 141554c0a3aSHans de Goede return state[(sx + sy) & 0xff]; 142554c0a3aSHans de Goede } 143554c0a3aSHans de Goede 144554c0a3aSHans de Goede static void arcfour_encrypt( 145554c0a3aSHans de Goede struct arc4context *parc4ctx, 146554c0a3aSHans de Goede u8 *dest, 147554c0a3aSHans de Goede u8 *src, 148554c0a3aSHans de Goede u32 len 149554c0a3aSHans de Goede ) 150554c0a3aSHans de Goede { 151554c0a3aSHans de Goede u32 i; 152554c0a3aSHans de Goede 153554c0a3aSHans de Goede for (i = 0; i < len; i++) 154554c0a3aSHans de Goede dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx); 155554c0a3aSHans de Goede } 156554c0a3aSHans de Goede 15740d4aa0fSShreeya Patel static sint bcrc32initialized; 158554c0a3aSHans de Goede static u32 crc32_table[256]; 159554c0a3aSHans de Goede 160554c0a3aSHans de Goede 161554c0a3aSHans de Goede static u8 crc32_reverseBit(u8 data) 162554c0a3aSHans de Goede { 163554c0a3aSHans de Goede return((u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01)); 164554c0a3aSHans de Goede } 165554c0a3aSHans de Goede 166554c0a3aSHans de Goede static void crc32_init(void) 167554c0a3aSHans de Goede { 168554c0a3aSHans de Goede if (bcrc32initialized == 1) 169554c0a3aSHans de Goede return; 170554c0a3aSHans de Goede else { 171554c0a3aSHans de Goede sint i, j; 172554c0a3aSHans de Goede u32 c; 173554c0a3aSHans de Goede u8 *p = (u8 *)&c, *p1; 174554c0a3aSHans de Goede u8 k; 175554c0a3aSHans de Goede 176554c0a3aSHans de Goede c = 0x12340000; 177554c0a3aSHans de Goede 178554c0a3aSHans de Goede for (i = 0; i < 256; ++i) { 179554c0a3aSHans de Goede k = crc32_reverseBit((u8)i); 180554c0a3aSHans de Goede for (c = ((u32)k) << 24, j = 8; j > 0; --j) { 181554c0a3aSHans de Goede c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1); 182554c0a3aSHans de Goede } 183554c0a3aSHans de Goede p1 = (u8 *)&crc32_table[i]; 184554c0a3aSHans de Goede 185554c0a3aSHans de Goede p1[0] = crc32_reverseBit(p[3]); 186554c0a3aSHans de Goede p1[1] = crc32_reverseBit(p[2]); 187554c0a3aSHans de Goede p1[2] = crc32_reverseBit(p[1]); 188554c0a3aSHans de Goede p1[3] = crc32_reverseBit(p[0]); 189554c0a3aSHans de Goede } 190554c0a3aSHans de Goede bcrc32initialized = 1; 191554c0a3aSHans de Goede } 192554c0a3aSHans de Goede } 193554c0a3aSHans de Goede 194554c0a3aSHans de Goede static __le32 getcrc32(u8 *buf, sint len) 195554c0a3aSHans de Goede { 196554c0a3aSHans de Goede u8 *p; 197554c0a3aSHans de Goede u32 crc; 198554c0a3aSHans de Goede 199554c0a3aSHans de Goede if (bcrc32initialized == 0) 200554c0a3aSHans de Goede crc32_init(); 201554c0a3aSHans de Goede 202554c0a3aSHans de Goede crc = 0xffffffff; /* preload shift register, per CRC-32 spec */ 203554c0a3aSHans de Goede 204554c0a3aSHans de Goede for (p = buf; len > 0; ++p, --len) { 205554c0a3aSHans de Goede crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8); 206554c0a3aSHans de Goede } 207554c0a3aSHans de Goede return cpu_to_le32(~crc); /* transmit complement, per CRC-32 spec */ 208554c0a3aSHans de Goede } 209554c0a3aSHans de Goede 210554c0a3aSHans de Goede 211554c0a3aSHans de Goede /* 212554c0a3aSHans de Goede Need to consider the fragment situation 213554c0a3aSHans de Goede */ 214554c0a3aSHans de Goede void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe) 215554c0a3aSHans de Goede { /* exclude ICV */ 216554c0a3aSHans de Goede 217554c0a3aSHans de Goede unsigned char crc[4]; 218554c0a3aSHans de Goede struct arc4context mycontext; 219554c0a3aSHans de Goede 220554c0a3aSHans de Goede sint curfragnum, length; 221554c0a3aSHans de Goede u32 keylength; 222554c0a3aSHans de Goede 223554c0a3aSHans de Goede u8 *pframe, *payload, *iv; /* wepkey */ 224554c0a3aSHans de Goede u8 wepkey[16]; 225554c0a3aSHans de Goede u8 hw_hdr_offset = 0; 226554c0a3aSHans de Goede struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; 227554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 228554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 229554c0a3aSHans de Goede 230554c0a3aSHans de Goede if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) 231554c0a3aSHans de Goede return; 232554c0a3aSHans de Goede 233554c0a3aSHans de Goede hw_hdr_offset = TXDESC_OFFSET; 234554c0a3aSHans de Goede pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; 235554c0a3aSHans de Goede 236554c0a3aSHans de Goede /* start to encrypt each fragment */ 237554c0a3aSHans de Goede if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) { 238554c0a3aSHans de Goede keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex]; 239554c0a3aSHans de Goede 240554c0a3aSHans de Goede for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { 241554c0a3aSHans de Goede iv = pframe+pattrib->hdrlen; 242554c0a3aSHans de Goede memcpy(&wepkey[0], iv, 3); 243554c0a3aSHans de Goede memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); 244554c0a3aSHans de Goede payload = pframe+pattrib->iv_len+pattrib->hdrlen; 245554c0a3aSHans de Goede 246554c0a3aSHans de Goede if ((curfragnum+1) == pattrib->nr_frags) { /* the last fragment */ 247554c0a3aSHans de Goede 248554c0a3aSHans de Goede length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 249554c0a3aSHans de Goede 250554c0a3aSHans de Goede *((__le32 *)crc) = getcrc32(payload, length); 251554c0a3aSHans de Goede 252554c0a3aSHans de Goede arcfour_init(&mycontext, wepkey, 3+keylength); 253554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 254554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload+length, crc, 4); 255554c0a3aSHans de Goede 256554c0a3aSHans de Goede } else{ 257554c0a3aSHans de Goede length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 258554c0a3aSHans de Goede *((__le32 *)crc) = getcrc32(payload, length); 259554c0a3aSHans de Goede arcfour_init(&mycontext, wepkey, 3+keylength); 260554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 261554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload+length, crc, 4); 262554c0a3aSHans de Goede 263554c0a3aSHans de Goede pframe += pxmitpriv->frag_len; 264554c0a3aSHans de Goede pframe = (u8 *)RND4((SIZE_PTR)(pframe)); 265554c0a3aSHans de Goede } 266554c0a3aSHans de Goede } 267554c0a3aSHans de Goede 268554c0a3aSHans de Goede WEP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra); 269554c0a3aSHans de Goede } 270554c0a3aSHans de Goede } 271554c0a3aSHans de Goede 272554c0a3aSHans de Goede void rtw_wep_decrypt(struct adapter *padapter, u8 *precvframe) 273554c0a3aSHans de Goede { 274554c0a3aSHans de Goede /* exclude ICV */ 275554c0a3aSHans de Goede u8 crc[4]; 276554c0a3aSHans de Goede struct arc4context mycontext; 277554c0a3aSHans de Goede sint length; 278554c0a3aSHans de Goede u32 keylength; 279554c0a3aSHans de Goede u8 *pframe, *payload, *iv, wepkey[16]; 280554c0a3aSHans de Goede u8 keyindex; 281554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &(((union recv_frame *)precvframe)->u.hdr.attrib); 282554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 283554c0a3aSHans de Goede 284554c0a3aSHans de Goede pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; 285554c0a3aSHans de Goede 286554c0a3aSHans de Goede /* start to decrypt recvframe */ 287554c0a3aSHans de Goede if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) { 288554c0a3aSHans de Goede iv = pframe+prxattrib->hdrlen; 289554c0a3aSHans de Goede /* keyindex =(iv[3]&0x3); */ 290554c0a3aSHans de Goede keyindex = prxattrib->key_index; 291554c0a3aSHans de Goede keylength = psecuritypriv->dot11DefKeylen[keyindex]; 292554c0a3aSHans de Goede memcpy(&wepkey[0], iv, 3); 293554c0a3aSHans de Goede /* memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength); */ 294554c0a3aSHans de Goede memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength); 295554c0a3aSHans de Goede length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; 296554c0a3aSHans de Goede 297554c0a3aSHans de Goede payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; 298554c0a3aSHans de Goede 299554c0a3aSHans de Goede /* decrypt payload include icv */ 300554c0a3aSHans de Goede arcfour_init(&mycontext, wepkey, 3+keylength); 301554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 302554c0a3aSHans de Goede 303554c0a3aSHans de Goede /* calculate icv and compare the icv */ 304554c0a3aSHans de Goede *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4)); 305554c0a3aSHans de Goede 306554c0a3aSHans de Goede if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) { 307554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n", 308554c0a3aSHans de Goede crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4])); 309554c0a3aSHans de Goede } 310554c0a3aSHans de Goede 311554c0a3aSHans de Goede WEP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra); 312554c0a3aSHans de Goede } 313554c0a3aSHans de Goede return; 314554c0a3aSHans de Goede } 315554c0a3aSHans de Goede 316554c0a3aSHans de Goede /* 3 =====TKIP related ===== */ 317554c0a3aSHans de Goede 318554c0a3aSHans de Goede static u32 secmicgetuint32(u8 *p) 319554c0a3aSHans de Goede /* Convert from Byte[] to Us3232 in a portable way */ 320554c0a3aSHans de Goede { 321554c0a3aSHans de Goede s32 i; 322554c0a3aSHans de Goede u32 res = 0; 323554c0a3aSHans de Goede 324554c0a3aSHans de Goede for (i = 0; i < 4; i++) { 325554c0a3aSHans de Goede res |= ((u32)(*p++)) << (8*i); 326554c0a3aSHans de Goede } 327554c0a3aSHans de Goede 328554c0a3aSHans de Goede return res; 329554c0a3aSHans de Goede } 330554c0a3aSHans de Goede 331554c0a3aSHans de Goede static void secmicputuint32(u8 *p, u32 val) 332554c0a3aSHans de Goede /* Convert from Us3232 to Byte[] in a portable way */ 333554c0a3aSHans de Goede { 334554c0a3aSHans de Goede long i; 335554c0a3aSHans de Goede 336554c0a3aSHans de Goede for (i = 0; i < 4; i++) { 337554c0a3aSHans de Goede *p++ = (u8) (val & 0xff); 338554c0a3aSHans de Goede val >>= 8; 339554c0a3aSHans de Goede } 340554c0a3aSHans de Goede } 341554c0a3aSHans de Goede 342554c0a3aSHans de Goede static void secmicclear(struct mic_data *pmicdata) 343554c0a3aSHans de Goede { 344554c0a3aSHans de Goede /* Reset the state to the empty message. */ 345554c0a3aSHans de Goede pmicdata->L = pmicdata->K0; 346554c0a3aSHans de Goede pmicdata->R = pmicdata->K1; 347554c0a3aSHans de Goede pmicdata->nBytesInM = 0; 348554c0a3aSHans de Goede pmicdata->M = 0; 349554c0a3aSHans de Goede } 350554c0a3aSHans de Goede 351554c0a3aSHans de Goede void rtw_secmicsetkey(struct mic_data *pmicdata, u8 *key) 352554c0a3aSHans de Goede { 353554c0a3aSHans de Goede /* Set the key */ 354554c0a3aSHans de Goede pmicdata->K0 = secmicgetuint32(key); 355554c0a3aSHans de Goede pmicdata->K1 = secmicgetuint32(key + 4); 356554c0a3aSHans de Goede /* and reset the message */ 357554c0a3aSHans de Goede secmicclear(pmicdata); 358554c0a3aSHans de Goede } 359554c0a3aSHans de Goede 360554c0a3aSHans de Goede void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b) 361554c0a3aSHans de Goede { 362554c0a3aSHans de Goede /* Append the byte to our word-sized buffer */ 363554c0a3aSHans de Goede pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM); 364554c0a3aSHans de Goede pmicdata->nBytesInM++; 365554c0a3aSHans de Goede /* Process the word if it is full. */ 366554c0a3aSHans de Goede if (pmicdata->nBytesInM >= 4) { 367554c0a3aSHans de Goede pmicdata->L ^= pmicdata->M; 368554c0a3aSHans de Goede pmicdata->R ^= ROL32(pmicdata->L, 17); 369554c0a3aSHans de Goede pmicdata->L += pmicdata->R; 370554c0a3aSHans de Goede pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8); 371554c0a3aSHans de Goede pmicdata->L += pmicdata->R; 372554c0a3aSHans de Goede pmicdata->R ^= ROL32(pmicdata->L, 3); 373554c0a3aSHans de Goede pmicdata->L += pmicdata->R; 374554c0a3aSHans de Goede pmicdata->R ^= ROR32(pmicdata->L, 2); 375554c0a3aSHans de Goede pmicdata->L += pmicdata->R; 376554c0a3aSHans de Goede /* Clear the buffer */ 377554c0a3aSHans de Goede pmicdata->M = 0; 378554c0a3aSHans de Goede pmicdata->nBytesInM = 0; 379554c0a3aSHans de Goede } 380554c0a3aSHans de Goede } 381554c0a3aSHans de Goede 382554c0a3aSHans de Goede void rtw_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes) 383554c0a3aSHans de Goede { 384554c0a3aSHans de Goede /* This is simple */ 385554c0a3aSHans de Goede while (nbytes > 0) { 386554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, *src++); 387554c0a3aSHans de Goede nbytes--; 388554c0a3aSHans de Goede } 389554c0a3aSHans de Goede } 390554c0a3aSHans de Goede 391554c0a3aSHans de Goede void rtw_secgetmic(struct mic_data *pmicdata, u8 *dst) 392554c0a3aSHans de Goede { 393554c0a3aSHans de Goede /* Append the minimum padding */ 394554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0x5a); 395554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0); 396554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0); 397554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0); 398554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0); 399554c0a3aSHans de Goede /* and then zeroes until the length is a multiple of 4 */ 400554c0a3aSHans de Goede while (pmicdata->nBytesInM != 0) { 401554c0a3aSHans de Goede rtw_secmicappendbyte(pmicdata, 0); 402554c0a3aSHans de Goede } 403554c0a3aSHans de Goede /* The appendByte function has already computed the result. */ 404554c0a3aSHans de Goede secmicputuint32(dst, pmicdata->L); 405554c0a3aSHans de Goede secmicputuint32(dst+4, pmicdata->R); 406554c0a3aSHans de Goede /* Reset to the empty message. */ 407554c0a3aSHans de Goede secmicclear(pmicdata); 408554c0a3aSHans de Goede } 409554c0a3aSHans de Goede 410554c0a3aSHans de Goede 411554c0a3aSHans de Goede void rtw_seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code, u8 pri) 412554c0a3aSHans de Goede { 413554c0a3aSHans de Goede 414554c0a3aSHans de Goede struct mic_data micdata; 415554c0a3aSHans de Goede u8 priority[4] = {0x0, 0x0, 0x0, 0x0}; 416554c0a3aSHans de Goede 417554c0a3aSHans de Goede rtw_secmicsetkey(&micdata, key); 418554c0a3aSHans de Goede priority[0] = pri; 419554c0a3aSHans de Goede 420554c0a3aSHans de Goede /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */ 421554c0a3aSHans de Goede if (header[1]&1) { /* ToDS == 1 */ 422554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[16], 6); /* DA */ 423554c0a3aSHans de Goede if (header[1]&2) /* From Ds == 1 */ 424554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[24], 6); 425554c0a3aSHans de Goede else 426554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[10], 6); 427554c0a3aSHans de Goede } else { /* ToDS == 0 */ 428554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[4], 6); /* DA */ 429554c0a3aSHans de Goede if (header[1]&2) /* From Ds == 1 */ 430554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[16], 6); 431554c0a3aSHans de Goede else 432554c0a3aSHans de Goede rtw_secmicappend(&micdata, &header[10], 6); 433554c0a3aSHans de Goede 434554c0a3aSHans de Goede } 435554c0a3aSHans de Goede rtw_secmicappend(&micdata, &priority[0], 4); 436554c0a3aSHans de Goede 437554c0a3aSHans de Goede 438554c0a3aSHans de Goede rtw_secmicappend(&micdata, data, data_len); 439554c0a3aSHans de Goede 440554c0a3aSHans de Goede rtw_secgetmic(&micdata, mic_code); 441554c0a3aSHans de Goede } 442554c0a3aSHans de Goede 443554c0a3aSHans de Goede /* macros for extraction/creation of unsigned char/unsigned short values */ 444554c0a3aSHans de Goede #define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15)) 445554c0a3aSHans de Goede #define Lo8(v16) ((u8)((v16) & 0x00FF)) 446554c0a3aSHans de Goede #define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF)) 447554c0a3aSHans de Goede #define Lo16(v32) ((u16)((v32) & 0xFFFF)) 448554c0a3aSHans de Goede #define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF)) 449554c0a3aSHans de Goede #define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8)) 450554c0a3aSHans de Goede 451554c0a3aSHans de Goede /* select the Nth 16-bit word of the temporal key unsigned char array TK[] */ 452554c0a3aSHans de Goede #define TK16(N) Mk16(tk[2*(N)+1], tk[2*(N)]) 453554c0a3aSHans de Goede 454554c0a3aSHans de Goede /* S-box lookup: 16 bits --> 16 bits */ 455554c0a3aSHans de Goede #define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)]) 456554c0a3aSHans de Goede 457554c0a3aSHans de Goede /* fixed algorithm "parameters" */ 458554c0a3aSHans de Goede #define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */ 459554c0a3aSHans de Goede #define TA_SIZE 6 /* 48-bit transmitter address */ 460554c0a3aSHans de Goede #define TK_SIZE 16 /* 128-bit temporal key */ 461554c0a3aSHans de Goede #define P1K_SIZE 10 /* 80-bit Phase1 key */ 462554c0a3aSHans de Goede #define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */ 463554c0a3aSHans de Goede 464554c0a3aSHans de Goede 465554c0a3aSHans de Goede /* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */ 466554c0a3aSHans de Goede static const unsigned short Sbox1[2][256] = { /* Sbox for hash (can be in ROM) */ 467554c0a3aSHans de Goede { 468554c0a3aSHans de Goede 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154, 469554c0a3aSHans de Goede 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A, 470554c0a3aSHans de Goede 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B, 471554c0a3aSHans de Goede 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B, 472554c0a3aSHans de Goede 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F, 473554c0a3aSHans de Goede 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F, 474554c0a3aSHans de Goede 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5, 475554c0a3aSHans de Goede 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F, 476554c0a3aSHans de Goede 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB, 477554c0a3aSHans de Goede 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397, 478554c0a3aSHans de Goede 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED, 479554c0a3aSHans de Goede 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A, 480554c0a3aSHans de Goede 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194, 481554c0a3aSHans de Goede 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3, 482554c0a3aSHans de Goede 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104, 483554c0a3aSHans de Goede 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D, 484554c0a3aSHans de Goede 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39, 485554c0a3aSHans de Goede 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695, 486554c0a3aSHans de Goede 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83, 487554c0a3aSHans de Goede 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76, 488554c0a3aSHans de Goede 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4, 489554c0a3aSHans de Goede 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B, 490554c0a3aSHans de Goede 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0, 491554c0a3aSHans de Goede 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018, 492554c0a3aSHans de Goede 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751, 493554c0a3aSHans de Goede 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85, 494554c0a3aSHans de Goede 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12, 495554c0a3aSHans de Goede 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9, 496554c0a3aSHans de Goede 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7, 497554c0a3aSHans de Goede 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A, 498554c0a3aSHans de Goede 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8, 499554c0a3aSHans de Goede 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A, 500554c0a3aSHans de Goede }, 501554c0a3aSHans de Goede 502554c0a3aSHans de Goede 503554c0a3aSHans de Goede { /* second half of table is unsigned char-reversed version of first! */ 504554c0a3aSHans de Goede 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491, 505554c0a3aSHans de Goede 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC, 506554c0a3aSHans de Goede 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB, 507554c0a3aSHans de Goede 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B, 508554c0a3aSHans de Goede 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83, 509554c0a3aSHans de Goede 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A, 510554c0a3aSHans de Goede 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F, 511554c0a3aSHans de Goede 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA, 512554c0a3aSHans de Goede 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B, 513554c0a3aSHans de Goede 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713, 514554c0a3aSHans de Goede 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6, 515554c0a3aSHans de Goede 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85, 516554c0a3aSHans de Goede 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411, 517554c0a3aSHans de Goede 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B, 518554c0a3aSHans de Goede 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1, 519554c0a3aSHans de Goede 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF, 520554c0a3aSHans de Goede 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E, 521554c0a3aSHans de Goede 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6, 522554c0a3aSHans de Goede 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B, 523554c0a3aSHans de Goede 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD, 524554c0a3aSHans de Goede 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8, 525554c0a3aSHans de Goede 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2, 526554c0a3aSHans de Goede 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049, 527554c0a3aSHans de Goede 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810, 528554c0a3aSHans de Goede 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197, 529554c0a3aSHans de Goede 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F, 530554c0a3aSHans de Goede 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C, 531554c0a3aSHans de Goede 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927, 532554c0a3aSHans de Goede 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733, 533554c0a3aSHans de Goede 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5, 534554c0a3aSHans de Goede 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0, 535554c0a3aSHans de Goede 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C, 536554c0a3aSHans de Goede } 537554c0a3aSHans de Goede }; 538554c0a3aSHans de Goede 539554c0a3aSHans de Goede /* 540554c0a3aSHans de Goede ********************************************************************** 541554c0a3aSHans de Goede * Routine: Phase 1 -- generate P1K, given TA, TK, IV32 542554c0a3aSHans de Goede * 543554c0a3aSHans de Goede * Inputs: 544554c0a3aSHans de Goede * tk[] = temporal key [128 bits] 545554c0a3aSHans de Goede * ta[] = transmitter's MAC address [ 48 bits] 546554c0a3aSHans de Goede * iv32 = upper 32 bits of IV [ 32 bits] 547554c0a3aSHans de Goede * Output: 548554c0a3aSHans de Goede * p1k[] = Phase 1 key [ 80 bits] 549554c0a3aSHans de Goede * 550554c0a3aSHans de Goede * Note: 551554c0a3aSHans de Goede * This function only needs to be called every 2**16 packets, 552554c0a3aSHans de Goede * although in theory it could be called every packet. 553554c0a3aSHans de Goede * 554554c0a3aSHans de Goede ********************************************************************** 555554c0a3aSHans de Goede */ 556554c0a3aSHans de Goede static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32) 557554c0a3aSHans de Goede { 558554c0a3aSHans de Goede sint i; 559554c0a3aSHans de Goede 560554c0a3aSHans de Goede /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */ 561554c0a3aSHans de Goede p1k[0] = Lo16(iv32); 562554c0a3aSHans de Goede p1k[1] = Hi16(iv32); 563554c0a3aSHans de Goede p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */ 564554c0a3aSHans de Goede p1k[3] = Mk16(ta[3], ta[2]); 565554c0a3aSHans de Goede p1k[4] = Mk16(ta[5], ta[4]); 566554c0a3aSHans de Goede 567554c0a3aSHans de Goede /* Now compute an unbalanced Feistel cipher with 80-bit block */ 568554c0a3aSHans de Goede /* size on the 80-bit block P1K[], using the 128-bit key TK[] */ 569554c0a3aSHans de Goede for (i = 0; i < PHASE1_LOOP_CNT; i++) { 570554c0a3aSHans de Goede /* Each add operation here is mod 2**16 */ 571554c0a3aSHans de Goede p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0)); 572554c0a3aSHans de Goede p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2)); 573554c0a3aSHans de Goede p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4)); 574554c0a3aSHans de Goede p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6)); 575554c0a3aSHans de Goede p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0)); 576554c0a3aSHans de Goede p1k[4] += (unsigned short)i; /* avoid "slide attacks" */ 577554c0a3aSHans de Goede } 578554c0a3aSHans de Goede } 579554c0a3aSHans de Goede 580554c0a3aSHans de Goede 581554c0a3aSHans de Goede /* 582554c0a3aSHans de Goede ********************************************************************** 583554c0a3aSHans de Goede * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16 584554c0a3aSHans de Goede * 585554c0a3aSHans de Goede * Inputs: 586554c0a3aSHans de Goede * tk[] = Temporal key [128 bits] 587554c0a3aSHans de Goede * p1k[] = Phase 1 output key [ 80 bits] 588554c0a3aSHans de Goede * iv16 = low 16 bits of IV counter [ 16 bits] 589554c0a3aSHans de Goede * Output: 590554c0a3aSHans de Goede * rc4key[] = the key used to encrypt the packet [128 bits] 591554c0a3aSHans de Goede * 592554c0a3aSHans de Goede * Note: 593554c0a3aSHans de Goede * The value {TA, IV32, IV16} for Phase1/Phase2 must be unique 594554c0a3aSHans de Goede * across all packets using the same key TK value. Then, for a 595554c0a3aSHans de Goede * given value of TK[], this TKIP48 construction guarantees that 596554c0a3aSHans de Goede * the final RC4KEY value is unique across all packets. 597554c0a3aSHans de Goede * 598554c0a3aSHans de Goede * Suggested implementation optimization: if PPK[] is "overlaid" 599554c0a3aSHans de Goede * appropriately on RC4KEY[], there is no need for the final 600554c0a3aSHans de Goede * for loop below that copies the PPK[] result into RC4KEY[]. 601554c0a3aSHans de Goede * 602554c0a3aSHans de Goede ********************************************************************** 603554c0a3aSHans de Goede */ 604554c0a3aSHans de Goede static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16) 605554c0a3aSHans de Goede { 606554c0a3aSHans de Goede sint i; 607554c0a3aSHans de Goede u16 PPK[6]; /* temporary key for mixing */ 608554c0a3aSHans de Goede 609554c0a3aSHans de Goede /* Note: all adds in the PPK[] equations below are mod 2**16 */ 610554c0a3aSHans de Goede for (i = 0; i < 5; i++) 611554c0a3aSHans de Goede PPK[i] = p1k[i]; /* first, copy P1K to PPK */ 612554c0a3aSHans de Goede 613554c0a3aSHans de Goede PPK[5] = p1k[4]+iv16; /* next, add in IV16 */ 614554c0a3aSHans de Goede 615554c0a3aSHans de Goede /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */ 616554c0a3aSHans de Goede PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */ 617554c0a3aSHans de Goede PPK[1] += _S_(PPK[0] ^ TK16(1)); 618554c0a3aSHans de Goede PPK[2] += _S_(PPK[1] ^ TK16(2)); 619554c0a3aSHans de Goede PPK[3] += _S_(PPK[2] ^ TK16(3)); 620554c0a3aSHans de Goede PPK[4] += _S_(PPK[3] ^ TK16(4)); 621554c0a3aSHans de Goede PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */ 622554c0a3aSHans de Goede 623554c0a3aSHans de Goede /* Final sweep: bijective, "linear". Rotates kill LSB correlations */ 624554c0a3aSHans de Goede PPK[0] += RotR1(PPK[5] ^ TK16(6)); 625554c0a3aSHans de Goede PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */ 626554c0a3aSHans de Goede PPK[2] += RotR1(PPK[1]); 627554c0a3aSHans de Goede PPK[3] += RotR1(PPK[2]); 628554c0a3aSHans de Goede PPK[4] += RotR1(PPK[3]); 629554c0a3aSHans de Goede PPK[5] += RotR1(PPK[4]); 630554c0a3aSHans de Goede /* Note: At this point, for a given key TK[0..15], the 96-bit output */ 631554c0a3aSHans de Goede /* value PPK[0..5] is guaranteed to be unique, as a function */ 632554c0a3aSHans de Goede /* of the 96-bit "input" value {TA, IV32, IV16}. That is, P1K */ 633554c0a3aSHans de Goede /* is now a keyed permutation of {TA, IV32, IV16}. */ 634554c0a3aSHans de Goede 635554c0a3aSHans de Goede /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */ 636554c0a3aSHans de Goede rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */ 637554c0a3aSHans de Goede rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */ 638554c0a3aSHans de Goede rc4key[2] = Lo8(iv16); 639554c0a3aSHans de Goede rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1); 640554c0a3aSHans de Goede 641554c0a3aSHans de Goede 642554c0a3aSHans de Goede /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */ 643554c0a3aSHans de Goede for (i = 0; i < 6; i++) { 644554c0a3aSHans de Goede rc4key[4+2*i] = Lo8(PPK[i]); 645554c0a3aSHans de Goede rc4key[5+2*i] = Hi8(PPK[i]); 646554c0a3aSHans de Goede } 647554c0a3aSHans de Goede } 648554c0a3aSHans de Goede 649554c0a3aSHans de Goede 650554c0a3aSHans de Goede /* The hlen isn't include the IV */ 651554c0a3aSHans de Goede u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe) 652554c0a3aSHans de Goede { /* exclude ICV */ 653554c0a3aSHans de Goede u16 pnl; 654554c0a3aSHans de Goede u32 pnh; 655554c0a3aSHans de Goede u8 rc4key[16]; 656554c0a3aSHans de Goede u8 ttkey[16]; 657554c0a3aSHans de Goede u8 crc[4]; 658554c0a3aSHans de Goede u8 hw_hdr_offset = 0; 659554c0a3aSHans de Goede struct arc4context mycontext; 660554c0a3aSHans de Goede sint curfragnum, length; 661554c0a3aSHans de Goede u32 prwskeylen; 662554c0a3aSHans de Goede 663554c0a3aSHans de Goede u8 *pframe, *payload, *iv, *prwskey; 664554c0a3aSHans de Goede union pn48 dot11txpn; 665554c0a3aSHans de Goede /* struct sta_info *stainfo; */ 666554c0a3aSHans de Goede struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; 667554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 668554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 669554c0a3aSHans de Goede u32 res = _SUCCESS; 670554c0a3aSHans de Goede 671554c0a3aSHans de Goede if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) 672554c0a3aSHans de Goede return _FAIL; 673554c0a3aSHans de Goede 674554c0a3aSHans de Goede hw_hdr_offset = TXDESC_OFFSET; 675554c0a3aSHans de Goede pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; 676554c0a3aSHans de Goede 677554c0a3aSHans de Goede /* 4 start to encrypt each fragment */ 678554c0a3aSHans de Goede if (pattrib->encrypt == _TKIP_) { 679554c0a3aSHans de Goede 680554c0a3aSHans de Goede /* 681554c0a3aSHans de Goede if (pattrib->psta) 682554c0a3aSHans de Goede { 683554c0a3aSHans de Goede stainfo = pattrib->psta; 684554c0a3aSHans de Goede } 685554c0a3aSHans de Goede else 686554c0a3aSHans de Goede { 687554c0a3aSHans de Goede DBG_871X("%s, call rtw_get_stainfo()\n", __func__); 688554c0a3aSHans de Goede stainfo =rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]); 689554c0a3aSHans de Goede } 690554c0a3aSHans de Goede */ 691554c0a3aSHans de Goede /* if (stainfo!= NULL) */ 692554c0a3aSHans de Goede { 693554c0a3aSHans de Goede /* 694554c0a3aSHans de Goede if (!(stainfo->state &_FW_LINKED)) 695554c0a3aSHans de Goede { 696554c0a3aSHans de Goede DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state); 697554c0a3aSHans de Goede return _FAIL; 698554c0a3aSHans de Goede } 699554c0a3aSHans de Goede */ 700554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo!= NULL!!!\n")); 701554c0a3aSHans de Goede 702554c0a3aSHans de Goede if (IS_MCAST(pattrib->ra)) 703554c0a3aSHans de Goede prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; 704554c0a3aSHans de Goede else 705554c0a3aSHans de Goede /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */ 706554c0a3aSHans de Goede prwskey = pattrib->dot118021x_UncstKey.skey; 707554c0a3aSHans de Goede 708554c0a3aSHans de Goede prwskeylen = 16; 709554c0a3aSHans de Goede 710554c0a3aSHans de Goede for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { 711554c0a3aSHans de Goede iv = pframe+pattrib->hdrlen; 712554c0a3aSHans de Goede payload = pframe+pattrib->iv_len+pattrib->hdrlen; 713554c0a3aSHans de Goede 714554c0a3aSHans de Goede GET_TKIP_PN(iv, dot11txpn); 715554c0a3aSHans de Goede 716554c0a3aSHans de Goede pnl = (u16)(dot11txpn.val); 717554c0a3aSHans de Goede pnh = (u32)(dot11txpn.val>>16); 718554c0a3aSHans de Goede 719554c0a3aSHans de Goede phase1((u16 *)&ttkey[0], prwskey, &pattrib->ta[0], pnh); 720554c0a3aSHans de Goede 721554c0a3aSHans de Goede phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0], pnl); 722554c0a3aSHans de Goede 723554c0a3aSHans de Goede if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ 724554c0a3aSHans de Goede length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 725554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_info_, ("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len, pattrib->icv_len)); 726554c0a3aSHans de Goede *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ 727554c0a3aSHans de Goede 728554c0a3aSHans de Goede arcfour_init(&mycontext, rc4key, 16); 729554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 730554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload+length, crc, 4); 731554c0a3aSHans de Goede 732554c0a3aSHans de Goede } else { 733554c0a3aSHans de Goede length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 734554c0a3aSHans de Goede *((__le32 *)crc) = getcrc32(payload, length);/* modified by Amy*/ 735554c0a3aSHans de Goede arcfour_init(&mycontext, rc4key, 16); 736554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 737554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload+length, crc, 4); 738554c0a3aSHans de Goede 739554c0a3aSHans de Goede pframe += pxmitpriv->frag_len; 740554c0a3aSHans de Goede pframe = (u8 *)RND4((SIZE_PTR)(pframe)); 741554c0a3aSHans de Goede } 742554c0a3aSHans de Goede } 743554c0a3aSHans de Goede 744554c0a3aSHans de Goede TKIP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra); 745554c0a3aSHans de Goede } 746554c0a3aSHans de Goede /* 747554c0a3aSHans de Goede else { 748554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_encrypt: stainfo == NULL!!!\n")); 749554c0a3aSHans de Goede DBG_871X("%s, psta ==NUL\n", __func__); 750554c0a3aSHans de Goede res = _FAIL; 751554c0a3aSHans de Goede } 752554c0a3aSHans de Goede */ 753554c0a3aSHans de Goede 754554c0a3aSHans de Goede } 755554c0a3aSHans de Goede return res; 756554c0a3aSHans de Goede } 757554c0a3aSHans de Goede 758554c0a3aSHans de Goede 759554c0a3aSHans de Goede /* The hlen isn't include the IV */ 760554c0a3aSHans de Goede u32 rtw_tkip_decrypt(struct adapter *padapter, u8 *precvframe) 761554c0a3aSHans de Goede { /* exclude ICV */ 762554c0a3aSHans de Goede u16 pnl; 763554c0a3aSHans de Goede u32 pnh; 764554c0a3aSHans de Goede u8 rc4key[16]; 765554c0a3aSHans de Goede u8 ttkey[16]; 766554c0a3aSHans de Goede u8 crc[4]; 767554c0a3aSHans de Goede struct arc4context mycontext; 768554c0a3aSHans de Goede sint length; 769554c0a3aSHans de Goede u32 prwskeylen; 770554c0a3aSHans de Goede 771554c0a3aSHans de Goede u8 *pframe, *payload, *iv, *prwskey; 772554c0a3aSHans de Goede union pn48 dot11txpn; 773554c0a3aSHans de Goede struct sta_info *stainfo; 774554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib; 775554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 776554c0a3aSHans de Goede /* struct recv_priv *precvpriv =&padapter->recvpriv; */ 777554c0a3aSHans de Goede u32 res = _SUCCESS; 778554c0a3aSHans de Goede 779554c0a3aSHans de Goede pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; 780554c0a3aSHans de Goede 781554c0a3aSHans de Goede /* 4 start to decrypt recvframe */ 782554c0a3aSHans de Goede if (prxattrib->encrypt == _TKIP_) { 783554c0a3aSHans de Goede stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]); 784554c0a3aSHans de Goede if (stainfo != NULL) { 785554c0a3aSHans de Goede if (IS_MCAST(prxattrib->ra)) { 78640d4aa0fSShreeya Patel static unsigned long start; 78740d4aa0fSShreeya Patel static u32 no_gkey_bc_cnt; 78840d4aa0fSShreeya Patel static u32 no_gkey_mc_cnt; 789554c0a3aSHans de Goede 790554c0a3aSHans de Goede if (psecuritypriv->binstallGrpkey == false) { 791554c0a3aSHans de Goede res = _FAIL; 792554c0a3aSHans de Goede 793554c0a3aSHans de Goede if (start == 0) 794554c0a3aSHans de Goede start = jiffies; 795554c0a3aSHans de Goede 796554c0a3aSHans de Goede if (is_broadcast_mac_addr(prxattrib->ra)) 797554c0a3aSHans de Goede no_gkey_bc_cnt++; 798554c0a3aSHans de Goede else 799554c0a3aSHans de Goede no_gkey_mc_cnt++; 800554c0a3aSHans de Goede 801554c0a3aSHans de Goede if (jiffies_to_msecs(jiffies - start) > 1000) { 802554c0a3aSHans de Goede if (no_gkey_bc_cnt || no_gkey_mc_cnt) { 803554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", 804554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); 805554c0a3aSHans de Goede } 806554c0a3aSHans de Goede start = jiffies; 807554c0a3aSHans de Goede no_gkey_bc_cnt = 0; 808554c0a3aSHans de Goede no_gkey_mc_cnt = 0; 809554c0a3aSHans de Goede } 810554c0a3aSHans de Goede goto exit; 811554c0a3aSHans de Goede } 812554c0a3aSHans de Goede 813554c0a3aSHans de Goede if (no_gkey_bc_cnt || no_gkey_mc_cnt) { 814554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", 815554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); 816554c0a3aSHans de Goede } 817554c0a3aSHans de Goede start = 0; 818554c0a3aSHans de Goede no_gkey_bc_cnt = 0; 819554c0a3aSHans de Goede no_gkey_mc_cnt = 0; 820554c0a3aSHans de Goede 821554c0a3aSHans de Goede /* DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n"); */ 822554c0a3aSHans de Goede /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */ 823554c0a3aSHans de Goede prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; 824554c0a3aSHans de Goede prwskeylen = 16; 825554c0a3aSHans de Goede } else{ 826554c0a3aSHans de Goede prwskey = &stainfo->dot118021x_UncstKey.skey[0]; 827554c0a3aSHans de Goede prwskeylen = 16; 828554c0a3aSHans de Goede } 829554c0a3aSHans de Goede 830554c0a3aSHans de Goede iv = pframe+prxattrib->hdrlen; 831554c0a3aSHans de Goede payload = pframe+prxattrib->iv_len+prxattrib->hdrlen; 832554c0a3aSHans de Goede length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; 833554c0a3aSHans de Goede 834554c0a3aSHans de Goede GET_TKIP_PN(iv, dot11txpn); 835554c0a3aSHans de Goede 836554c0a3aSHans de Goede pnl = (u16)(dot11txpn.val); 837554c0a3aSHans de Goede pnh = (u32)(dot11txpn.val>>16); 838554c0a3aSHans de Goede 839554c0a3aSHans de Goede phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0], pnh); 840554c0a3aSHans de Goede phase2(&rc4key[0], prwskey, (unsigned short *)&ttkey[0], pnl); 841554c0a3aSHans de Goede 842554c0a3aSHans de Goede /* 4 decrypt payload include icv */ 843554c0a3aSHans de Goede 844554c0a3aSHans de Goede arcfour_init(&mycontext, rc4key, 16); 845554c0a3aSHans de Goede arcfour_encrypt(&mycontext, payload, payload, length); 846554c0a3aSHans de Goede 847554c0a3aSHans de Goede *((u32 *)crc) = le32_to_cpu(getcrc32(payload, length-4)); 848554c0a3aSHans de Goede 849554c0a3aSHans de Goede if (crc[3] != payload[length-1] || crc[2] != payload[length-2] || crc[1] != payload[length-3] || crc[0] != payload[length-4]) { 8500ba8d4b9SLarry Finger RT_TRACE(_module_rtl871x_security_c_, _drv_err_, 8510ba8d4b9SLarry Finger ("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n", 852554c0a3aSHans de Goede crc[3], payload[length-1], crc[2], payload[length-2], crc[1], payload[length-3], crc[0], payload[length-4])); 853554c0a3aSHans de Goede res = _FAIL; 854554c0a3aSHans de Goede } 855554c0a3aSHans de Goede 856554c0a3aSHans de Goede TKIP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra); 857554c0a3aSHans de Goede } else { 858554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_tkip_decrypt: stainfo == NULL!!!\n")); 859554c0a3aSHans de Goede res = _FAIL; 860554c0a3aSHans de Goede } 861554c0a3aSHans de Goede 862554c0a3aSHans de Goede } 863554c0a3aSHans de Goede exit: 864554c0a3aSHans de Goede return res; 865554c0a3aSHans de Goede 866554c0a3aSHans de Goede } 867554c0a3aSHans de Goede 868554c0a3aSHans de Goede 869554c0a3aSHans de Goede /* 3 =====AES related ===== */ 870554c0a3aSHans de Goede 871554c0a3aSHans de Goede 872554c0a3aSHans de Goede 873554c0a3aSHans de Goede #define MAX_MSG_SIZE 2048 874554c0a3aSHans de Goede /*****************************/ 875554c0a3aSHans de Goede /******** SBOX Table *********/ 876554c0a3aSHans de Goede /*****************************/ 877554c0a3aSHans de Goede 878554c0a3aSHans de Goede static u8 sbox_table[256] = { 879554c0a3aSHans de Goede 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 880554c0a3aSHans de Goede 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 881554c0a3aSHans de Goede 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 882554c0a3aSHans de Goede 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 883554c0a3aSHans de Goede 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 884554c0a3aSHans de Goede 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 885554c0a3aSHans de Goede 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 886554c0a3aSHans de Goede 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 887554c0a3aSHans de Goede 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 888554c0a3aSHans de Goede 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 889554c0a3aSHans de Goede 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 890554c0a3aSHans de Goede 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 891554c0a3aSHans de Goede 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 892554c0a3aSHans de Goede 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 893554c0a3aSHans de Goede 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 894554c0a3aSHans de Goede 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 895554c0a3aSHans de Goede 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 896554c0a3aSHans de Goede 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 897554c0a3aSHans de Goede 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 898554c0a3aSHans de Goede 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 899554c0a3aSHans de Goede 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 900554c0a3aSHans de Goede 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 901554c0a3aSHans de Goede 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 902554c0a3aSHans de Goede 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 903554c0a3aSHans de Goede 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 904554c0a3aSHans de Goede 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 905554c0a3aSHans de Goede 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 906554c0a3aSHans de Goede 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 907554c0a3aSHans de Goede 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 908554c0a3aSHans de Goede 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 909554c0a3aSHans de Goede 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 910554c0a3aSHans de Goede 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 911554c0a3aSHans de Goede }; 912554c0a3aSHans de Goede 913554c0a3aSHans de Goede /*****************************/ 914554c0a3aSHans de Goede /**** Function Prototypes ****/ 915554c0a3aSHans de Goede /*****************************/ 916554c0a3aSHans de Goede 917554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out); 918554c0a3aSHans de Goede static void construct_mic_iv( 919554c0a3aSHans de Goede u8 *mic_header1, 920554c0a3aSHans de Goede sint qc_exists, 921554c0a3aSHans de Goede sint a4_exists, 922554c0a3aSHans de Goede u8 *mpdu, 923554c0a3aSHans de Goede uint payload_length, 924554c0a3aSHans de Goede u8 *pn_vector, 925554c0a3aSHans de Goede uint frtype 926554c0a3aSHans de Goede );/* add for CONFIG_IEEE80211W, none 11w also can use */ 927554c0a3aSHans de Goede static void construct_mic_header1( 928554c0a3aSHans de Goede u8 *mic_header1, 929554c0a3aSHans de Goede sint header_length, 930554c0a3aSHans de Goede u8 *mpdu, 931554c0a3aSHans de Goede uint frtype 932554c0a3aSHans de Goede );/* add for CONFIG_IEEE80211W, none 11w also can use */ 933554c0a3aSHans de Goede static void construct_mic_header2( 934554c0a3aSHans de Goede u8 *mic_header2, 935554c0a3aSHans de Goede u8 *mpdu, 936554c0a3aSHans de Goede sint a4_exists, 937554c0a3aSHans de Goede sint qc_exists 938554c0a3aSHans de Goede ); 939554c0a3aSHans de Goede static void construct_ctr_preload( 940554c0a3aSHans de Goede u8 *ctr_preload, 941554c0a3aSHans de Goede sint a4_exists, 942554c0a3aSHans de Goede sint qc_exists, 943554c0a3aSHans de Goede u8 *mpdu, 944554c0a3aSHans de Goede u8 *pn_vector, 945554c0a3aSHans de Goede sint c, 946554c0a3aSHans de Goede uint frtype 947554c0a3aSHans de Goede );/* add for CONFIG_IEEE80211W, none 11w also can use */ 948554c0a3aSHans de Goede static void xor_128(u8 *a, u8 *b, u8 *out); 949554c0a3aSHans de Goede static void xor_32(u8 *a, u8 *b, u8 *out); 950554c0a3aSHans de Goede static u8 sbox(u8 a); 951554c0a3aSHans de Goede static void next_key(u8 *key, sint round); 952554c0a3aSHans de Goede static void byte_sub(u8 *in, u8 *out); 953554c0a3aSHans de Goede static void shift_row(u8 *in, u8 *out); 954554c0a3aSHans de Goede static void mix_column(u8 *in, u8 *out); 955554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext); 956554c0a3aSHans de Goede 957554c0a3aSHans de Goede 958554c0a3aSHans de Goede /****************************************/ 959554c0a3aSHans de Goede /* aes128k128d() */ 960554c0a3aSHans de Goede /* Performs a 128 bit AES encrypt with */ 961554c0a3aSHans de Goede /* 128 bit data. */ 962554c0a3aSHans de Goede /****************************************/ 963554c0a3aSHans de Goede static void xor_128(u8 *a, u8 *b, u8 *out) 964554c0a3aSHans de Goede { 965554c0a3aSHans de Goede sint i; 966554c0a3aSHans de Goede 967554c0a3aSHans de Goede for (i = 0; i < 16; i++) { 968554c0a3aSHans de Goede out[i] = a[i] ^ b[i]; 969554c0a3aSHans de Goede } 970554c0a3aSHans de Goede } 971554c0a3aSHans de Goede 972554c0a3aSHans de Goede 973554c0a3aSHans de Goede static void xor_32(u8 *a, u8 *b, u8 *out) 974554c0a3aSHans de Goede { 975554c0a3aSHans de Goede sint i; 976554c0a3aSHans de Goede 977554c0a3aSHans de Goede for (i = 0; i < 4; i++) { 978554c0a3aSHans de Goede out[i] = a[i] ^ b[i]; 979554c0a3aSHans de Goede } 980554c0a3aSHans de Goede } 981554c0a3aSHans de Goede 982554c0a3aSHans de Goede 983554c0a3aSHans de Goede static u8 sbox(u8 a) 984554c0a3aSHans de Goede { 985554c0a3aSHans de Goede return sbox_table[(sint)a]; 986554c0a3aSHans de Goede } 987554c0a3aSHans de Goede 988554c0a3aSHans de Goede 989554c0a3aSHans de Goede static void next_key(u8 *key, sint round) 990554c0a3aSHans de Goede { 991554c0a3aSHans de Goede u8 rcon; 992554c0a3aSHans de Goede u8 sbox_key[4]; 993554c0a3aSHans de Goede u8 rcon_table[12] = { 994554c0a3aSHans de Goede 0x01, 0x02, 0x04, 0x08, 995554c0a3aSHans de Goede 0x10, 0x20, 0x40, 0x80, 996554c0a3aSHans de Goede 0x1b, 0x36, 0x36, 0x36 997554c0a3aSHans de Goede }; 998554c0a3aSHans de Goede sbox_key[0] = sbox(key[13]); 999554c0a3aSHans de Goede sbox_key[1] = sbox(key[14]); 1000554c0a3aSHans de Goede sbox_key[2] = sbox(key[15]); 1001554c0a3aSHans de Goede sbox_key[3] = sbox(key[12]); 1002554c0a3aSHans de Goede 1003554c0a3aSHans de Goede rcon = rcon_table[round]; 1004554c0a3aSHans de Goede 1005554c0a3aSHans de Goede xor_32(&key[0], sbox_key, &key[0]); 1006554c0a3aSHans de Goede key[0] = key[0] ^ rcon; 1007554c0a3aSHans de Goede 1008554c0a3aSHans de Goede xor_32(&key[4], &key[0], &key[4]); 1009554c0a3aSHans de Goede xor_32(&key[8], &key[4], &key[8]); 1010554c0a3aSHans de Goede xor_32(&key[12], &key[8], &key[12]); 1011554c0a3aSHans de Goede } 1012554c0a3aSHans de Goede 1013554c0a3aSHans de Goede 1014554c0a3aSHans de Goede static void byte_sub(u8 *in, u8 *out) 1015554c0a3aSHans de Goede { 1016554c0a3aSHans de Goede sint i; 1017554c0a3aSHans de Goede 1018554c0a3aSHans de Goede for (i = 0; i < 16; i++) { 1019554c0a3aSHans de Goede out[i] = sbox(in[i]); 1020554c0a3aSHans de Goede } 1021554c0a3aSHans de Goede } 1022554c0a3aSHans de Goede 1023554c0a3aSHans de Goede 1024554c0a3aSHans de Goede static void shift_row(u8 *in, u8 *out) 1025554c0a3aSHans de Goede { 1026554c0a3aSHans de Goede out[0] = in[0]; 1027554c0a3aSHans de Goede out[1] = in[5]; 1028554c0a3aSHans de Goede out[2] = in[10]; 1029554c0a3aSHans de Goede out[3] = in[15]; 1030554c0a3aSHans de Goede out[4] = in[4]; 1031554c0a3aSHans de Goede out[5] = in[9]; 1032554c0a3aSHans de Goede out[6] = in[14]; 1033554c0a3aSHans de Goede out[7] = in[3]; 1034554c0a3aSHans de Goede out[8] = in[8]; 1035554c0a3aSHans de Goede out[9] = in[13]; 1036554c0a3aSHans de Goede out[10] = in[2]; 1037554c0a3aSHans de Goede out[11] = in[7]; 1038554c0a3aSHans de Goede out[12] = in[12]; 1039554c0a3aSHans de Goede out[13] = in[1]; 1040554c0a3aSHans de Goede out[14] = in[6]; 1041554c0a3aSHans de Goede out[15] = in[11]; 1042554c0a3aSHans de Goede } 1043554c0a3aSHans de Goede 1044554c0a3aSHans de Goede 1045554c0a3aSHans de Goede static void mix_column(u8 *in, u8 *out) 1046554c0a3aSHans de Goede { 1047554c0a3aSHans de Goede sint i; 1048554c0a3aSHans de Goede u8 add1b[4]; 1049554c0a3aSHans de Goede u8 add1bf7[4]; 1050554c0a3aSHans de Goede u8 rotl[4]; 1051554c0a3aSHans de Goede u8 swap_halfs[4]; 1052554c0a3aSHans de Goede u8 andf7[4]; 1053554c0a3aSHans de Goede u8 rotr[4]; 1054554c0a3aSHans de Goede u8 temp[4]; 1055554c0a3aSHans de Goede u8 tempb[4]; 1056554c0a3aSHans de Goede 1057554c0a3aSHans de Goede for (i = 0; i < 4; i++) { 1058554c0a3aSHans de Goede if ((in[i] & 0x80) == 0x80) 1059554c0a3aSHans de Goede add1b[i] = 0x1b; 1060554c0a3aSHans de Goede else 1061554c0a3aSHans de Goede add1b[i] = 0x00; 1062554c0a3aSHans de Goede } 1063554c0a3aSHans de Goede 1064554c0a3aSHans de Goede swap_halfs[0] = in[2]; /* Swap halfs */ 1065554c0a3aSHans de Goede swap_halfs[1] = in[3]; 1066554c0a3aSHans de Goede swap_halfs[2] = in[0]; 1067554c0a3aSHans de Goede swap_halfs[3] = in[1]; 1068554c0a3aSHans de Goede 1069554c0a3aSHans de Goede rotl[0] = in[3]; /* Rotate left 8 bits */ 1070554c0a3aSHans de Goede rotl[1] = in[0]; 1071554c0a3aSHans de Goede rotl[2] = in[1]; 1072554c0a3aSHans de Goede rotl[3] = in[2]; 1073554c0a3aSHans de Goede 1074554c0a3aSHans de Goede andf7[0] = in[0] & 0x7f; 1075554c0a3aSHans de Goede andf7[1] = in[1] & 0x7f; 1076554c0a3aSHans de Goede andf7[2] = in[2] & 0x7f; 1077554c0a3aSHans de Goede andf7[3] = in[3] & 0x7f; 1078554c0a3aSHans de Goede 1079554c0a3aSHans de Goede for (i = 3; i > 0; i--) { /* logical shift left 1 bit */ 1080554c0a3aSHans de Goede andf7[i] = andf7[i] << 1; 1081554c0a3aSHans de Goede if ((andf7[i-1] & 0x80) == 0x80) 1082554c0a3aSHans de Goede andf7[i] = (andf7[i] | 0x01); 1083554c0a3aSHans de Goede } 1084554c0a3aSHans de Goede andf7[0] = andf7[0] << 1; 1085554c0a3aSHans de Goede andf7[0] = andf7[0] & 0xfe; 1086554c0a3aSHans de Goede 1087554c0a3aSHans de Goede xor_32(add1b, andf7, add1bf7); 1088554c0a3aSHans de Goede 1089554c0a3aSHans de Goede xor_32(in, add1bf7, rotr); 1090554c0a3aSHans de Goede 1091554c0a3aSHans de Goede temp[0] = rotr[0]; /* Rotate right 8 bits */ 1092554c0a3aSHans de Goede rotr[0] = rotr[1]; 1093554c0a3aSHans de Goede rotr[1] = rotr[2]; 1094554c0a3aSHans de Goede rotr[2] = rotr[3]; 1095554c0a3aSHans de Goede rotr[3] = temp[0]; 1096554c0a3aSHans de Goede 1097554c0a3aSHans de Goede xor_32(add1bf7, rotr, temp); 1098554c0a3aSHans de Goede xor_32(swap_halfs, rotl, tempb); 1099554c0a3aSHans de Goede xor_32(temp, tempb, out); 1100554c0a3aSHans de Goede } 1101554c0a3aSHans de Goede 1102554c0a3aSHans de Goede static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext) 1103554c0a3aSHans de Goede { 1104554c0a3aSHans de Goede sint round; 1105554c0a3aSHans de Goede sint i; 1106554c0a3aSHans de Goede u8 intermediatea[16]; 1107554c0a3aSHans de Goede u8 intermediateb[16]; 1108554c0a3aSHans de Goede u8 round_key[16]; 1109554c0a3aSHans de Goede 1110554c0a3aSHans de Goede for (i = 0; i < 16; i++) 1111554c0a3aSHans de Goede round_key[i] = key[i]; 1112554c0a3aSHans de Goede 1113554c0a3aSHans de Goede for (round = 0; round < 11; round++) { 1114554c0a3aSHans de Goede if (round == 0) { 1115554c0a3aSHans de Goede xor_128(round_key, data, ciphertext); 1116554c0a3aSHans de Goede next_key(round_key, round); 1117554c0a3aSHans de Goede } else if (round == 10) { 1118554c0a3aSHans de Goede byte_sub(ciphertext, intermediatea); 1119554c0a3aSHans de Goede shift_row(intermediatea, intermediateb); 1120554c0a3aSHans de Goede xor_128(intermediateb, round_key, ciphertext); 1121554c0a3aSHans de Goede } else{ /* 1 - 9 */ 1122554c0a3aSHans de Goede byte_sub(ciphertext, intermediatea); 1123554c0a3aSHans de Goede shift_row(intermediatea, intermediateb); 1124554c0a3aSHans de Goede mix_column(&intermediateb[0], &intermediatea[0]); 1125554c0a3aSHans de Goede mix_column(&intermediateb[4], &intermediatea[4]); 1126554c0a3aSHans de Goede mix_column(&intermediateb[8], &intermediatea[8]); 1127554c0a3aSHans de Goede mix_column(&intermediateb[12], &intermediatea[12]); 1128554c0a3aSHans de Goede xor_128(intermediatea, round_key, ciphertext); 1129554c0a3aSHans de Goede next_key(round_key, round); 1130554c0a3aSHans de Goede } 1131554c0a3aSHans de Goede } 1132554c0a3aSHans de Goede } 1133554c0a3aSHans de Goede 1134554c0a3aSHans de Goede 1135554c0a3aSHans de Goede /************************************************/ 1136554c0a3aSHans de Goede /* construct_mic_iv() */ 1137554c0a3aSHans de Goede /* Builds the MIC IV from header fields and PN */ 1138554c0a3aSHans de Goede /* Baron think the function is construct CCM */ 1139554c0a3aSHans de Goede /* nonce */ 1140554c0a3aSHans de Goede /************************************************/ 1141554c0a3aSHans de Goede static void construct_mic_iv( 1142554c0a3aSHans de Goede u8 *mic_iv, 1143554c0a3aSHans de Goede sint qc_exists, 1144554c0a3aSHans de Goede sint a4_exists, 1145554c0a3aSHans de Goede u8 *mpdu, 1146554c0a3aSHans de Goede uint payload_length, 1147554c0a3aSHans de Goede u8 *pn_vector, 1148554c0a3aSHans de Goede uint frtype/* add for CONFIG_IEEE80211W, none 11w also can use */ 1149554c0a3aSHans de Goede ) 1150554c0a3aSHans de Goede { 1151554c0a3aSHans de Goede sint i; 1152554c0a3aSHans de Goede 1153554c0a3aSHans de Goede mic_iv[0] = 0x59; 1154554c0a3aSHans de Goede 1155554c0a3aSHans de Goede if (qc_exists && a4_exists) 1156554c0a3aSHans de Goede mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */ 1157554c0a3aSHans de Goede 1158554c0a3aSHans de Goede if (qc_exists && !a4_exists) 1159554c0a3aSHans de Goede mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */ 1160554c0a3aSHans de Goede 1161554c0a3aSHans de Goede if (!qc_exists) 1162554c0a3aSHans de Goede mic_iv[1] = 0x00; 1163554c0a3aSHans de Goede 1164554c0a3aSHans de Goede /* 802.11w management frame should set management bit(4) */ 1165554c0a3aSHans de Goede if (frtype == WIFI_MGT_TYPE) 1166554c0a3aSHans de Goede mic_iv[1] |= BIT(4); 1167554c0a3aSHans de Goede 1168554c0a3aSHans de Goede for (i = 2; i < 8; i++) 1169554c0a3aSHans de Goede mic_iv[i] = mpdu[i + 8]; /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */ 1170554c0a3aSHans de Goede #ifdef CONSISTENT_PN_ORDER 1171554c0a3aSHans de Goede for (i = 8; i < 14; i++) 1172554c0a3aSHans de Goede mic_iv[i] = pn_vector[i - 8]; /* mic_iv[8:13] = PN[0:5] */ 1173554c0a3aSHans de Goede #else 1174554c0a3aSHans de Goede for (i = 8; i < 14; i++) 1175554c0a3aSHans de Goede mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */ 1176554c0a3aSHans de Goede #endif 1177554c0a3aSHans de Goede mic_iv[14] = (unsigned char) (payload_length / 256); 1178554c0a3aSHans de Goede mic_iv[15] = (unsigned char) (payload_length % 256); 1179554c0a3aSHans de Goede } 1180554c0a3aSHans de Goede 1181554c0a3aSHans de Goede 1182554c0a3aSHans de Goede /************************************************/ 1183554c0a3aSHans de Goede /* construct_mic_header1() */ 1184554c0a3aSHans de Goede /* Builds the first MIC header block from */ 1185554c0a3aSHans de Goede /* header fields. */ 1186554c0a3aSHans de Goede /* Build AAD SC, A1, A2 */ 1187554c0a3aSHans de Goede /************************************************/ 1188554c0a3aSHans de Goede static void construct_mic_header1( 1189554c0a3aSHans de Goede u8 *mic_header1, 1190554c0a3aSHans de Goede sint header_length, 1191554c0a3aSHans de Goede u8 *mpdu, 1192554c0a3aSHans de Goede uint frtype/* add for CONFIG_IEEE80211W, none 11w also can use */ 1193554c0a3aSHans de Goede ) 1194554c0a3aSHans de Goede { 1195554c0a3aSHans de Goede mic_header1[0] = (u8)((header_length - 2) / 256); 1196554c0a3aSHans de Goede mic_header1[1] = (u8)((header_length - 2) % 256); 1197554c0a3aSHans de Goede 1198554c0a3aSHans de Goede /* 802.11w management frame don't AND subtype bits 4, 5, 6 of frame control field */ 1199554c0a3aSHans de Goede if (frtype == WIFI_MGT_TYPE) 1200554c0a3aSHans de Goede mic_header1[2] = mpdu[0]; 1201554c0a3aSHans de Goede else 1202554c0a3aSHans de Goede mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */ 1203554c0a3aSHans de Goede 1204554c0a3aSHans de Goede mic_header1[3] = mpdu[1] & 0xc7; /* Mute retry, more data and pwr mgt bits */ 1205554c0a3aSHans de Goede mic_header1[4] = mpdu[4]; /* A1 */ 1206554c0a3aSHans de Goede mic_header1[5] = mpdu[5]; 1207554c0a3aSHans de Goede mic_header1[6] = mpdu[6]; 1208554c0a3aSHans de Goede mic_header1[7] = mpdu[7]; 1209554c0a3aSHans de Goede mic_header1[8] = mpdu[8]; 1210554c0a3aSHans de Goede mic_header1[9] = mpdu[9]; 1211554c0a3aSHans de Goede mic_header1[10] = mpdu[10]; /* A2 */ 1212554c0a3aSHans de Goede mic_header1[11] = mpdu[11]; 1213554c0a3aSHans de Goede mic_header1[12] = mpdu[12]; 1214554c0a3aSHans de Goede mic_header1[13] = mpdu[13]; 1215554c0a3aSHans de Goede mic_header1[14] = mpdu[14]; 1216554c0a3aSHans de Goede mic_header1[15] = mpdu[15]; 1217554c0a3aSHans de Goede } 1218554c0a3aSHans de Goede 1219554c0a3aSHans de Goede 1220554c0a3aSHans de Goede /************************************************/ 1221554c0a3aSHans de Goede /* construct_mic_header2() */ 1222554c0a3aSHans de Goede /* Builds the last MIC header block from */ 1223554c0a3aSHans de Goede /* header fields. */ 1224554c0a3aSHans de Goede /************************************************/ 1225554c0a3aSHans de Goede static void construct_mic_header2( 1226554c0a3aSHans de Goede u8 *mic_header2, 1227554c0a3aSHans de Goede u8 *mpdu, 1228554c0a3aSHans de Goede sint a4_exists, 1229554c0a3aSHans de Goede sint qc_exists 1230554c0a3aSHans de Goede ) 1231554c0a3aSHans de Goede { 1232554c0a3aSHans de Goede sint i; 1233554c0a3aSHans de Goede 1234554c0a3aSHans de Goede for (i = 0; i < 16; i++) 1235554c0a3aSHans de Goede mic_header2[i] = 0x00; 1236554c0a3aSHans de Goede 1237554c0a3aSHans de Goede mic_header2[0] = mpdu[16]; /* A3 */ 1238554c0a3aSHans de Goede mic_header2[1] = mpdu[17]; 1239554c0a3aSHans de Goede mic_header2[2] = mpdu[18]; 1240554c0a3aSHans de Goede mic_header2[3] = mpdu[19]; 1241554c0a3aSHans de Goede mic_header2[4] = mpdu[20]; 1242554c0a3aSHans de Goede mic_header2[5] = mpdu[21]; 1243554c0a3aSHans de Goede 1244554c0a3aSHans de Goede mic_header2[6] = 0x00; 1245554c0a3aSHans de Goede mic_header2[7] = 0x00; /* mpdu[23]; */ 1246554c0a3aSHans de Goede 1247554c0a3aSHans de Goede 1248554c0a3aSHans de Goede if (!qc_exists && a4_exists) { 1249554c0a3aSHans de Goede for (i = 0; i < 6; i++) 1250554c0a3aSHans de Goede mic_header2[8+i] = mpdu[24+i]; /* A4 */ 1251554c0a3aSHans de Goede 1252554c0a3aSHans de Goede } 1253554c0a3aSHans de Goede 1254554c0a3aSHans de Goede if (qc_exists && !a4_exists) { 1255554c0a3aSHans de Goede mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */ 1256554c0a3aSHans de Goede mic_header2[9] = mpdu[25] & 0x00; 1257554c0a3aSHans de Goede } 1258554c0a3aSHans de Goede 1259554c0a3aSHans de Goede if (qc_exists && a4_exists) { 1260554c0a3aSHans de Goede for (i = 0; i < 6; i++) 1261554c0a3aSHans de Goede mic_header2[8+i] = mpdu[24+i]; /* A4 */ 1262554c0a3aSHans de Goede 1263554c0a3aSHans de Goede mic_header2[14] = mpdu[30] & 0x0f; 1264554c0a3aSHans de Goede mic_header2[15] = mpdu[31] & 0x00; 1265554c0a3aSHans de Goede } 1266554c0a3aSHans de Goede 1267554c0a3aSHans de Goede } 1268554c0a3aSHans de Goede 1269554c0a3aSHans de Goede /************************************************/ 1270554c0a3aSHans de Goede /* construct_mic_header2() */ 1271554c0a3aSHans de Goede /* Builds the last MIC header block from */ 1272554c0a3aSHans de Goede /* header fields. */ 1273554c0a3aSHans de Goede /* Baron think the function is construct CCM */ 1274554c0a3aSHans de Goede /* nonce */ 1275554c0a3aSHans de Goede /************************************************/ 1276554c0a3aSHans de Goede static void construct_ctr_preload( 1277554c0a3aSHans de Goede u8 *ctr_preload, 1278554c0a3aSHans de Goede sint a4_exists, 1279554c0a3aSHans de Goede sint qc_exists, 1280554c0a3aSHans de Goede u8 *mpdu, 1281554c0a3aSHans de Goede u8 *pn_vector, 1282554c0a3aSHans de Goede sint c, 1283554c0a3aSHans de Goede uint frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1284554c0a3aSHans de Goede ) 1285554c0a3aSHans de Goede { 1286554c0a3aSHans de Goede sint i = 0; 1287554c0a3aSHans de Goede 1288554c0a3aSHans de Goede for (i = 0; i < 16; i++) 1289554c0a3aSHans de Goede ctr_preload[i] = 0x00; 1290554c0a3aSHans de Goede i = 0; 1291554c0a3aSHans de Goede 1292554c0a3aSHans de Goede ctr_preload[0] = 0x01; /* flag */ 1293554c0a3aSHans de Goede if (qc_exists && a4_exists) 1294554c0a3aSHans de Goede ctr_preload[1] = mpdu[30] & 0x0f; /* QoC_Control */ 1295554c0a3aSHans de Goede if (qc_exists && !a4_exists) 1296554c0a3aSHans de Goede ctr_preload[1] = mpdu[24] & 0x0f; 1297554c0a3aSHans de Goede 1298554c0a3aSHans de Goede /* 802.11w management frame should set management bit(4) */ 1299554c0a3aSHans de Goede if (frtype == WIFI_MGT_TYPE) 1300554c0a3aSHans de Goede ctr_preload[1] |= BIT(4); 1301554c0a3aSHans de Goede 1302554c0a3aSHans de Goede for (i = 2; i < 8; i++) 1303554c0a3aSHans de Goede ctr_preload[i] = mpdu[i + 8]; /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */ 1304554c0a3aSHans de Goede #ifdef CONSISTENT_PN_ORDER 1305554c0a3aSHans de Goede for (i = 8; i < 14; i++) 1306554c0a3aSHans de Goede ctr_preload[i] = pn_vector[i - 8]; /* ctr_preload[8:13] = PN[0:5] */ 1307554c0a3aSHans de Goede #else 1308554c0a3aSHans de Goede for (i = 8; i < 14; i++) 1309554c0a3aSHans de Goede ctr_preload[i] = pn_vector[13 - i]; /* ctr_preload[8:13] = PN[5:0] */ 1310554c0a3aSHans de Goede #endif 1311554c0a3aSHans de Goede ctr_preload[14] = (unsigned char) (c / 256); /* Ctr */ 1312554c0a3aSHans de Goede ctr_preload[15] = (unsigned char) (c % 256); 1313554c0a3aSHans de Goede } 1314554c0a3aSHans de Goede 1315554c0a3aSHans de Goede 1316554c0a3aSHans de Goede /************************************/ 1317554c0a3aSHans de Goede /* bitwise_xor() */ 1318554c0a3aSHans de Goede /* A 128 bit, bitwise exclusive or */ 1319554c0a3aSHans de Goede /************************************/ 1320554c0a3aSHans de Goede static void bitwise_xor(u8 *ina, u8 *inb, u8 *out) 1321554c0a3aSHans de Goede { 1322554c0a3aSHans de Goede sint i; 1323554c0a3aSHans de Goede 1324554c0a3aSHans de Goede for (i = 0; i < 16; i++) { 1325554c0a3aSHans de Goede out[i] = ina[i] ^ inb[i]; 1326554c0a3aSHans de Goede } 1327554c0a3aSHans de Goede } 1328554c0a3aSHans de Goede 1329554c0a3aSHans de Goede 1330554c0a3aSHans de Goede static sint aes_cipher(u8 *key, uint hdrlen, 1331554c0a3aSHans de Goede u8 *pframe, uint plen) 1332554c0a3aSHans de Goede { 1333554c0a3aSHans de Goede uint qc_exists, a4_exists, i, j, payload_remainder, 1334554c0a3aSHans de Goede num_blocks, payload_index; 1335554c0a3aSHans de Goede 1336554c0a3aSHans de Goede u8 pn_vector[6]; 1337554c0a3aSHans de Goede u8 mic_iv[16]; 1338554c0a3aSHans de Goede u8 mic_header1[16]; 1339554c0a3aSHans de Goede u8 mic_header2[16]; 1340554c0a3aSHans de Goede u8 ctr_preload[16]; 1341554c0a3aSHans de Goede 1342554c0a3aSHans de Goede /* Intermediate Buffers */ 1343554c0a3aSHans de Goede u8 chain_buffer[16]; 1344554c0a3aSHans de Goede u8 aes_out[16]; 1345554c0a3aSHans de Goede u8 padded_buffer[16]; 1346554c0a3aSHans de Goede u8 mic[8]; 1347554c0a3aSHans de Goede uint frtype = GetFrameType(pframe); 1348554c0a3aSHans de Goede uint frsubtype = GetFrameSubType(pframe); 1349554c0a3aSHans de Goede 1350554c0a3aSHans de Goede frsubtype = frsubtype>>4; 1351554c0a3aSHans de Goede 1352554c0a3aSHans de Goede 1353554c0a3aSHans de Goede memset((void *)mic_iv, 0, 16); 1354554c0a3aSHans de Goede memset((void *)mic_header1, 0, 16); 1355554c0a3aSHans de Goede memset((void *)mic_header2, 0, 16); 1356554c0a3aSHans de Goede memset((void *)ctr_preload, 0, 16); 1357554c0a3aSHans de Goede memset((void *)chain_buffer, 0, 16); 1358554c0a3aSHans de Goede memset((void *)aes_out, 0, 16); 1359554c0a3aSHans de Goede memset((void *)padded_buffer, 0, 16); 1360554c0a3aSHans de Goede 1361554c0a3aSHans de Goede if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) 1362554c0a3aSHans de Goede a4_exists = 0; 1363554c0a3aSHans de Goede else 1364554c0a3aSHans de Goede a4_exists = 1; 1365554c0a3aSHans de Goede 13660ba8d4b9SLarry Finger if (((frtype|frsubtype) == WIFI_DATA_CFACK) || 1367554c0a3aSHans de Goede ((frtype|frsubtype) == WIFI_DATA_CFPOLL) || 1368554c0a3aSHans de Goede ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { 1369554c0a3aSHans de Goede qc_exists = 1; 1370554c0a3aSHans de Goede if (hdrlen != WLAN_HDR_A3_QOS_LEN) 1371554c0a3aSHans de Goede hdrlen += 2; 1372554c0a3aSHans de Goede 1373554c0a3aSHans de Goede } else if ((frtype == WIFI_DATA) && /* add for CONFIG_IEEE80211W, none 11w also can use */ 1374554c0a3aSHans de Goede ((frsubtype == 0x08) || 1375554c0a3aSHans de Goede (frsubtype == 0x09) || 1376554c0a3aSHans de Goede (frsubtype == 0x0a) || 1377554c0a3aSHans de Goede (frsubtype == 0x0b))) { 1378554c0a3aSHans de Goede if (hdrlen != WLAN_HDR_A3_QOS_LEN) 1379554c0a3aSHans de Goede hdrlen += 2; 1380554c0a3aSHans de Goede 1381554c0a3aSHans de Goede qc_exists = 1; 1382554c0a3aSHans de Goede } else 1383554c0a3aSHans de Goede qc_exists = 0; 1384554c0a3aSHans de Goede 1385554c0a3aSHans de Goede pn_vector[0] = pframe[hdrlen]; 1386554c0a3aSHans de Goede pn_vector[1] = pframe[hdrlen+1]; 1387554c0a3aSHans de Goede pn_vector[2] = pframe[hdrlen+4]; 1388554c0a3aSHans de Goede pn_vector[3] = pframe[hdrlen+5]; 1389554c0a3aSHans de Goede pn_vector[4] = pframe[hdrlen+6]; 1390554c0a3aSHans de Goede pn_vector[5] = pframe[hdrlen+7]; 1391554c0a3aSHans de Goede 1392554c0a3aSHans de Goede construct_mic_iv( 1393554c0a3aSHans de Goede mic_iv, 1394554c0a3aSHans de Goede qc_exists, 1395554c0a3aSHans de Goede a4_exists, 1396554c0a3aSHans de Goede pframe, /* message, */ 1397554c0a3aSHans de Goede plen, 1398554c0a3aSHans de Goede pn_vector, 1399554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1400554c0a3aSHans de Goede ); 1401554c0a3aSHans de Goede 1402554c0a3aSHans de Goede construct_mic_header1( 1403554c0a3aSHans de Goede mic_header1, 1404554c0a3aSHans de Goede hdrlen, 1405554c0a3aSHans de Goede pframe, /* message */ 1406554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1407554c0a3aSHans de Goede ); 1408554c0a3aSHans de Goede construct_mic_header2( 1409554c0a3aSHans de Goede mic_header2, 1410554c0a3aSHans de Goede pframe, /* message, */ 1411554c0a3aSHans de Goede a4_exists, 1412554c0a3aSHans de Goede qc_exists 1413554c0a3aSHans de Goede ); 1414554c0a3aSHans de Goede 1415554c0a3aSHans de Goede 1416554c0a3aSHans de Goede payload_remainder = plen % 16; 1417554c0a3aSHans de Goede num_blocks = plen / 16; 1418554c0a3aSHans de Goede 1419554c0a3aSHans de Goede /* Find start of payload */ 1420554c0a3aSHans de Goede payload_index = (hdrlen + 8); 1421554c0a3aSHans de Goede 1422554c0a3aSHans de Goede /* Calculate MIC */ 1423554c0a3aSHans de Goede aes128k128d(key, mic_iv, aes_out); 1424554c0a3aSHans de Goede bitwise_xor(aes_out, mic_header1, chain_buffer); 1425554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1426554c0a3aSHans de Goede bitwise_xor(aes_out, mic_header2, chain_buffer); 1427554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1428554c0a3aSHans de Goede 1429554c0a3aSHans de Goede for (i = 0; i < num_blocks; i++) { 1430554c0a3aSHans de Goede bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */ 1431554c0a3aSHans de Goede 1432554c0a3aSHans de Goede payload_index += 16; 1433554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1434554c0a3aSHans de Goede } 1435554c0a3aSHans de Goede 1436554c0a3aSHans de Goede /* Add on the final payload block if it needs padding */ 1437554c0a3aSHans de Goede if (payload_remainder > 0) { 1438554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1439554c0a3aSHans de Goede padded_buffer[j] = 0x00; 1440554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) { 1441554c0a3aSHans de Goede padded_buffer[j] = pframe[payload_index++];/* padded_buffer[j] = message[payload_index++]; */ 1442554c0a3aSHans de Goede } 1443554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1444554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1445554c0a3aSHans de Goede 1446554c0a3aSHans de Goede } 1447554c0a3aSHans de Goede 1448554c0a3aSHans de Goede for (j = 0 ; j < 8; j++) 1449554c0a3aSHans de Goede mic[j] = aes_out[j]; 1450554c0a3aSHans de Goede 1451554c0a3aSHans de Goede /* Insert MIC into payload */ 1452554c0a3aSHans de Goede for (j = 0; j < 8; j++) 1453554c0a3aSHans de Goede pframe[payload_index+j] = mic[j]; /* message[payload_index+j] = mic[j]; */ 1454554c0a3aSHans de Goede 1455554c0a3aSHans de Goede payload_index = hdrlen + 8; 1456554c0a3aSHans de Goede for (i = 0; i < num_blocks; i++) { 1457554c0a3aSHans de Goede construct_ctr_preload( 1458554c0a3aSHans de Goede ctr_preload, 1459554c0a3aSHans de Goede a4_exists, 1460554c0a3aSHans de Goede qc_exists, 1461554c0a3aSHans de Goede pframe, /* message, */ 1462554c0a3aSHans de Goede pn_vector, 1463554c0a3aSHans de Goede i+1, 1464554c0a3aSHans de Goede frtype 1465554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1466554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1467554c0a3aSHans de Goede bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);/* bitwise_xor(aes_out, &message[payload_index], chain_buffer); */ 1468554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1469554c0a3aSHans de Goede pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<16;j++) message[payload_index++] = chain_buffer[j]; */ 1470554c0a3aSHans de Goede } 1471554c0a3aSHans de Goede 1472554c0a3aSHans de Goede if (payload_remainder > 0) { 1473554c0a3aSHans de Goede /* If there is a short final block, then pad it,*/ 1474554c0a3aSHans de Goede /* encrypt it and copy the unpadded part back */ 1475554c0a3aSHans de Goede construct_ctr_preload( 1476554c0a3aSHans de Goede ctr_preload, 1477554c0a3aSHans de Goede a4_exists, 1478554c0a3aSHans de Goede qc_exists, 1479554c0a3aSHans de Goede pframe, /* message, */ 1480554c0a3aSHans de Goede pn_vector, 1481554c0a3aSHans de Goede num_blocks+1, 1482554c0a3aSHans de Goede frtype 1483554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1484554c0a3aSHans de Goede 1485554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1486554c0a3aSHans de Goede padded_buffer[j] = 0x00; 14870ba8d4b9SLarry Finger for (j = 0; j < payload_remainder; j++) 1488554c0a3aSHans de Goede padded_buffer[j] = pframe[payload_index+j];/* padded_buffer[j] = message[payload_index+j]; */ 14890ba8d4b9SLarry Finger 1490554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1491554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1492554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) 1493554c0a3aSHans de Goede pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<payload_remainder;j++) message[payload_index++] = chain_buffer[j]; */ 1494554c0a3aSHans de Goede } 1495554c0a3aSHans de Goede 1496554c0a3aSHans de Goede /* Encrypt the MIC */ 1497554c0a3aSHans de Goede construct_ctr_preload( 1498554c0a3aSHans de Goede ctr_preload, 1499554c0a3aSHans de Goede a4_exists, 1500554c0a3aSHans de Goede qc_exists, 1501554c0a3aSHans de Goede pframe, /* message, */ 1502554c0a3aSHans de Goede pn_vector, 1503554c0a3aSHans de Goede 0, 1504554c0a3aSHans de Goede frtype 1505554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1506554c0a3aSHans de Goede 1507554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1508554c0a3aSHans de Goede padded_buffer[j] = 0x00; 15090ba8d4b9SLarry Finger for (j = 0; j < 8; j++) 1510554c0a3aSHans de Goede padded_buffer[j] = pframe[j+hdrlen+8+plen];/* padded_buffer[j] = message[j+hdrlen+8+plen]; */ 1511554c0a3aSHans de Goede 1512554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1513554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1514554c0a3aSHans de Goede for (j = 0; j < 8; j++) 1515554c0a3aSHans de Goede pframe[payload_index++] = chain_buffer[j];/* for (j = 0; j<8;j++) message[payload_index++] = chain_buffer[j]; */ 1516554c0a3aSHans de Goede 1517554c0a3aSHans de Goede return _SUCCESS; 1518554c0a3aSHans de Goede } 1519554c0a3aSHans de Goede 1520554c0a3aSHans de Goede u32 rtw_aes_encrypt(struct adapter *padapter, u8 *pxmitframe) 1521554c0a3aSHans de Goede { /* exclude ICV */ 1522554c0a3aSHans de Goede 1523554c0a3aSHans de Goede 1524554c0a3aSHans de Goede /*static*/ 1525554c0a3aSHans de Goede /* unsigned char message[MAX_MSG_SIZE]; */ 1526554c0a3aSHans de Goede 1527554c0a3aSHans de Goede /* Intermediate Buffers */ 1528554c0a3aSHans de Goede sint curfragnum, length; 1529554c0a3aSHans de Goede u32 prwskeylen; 1530554c0a3aSHans de Goede u8 *pframe, *prwskey; /* *payload,*iv */ 1531554c0a3aSHans de Goede u8 hw_hdr_offset = 0; 1532554c0a3aSHans de Goede /* struct sta_info *stainfo = NULL; */ 1533554c0a3aSHans de Goede struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib; 1534554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1535554c0a3aSHans de Goede struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 1536554c0a3aSHans de Goede 1537554c0a3aSHans de Goede /* uint offset = 0; */ 1538554c0a3aSHans de Goede u32 res = _SUCCESS; 1539554c0a3aSHans de Goede 1540554c0a3aSHans de Goede if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL) 1541554c0a3aSHans de Goede return _FAIL; 1542554c0a3aSHans de Goede 1543554c0a3aSHans de Goede hw_hdr_offset = TXDESC_OFFSET; 1544554c0a3aSHans de Goede pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset; 1545554c0a3aSHans de Goede 1546554c0a3aSHans de Goede /* 4 start to encrypt each fragment */ 1547554c0a3aSHans de Goede if ((pattrib->encrypt == _AES_)) { 1548554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_encrypt: stainfo!= NULL!!!\n")); 1549554c0a3aSHans de Goede 1550554c0a3aSHans de Goede if (IS_MCAST(pattrib->ra)) 1551554c0a3aSHans de Goede prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; 1552554c0a3aSHans de Goede else 1553554c0a3aSHans de Goede /* prwskey =&stainfo->dot118021x_UncstKey.skey[0]; */ 1554554c0a3aSHans de Goede prwskey = pattrib->dot118021x_UncstKey.skey; 1555554c0a3aSHans de Goede 1556554c0a3aSHans de Goede prwskeylen = 16; 1557554c0a3aSHans de Goede 1558554c0a3aSHans de Goede for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { 1559554c0a3aSHans de Goede if ((curfragnum+1) == pattrib->nr_frags) { /* 4 the last fragment */ 1560554c0a3aSHans de Goede length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 1561554c0a3aSHans de Goede 1562554c0a3aSHans de Goede aes_cipher(prwskey, pattrib->hdrlen, pframe, length); 1563554c0a3aSHans de Goede } else { 1564554c0a3aSHans de Goede length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len; 1565554c0a3aSHans de Goede 1566554c0a3aSHans de Goede aes_cipher(prwskey, pattrib->hdrlen, pframe, length); 1567554c0a3aSHans de Goede pframe += pxmitpriv->frag_len; 1568554c0a3aSHans de Goede pframe = (u8 *)RND4((SIZE_PTR)(pframe)); 1569554c0a3aSHans de Goede } 1570554c0a3aSHans de Goede } 1571554c0a3aSHans de Goede 1572554c0a3aSHans de Goede AES_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra); 1573554c0a3aSHans de Goede } 1574554c0a3aSHans de Goede return res; 1575554c0a3aSHans de Goede } 1576554c0a3aSHans de Goede 1577554c0a3aSHans de Goede static sint aes_decipher(u8 *key, uint hdrlen, 1578554c0a3aSHans de Goede u8 *pframe, uint plen) 1579554c0a3aSHans de Goede { 1580554c0a3aSHans de Goede static u8 message[MAX_MSG_SIZE]; 1581554c0a3aSHans de Goede uint qc_exists, a4_exists, i, j, payload_remainder, 1582554c0a3aSHans de Goede num_blocks, payload_index; 1583554c0a3aSHans de Goede sint res = _SUCCESS; 1584554c0a3aSHans de Goede u8 pn_vector[6]; 1585554c0a3aSHans de Goede u8 mic_iv[16]; 1586554c0a3aSHans de Goede u8 mic_header1[16]; 1587554c0a3aSHans de Goede u8 mic_header2[16]; 1588554c0a3aSHans de Goede u8 ctr_preload[16]; 1589554c0a3aSHans de Goede 1590554c0a3aSHans de Goede /* Intermediate Buffers */ 1591554c0a3aSHans de Goede u8 chain_buffer[16]; 1592554c0a3aSHans de Goede u8 aes_out[16]; 1593554c0a3aSHans de Goede u8 padded_buffer[16]; 1594554c0a3aSHans de Goede u8 mic[8]; 1595554c0a3aSHans de Goede 1596554c0a3aSHans de Goede 1597554c0a3aSHans de Goede /* uint offset = 0; */ 1598554c0a3aSHans de Goede uint frtype = GetFrameType(pframe); 1599554c0a3aSHans de Goede uint frsubtype = GetFrameSubType(pframe); 1600554c0a3aSHans de Goede 1601554c0a3aSHans de Goede frsubtype = frsubtype>>4; 1602554c0a3aSHans de Goede 1603554c0a3aSHans de Goede 1604554c0a3aSHans de Goede memset((void *)mic_iv, 0, 16); 1605554c0a3aSHans de Goede memset((void *)mic_header1, 0, 16); 1606554c0a3aSHans de Goede memset((void *)mic_header2, 0, 16); 1607554c0a3aSHans de Goede memset((void *)ctr_preload, 0, 16); 1608554c0a3aSHans de Goede memset((void *)chain_buffer, 0, 16); 1609554c0a3aSHans de Goede memset((void *)aes_out, 0, 16); 1610554c0a3aSHans de Goede memset((void *)padded_buffer, 0, 16); 1611554c0a3aSHans de Goede 1612554c0a3aSHans de Goede /* start to decrypt the payload */ 1613554c0a3aSHans de Goede 1614554c0a3aSHans de Goede num_blocks = (plen-8) / 16; /* plen including LLC, payload_length and mic) */ 1615554c0a3aSHans de Goede 1616554c0a3aSHans de Goede payload_remainder = (plen-8) % 16; 1617554c0a3aSHans de Goede 1618554c0a3aSHans de Goede pn_vector[0] = pframe[hdrlen]; 1619554c0a3aSHans de Goede pn_vector[1] = pframe[hdrlen+1]; 1620554c0a3aSHans de Goede pn_vector[2] = pframe[hdrlen+4]; 1621554c0a3aSHans de Goede pn_vector[3] = pframe[hdrlen+5]; 1622554c0a3aSHans de Goede pn_vector[4] = pframe[hdrlen+6]; 1623554c0a3aSHans de Goede pn_vector[5] = pframe[hdrlen+7]; 1624554c0a3aSHans de Goede 1625554c0a3aSHans de Goede if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN)) 1626554c0a3aSHans de Goede a4_exists = 0; 1627554c0a3aSHans de Goede else 1628554c0a3aSHans de Goede a4_exists = 1; 1629554c0a3aSHans de Goede 16300ba8d4b9SLarry Finger if (((frtype|frsubtype) == WIFI_DATA_CFACK) || 1631554c0a3aSHans de Goede ((frtype|frsubtype) == WIFI_DATA_CFPOLL) || 1632554c0a3aSHans de Goede ((frtype|frsubtype) == WIFI_DATA_CFACKPOLL)) { 1633554c0a3aSHans de Goede qc_exists = 1; 1634554c0a3aSHans de Goede if (hdrlen != WLAN_HDR_A3_QOS_LEN) { 1635554c0a3aSHans de Goede hdrlen += 2; 1636554c0a3aSHans de Goede } 1637554c0a3aSHans de Goede } else if ((frtype == WIFI_DATA) && /* only for data packet . add for CONFIG_IEEE80211W, none 11w also can use */ 1638554c0a3aSHans de Goede ((frsubtype == 0x08) || 1639554c0a3aSHans de Goede (frsubtype == 0x09) || 1640554c0a3aSHans de Goede (frsubtype == 0x0a) || 1641554c0a3aSHans de Goede (frsubtype == 0x0b))) { 1642554c0a3aSHans de Goede if (hdrlen != WLAN_HDR_A3_QOS_LEN) { 1643554c0a3aSHans de Goede hdrlen += 2; 1644554c0a3aSHans de Goede } 1645554c0a3aSHans de Goede qc_exists = 1; 1646554c0a3aSHans de Goede } else 1647554c0a3aSHans de Goede qc_exists = 0; 1648554c0a3aSHans de Goede 1649554c0a3aSHans de Goede 1650554c0a3aSHans de Goede /* now, decrypt pframe with hdrlen offset and plen long */ 1651554c0a3aSHans de Goede 1652554c0a3aSHans de Goede payload_index = hdrlen + 8; /* 8 is for extiv */ 1653554c0a3aSHans de Goede 1654554c0a3aSHans de Goede for (i = 0; i < num_blocks; i++) { 1655554c0a3aSHans de Goede construct_ctr_preload( 1656554c0a3aSHans de Goede ctr_preload, 1657554c0a3aSHans de Goede a4_exists, 1658554c0a3aSHans de Goede qc_exists, 1659554c0a3aSHans de Goede pframe, 1660554c0a3aSHans de Goede pn_vector, 1661554c0a3aSHans de Goede i+1, 1662554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1663554c0a3aSHans de Goede ); 1664554c0a3aSHans de Goede 1665554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1666554c0a3aSHans de Goede bitwise_xor(aes_out, &pframe[payload_index], chain_buffer); 1667554c0a3aSHans de Goede 1668554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1669554c0a3aSHans de Goede pframe[payload_index++] = chain_buffer[j]; 1670554c0a3aSHans de Goede } 1671554c0a3aSHans de Goede 1672554c0a3aSHans de Goede if (payload_remainder > 0) { 1673554c0a3aSHans de Goede /* If there is a short final block, then pad it,*/ 1674554c0a3aSHans de Goede /* encrypt it and copy the unpadded part back */ 1675554c0a3aSHans de Goede construct_ctr_preload( 1676554c0a3aSHans de Goede ctr_preload, 1677554c0a3aSHans de Goede a4_exists, 1678554c0a3aSHans de Goede qc_exists, 1679554c0a3aSHans de Goede pframe, 1680554c0a3aSHans de Goede pn_vector, 1681554c0a3aSHans de Goede num_blocks+1, 1682554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1683554c0a3aSHans de Goede ); 1684554c0a3aSHans de Goede 1685554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1686554c0a3aSHans de Goede padded_buffer[j] = 0x00; 1687554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) { 1688554c0a3aSHans de Goede padded_buffer[j] = pframe[payload_index+j]; 1689554c0a3aSHans de Goede } 1690554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1691554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1692554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) 1693554c0a3aSHans de Goede pframe[payload_index++] = chain_buffer[j]; 1694554c0a3aSHans de Goede } 1695554c0a3aSHans de Goede 1696554c0a3aSHans de Goede /* start to calculate the mic */ 1697554c0a3aSHans de Goede if ((hdrlen + plen+8) <= MAX_MSG_SIZE) 1698554c0a3aSHans de Goede memcpy((void *)message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv len */ 1699554c0a3aSHans de Goede 1700554c0a3aSHans de Goede 1701554c0a3aSHans de Goede pn_vector[0] = pframe[hdrlen]; 1702554c0a3aSHans de Goede pn_vector[1] = pframe[hdrlen+1]; 1703554c0a3aSHans de Goede pn_vector[2] = pframe[hdrlen+4]; 1704554c0a3aSHans de Goede pn_vector[3] = pframe[hdrlen+5]; 1705554c0a3aSHans de Goede pn_vector[4] = pframe[hdrlen+6]; 1706554c0a3aSHans de Goede pn_vector[5] = pframe[hdrlen+7]; 1707554c0a3aSHans de Goede 1708554c0a3aSHans de Goede 1709554c0a3aSHans de Goede 1710554c0a3aSHans de Goede construct_mic_iv( 1711554c0a3aSHans de Goede mic_iv, 1712554c0a3aSHans de Goede qc_exists, 1713554c0a3aSHans de Goede a4_exists, 1714554c0a3aSHans de Goede message, 1715554c0a3aSHans de Goede plen-8, 1716554c0a3aSHans de Goede pn_vector, 1717554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1718554c0a3aSHans de Goede ); 1719554c0a3aSHans de Goede 1720554c0a3aSHans de Goede construct_mic_header1( 1721554c0a3aSHans de Goede mic_header1, 1722554c0a3aSHans de Goede hdrlen, 1723554c0a3aSHans de Goede message, 1724554c0a3aSHans de Goede frtype /* add for CONFIG_IEEE80211W, none 11w also can use */ 1725554c0a3aSHans de Goede ); 1726554c0a3aSHans de Goede construct_mic_header2( 1727554c0a3aSHans de Goede mic_header2, 1728554c0a3aSHans de Goede message, 1729554c0a3aSHans de Goede a4_exists, 1730554c0a3aSHans de Goede qc_exists 1731554c0a3aSHans de Goede ); 1732554c0a3aSHans de Goede 1733554c0a3aSHans de Goede 1734554c0a3aSHans de Goede payload_remainder = (plen-8) % 16; 1735554c0a3aSHans de Goede num_blocks = (plen-8) / 16; 1736554c0a3aSHans de Goede 1737554c0a3aSHans de Goede /* Find start of payload */ 1738554c0a3aSHans de Goede payload_index = (hdrlen + 8); 1739554c0a3aSHans de Goede 1740554c0a3aSHans de Goede /* Calculate MIC */ 1741554c0a3aSHans de Goede aes128k128d(key, mic_iv, aes_out); 1742554c0a3aSHans de Goede bitwise_xor(aes_out, mic_header1, chain_buffer); 1743554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1744554c0a3aSHans de Goede bitwise_xor(aes_out, mic_header2, chain_buffer); 1745554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1746554c0a3aSHans de Goede 1747554c0a3aSHans de Goede for (i = 0; i < num_blocks; i++) { 1748554c0a3aSHans de Goede bitwise_xor(aes_out, &message[payload_index], chain_buffer); 1749554c0a3aSHans de Goede 1750554c0a3aSHans de Goede payload_index += 16; 1751554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1752554c0a3aSHans de Goede } 1753554c0a3aSHans de Goede 1754554c0a3aSHans de Goede /* Add on the final payload block if it needs padding */ 1755554c0a3aSHans de Goede if (payload_remainder > 0) { 1756554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1757554c0a3aSHans de Goede padded_buffer[j] = 0x00; 1758554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) { 1759554c0a3aSHans de Goede padded_buffer[j] = message[payload_index++]; 1760554c0a3aSHans de Goede } 1761554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1762554c0a3aSHans de Goede aes128k128d(key, chain_buffer, aes_out); 1763554c0a3aSHans de Goede 1764554c0a3aSHans de Goede } 1765554c0a3aSHans de Goede 1766554c0a3aSHans de Goede for (j = 0; j < 8; j++) 1767554c0a3aSHans de Goede mic[j] = aes_out[j]; 1768554c0a3aSHans de Goede 1769554c0a3aSHans de Goede /* Insert MIC into payload */ 1770554c0a3aSHans de Goede for (j = 0; j < 8; j++) 1771554c0a3aSHans de Goede message[payload_index+j] = mic[j]; 1772554c0a3aSHans de Goede 1773554c0a3aSHans de Goede payload_index = hdrlen + 8; 1774554c0a3aSHans de Goede for (i = 0; i < num_blocks; i++) { 1775554c0a3aSHans de Goede construct_ctr_preload( 1776554c0a3aSHans de Goede ctr_preload, 1777554c0a3aSHans de Goede a4_exists, 1778554c0a3aSHans de Goede qc_exists, 1779554c0a3aSHans de Goede message, 1780554c0a3aSHans de Goede pn_vector, 1781554c0a3aSHans de Goede i+1, 1782554c0a3aSHans de Goede frtype 1783554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1784554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1785554c0a3aSHans de Goede bitwise_xor(aes_out, &message[payload_index], chain_buffer); 1786554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1787554c0a3aSHans de Goede message[payload_index++] = chain_buffer[j]; 1788554c0a3aSHans de Goede } 1789554c0a3aSHans de Goede 1790554c0a3aSHans de Goede if (payload_remainder > 0) { 1791554c0a3aSHans de Goede /* If there is a short final block, then pad it,*/ 1792554c0a3aSHans de Goede /* encrypt it and copy the unpadded part back */ 1793554c0a3aSHans de Goede construct_ctr_preload( 1794554c0a3aSHans de Goede ctr_preload, 1795554c0a3aSHans de Goede a4_exists, 1796554c0a3aSHans de Goede qc_exists, 1797554c0a3aSHans de Goede message, 1798554c0a3aSHans de Goede pn_vector, 1799554c0a3aSHans de Goede num_blocks+1, 1800554c0a3aSHans de Goede frtype 1801554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1802554c0a3aSHans de Goede 1803554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1804554c0a3aSHans de Goede padded_buffer[j] = 0x00; 1805554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) { 1806554c0a3aSHans de Goede padded_buffer[j] = message[payload_index+j]; 1807554c0a3aSHans de Goede } 1808554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1809554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1810554c0a3aSHans de Goede for (j = 0; j < payload_remainder; j++) 1811554c0a3aSHans de Goede message[payload_index++] = chain_buffer[j]; 1812554c0a3aSHans de Goede } 1813554c0a3aSHans de Goede 1814554c0a3aSHans de Goede /* Encrypt the MIC */ 1815554c0a3aSHans de Goede construct_ctr_preload( 1816554c0a3aSHans de Goede ctr_preload, 1817554c0a3aSHans de Goede a4_exists, 1818554c0a3aSHans de Goede qc_exists, 1819554c0a3aSHans de Goede message, 1820554c0a3aSHans de Goede pn_vector, 1821554c0a3aSHans de Goede 0, 1822554c0a3aSHans de Goede frtype 1823554c0a3aSHans de Goede ); /* add for CONFIG_IEEE80211W, none 11w also can use */ 1824554c0a3aSHans de Goede 1825554c0a3aSHans de Goede for (j = 0; j < 16; j++) 1826554c0a3aSHans de Goede padded_buffer[j] = 0x00; 1827554c0a3aSHans de Goede for (j = 0; j < 8; j++) { 1828554c0a3aSHans de Goede padded_buffer[j] = message[j+hdrlen+8+plen-8]; 1829554c0a3aSHans de Goede } 1830554c0a3aSHans de Goede 1831554c0a3aSHans de Goede aes128k128d(key, ctr_preload, aes_out); 1832554c0a3aSHans de Goede bitwise_xor(aes_out, padded_buffer, chain_buffer); 1833554c0a3aSHans de Goede for (j = 0; j < 8; j++) 1834554c0a3aSHans de Goede message[payload_index++] = chain_buffer[j]; 1835554c0a3aSHans de Goede 1836554c0a3aSHans de Goede /* compare the mic */ 1837554c0a3aSHans de Goede for (i = 0; i < 8; i++) { 1838554c0a3aSHans de Goede if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) { 1839554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n", 1840554c0a3aSHans de Goede i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i])); 1841554c0a3aSHans de Goede DBG_871X("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x)\n", 1842554c0a3aSHans de Goede i, pframe[hdrlen+8+plen-8+i], message[hdrlen+8+plen-8+i]); 1843554c0a3aSHans de Goede res = _FAIL; 1844554c0a3aSHans de Goede } 1845554c0a3aSHans de Goede } 1846554c0a3aSHans de Goede return res; 1847554c0a3aSHans de Goede } 1848554c0a3aSHans de Goede 1849554c0a3aSHans de Goede u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe) 1850554c0a3aSHans de Goede { /* exclude ICV */ 1851554c0a3aSHans de Goede 1852554c0a3aSHans de Goede 1853554c0a3aSHans de Goede /*static*/ 1854554c0a3aSHans de Goede /* unsigned char message[MAX_MSG_SIZE]; */ 1855554c0a3aSHans de Goede 1856554c0a3aSHans de Goede 1857554c0a3aSHans de Goede /* Intermediate Buffers */ 1858554c0a3aSHans de Goede 1859554c0a3aSHans de Goede 1860554c0a3aSHans de Goede sint length; 1861554c0a3aSHans de Goede u8 *pframe, *prwskey; /* *payload,*iv */ 1862554c0a3aSHans de Goede struct sta_info *stainfo; 1863554c0a3aSHans de Goede struct rx_pkt_attrib *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib; 1864554c0a3aSHans de Goede struct security_priv *psecuritypriv = &padapter->securitypriv; 1865554c0a3aSHans de Goede /* struct recv_priv *precvpriv =&padapter->recvpriv; */ 1866554c0a3aSHans de Goede u32 res = _SUCCESS; 1867554c0a3aSHans de Goede 1868554c0a3aSHans de Goede pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; 1869554c0a3aSHans de Goede /* 4 start to encrypt each fragment */ 1870554c0a3aSHans de Goede if ((prxattrib->encrypt == _AES_)) { 1871554c0a3aSHans de Goede 1872554c0a3aSHans de Goede stainfo = rtw_get_stainfo(&padapter->stapriv, &prxattrib->ta[0]); 1873554c0a3aSHans de Goede if (stainfo != NULL) { 1874554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo!= NULL!!!\n")); 1875554c0a3aSHans de Goede 1876554c0a3aSHans de Goede if (IS_MCAST(prxattrib->ra)) { 187740d4aa0fSShreeya Patel static unsigned long start; 187840d4aa0fSShreeya Patel static u32 no_gkey_bc_cnt; 187940d4aa0fSShreeya Patel static u32 no_gkey_mc_cnt; 1880554c0a3aSHans de Goede 1881554c0a3aSHans de Goede /* DBG_871X("rx bc/mc packets, to perform sw rtw_aes_decrypt\n"); */ 1882554c0a3aSHans de Goede /* prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey; */ 1883554c0a3aSHans de Goede if (psecuritypriv->binstallGrpkey == false) { 1884554c0a3aSHans de Goede res = _FAIL; 1885554c0a3aSHans de Goede 1886554c0a3aSHans de Goede if (start == 0) 1887554c0a3aSHans de Goede start = jiffies; 1888554c0a3aSHans de Goede 1889554c0a3aSHans de Goede if (is_broadcast_mac_addr(prxattrib->ra)) 1890554c0a3aSHans de Goede no_gkey_bc_cnt++; 1891554c0a3aSHans de Goede else 1892554c0a3aSHans de Goede no_gkey_mc_cnt++; 1893554c0a3aSHans de Goede 1894554c0a3aSHans de Goede if (jiffies_to_msecs(jiffies - start) > 1000) { 1895554c0a3aSHans de Goede if (no_gkey_bc_cnt || no_gkey_mc_cnt) { 1896554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", 1897554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); 1898554c0a3aSHans de Goede } 1899554c0a3aSHans de Goede start = jiffies; 1900554c0a3aSHans de Goede no_gkey_bc_cnt = 0; 1901554c0a3aSHans de Goede no_gkey_mc_cnt = 0; 1902554c0a3aSHans de Goede } 1903554c0a3aSHans de Goede 1904554c0a3aSHans de Goede goto exit; 1905554c0a3aSHans de Goede } 1906554c0a3aSHans de Goede 1907554c0a3aSHans de Goede if (no_gkey_bc_cnt || no_gkey_mc_cnt) { 1908554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n", 1909554c0a3aSHans de Goede FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt); 1910554c0a3aSHans de Goede } 1911554c0a3aSHans de Goede start = 0; 1912554c0a3aSHans de Goede no_gkey_bc_cnt = 0; 1913554c0a3aSHans de Goede no_gkey_mc_cnt = 0; 1914554c0a3aSHans de Goede 1915554c0a3aSHans de Goede prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey; 1916554c0a3aSHans de Goede if (psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index) { 1917554c0a3aSHans de Goede DBG_871X("not match packet_index =%d, install_index =%d\n" 1918554c0a3aSHans de Goede , prxattrib->key_index, psecuritypriv->dot118021XGrpKeyid); 1919554c0a3aSHans de Goede res = _FAIL; 1920554c0a3aSHans de Goede goto exit; 1921554c0a3aSHans de Goede } 1922554c0a3aSHans de Goede } else 1923554c0a3aSHans de Goede prwskey = &stainfo->dot118021x_UncstKey.skey[0]; 1924554c0a3aSHans de Goede 1925554c0a3aSHans de Goede 1926554c0a3aSHans de Goede length = ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len; 1927554c0a3aSHans de Goede 1928554c0a3aSHans de Goede res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, length); 1929554c0a3aSHans de Goede 1930554c0a3aSHans de Goede AES_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra); 1931554c0a3aSHans de Goede } else { 1932554c0a3aSHans de Goede RT_TRACE(_module_rtl871x_security_c_, _drv_err_, ("rtw_aes_decrypt: stainfo == NULL!!!\n")); 1933554c0a3aSHans de Goede res = _FAIL; 1934554c0a3aSHans de Goede } 1935554c0a3aSHans de Goede } 1936554c0a3aSHans de Goede exit: 1937554c0a3aSHans de Goede return res; 1938554c0a3aSHans de Goede } 1939554c0a3aSHans de Goede 1940554c0a3aSHans de Goede u32 rtw_BIP_verify(struct adapter *padapter, u8 *precvframe) 1941554c0a3aSHans de Goede { 1942554c0a3aSHans de Goede struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib; 1943554c0a3aSHans de Goede u8 *pframe; 1944554c0a3aSHans de Goede u8 *BIP_AAD, *p; 1945554c0a3aSHans de Goede u32 res = _FAIL; 1946554c0a3aSHans de Goede uint len, ori_len; 1947554c0a3aSHans de Goede struct ieee80211_hdr *pwlanhdr; 1948554c0a3aSHans de Goede u8 mic[16]; 1949554c0a3aSHans de Goede struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; 1950554c0a3aSHans de Goede __le16 le_tmp; 1951554c0a3aSHans de Goede __le64 le_tmp64; 1952554c0a3aSHans de Goede 1953554c0a3aSHans de Goede ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE; 1954554c0a3aSHans de Goede BIP_AAD = rtw_zmalloc(ori_len); 1955554c0a3aSHans de Goede 1956554c0a3aSHans de Goede if (BIP_AAD == NULL) { 1957554c0a3aSHans de Goede DBG_871X("BIP AAD allocate fail\n"); 1958554c0a3aSHans de Goede return _FAIL; 1959554c0a3aSHans de Goede } 1960554c0a3aSHans de Goede /* PKT start */ 1961554c0a3aSHans de Goede pframe = (unsigned char *)((union recv_frame *)precvframe)->u.hdr.rx_data; 1962554c0a3aSHans de Goede /* mapping to wlan header */ 1963554c0a3aSHans de Goede pwlanhdr = (struct ieee80211_hdr *)pframe; 1964554c0a3aSHans de Goede /* save the frame body + MME */ 1965554c0a3aSHans de Goede memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN); 1966554c0a3aSHans de Goede /* find MME IE pointer */ 1967554c0a3aSHans de Goede p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN); 1968554c0a3aSHans de Goede /* Baron */ 1969554c0a3aSHans de Goede if (p) { 1970554c0a3aSHans de Goede u16 keyid = 0; 1971554c0a3aSHans de Goede u64 temp_ipn = 0; 1972554c0a3aSHans de Goede /* save packet number */ 1973554c0a3aSHans de Goede memcpy(&le_tmp64, p+4, 6); 1974554c0a3aSHans de Goede temp_ipn = le64_to_cpu(le_tmp64); 1975554c0a3aSHans de Goede /* BIP packet number should bigger than previous BIP packet */ 1976554c0a3aSHans de Goede if (temp_ipn <= pmlmeext->mgnt_80211w_IPN_rx) { 1977554c0a3aSHans de Goede DBG_871X("replay BIP packet\n"); 1978554c0a3aSHans de Goede goto BIP_exit; 1979554c0a3aSHans de Goede } 1980554c0a3aSHans de Goede /* copy key index */ 1981554c0a3aSHans de Goede memcpy(&le_tmp, p+2, 2); 1982554c0a3aSHans de Goede keyid = le16_to_cpu(le_tmp); 1983554c0a3aSHans de Goede if (keyid != padapter->securitypriv.dot11wBIPKeyid) { 1984554c0a3aSHans de Goede DBG_871X("BIP key index error!\n"); 1985554c0a3aSHans de Goede goto BIP_exit; 1986554c0a3aSHans de Goede } 1987554c0a3aSHans de Goede /* clear the MIC field of MME to zero */ 1988554c0a3aSHans de Goede memset(p+2+len-8, 0, 8); 1989554c0a3aSHans de Goede 1990554c0a3aSHans de Goede /* conscruct AAD, copy frame control field */ 1991554c0a3aSHans de Goede memcpy(BIP_AAD, &pwlanhdr->frame_control, 2); 1992554c0a3aSHans de Goede ClearRetry(BIP_AAD); 1993554c0a3aSHans de Goede ClearPwrMgt(BIP_AAD); 1994554c0a3aSHans de Goede ClearMData(BIP_AAD); 1995554c0a3aSHans de Goede /* conscruct AAD, copy address 1 to address 3 */ 1996554c0a3aSHans de Goede memcpy(BIP_AAD+2, pwlanhdr->addr1, 18); 1997554c0a3aSHans de Goede 1998554c0a3aSHans de Goede if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey 1999554c0a3aSHans de Goede , BIP_AAD, ori_len, mic)) 2000554c0a3aSHans de Goede goto BIP_exit; 2001554c0a3aSHans de Goede 2002554c0a3aSHans de Goede /* MIC field should be last 8 bytes of packet (packet without FCS) */ 2003554c0a3aSHans de Goede if (!memcmp(mic, pframe+pattrib->pkt_len-8, 8)) { 2004554c0a3aSHans de Goede pmlmeext->mgnt_80211w_IPN_rx = temp_ipn; 2005554c0a3aSHans de Goede res = _SUCCESS; 2006554c0a3aSHans de Goede } else 2007554c0a3aSHans de Goede DBG_871X("BIP MIC error!\n"); 2008554c0a3aSHans de Goede 2009554c0a3aSHans de Goede } else 2010554c0a3aSHans de Goede res = RTW_RX_HANDLED; 2011554c0a3aSHans de Goede BIP_exit: 2012554c0a3aSHans de Goede 2013554c0a3aSHans de Goede kfree(BIP_AAD); 2014554c0a3aSHans de Goede return res; 2015554c0a3aSHans de Goede } 2016554c0a3aSHans de Goede 2017554c0a3aSHans de Goede /* AES tables*/ 2018554c0a3aSHans de Goede const u32 Te0[256] = { 2019554c0a3aSHans de Goede 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, 2020554c0a3aSHans de Goede 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, 2021554c0a3aSHans de Goede 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, 2022554c0a3aSHans de Goede 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, 2023554c0a3aSHans de Goede 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, 2024554c0a3aSHans de Goede 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, 2025554c0a3aSHans de Goede 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, 2026554c0a3aSHans de Goede 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, 2027554c0a3aSHans de Goede 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, 2028554c0a3aSHans de Goede 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, 2029554c0a3aSHans de Goede 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, 2030554c0a3aSHans de Goede 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, 2031554c0a3aSHans de Goede 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, 2032554c0a3aSHans de Goede 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, 2033554c0a3aSHans de Goede 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, 2034554c0a3aSHans de Goede 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, 2035554c0a3aSHans de Goede 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, 2036554c0a3aSHans de Goede 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, 2037554c0a3aSHans de Goede 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, 2038554c0a3aSHans de Goede 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, 2039554c0a3aSHans de Goede 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, 2040554c0a3aSHans de Goede 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, 2041554c0a3aSHans de Goede 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, 2042554c0a3aSHans de Goede 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, 2043554c0a3aSHans de Goede 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, 2044554c0a3aSHans de Goede 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, 2045554c0a3aSHans de Goede 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, 2046554c0a3aSHans de Goede 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, 2047554c0a3aSHans de Goede 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, 2048554c0a3aSHans de Goede 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, 2049554c0a3aSHans de Goede 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, 2050554c0a3aSHans de Goede 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, 2051554c0a3aSHans de Goede 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, 2052554c0a3aSHans de Goede 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, 2053554c0a3aSHans de Goede 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, 2054554c0a3aSHans de Goede 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, 2055554c0a3aSHans de Goede 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, 2056554c0a3aSHans de Goede 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, 2057554c0a3aSHans de Goede 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, 2058554c0a3aSHans de Goede 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, 2059554c0a3aSHans de Goede 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, 2060554c0a3aSHans de Goede 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, 2061554c0a3aSHans de Goede 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, 2062554c0a3aSHans de Goede 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, 2063554c0a3aSHans de Goede 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, 2064554c0a3aSHans de Goede 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, 2065554c0a3aSHans de Goede 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, 2066554c0a3aSHans de Goede 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, 2067554c0a3aSHans de Goede 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, 2068554c0a3aSHans de Goede 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, 2069554c0a3aSHans de Goede 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, 2070554c0a3aSHans de Goede 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, 2071554c0a3aSHans de Goede 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, 2072554c0a3aSHans de Goede 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, 2073554c0a3aSHans de Goede 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, 2074554c0a3aSHans de Goede 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, 2075554c0a3aSHans de Goede 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, 2076554c0a3aSHans de Goede 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, 2077554c0a3aSHans de Goede 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, 2078554c0a3aSHans de Goede 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, 2079554c0a3aSHans de Goede 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, 2080554c0a3aSHans de Goede 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, 2081554c0a3aSHans de Goede 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, 2082554c0a3aSHans de Goede 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, 2083554c0a3aSHans de Goede }; 2084554c0a3aSHans de Goede const u32 Td0[256] = { 2085554c0a3aSHans de Goede 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, 2086554c0a3aSHans de Goede 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, 2087554c0a3aSHans de Goede 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, 2088554c0a3aSHans de Goede 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, 2089554c0a3aSHans de Goede 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, 2090554c0a3aSHans de Goede 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, 2091554c0a3aSHans de Goede 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, 2092554c0a3aSHans de Goede 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, 2093554c0a3aSHans de Goede 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, 2094554c0a3aSHans de Goede 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, 2095554c0a3aSHans de Goede 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, 2096554c0a3aSHans de Goede 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, 2097554c0a3aSHans de Goede 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, 2098554c0a3aSHans de Goede 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, 2099554c0a3aSHans de Goede 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, 2100554c0a3aSHans de Goede 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, 2101554c0a3aSHans de Goede 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, 2102554c0a3aSHans de Goede 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, 2103554c0a3aSHans de Goede 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, 2104554c0a3aSHans de Goede 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, 2105554c0a3aSHans de Goede 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, 2106554c0a3aSHans de Goede 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, 2107554c0a3aSHans de Goede 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, 2108554c0a3aSHans de Goede 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, 2109554c0a3aSHans de Goede 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, 2110554c0a3aSHans de Goede 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, 2111554c0a3aSHans de Goede 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, 2112554c0a3aSHans de Goede 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, 2113554c0a3aSHans de Goede 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, 2114554c0a3aSHans de Goede 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, 2115554c0a3aSHans de Goede 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, 2116554c0a3aSHans de Goede 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, 2117554c0a3aSHans de Goede 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, 2118554c0a3aSHans de Goede 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, 2119554c0a3aSHans de Goede 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, 2120554c0a3aSHans de Goede 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, 2121554c0a3aSHans de Goede 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, 2122554c0a3aSHans de Goede 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, 2123554c0a3aSHans de Goede 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, 2124554c0a3aSHans de Goede 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, 2125554c0a3aSHans de Goede 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, 2126554c0a3aSHans de Goede 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, 2127554c0a3aSHans de Goede 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, 2128554c0a3aSHans de Goede 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, 2129554c0a3aSHans de Goede 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, 2130554c0a3aSHans de Goede 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, 2131554c0a3aSHans de Goede 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, 2132554c0a3aSHans de Goede 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, 2133554c0a3aSHans de Goede 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, 2134554c0a3aSHans de Goede 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, 2135554c0a3aSHans de Goede 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, 2136554c0a3aSHans de Goede 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, 2137554c0a3aSHans de Goede 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, 2138554c0a3aSHans de Goede 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, 2139554c0a3aSHans de Goede 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, 2140554c0a3aSHans de Goede 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, 2141554c0a3aSHans de Goede 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, 2142554c0a3aSHans de Goede 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, 2143554c0a3aSHans de Goede 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, 2144554c0a3aSHans de Goede 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, 2145554c0a3aSHans de Goede 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, 2146554c0a3aSHans de Goede 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, 2147554c0a3aSHans de Goede 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, 2148554c0a3aSHans de Goede 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, 2149554c0a3aSHans de Goede }; 2150554c0a3aSHans de Goede const u8 Td4s[256] = { 2151554c0a3aSHans de Goede 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, 2152554c0a3aSHans de Goede 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, 2153554c0a3aSHans de Goede 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, 2154554c0a3aSHans de Goede 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, 2155554c0a3aSHans de Goede 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, 2156554c0a3aSHans de Goede 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, 2157554c0a3aSHans de Goede 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, 2158554c0a3aSHans de Goede 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, 2159554c0a3aSHans de Goede 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, 2160554c0a3aSHans de Goede 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, 2161554c0a3aSHans de Goede 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, 2162554c0a3aSHans de Goede 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, 2163554c0a3aSHans de Goede 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, 2164554c0a3aSHans de Goede 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, 2165554c0a3aSHans de Goede 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, 2166554c0a3aSHans de Goede 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, 2167554c0a3aSHans de Goede 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, 2168554c0a3aSHans de Goede 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, 2169554c0a3aSHans de Goede 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, 2170554c0a3aSHans de Goede 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, 2171554c0a3aSHans de Goede 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, 2172554c0a3aSHans de Goede 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, 2173554c0a3aSHans de Goede 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, 2174554c0a3aSHans de Goede 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, 2175554c0a3aSHans de Goede 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, 2176554c0a3aSHans de Goede 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, 2177554c0a3aSHans de Goede 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, 2178554c0a3aSHans de Goede 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, 2179554c0a3aSHans de Goede 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, 2180554c0a3aSHans de Goede 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, 2181554c0a3aSHans de Goede 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, 2182554c0a3aSHans de Goede 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, 2183554c0a3aSHans de Goede }; 2184554c0a3aSHans de Goede const u8 rcons[] = { 2185554c0a3aSHans de Goede 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 2186554c0a3aSHans de Goede /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ 2187554c0a3aSHans de Goede }; 2188554c0a3aSHans de Goede 2189554c0a3aSHans de Goede /** 2190554c0a3aSHans de Goede * Expand the cipher key into the encryption key schedule. 2191554c0a3aSHans de Goede * 2192554c0a3aSHans de Goede * @return the number of rounds for the given cipher key size. 2193554c0a3aSHans de Goede */ 2194554c0a3aSHans de Goede static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[]) 2195554c0a3aSHans de Goede { 2196554c0a3aSHans de Goede int i; 2197554c0a3aSHans de Goede u32 temp; 2198554c0a3aSHans de Goede 2199554c0a3aSHans de Goede rk[0] = GETU32(cipherKey); 2200554c0a3aSHans de Goede rk[1] = GETU32(cipherKey + 4); 2201554c0a3aSHans de Goede rk[2] = GETU32(cipherKey + 8); 2202554c0a3aSHans de Goede rk[3] = GETU32(cipherKey + 12); 2203554c0a3aSHans de Goede for (i = 0; i < 10; i++) { 2204554c0a3aSHans de Goede temp = rk[3]; 2205554c0a3aSHans de Goede rk[4] = rk[0] ^ 2206554c0a3aSHans de Goede TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^ 2207554c0a3aSHans de Goede RCON(i); 2208554c0a3aSHans de Goede rk[5] = rk[1] ^ rk[4]; 2209554c0a3aSHans de Goede rk[6] = rk[2] ^ rk[5]; 2210554c0a3aSHans de Goede rk[7] = rk[3] ^ rk[6]; 2211554c0a3aSHans de Goede rk += 4; 2212554c0a3aSHans de Goede } 2213554c0a3aSHans de Goede } 2214554c0a3aSHans de Goede 2215554c0a3aSHans de Goede static void rijndaelEncrypt(u32 rk[/*44*/], u8 pt[16], u8 ct[16]) 2216554c0a3aSHans de Goede { 2217554c0a3aSHans de Goede u32 s0, s1, s2, s3, t0, t1, t2, t3; 2218554c0a3aSHans de Goede int Nr = 10; 2219554c0a3aSHans de Goede int r; 2220554c0a3aSHans de Goede 2221554c0a3aSHans de Goede /* 2222554c0a3aSHans de Goede * map byte array block to cipher state 2223554c0a3aSHans de Goede * and add initial round key: 2224554c0a3aSHans de Goede */ 2225554c0a3aSHans de Goede s0 = GETU32(pt) ^ rk[0]; 2226554c0a3aSHans de Goede s1 = GETU32(pt + 4) ^ rk[1]; 2227554c0a3aSHans de Goede s2 = GETU32(pt + 8) ^ rk[2]; 2228554c0a3aSHans de Goede s3 = GETU32(pt + 12) ^ rk[3]; 2229554c0a3aSHans de Goede 2230554c0a3aSHans de Goede #define ROUND(i, d, s) \ 2231554c0a3aSHans de Goede d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ 2232554c0a3aSHans de Goede d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ 2233554c0a3aSHans de Goede d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ 2234554c0a3aSHans de Goede d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] 2235554c0a3aSHans de Goede 2236554c0a3aSHans de Goede /* Nr - 1 full rounds: */ 2237554c0a3aSHans de Goede r = Nr >> 1; 2238554c0a3aSHans de Goede for (;;) { 2239554c0a3aSHans de Goede ROUND(1, t, s); 2240554c0a3aSHans de Goede rk += 8; 2241554c0a3aSHans de Goede if (--r == 0) 2242554c0a3aSHans de Goede break; 2243554c0a3aSHans de Goede ROUND(0, s, t); 2244554c0a3aSHans de Goede } 2245554c0a3aSHans de Goede 2246554c0a3aSHans de Goede #undef ROUND 2247554c0a3aSHans de Goede 2248554c0a3aSHans de Goede /* 2249554c0a3aSHans de Goede * apply last round and 2250554c0a3aSHans de Goede * map cipher state to byte array block: 2251554c0a3aSHans de Goede */ 2252554c0a3aSHans de Goede s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; 2253554c0a3aSHans de Goede PUTU32(ct, s0); 2254554c0a3aSHans de Goede s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; 2255554c0a3aSHans de Goede PUTU32(ct + 4, s1); 2256554c0a3aSHans de Goede s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; 2257554c0a3aSHans de Goede PUTU32(ct + 8, s2); 2258554c0a3aSHans de Goede s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; 2259554c0a3aSHans de Goede PUTU32(ct + 12, s3); 2260554c0a3aSHans de Goede } 2261554c0a3aSHans de Goede 2262554c0a3aSHans de Goede static void *aes_encrypt_init(u8 *key, size_t len) 2263554c0a3aSHans de Goede { 2264554c0a3aSHans de Goede u32 *rk; 2265554c0a3aSHans de Goede if (len != 16) 2266554c0a3aSHans de Goede return NULL; 22672ef2b7c2SJoe Perches rk = rtw_malloc(AES_PRIV_SIZE); 2268554c0a3aSHans de Goede if (rk == NULL) 2269554c0a3aSHans de Goede return NULL; 2270554c0a3aSHans de Goede rijndaelKeySetupEnc(rk, key); 2271554c0a3aSHans de Goede return rk; 2272554c0a3aSHans de Goede } 2273554c0a3aSHans de Goede 2274554c0a3aSHans de Goede static void aes_128_encrypt(void *ctx, u8 *plain, u8 *crypt) 2275554c0a3aSHans de Goede { 2276554c0a3aSHans de Goede rijndaelEncrypt(ctx, plain, crypt); 2277554c0a3aSHans de Goede } 2278554c0a3aSHans de Goede 2279554c0a3aSHans de Goede 2280554c0a3aSHans de Goede static void gf_mulx(u8 *pad) 2281554c0a3aSHans de Goede { 2282554c0a3aSHans de Goede int i, carry; 2283554c0a3aSHans de Goede 2284554c0a3aSHans de Goede carry = pad[0] & 0x80; 2285554c0a3aSHans de Goede for (i = 0; i < AES_BLOCK_SIZE - 1; i++) 2286554c0a3aSHans de Goede pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); 2287554c0a3aSHans de Goede 2288554c0a3aSHans de Goede pad[AES_BLOCK_SIZE - 1] <<= 1; 2289554c0a3aSHans de Goede if (carry) 2290554c0a3aSHans de Goede pad[AES_BLOCK_SIZE - 1] ^= 0x87; 2291554c0a3aSHans de Goede } 2292554c0a3aSHans de Goede 2293554c0a3aSHans de Goede static void aes_encrypt_deinit(void *ctx) 2294554c0a3aSHans de Goede { 2295554c0a3aSHans de Goede memset(ctx, 0, AES_PRIV_SIZE); 2296554c0a3aSHans de Goede kfree(ctx); 2297554c0a3aSHans de Goede } 2298554c0a3aSHans de Goede 2299554c0a3aSHans de Goede 2300554c0a3aSHans de Goede /** 2301554c0a3aSHans de Goede * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 2302554c0a3aSHans de Goede * @key: 128-bit key for the hash operation 2303554c0a3aSHans de Goede * @num_elem: Number of elements in the data vector 2304554c0a3aSHans de Goede * @addr: Pointers to the data areas 2305554c0a3aSHans de Goede * @len: Lengths of the data blocks 2306554c0a3aSHans de Goede * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 2307554c0a3aSHans de Goede * Returns: 0 on success, -1 on failure 2308554c0a3aSHans de Goede * 2309554c0a3aSHans de Goede * This is a mode for using block cipher (AES in this case) for authentication. 2310554c0a3aSHans de Goede * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 2311554c0a3aSHans de Goede * (SP) 800-38B. 2312554c0a3aSHans de Goede */ 2313554c0a3aSHans de Goede static int omac1_aes_128_vector(u8 *key, size_t num_elem, 2314554c0a3aSHans de Goede u8 *addr[], size_t *len, u8 *mac) 2315554c0a3aSHans de Goede { 2316554c0a3aSHans de Goede void *ctx; 2317554c0a3aSHans de Goede u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; 2318554c0a3aSHans de Goede u8 *pos, *end; 2319554c0a3aSHans de Goede size_t i, e, left, total_len; 2320554c0a3aSHans de Goede 2321554c0a3aSHans de Goede ctx = aes_encrypt_init(key, 16); 2322554c0a3aSHans de Goede if (ctx == NULL) 2323554c0a3aSHans de Goede return -1; 2324554c0a3aSHans de Goede memset(cbc, 0, AES_BLOCK_SIZE); 2325554c0a3aSHans de Goede 2326554c0a3aSHans de Goede total_len = 0; 2327554c0a3aSHans de Goede for (e = 0; e < num_elem; e++) 2328554c0a3aSHans de Goede total_len += len[e]; 2329554c0a3aSHans de Goede left = total_len; 2330554c0a3aSHans de Goede 2331554c0a3aSHans de Goede e = 0; 2332554c0a3aSHans de Goede pos = addr[0]; 2333554c0a3aSHans de Goede end = pos + len[0]; 2334554c0a3aSHans de Goede 2335554c0a3aSHans de Goede while (left >= AES_BLOCK_SIZE) { 2336554c0a3aSHans de Goede for (i = 0; i < AES_BLOCK_SIZE; i++) { 2337554c0a3aSHans de Goede cbc[i] ^= *pos++; 2338554c0a3aSHans de Goede if (pos >= end) { 2339554c0a3aSHans de Goede e++; 2340554c0a3aSHans de Goede pos = addr[e]; 2341554c0a3aSHans de Goede end = pos + len[e]; 2342554c0a3aSHans de Goede } 2343554c0a3aSHans de Goede } 2344554c0a3aSHans de Goede if (left > AES_BLOCK_SIZE) 2345554c0a3aSHans de Goede aes_128_encrypt(ctx, cbc, cbc); 2346554c0a3aSHans de Goede left -= AES_BLOCK_SIZE; 2347554c0a3aSHans de Goede } 2348554c0a3aSHans de Goede 2349554c0a3aSHans de Goede memset(pad, 0, AES_BLOCK_SIZE); 2350554c0a3aSHans de Goede aes_128_encrypt(ctx, pad, pad); 2351554c0a3aSHans de Goede gf_mulx(pad); 2352554c0a3aSHans de Goede 2353554c0a3aSHans de Goede if (left || total_len == 0) { 2354554c0a3aSHans de Goede for (i = 0; i < left; i++) { 2355554c0a3aSHans de Goede cbc[i] ^= *pos++; 2356554c0a3aSHans de Goede if (pos >= end) { 2357554c0a3aSHans de Goede e++; 2358554c0a3aSHans de Goede pos = addr[e]; 2359554c0a3aSHans de Goede end = pos + len[e]; 2360554c0a3aSHans de Goede } 2361554c0a3aSHans de Goede } 2362554c0a3aSHans de Goede cbc[left] ^= 0x80; 2363554c0a3aSHans de Goede gf_mulx(pad); 2364554c0a3aSHans de Goede } 2365554c0a3aSHans de Goede 2366554c0a3aSHans de Goede for (i = 0; i < AES_BLOCK_SIZE; i++) 2367554c0a3aSHans de Goede pad[i] ^= cbc[i]; 2368554c0a3aSHans de Goede aes_128_encrypt(ctx, pad, mac); 2369554c0a3aSHans de Goede aes_encrypt_deinit(ctx); 2370554c0a3aSHans de Goede return 0; 2371554c0a3aSHans de Goede } 2372554c0a3aSHans de Goede 2373554c0a3aSHans de Goede 2374554c0a3aSHans de Goede /** 2375554c0a3aSHans de Goede * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) 2376554c0a3aSHans de Goede * @key: 128-bit key for the hash operation 2377554c0a3aSHans de Goede * @data: Data buffer for which a MAC is determined 2378554c0a3aSHans de Goede * @data_len: Length of data buffer in bytes 2379554c0a3aSHans de Goede * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) 2380554c0a3aSHans de Goede * Returns: 0 on success, -1 on failure 2381554c0a3aSHans de Goede * 2382554c0a3aSHans de Goede * This is a mode for using block cipher (AES in this case) for authentication. 2383554c0a3aSHans de Goede * OMAC1 was standardized with the name CMAC by NIST in a Special Publication 2384554c0a3aSHans de Goede * (SP) 800-38B. 2385554c0a3aSHans de Goede * modify for CONFIG_IEEE80211W */ 2386554c0a3aSHans de Goede int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac) 2387554c0a3aSHans de Goede { 2388554c0a3aSHans de Goede return omac1_aes_128_vector(key, 1, &data, &data_len, mac); 2389554c0a3aSHans de Goede } 2390554c0a3aSHans de Goede 2391554c0a3aSHans de Goede /* Restore HW wep key setting according to key_mask */ 2392554c0a3aSHans de Goede void rtw_sec_restore_wep_key(struct adapter *adapter) 2393554c0a3aSHans de Goede { 2394554c0a3aSHans de Goede struct security_priv *securitypriv = &(adapter->securitypriv); 2395554c0a3aSHans de Goede sint keyid; 2396554c0a3aSHans de Goede 2397554c0a3aSHans de Goede if ((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) || (_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) { 2398554c0a3aSHans de Goede for (keyid = 0; keyid < 4; keyid++) { 2399554c0a3aSHans de Goede if (securitypriv->key_mask & BIT(keyid)) { 2400554c0a3aSHans de Goede if (keyid == securitypriv->dot11PrivacyKeyIndex) 2401554c0a3aSHans de Goede rtw_set_key(adapter, securitypriv, keyid, 1, false); 2402554c0a3aSHans de Goede else 2403554c0a3aSHans de Goede rtw_set_key(adapter, securitypriv, keyid, 0, false); 2404554c0a3aSHans de Goede } 2405554c0a3aSHans de Goede } 2406554c0a3aSHans de Goede } 2407554c0a3aSHans de Goede } 2408554c0a3aSHans de Goede 2409554c0a3aSHans de Goede u8 rtw_handle_tkip_countermeasure(struct adapter *adapter, const char *caller) 2410554c0a3aSHans de Goede { 2411554c0a3aSHans de Goede struct security_priv *securitypriv = &(adapter->securitypriv); 2412554c0a3aSHans de Goede u8 status = _SUCCESS; 2413554c0a3aSHans de Goede 2414554c0a3aSHans de Goede if (securitypriv->btkip_countermeasure == true) { 2415554c0a3aSHans de Goede unsigned long passing_ms = jiffies_to_msecs(jiffies - securitypriv->btkip_countermeasure_time); 2416554c0a3aSHans de Goede if (passing_ms > 60*1000) { 2417554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus > 60s\n", 2418554c0a3aSHans de Goede caller, ADPT_ARG(adapter), passing_ms/1000); 2419554c0a3aSHans de Goede securitypriv->btkip_countermeasure = false; 2420554c0a3aSHans de Goede securitypriv->btkip_countermeasure_time = 0; 2421554c0a3aSHans de Goede } else { 2422554c0a3aSHans de Goede DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%lus < 60s\n", 2423554c0a3aSHans de Goede caller, ADPT_ARG(adapter), passing_ms/1000); 2424554c0a3aSHans de Goede status = _FAIL; 2425554c0a3aSHans de Goede } 2426554c0a3aSHans de Goede } 2427554c0a3aSHans de Goede 2428554c0a3aSHans de Goede return status; 2429554c0a3aSHans de Goede } 2430