staging:r8188eu: Use lib80211 to decrypt WEP-frames

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>
This commit is contained in:
Ivan Safonov 2018-02-18 14:37:38 +03:00 committed by Greg Kroah-Hartman
parent fd161c6198
commit 2b2ea09e74
4 changed files with 49 additions and 37 deletions

View 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.

View 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);

View 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;
pframe = (unsigned char *)((struct recv_frame *)precvframe)->pkt->data;
/* 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;
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];
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]));
if (!crypto_ops) {
status = _FAIL;
goto exit;
}
memcpy(iv, pframe + prxattrib->hdrlen, 4);
memcpy(icv, pframe + skb->len - 4, 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 ===== */

View 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_ */