Custom AES decrypt implementation replaced with lib80211 library.

Signed-off-by: Ivan Safonov <insafo...@gmail.com>
---
 drivers/staging/rtl8188eu/Kconfig             |   1 +
 drivers/staging/rtl8188eu/core/rtw_security.c | 266 +++++---------------------
 2 files changed, 51 insertions(+), 216 deletions(-)

diff --git a/drivers/staging/rtl8188eu/Kconfig 
b/drivers/staging/rtl8188eu/Kconfig
index d787a091d3c1..ff7832798a77 100644
--- a/drivers/staging/rtl8188eu/Kconfig
+++ b/drivers/staging/rtl8188eu/Kconfig
@@ -6,6 +6,7 @@ config R8188EU
        select WEXT_PRIV
        select LIB80211
        select LIB80211_CRYPT_WEP
+       select LIB80211_CRYPT_CCMP
        ---help---
        This option adds the Realtek RTL8188EU USB device such as TP-Link 
TL-WN725N.
        If built as a module, it will be called r8188eu.
diff --git a/drivers/staging/rtl8188eu/core/rtw_security.c 
b/drivers/staging/rtl8188eu/core/rtw_security.c
index 72da86fdd264..68e2c6790ee6 100644
--- a/drivers/staging/rtl8188eu/core/rtw_security.c
+++ b/drivers/staging/rtl8188eu/core/rtw_security.c
@@ -1275,217 +1275,24 @@ u32    rtw_aes_encrypt(struct adapter *padapter, u8 
*pxmitframe)
                return res;
 }
 
