mac80211: port CCMP to cryptoapi's CCM driver
[deliverable/linux.git] / net / mac80211 / wpa.c
index c9edfcb7a13b65ad6d766b182e54cf6cfcc83c0b..d6572822076367cdf203207892a2880c7e4487c2 100644 (file)
@@ -301,22 +301,16 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
 }
 
 
-static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
+static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad,
                                int encrypted)
 {
        __le16 mask_fc;
        int a4_included, mgmt;
        u8 qos_tid;
-       u8 *b_0, *aad;
-       u16 data_len, len_a;
+       u16 len_a;
        unsigned int hdrlen;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 
-       memset(scratch, 0, 6 * AES_BLOCK_SIZE);
-
-       b_0 = scratch + 3 * AES_BLOCK_SIZE;
-       aad = scratch + 4 * AES_BLOCK_SIZE;
-
        /*
         * Mask FC: zero subtype b4 b5 b6 (if not mgmt)
         * Retry, PwrMgt, MoreData; set Protected
@@ -338,20 +332,21 @@ static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *scratch,
        else
                qos_tid = 0;
 
-       data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN;
-       if (encrypted)
-               data_len -= IEEE80211_CCMP_MIC_LEN;
+       /* In CCM, the initial vectors (IV) used for CTR mode encryption and CBC
+        * mode authentication are not allowed to collide, yet both are derived
+        * from this vector b_0. We only set L := 1 here to indicate that the
+        * data size can be represented in (L+1) bytes. The CCM layer will take
+        * care of storing the data length in the top (L+1) bytes and setting
+        * and clearing the other bits as is required to derive the two IVs.
+        */
+       b_0[0] = 0x1;
 
-       /* First block, b_0 */
-       b_0[0] = 0x59; /* flags: Adata: 1, M: 011, L: 001 */
        /* Nonce: Nonce Flags | A2 | PN
         * Nonce Flags: Priority (b0..b3) | Management (b4) | Reserved (b5..b7)
         */
        b_0[1] = qos_tid | (mgmt << 4);
        memcpy(&b_0[2], hdr->addr2, ETH_ALEN);
        memcpy(&b_0[8], pn, IEEE80211_CCMP_PN_LEN);
-       /* l(m) */
-       put_unaligned_be16(data_len, &b_0[14]);
 
        /* AAD (extra authenticate-only data) / masked 802.11 header
         * FC | A1 | A2 | A3 | SC | [A4] | [QC] */
@@ -407,7 +402,8 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        u8 *pos;
        u8 pn[6];
        u64 pn64;
-       u8 scratch[6 * AES_BLOCK_SIZE];
+       u8 aad[2 * AES_BLOCK_SIZE];
+       u8 b_0[AES_BLOCK_SIZE];
 
        if (info->control.hw_key &&
            !(info->control.hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV) &&
@@ -460,9 +456,9 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
                return 0;
 
        pos += IEEE80211_CCMP_HDR_LEN;
-       ccmp_special_blocks(skb, pn, scratch, 0);
-       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, scratch, pos, len,
-                                 pos, skb_put(skb, IEEE80211_CCMP_MIC_LEN));
+       ccmp_special_blocks(skb, pn, b_0, aad, 0);
+       ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len,
+                                 skb_put(skb, IEEE80211_CCMP_MIC_LEN));
 
        return 0;
 }
@@ -525,16 +521,16 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx)
        }
 
        if (!(status->flag & RX_FLAG_DECRYPTED)) {
-               u8 scratch[6 * AES_BLOCK_SIZE];
+               u8 aad[2 * AES_BLOCK_SIZE];
+               u8 b_0[AES_BLOCK_SIZE];
                /* hardware didn't decrypt/verify MIC */
-               ccmp_special_blocks(skb, pn, scratch, 1);
+               ccmp_special_blocks(skb, pn, b_0, aad, 1);
 
                if (ieee80211_aes_ccm_decrypt(
-                           key->u.ccmp.tfm, scratch,
+                           key->u.ccmp.tfm, b_0, aad,
                            skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
                            data_len,
-                           skb->data + skb->len - IEEE80211_CCMP_MIC_LEN,
-                           skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN))
+                           skb->data + skb->len - IEEE80211_CCMP_MIC_LEN))
                        return RX_DROP_UNUSABLE;
        }
 
This page took 0.027506 seconds and 5 git commands to generate.