]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/mac80211/fils_aead.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / net / mac80211 / fils_aead.c
index 5c3af5eb405232167bbd62a13b4d1f37370d6bc0..3cfb1e2ab7ac7c183efe250f1a7096627b88e969 100644 (file)
@@ -9,66 +9,58 @@
 
 #include <crypto/aes.h>
 #include <crypto/algapi.h>
+#include <crypto/hash.h>
 #include <crypto/skcipher.h>
 
 #include "ieee80211_i.h"
 #include "aes_cmac.h"
 #include "fils_aead.h"
 
-static int aes_s2v(struct crypto_cipher *tfm,
+static void gf_mulx(u8 *pad)
+{
+       u64 a = get_unaligned_be64(pad);
+       u64 b = get_unaligned_be64(pad + 8);
+
+       put_unaligned_be64((a << 1) | (b >> 63), pad);
+       put_unaligned_be64((b << 1) ^ ((a >> 63) ? 0x87 : 0), pad + 8);
+}
+
+static int aes_s2v(struct crypto_shash *tfm,
                   size_t num_elem, const u8 *addr[], size_t len[], u8 *v)
 {
-       u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+       u8 d[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE] = {};
+       SHASH_DESC_ON_STACK(desc, tfm);
        size_t i;
-       const u8 *data[2];
-       size_t data_len[2], data_elems;
+
+       desc->tfm = tfm;
 
        /* D = AES-CMAC(K, <zero>) */
-       memset(tmp, 0, AES_BLOCK_SIZE);
-       data[0] = tmp;
-       data_len[0] = AES_BLOCK_SIZE;
-       aes_cmac_vector(tfm, 1, data, data_len, d, AES_BLOCK_SIZE);
+       crypto_shash_digest(desc, tmp, AES_BLOCK_SIZE, d);
 
        for (i = 0; i < num_elem - 1; i++) {
                /* D = dbl(D) xor AES_CMAC(K, Si) */
                gf_mulx(d); /* dbl */
-               aes_cmac_vector(tfm, 1, &addr[i], &len[i], tmp,
-                               AES_BLOCK_SIZE);
+               crypto_shash_digest(desc, addr[i], len[i], tmp);
                crypto_xor(d, tmp, AES_BLOCK_SIZE);
        }
 
+       crypto_shash_init(desc);
+
        if (len[i] >= AES_BLOCK_SIZE) {
                /* len(Sn) >= 128 */
-               size_t j;
-               const u8 *pos;
-
                /* T = Sn xorend D */
-
-               /* Use a temporary buffer to perform xorend on Sn (addr[i]) to
-                * avoid modifying the const input argument.
-                */
-               data[0] = addr[i];
-               data_len[0] = len[i] - AES_BLOCK_SIZE;
-               pos = addr[i] + data_len[0];
-               for (j = 0; j < AES_BLOCK_SIZE; j++)
-                       tmp[j] = pos[j] ^ d[j];
-               data[1] = tmp;
-               data_len[1] = AES_BLOCK_SIZE;
-               data_elems = 2;
+               crypto_shash_update(desc, addr[i], len[i] - AES_BLOCK_SIZE);
+               crypto_xor(d, addr[i] + len[i] - AES_BLOCK_SIZE,
+                          AES_BLOCK_SIZE);
        } else {
                /* len(Sn) < 128 */
                /* T = dbl(D) xor pad(Sn) */
                gf_mulx(d); /* dbl */
-               memset(tmp, 0, AES_BLOCK_SIZE);
-               memcpy(tmp, addr[i], len[i]);
-               tmp[len[i]] = 0x80;
-               crypto_xor(d, tmp, AES_BLOCK_SIZE);
-               data[0] = d;
-               data_len[0] = sizeof(d);
-               data_elems = 1;
+               crypto_xor(d, addr[i], len[i]);
+               d[len[i]] ^= 0x80;
        }
        /* V = AES-CMAC(K, T) */
-       aes_cmac_vector(tfm, data_elems, data, data_len, v, AES_BLOCK_SIZE);
+       crypto_shash_finup(desc, d, AES_BLOCK_SIZE, v);
 
        return 0;
 }
@@ -80,7 +72,7 @@ static int aes_siv_encrypt(const u8 *key, size_t key_len,
                           size_t len[], u8 *out)
 {
        u8 v[AES_BLOCK_SIZE];
-       struct crypto_cipher *tfm;
+       struct crypto_shash *tfm;
        struct crypto_skcipher *tfm2;
        struct skcipher_request *req;
        int res;
@@ -95,14 +87,14 @@ static int aes_siv_encrypt(const u8 *key, size_t key_len,
 
        /* S2V */
 
-       tfm = crypto_alloc_cipher("aes", 0, 0);
+       tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
        /* K1 for S2V */
-       res = crypto_cipher_setkey(tfm, key, key_len);
+       res = crypto_shash_setkey(tfm, key, key_len);
        if (!res)
                res = aes_s2v(tfm, num_elem, addr, len, v);
-       crypto_free_cipher(tfm);
+       crypto_free_shash(tfm);
        if (res)
                return res;
 
@@ -157,7 +149,7 @@ static int aes_siv_decrypt(const u8 *key, size_t key_len,
                           size_t num_elem, const u8 *addr[], size_t len[],
                           u8 *out)
 {
-       struct crypto_cipher *tfm;
+       struct crypto_shash *tfm;
        struct crypto_skcipher *tfm2;
        struct skcipher_request *req;
        struct scatterlist src[1], dst[1];
@@ -210,14 +202,14 @@ static int aes_siv_decrypt(const u8 *key, size_t key_len,
 
        /* S2V */
 
-       tfm = crypto_alloc_cipher("aes", 0, 0);
+       tfm = crypto_alloc_shash("cmac(aes)", 0, 0);
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
        /* K1 for S2V */
-       res = crypto_cipher_setkey(tfm, key, key_len);
+       res = crypto_shash_setkey(tfm, key, key_len);
        if (!res)
                res = aes_s2v(tfm, num_elem, addr, len, check);
-       crypto_free_cipher(tfm);
+       crypto_free_shash(tfm);
        if (res)
                return res;
        if (memcmp(check, frame_iv, AES_BLOCK_SIZE) != 0)