-static int aes_decipher(u8 *key, uint  hdrlen,
-                       u8 *pframe, uint plen)
+u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
 {
-       static u8       message[MAX_MSG_SIZE];
-       uint    qc_exists, a4_exists, i, j, payload_remainder,
-                       num_blocks, payload_index;
-       int res = _SUCCESS;
-
-       u8 pn_vector[6];
-       u8 mic_iv[16];
-       u8 mic_header1[16];
-       u8 mic_header2[16];
-       u8 ctr_preload[16];
-
-       /* Intermediate Buffers */
-       u8 chain_buffer[16];
-       u8 aes_out[16];
-       u8 padded_buffer[16];
-       u8 mic[8];
-
-/*     uint    offset = 0; */
-       uint    frtype  = GetFrameType(pframe);
-       uint    frsubtype  = GetFrameSubType(pframe);
-       frsubtype >>= 4;
-
-       memset(mic_iv, 0, 16);
-       memset(mic_header1, 0, 16);
-       memset(mic_header2, 0, 16);
-       memset(ctr_preload, 0, 16);
-       memset(chain_buffer, 0, 16);
-       memset(aes_out, 0, 16);
-       memset(padded_buffer, 0, 16);
-
-       /* start to decrypt the payload */
-
-       num_blocks = (plen-8) / 16; /* plen including llc, payload_length and 
mic) */
-
-       payload_remainder = (plen-8) % 16;
-
-       pn_vector[0]  = pframe[hdrlen];
-       pn_vector[1]  = pframe[hdrlen+1];
-       pn_vector[2]  = pframe[hdrlen+4];
-       pn_vector[3]  = pframe[hdrlen+5];
-       pn_vector[4]  = pframe[hdrlen+6];
-       pn_vector[5]  = pframe[hdrlen+7];
-
-       if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen ==  WLAN_HDR_A3_QOS_LEN))
-               a4_exists = 0;
-       else
-               a4_exists = 1;
-
-       if ((frtype == WIFI_DATA_CFACK) || (frtype == WIFI_DATA_CFPOLL) ||
-           (frtype == WIFI_DATA_CFACKPOLL)) {
-                       qc_exists = 1;
-                       if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
-                               hdrlen += 2;
-       } else if ((frsubtype == 0x08) || (frsubtype == 0x09) ||
-                  (frsubtype == 0x0a) || (frsubtype == 0x0b)) {
-               if (hdrlen !=  WLAN_HDR_A3_QOS_LEN)
-                       hdrlen += 2;
-               qc_exists = 1;
-       } else {
-               qc_exists = 0;
-       }
-
-       /*  now, decrypt pframe with hdrlen offset and plen long */
-
-       payload_index = hdrlen + 8; /*  8 is for extiv */
-
-       for (i = 0; i < num_blocks; i++) {
-               construct_ctr_preload(ctr_preload, a4_exists, qc_exists, 
pframe, pn_vector, i+1);
-
-               aes128k128d(key, ctr_preload, aes_out);
-               bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
-
-               for (j = 0; j < 16; j++)
-                       pframe[payload_index++] = chain_buffer[j];
-       }
-
-       if (payload_remainder > 0) {    /* If there is a short final block, 
then pad it,*/
-                                       /* encrypt it and copy the unpadded 
part back   */
-               construct_ctr_preload(ctr_preload, a4_exists, qc_exists, 
pframe, pn_vector, num_blocks+1);
-
-               for (j = 0; j < 16; j++)
-                       padded_buffer[j] = 0x00;
-               for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = pframe[payload_index+j];
-               aes128k128d(key, ctr_preload, aes_out);
-               bitwise_xor(aes_out, padded_buffer, chain_buffer);
-               for (j = 0; j < payload_remainder; j++)
-                       pframe[payload_index++] = chain_buffer[j];
-       }
-
-       /* start to calculate the mic */
-       if ((hdrlen+plen+8) <= MAX_MSG_SIZE)
-               memcpy(message, pframe, (hdrlen + plen+8)); /* 8 is for ext iv 
len */
-
-       pn_vector[0] = pframe[hdrlen];
-       pn_vector[1] = pframe[hdrlen+1];
-       pn_vector[2] = pframe[hdrlen+4];
-       pn_vector[3] = pframe[hdrlen+5];
-       pn_vector[4] = pframe[hdrlen+6];
-       pn_vector[5] = pframe[hdrlen+7];
-       construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen-8, 
pn_vector);
-
-       construct_mic_header1(mic_header1, hdrlen, message);
-       construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
-
-       payload_remainder = (plen-8) % 16;
-       num_blocks = (plen-8) / 16;
-
-       /* Find start of payload */
-       payload_index = hdrlen + 8;
-
-       /* Calculate MIC */
-       aes128k128d(key, mic_iv, aes_out);
-       bitwise_xor(aes_out, mic_header1, chain_buffer);
-       aes128k128d(key, chain_buffer, aes_out);
-       bitwise_xor(aes_out, mic_header2, chain_buffer);
-       aes128k128d(key, chain_buffer, aes_out);
-
-       for (i = 0; i < num_blocks; i++) {
-               bitwise_xor(aes_out, &message[payload_index], chain_buffer);
-
-               payload_index += 16;
-               aes128k128d(key, chain_buffer, aes_out);
-       }
-
-       /* Add on the final payload block if it needs padding */
-       if (payload_remainder > 0) {
-               for (j = 0; j < 16; j++)
-                       padded_buffer[j] = 0x00;
-               for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = message[payload_index++];
-               bitwise_xor(aes_out, padded_buffer, chain_buffer);
-               aes128k128d(key, chain_buffer, aes_out);
-       }
-
-       for (j = 0 ; j < 8; j++)
-               mic[j] = aes_out[j];
-
-       /* Insert MIC into payload */
-       for (j = 0; j < 8; j++)
-               message[payload_index+j] = mic[j];
-
-       payload_index = hdrlen + 8;
-       for (i = 0; i < num_blocks; i++) {
-               construct_ctr_preload(ctr_preload, a4_exists, qc_exists, 
message, pn_vector, i+1);
-               aes128k128d(key, ctr_preload, aes_out);
-               bitwise_xor(aes_out, &message[payload_index], chain_buffer);
-               for (j = 0; j < 16; j++)
-                       message[payload_index++] = chain_buffer[j];
-       }
-
-       if (payload_remainder > 0) { /* If there is a short final block, then 
pad it,*/
-               /* encrypt it and copy the unpadded part back   */
-               construct_ctr_preload(ctr_preload, a4_exists, qc_exists, 
message, pn_vector, num_blocks+1);
-
-               for (j = 0; j < 16; j++)
-                       padded_buffer[j] = 0x00;
-               for (j = 0; j < payload_remainder; j++)
-                       padded_buffer[j] = message[payload_index+j];
-               aes128k128d(key, ctr_preload, aes_out);
-               bitwise_xor(aes_out, padded_buffer, chain_buffer);
-               for (j = 0; j < payload_remainder; j++)
-                       message[payload_index++] = chain_buffer[j];
-       }
-
-       /* Encrypt the MIC */
-       construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message, 
pn_vector, 0);
-
-       for (j = 0; j < 16; j++)
-               padded_buffer[j] = 0x00;
-       for (j = 0; j < 8; j++)
-               padded_buffer[j] = message[j+hdrlen+8+plen-8];
-
-       aes128k128d(key, ctr_preload, aes_out);
-       bitwise_xor(aes_out, padded_buffer, chain_buffer);
-       for (j = 0; j < 8; j++)
-               message[payload_index++] = chain_buffer[j];
-
-       /* compare the mic */
-       for (i = 0; i < 8; i++) {
-               if (pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i]) {
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                                ("aes_decipher:mic check error mic[%d]: 
pframe(%x)!=message(%x)\n",
-                                i, pframe[hdrlen+8+plen-8+i], 
message[hdrlen+8+plen-8+i]));
-                       DBG_88E("aes_decipher:mic check error mic[%d]: 
pframe(%x)!=message(%x)\n",
-                               i, pframe[hdrlen+8+plen-8+i], 
message[hdrlen+8+plen-8+i]);
-                       res = _FAIL;
-               }
-       }
-       return res;
-}
-
-u32    rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
-{      /*  exclude ICV */
-       /* Intermediate Buffers */
-       int             length;
-       u8      *pframe, *prwskey;      /*  *payload,*iv */
-       struct  sta_info                *stainfo;
-       struct  rx_pkt_attrib    *prxattrib = &((struct recv_frame 
*)precvframe)->attrib;
-       struct  security_priv   *psecuritypriv = &padapter->securitypriv;
-       u32     res = _SUCCESS;
+       struct rx_pkt_attrib *prxattrib = &((struct recv_frame 
*)precvframe)->attrib;
+       u32 res = _SUCCESS;
 
-       pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data;
        /* 4 start to encrypt each fragment */
        if (prxattrib->encrypt == _AES_) {
-               stainfo = rtw_get_stainfo(&padapter->stapriv, 
&prxattrib->ta[0]);
+               struct sta_info *stainfo = rtw_get_stainfo(&padapter->stapriv, 
&prxattrib->ta[0]);
+
                if (stainfo != NULL) {
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_, 
("rtw_aes_decrypt: stainfo!= NULL!!!\n"));
+                       int key_idx;
+                       const int key_length = 16, iv_len = 8, icv_len = 8;
+                       struct sk_buff *skb = ((struct recv_frame 
*)precvframe)->pkt;
+                       void *crypto_private = NULL;
+                       u8 *key, *pframe = skb->data;
+                       struct lib80211_crypto_ops *crypto_ops = 
try_then_request_module(lib80211_get_crypto_ops("CCMP"), "lib80211_crypt_ccmp");
+                       struct security_priv *psecuritypriv = 
&padapter->securitypriv;
+                       char iv[8], icv[8];
 
                        if (IS_MCAST(prxattrib->ra)) {
                                /* in concurrent we should use sw descrypt in 
group key, so we remove this message */
@@ -1494,18 +1301,45 @@ u32     rtw_aes_decrypt(struct adapter *padapter, u8 
*precvframe)
                                        DBG_88E("%s:rx bc/mc packets, but 
didn't install group key!!!!!!!!!!\n", __func__);
                                        goto exit;
                                }
-                               prwskey = 
psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
-                               if (psecuritypriv->dot118021XGrpKeyid != 
prxattrib->key_index) {
-                                       DBG_88E("not match packet_index=%d, 
install_index=%d\n",
-                                               prxattrib->key_index, 
psecuritypriv->dot118021XGrpKeyid);
-                                       res = _FAIL;
-                                       goto exit;
-                               }
+                               key_idx = psecuritypriv->dot118021XGrpKeyid;
+                               key = 
psecuritypriv->dot118021XGrpKey[key_idx].skey;
                        } else {
-                               prwskey = &stainfo->dot118021x_UncstKey.skey[0];
+                               key_idx = 0;
+                               key = stainfo->dot118021x_UncstKey.skey;
                        }
-                       length = ((struct recv_frame 
*)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len;
-                       res = aes_decipher(prwskey, prxattrib->hdrlen, pframe, 
length);
+
+                       if (!crypto_ops) {
+                               res = _FAIL;
+                               goto exit_lib80211_ccmp;
+                       }
+
+                       memcpy(iv, pframe + prxattrib->hdrlen, iv_len);
+                       memcpy(icv, pframe + skb->len - icv_len, icv_len);
+
+                       crypto_private = crypto_ops->init(key_idx);
+                       if (!crypto_private) {
+                               res = _FAIL;
+                               goto exit_lib80211_ccmp;
+                       }
+                       if (crypto_ops->set_key(key, key_length, NULL, 
crypto_private) < 0) {
+                               res = _FAIL;
+                               goto exit_lib80211_ccmp;
+                       }
+                       if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, 
crypto_private)) {
+                               res = _FAIL;
+                               goto exit_lib80211_ccmp;
+                       }
+
+                       memmove(pframe, pframe + iv_len, prxattrib->hdrlen);
+                       skb_push(skb, iv_len);
+                       skb_put(skb, icv_len);
+
+                       memcpy(pframe + prxattrib->hdrlen, iv, iv_len);
+                       memcpy(pframe + skb->len - icv_len, icv, icv_len);
+
+exit_lib80211_ccmp:
+                       if (crypto_ops && crypto_private)
+                               crypto_ops->deinit(crypto_private);
                } else {
                        RT_TRACE(_module_rtl871x_security_c_, _drv_err_, 
("rtw_aes_encrypt: stainfo==NULL!!!\n"));
                        res = _FAIL;
-- 
2.16.1

_______________________________________________
devel mailing list
de...@linuxdriverproject.org
http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel

Reply via email to