diff options
Diffstat (limited to 'net/mac80211/wapi.c')
-rw-r--r-- | net/mac80211/wapi.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/net/mac80211/wapi.c b/net/mac80211/wapi.c new file mode 100644 index 00000000000..4780808ad2f --- /dev/null +++ b/net/mac80211/wapi.c @@ -0,0 +1,71 @@ +/* + * Software WAPI encryption implementation + * Copyright (c) 2011, ST-Ericsson + * Author: Janusz Dziedzic <janusz.dziedzic@tieto.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include <linux/netdevice.h> +#include <linux/types.h> +#include <linux/random.h> +#include <linux/compiler.h> +#include <linux/crc32.h> +#include <linux/crypto.h> +#include <linux/err.h> +#include <linux/mm.h> +#include <linux/scatterlist.h> +#include <linux/slab.h> +#include <asm/unaligned.h> + +#include <net/mac80211.h> +#include "ieee80211_i.h" +#include "wapi.h" + + +static int ieee80211_wapi_decrypt(struct ieee80211_local *local, + struct sk_buff *skb, + struct ieee80211_key *key) +{ + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + int hdrlen = ieee80211_hdrlen(hdr->frame_control); + struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); + int data_len; + + if (!(status->flag & RX_FLAG_DECRYPTED)) { + /* TODO - SMS4 decryption for firmware without + * SMS4 support */ + return RX_DROP_UNUSABLE; + } + + + data_len = skb->len - hdrlen - WAPI_IV_LEN - WAPI_ICV_LEN; + if (data_len < 0) + return RX_DROP_UNUSABLE; + + /* Trim ICV */ + skb_trim(skb, skb->len - WAPI_ICV_LEN); + + /* Remove IV */ + memmove(skb->data + WAPI_IV_LEN, skb->data, hdrlen); + skb_pull(skb, WAPI_IV_LEN); + + return RX_CONTINUE; +} + +ieee80211_rx_result +ieee80211_crypto_wapi_decrypt(struct ieee80211_rx_data *rx) +{ + struct sk_buff *skb = rx->skb; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; + + if (!ieee80211_is_data(hdr->frame_control)) + return RX_CONTINUE; + + if (ieee80211_wapi_decrypt(rx->local, rx->skb, rx->key)) + return RX_DROP_UNUSABLE; + + return RX_CONTINUE; +} |