staging:r8188eu: Use lib80211 to decrypt WEP-frames
authorIvan Safonov <insafonov@gmail.com>
Sun, 18 Feb 2018 11:37:38 +0000 (14:37 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Feb 2018 17:06:35 +0000 (18:06 +0100)
Use native lib80211 WEP decrypt instead of custom implementation.

Signed-off-by: Ivan Safonov <insafonov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/rtl8188eu/Kconfig
drivers/staging/rtl8188eu/core/rtw_recv.c
drivers/staging/rtl8188eu/core/rtw_security.c
drivers/staging/rtl8188eu/include/rtw_security.h

index cb836c59d5640b1f1c775399665f3e08a79740ba..d787a091d3c1e1550d38dcbbcd2b384013fa801a 100644 (file)
@@ -4,6 +4,8 @@ config R8188EU
        depends on m
        select WIRELESS_EXT
        select WEXT_PRIV
+       select LIB80211
+       select LIB80211_CRYPT_WEP
        ---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.
index 6506a1587df011a6be1f6aa4350eca54c7d4aa91..fe31ebbf36fb17f86a5b038678ae68325dc4598c 100644 (file)
@@ -404,7 +404,7 @@ static struct recv_frame *decryptor(struct adapter *padapter,
                switch (prxattrib->encrypt) {
                case _WEP40_:
                case _WEP104_:
-                       rtw_wep_decrypt(padapter, (u8 *)precv_frame);
+                       res = rtw_wep_decrypt(padapter, (u8 *)precv_frame);
                        break;
                case _TKIP_:
                        res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
index 5b1ef229df2a20578484a3d3bcf49bfffa6131d4..72da86fdd264632e6bd870b82d4b697da18bd6ab 100644 (file)
@@ -18,6 +18,7 @@
 #include <drv_types.h>
 #include <wifi.h>
 #include <osdep_intf.h>
+#include <net/lib80211.h>
 
 /* WEP related ===== */
 
@@ -195,48 +196,57 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
 
 }
 
-void rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
+int rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
 {
-       /*  exclude ICV */
-       u8      crc[4];
-       struct arc4context       mycontext;
-       int     length;
-       u32     keylength;
-       u8      *pframe, *payload, *iv, wepkey[16];
-       u8       keyindex;
        struct  rx_pkt_attrib    *prxattrib = &(((struct recv_frame *)precvframe)->attrib);
-       struct  security_priv   *psecuritypriv = &padapter->securitypriv;
 
+       if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
+               struct  security_priv   *psecuritypriv = &padapter->securitypriv;
+               struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
+               u8 *pframe = skb->data;
+               void *crypto_private = NULL;
+               int status = _SUCCESS;
+               const int keyindex = prxattrib->key_index;
+               struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+               char iv[4], icv[4];
+
+               if (!crypto_ops) {
+                       status = _FAIL;
+                       goto exit;
+               }
 
-       pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data;
+               memcpy(iv, pframe + prxattrib->hdrlen, 4);
+               memcpy(icv, pframe + skb->len - 4, 4);
 
-       /* start to decrypt recvframe */
-       if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt == _WEP104_)) {
-               iv = pframe+prxattrib->hdrlen;
-               keyindex = prxattrib->key_index;
-               keylength = psecuritypriv->dot11DefKeylen[keyindex];
-               memcpy(&wepkey[0], iv, 3);
-               memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0], keylength);
-               length = ((struct recv_frame *)precvframe)->pkt->len-prxattrib->hdrlen-prxattrib->iv_len;
-
-               payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
-
-               /* decrypt payload include icv */
-               arcfour_init(&mycontext, wepkey, 3+keylength);
-               arcfour_encrypt(&mycontext, payload, payload,  length);
-
-               /* calculate icv and compare the icv */
-               *((__le32 *)crc) = getcrc32(payload, length - 4);
-
-               if (crc[3] != payload[length-1] ||
-                   crc[2] != payload[length-2] ||
-                   crc[1] != payload[length-3] ||
-                   crc[0] != payload[length-4]) {
-                       RT_TRACE(_module_rtl871x_security_c_, _drv_err_,
-                                ("rtw_wep_decrypt:icv error crc (%4ph)!=payload (%4ph)\n",
-                                &crc, &payload[length-4]));
+               crypto_private = crypto_ops->init(keyindex);
+               if (!crypto_private) {
+                       status = _FAIL;
+                       goto exit;
+               }
+               if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
+                                       psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0) {
+                       status = _FAIL;
+                       goto exit;
                }
+               if (crypto_ops->decrypt_mpdu(skb, prxattrib->hdrlen, crypto_private)) {
+                       status = _FAIL;
+                       goto exit;
+               }
+
+               memmove(pframe, pframe + 4, prxattrib->hdrlen);
+               skb_push(skb, 4);
+               skb_put(skb, 4);
+
+               memcpy(pframe + prxattrib->hdrlen, iv, 4);
+               memcpy(pframe + skb->len - 4, icv, 4);
+
+exit:
+               if (crypto_ops && crypto_private)
+                       crypto_ops->deinit(crypto_private);
+               return status;
        }
+
+       return _FAIL;
 }
 
 /* 3           ===== TKIP related ===== */
index a0c6cf70621829ff59a9ee8375d2b12025046972..b1883ca852af07e35efa1962a8c4641a4dd4008d 100644 (file)
@@ -308,6 +308,6 @@ u32 rtw_tkip_encrypt(struct adapter *padapter, u8 *pxmitframe);
 void rtw_wep_encrypt(struct adapter *padapter, u8  *pxmitframe);
 u32 rtw_aes_decrypt(struct adapter *padapter, u8  *precvframe);
 u32 rtw_tkip_decrypt(struct adapter *padapter, u8  *precvframe);
-void rtw_wep_decrypt(struct adapter *padapter, u8  *precvframe);
+int rtw_wep_decrypt(struct adapter *padapter, u8  *precvframe);
 
 #endif /* __RTL871X_SECURITY_H_ */