Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2b2ea09e authored by Ivan Safonov's avatar Ivan Safonov Committed by Greg Kroah-Hartman
Browse files

staging:r8188eu: Use lib80211 to decrypt WEP-frames



Use native lib80211 WEP decrypt instead of custom implementation.

Signed-off-by: default avatarIvan Safonov <insafonov@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fd161c61
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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.
+1 −1
Original line number Diff line number Diff line
@@ -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);
+45 −35
Original line number Diff line number Diff line
@@ -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];

		if (!crypto_ops) {
			status = _FAIL;
			goto exit;
		}

		payload = pframe+prxattrib->iv_len+prxattrib->hdrlen;
		memcpy(iv, pframe + prxattrib->hdrlen, 4);
		memcpy(icv, pframe + skb->len - 4, 4);

		/* decrypt payload include icv */
		arcfour_init(&mycontext, wepkey, 3+keylength);
		arcfour_encrypt(&mycontext, payload, payload,  length);
		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;
		}

		/* calculate icv and compare the icv */
		*((__le32 *)crc) = getcrc32(payload, length - 4);
		memmove(pframe, pframe + 4, prxattrib->hdrlen);
		skb_push(skb, 4);
		skb_put(skb, 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]));
		}
		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 ===== */
+1 −1
Original line number Diff line number Diff line
@@ -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_ */