Commit 698b47cb authored by Ivan Safonov's avatar Ivan Safonov Committed by Greg Kroah-Hartman
Browse files

staging:r8188eu: Use lib80211 to encrypt (WEP) tx frames



Put data to skb, decrypt with lib80211_crypt_wep, and place back to tx buffer.

Signed-off-by: default avatarIvan Safonov <insafonov@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0a561b0f
Loading
Loading
Loading
Loading
+47 −35
Original line number Diff line number Diff line
@@ -131,60 +131,72 @@ static __le32 getcrc32(u8 *buf, int len)
	Need to consider the fragment  situation
*/
void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
{	/*  exclude ICV */

	unsigned char	crc[4];
	struct arc4context	 mycontext;

{
	int	curfragnum, length;
	u32	keylength;

	u8	*pframe, *payload, *iv;    /* wepkey */
	u8	wepkey[16];
	u8 *pframe;
	u8 hw_hdr_offset = 0;
	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
	struct	security_priv	*psecuritypriv = &padapter->securitypriv;
	struct	xmit_priv		*pxmitpriv = &padapter->xmitpriv;

	const int keyindex = psecuritypriv->dot11PrivacyKeyIndex;
	void *crypto_private;
	struct sk_buff *skb;
	struct lib80211_crypto_ops *crypto_ops;

	if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
		return;

	if ((pattrib->encrypt != _WEP40_) && (pattrib->encrypt != _WEP104_))
		return;

	hw_hdr_offset = TXDESC_SIZE +
		 (((struct xmit_frame *)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);

	pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;

	/* start to encrypt each fragment */
	if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
		keylength = psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
	crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");

	if (!crypto_ops)
		return;

	crypto_private = crypto_ops->init(keyindex);
	if (!crypto_private)
		return;

	if (crypto_ops->set_key(psecuritypriv->dot11DefKey[keyindex].skey,
				psecuritypriv->dot11DefKeylen[keyindex], NULL, crypto_private) < 0)
		goto free_crypto_private;

	for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {
			iv = pframe+pattrib->hdrlen;
			memcpy(&wepkey[0], iv, 3);
			memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0], keylength);
			payload = pframe+pattrib->iv_len+pattrib->hdrlen;
		if (curfragnum + 1 == pattrib->nr_frags)
			length = pattrib->last_txcmdsz;
		else
			length = pxmitpriv->frag_len;
		skb = dev_alloc_skb(length);
		if (!skb)
			goto free_crypto_private;

			if ((curfragnum+1) == pattrib->nr_frags) {	/* the last fragment */
				length = pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
		skb_put_data(skb, pframe, length);

				*((__le32 *)crc) = getcrc32(payload, length);
		memmove(skb->data + 4, skb->data, pattrib->hdrlen);
		skb_pull(skb, 4);
		skb_trim(skb, skb->len - 4);

				arcfour_init(&mycontext, wepkey, 3+keylength);
				arcfour_encrypt(&mycontext, payload, payload, length);
				arcfour_encrypt(&mycontext, payload+length, crc, 4);
			} else {
				length = pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len;
				*((__le32 *)crc) = getcrc32(payload, length);
				arcfour_init(&mycontext, wepkey, 3+keylength);
				arcfour_encrypt(&mycontext, payload, payload, length);
				arcfour_encrypt(&mycontext, payload+length, crc, 4);
		if (crypto_ops->encrypt_mpdu(skb, pattrib->hdrlen, crypto_private)) {
			kfree_skb(skb);
			goto free_crypto_private;
		}

				pframe += pxmitpriv->frag_len;
		memcpy(pframe, skb->data, skb->len);

		pframe += skb->len;
		pframe = (u8 *)round_up((size_t)(pframe), 4);

		kfree_skb(skb);
	}
		}
	}

free_crypto_private:
	crypto_ops->deinit(crypto_private);
}

int rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)