* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-11 8:21 ` Ard Biesheuvel
0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-11 8:21 UTC (permalink / raw)
To: linux-crypto, linux-arm-kernel; +Cc: herbert, will.deacon, nico, Ard Biesheuvel
This adds support for a synchronous implementation of AES in CCM mode
using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
Hi all,
I am posting this for review/RFC. The main topic for feedback is the way
I have used an inner blkcipher instance to process the encrypted + authenticated
data.
The point of having a dedicated module for synchronous ccm(aes) is the fact that
mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
IRQ context. In this case, the performance improvement offered by dedicated AES
instructions is likely wasted on stacking and unstacking the NEON register file,
as the generic CCM operates on a single AES block at a time.
Instead, this implementation interleaves the CTR and CBC modes at the round
level, eliminating 50% of both the input and round key loads and (hopefully)
eliminating pipeline stalls by operating on two AES blocks at a time.
Tested with tcrypt, no performance numbers yet.
--
Ard.
arch/arm64/Makefile | 1 +
arch/arm64/crypto/Makefile | 12 ++
arch/arm64/crypto/aesce-ccm-core.S | 222 +++++++++++++++++++++
arch/arm64/crypto/aesce-ccm-glue.c | 387 +++++++++++++++++++++++++++++++++++++
4 files changed, 622 insertions(+)
create mode 100644 arch/arm64/crypto/Makefile
create mode 100644 arch/arm64/crypto/aesce-ccm-core.S
create mode 100644 arch/arm64/crypto/aesce-ccm-glue.c
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index e0b75464b7f1..a4b3e253557d 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -46,6 +46,7 @@ core-y += arch/arm64/emu/
core-y += arch/arm64/kernel/ arch/arm64/mm/
core-$(CONFIG_KVM) += arch/arm64/kvm/
core-$(CONFIG_XEN) += arch/arm64/xen/
+core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
new file mode 100644
index 000000000000..ba10ebb53e9e
--- /dev/null
+++ b/arch/arm64/crypto/Makefile
@@ -0,0 +1,12 @@
+#
+# linux/arch/arm64/crypto/Makefile
+#
+# Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+#
+# 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.
+#
+
+aesce-ccm-y := aesce-ccm-glue.o aesce-ccm-core.o
+obj-m += aesce-ccm.o
diff --git a/arch/arm64/crypto/aesce-ccm-core.S b/arch/arm64/crypto/aesce-ccm-core.S
new file mode 100644
index 000000000000..f808c17eac45
--- /dev/null
+++ b/arch/arm64/crypto/aesce-ccm-core.S
@@ -0,0 +1,222 @@
+/*
+ * linux/arch/arm64/crypto/aesce-ccm-core.S - AES-CCM transform for
+ * ARMv8 with Crypto Extensions
+ *
+ * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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/linkage.h>
+
+ .text
+ .arch armv8-a+crypto
+
+ /*
+ * void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
+ * u32 *macp, u8 const rk[], u32 rounds);
+ */
+ENTRY(ce_aes_ccm_auth_data)
+ ldr w8, [x3] /* leftover from prev round? */
+ ld1 {v0.2d}, [x0] /* load mac */
+ cbz w8, 1f
+ sub w8, w8, #16
+ eor v1.16b, v1.16b, v1.16b
+0: ldrb w7, [x1], #1 /* get 1 byte of input */
+ subs w2, w2, #1
+ add w8, w8, #1
+ ins v1.b[0], w7
+ ext v1.16b, v1.16b, v1.16b, #1 /* rotate in the input bytes */
+ beq 8f /* out of input? */
+ cbnz w8, 0b
+ eor v0.16b, v0.16b, v1.16b
+1: ld1 {v3.2d}, [x4] /* load first round key */
+ prfm pldl1strm, [x1]
+ cmp w5, #12 /* which key size? */
+ add x6, x4, #16
+ sub w7, w5, #2 /* modified # of rounds */
+ bmi 2f
+ bne 5f
+ mov v5.16b, v3.16b
+ b 4f
+2: mov v4.16b, v3.16b
+ ld1 {v5.2d}, [x6], #16 /* load 2nd round key */
+3: aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+4: ld1 {v3.2d}, [x6], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+5: ld1 {v4.2d}, [x6], #16 /* load next round key */
+ subs w7, w7, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ ld1 {v5.2d}, [x6], #16 /* load next round key */
+ bpl 3b
+ aese v0.16b, v4.16b
+ subs w2, w2, #16 /* last data? */
+ eor v0.16b, v0.16b, v5.16b /* final round */
+ bmi 6f
+ ld1 {v1.16b}, [x1], #16 /* load next input block */
+ eor v0.16b, v0.16b, v1.16b /* xor with mac */
+ bne 1b
+6: st1 {v0.2d}, [x0] /* store mac */
+ beq 10f
+ adds w2, w2, #16
+ beq 10f
+ mov w8, w2
+7: ldrb w7, [x1], #1
+ umov w6, v0.b[0]
+ eor w6, w6, w7
+ strb w6, [x0], #1
+ subs w2, w2, #1
+ beq 10f
+ ext v0.16b, v0.16b, v0.16b, #1 /* rotate out the mac bytes */
+ b 7b
+8: mov w7, w8
+ add w8, w8, #16
+9: ext v1.16b, v1.16b, v1.16b, #1
+ adds w7, w7, #1
+ bne 9b
+ eor v0.16b, v0.16b, v1.16b
+ st1 {v0.2d}, [x0]
+10: str w8, [x3]
+ ret
+ENDPROC(ce_aes_ccm_auth_data)
+
+ /*
+ * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[],
+ * u32 rounds);
+ */
+ENTRY(ce_aes_ccm_final)
+ ld1 {v3.2d}, [x2], #16 /* load first round key */
+ ld1 {v0.2d}, [x0] /* load mac */
+ cmp w3, #12 /* which key size? */
+ sub w3, w3, #2 /* modified # of rounds */
+ ld1 {v1.2d}, [x1] /* load 1st ctriv */
+ bmi 0f
+ bne 3f
+ mov v5.16b, v3.16b
+ b 2f
+0: mov v4.16b, v3.16b
+1: ld1 {v5.2d}, [x2], #16 /* load next round key */
+ aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v4.16b
+ aesmc v1.16b, v1.16b
+2: ld1 {v3.2d}, [x2], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v5.16b
+ aesmc v1.16b, v1.16b
+3: ld1 {v4.2d}, [x2], #16 /* load next round key */
+ subs w3, w3, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v3.16b
+ aesmc v1.16b, v1.16b
+ bpl 1b
+ aese v0.16b, v4.16b
+ aese v1.16b, v4.16b
+ /* final round key cancels out */
+ eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */
+ st1 {v0.2d}, [x0] /* store result */
+ ret
+ENDPROC(ce_aes_ccm_final)
+
+ .macro aes_ccm_do_crypt,enc
+ ldr x8, [x6, #8] /* load lower ctr */
+ ld1 {v0.2d}, [x5] /* load mac */
+ rev x8, x8 /* keep swabbed ctr in reg */
+0: /* outer loop */
+ ld1 {v1.1d}, [x6] /* load upper ctr */
+ prfm pldl1strm, [x1]
+ add x8, x8, #1
+ rev x9, x8
+ cmp w4, #12 /* which key size? */
+ sub w7, w4, #2 /* get modified # of rounds */
+ ins v1.d[1], x9 /* no carry in lower ctr */
+ ld1 {v3.2d}, [x3] /* load first round key */
+ add x10, x3, #16
+ bmi 1f
+ bne 4f
+ mov v5.16b, v3.16b
+ b 3f
+1: mov v4.16b, v3.16b
+ ld1 {v5.2d}, [x10], #16 /* load 2nd round key */
+2: /* inner loop: 3 rounds, 2x interleaved */
+ aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v4.16b
+ aesmc v1.16b, v1.16b
+3: ld1 {v3.2d}, [x10], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v5.16b
+ aesmc v1.16b, v1.16b
+4: ld1 {v4.2d}, [x10], #16 /* load next round key */
+ subs w7, w7, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v3.16b
+ aesmc v1.16b, v1.16b
+ ld1 {v5.2d}, [x10], #16 /* load next round key */
+ bpl 2b
+ aese v0.16b, v4.16b
+ aese v1.16b, v4.16b
+ subs w2, w2, #16
+ bmi 5f
+ ld1 {v2.16b}, [x1], #16 /* load next input block */
+ .if \enc == 1
+ eor v2.16b, v2.16b, v5.16b /* final round enc+mac */
+ eor v1.16b, v1.16b, v2.16b /* xor with crypted ctr */
+ .else
+ eor v2.16b, v2.16b, v1.16b /* xor with crypted ctr */
+ eor v1.16b, v2.16b, v5.16b /* final round enc */
+ .endif
+ eor v0.16b, v0.16b, v2.16b /* xor mac with pt ^ rk[last] */
+ st1 {v1.16b}, [x0], #16 /* write output block */
+ bne 0b
+5: eor v0.16b, v0.16b, v5.16b /* final round mac */
+ eor v1.16b, v1.16b, v5.16b /* final round enc */
+ st1 {v0.2d}, [x5] /* store mac */
+ beq 7f
+ add w2, w2, #16 /* process partial tail block */
+6: ldrb w9, [x1], #1 /* get 1 byte of input */
+ umov w6, v1.b[0] /* get top crypted ctr byte */
+ umov w7, v0.b[0] /* get top mac byte */
+ .if \enc == 1
+ eor w7, w7, w9
+ eor w9, w9, w6
+ .else
+ eor w9, w9, w6
+ eor w7, w7, w9
+ .endif
+ strb w9, [x0], #1 /* store out byte */
+ strb w7, [x5], #1 /* store mac byte */
+ subs w2, w2, #1
+ beq 8f
+ ext v0.16b, v0.16b, v0.16b, #1 /* shift out mac byte */
+ ext v1.16b, v1.16b, v1.16b, #1 /* shift out ctr byte */
+ b 6b
+7: rev x8, x8
+ str x8, [x6, #8] /* store lsb end of ctr (BE) */
+8: ret
+ .endm
+
+ /*
+ * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
+ * u8 const rk[], u32 rounds, u8 mac[],
+ * u8 ctr[]);
+ * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
+ * u8 const rk[], u32 rounds, u8 mac[],
+ * u8 ctr[]);
+ */
+ENTRY(ce_aes_ccm_encrypt)
+ aes_ccm_do_crypt 1
+ENDPROC(ce_aes_ccm_encrypt)
+
+ENTRY(ce_aes_ccm_decrypt)
+ aes_ccm_do_crypt 0
+ENDPROC(ce_aes_ccm_decrypt)
diff --git a/arch/arm64/crypto/aesce-ccm-glue.c b/arch/arm64/crypto/aesce-ccm-glue.c
new file mode 100644
index 000000000000..153a40f43a6e
--- /dev/null
+++ b/arch/arm64/crypto/aesce-ccm-glue.c
@@ -0,0 +1,387 @@
+/*
+ * linux/arch/arm64/crypto/aes-ccm-glue.c
+ *
+ * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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 <asm/neon.h>
+#include <asm/unaligned.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+
+struct crypto_ccm_aes_ctx {
+ struct crypto_aes_ctx *key;
+ struct crypto_blkcipher *blk_tfm;
+};
+
+static int num_rounds(struct crypto_aes_ctx *ctx)
+{
+ /*
+ * # of rounds specified by AES:
+ * 128 bit key 10 rounds
+ * 192 bit key 12 rounds
+ * 256 bit key 14 rounds
+ * => n byte key => 6 + (n/4) rounds
+ */
+ return 6 + ctx->key_length / 4;
+}
+
+asmlinkage void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
+ u32 *macp, u32 const rk[], u32 rounds);
+
+asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
+ u32 const rk[], u32 rounds, u8 mac[],
+ u8 ctr[]);
+
+asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
+ u32 const rk[], u32 rounds, u8 mac[],
+ u8 ctr[]);
+
+asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[],
+ u32 rounds);
+
+static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(tfm);
+ int ret;
+
+ ret = crypto_aes_expand_key(ctx->key, in_key, key_len);
+ if (!ret)
+ return 0;
+
+ tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+}
+
+static int ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+ if ((authsize & 1) || authsize < 4)
+ return -EINVAL;
+ return 0;
+}
+
+static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ __be32 *n = (__be32 *)&maciv[AES_BLOCK_SIZE - 8];
+ u32 l = req->iv[0] + 1;
+
+ /* verify that CCM dimension 'L' is set correctly in the IV */
+ if (l < 2 || l > 8)
+ return -EINVAL;
+
+ /* verify that msglen can in fact be represented in L bytes */
+ if (msglen >> (8 * l))
+ return -EOVERFLOW;
+
+ /*
+ * Even if the CCM spec allows L values of up to 8, the Linux cryptoapi
+ * uses a u32 type to represent msglen so the top 4 bytes are always 0.
+ */
+ n[0] = 0;
+ n[1] = cpu_to_be32(msglen);
+
+ memcpy(maciv, req->iv, AES_BLOCK_SIZE - l);
+
+ /*
+ * Meaning of byte 0 according to CCM spec (RFC 3610/NIST 800-38C)
+ * - bits 0..2 : max # of bytes required to represent msglen, minus 1
+ * (already set by caller)
+ * - bits 3..5 : size of auth tag (1 => 4 bytes, 2 => 6 bytes, etc)
+ * - bit 6 : indicates presence of authenticate-only data
+ */
+ maciv[0] |= (crypto_aead_authsize(aead) - 2) << 2;
+ if (req->assoclen)
+ maciv[0] |= 0x40;
+
+ memset(&req->iv[AES_BLOCK_SIZE - l], 0, l);
+ return 0;
+}
+
+static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct __packed { __be16 l; __be32 h; u16 len; } ltag;
+ struct scatter_walk walk;
+ u32 len = req->assoclen;
+ u32 macp = 0;
+
+ /* prepend the AAD with a length tag */
+ if (len < 0xff00) {
+ ltag.l = cpu_to_be16(len);
+ ltag.len = 2;
+ } else {
+ ltag.l = cpu_to_be16(0xfffe);
+ put_unaligned_be32(len, <ag.h);
+ ltag.len = 6;
+ }
+
+ ce_aes_ccm_auth_data(mac, (u8 *)<ag, ltag.len, &macp,
+ ctx->key->key_enc, num_rounds(ctx->key));
+ scatterwalk_start(&walk, req->assoc);
+
+ do {
+ u32 n = scatterwalk_clamp(&walk, len);
+ u8 *p;
+
+ if (!n) {
+ scatterwalk_start(&walk, sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+ p = scatterwalk_map(&walk);
+ ce_aes_ccm_auth_data(mac, p, n, &macp,
+ ctx->key->key_enc, num_rounds(ctx->key));
+ len -= n;
+
+ scatterwalk_unmap(p);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, 0, len);
+ } while (len);
+}
+
+struct ccm_inner_desc_info {
+ u8 ctriv[AES_BLOCK_SIZE];
+ u8 mac[AES_BLOCK_SIZE];
+} __aligned(8);
+
+static int ccm_inner_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct ccm_inner_desc_info *descinfo = desc->info;
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+
+ if (walk.nbytes == nbytes)
+ tail = 0;
+
+ ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), descinfo->mac,
+ descinfo->ctriv);
+
+ nbytes -= walk.nbytes - tail;
+ err = blkcipher_walk_done(desc, &walk, tail);
+ }
+ return err;
+}
+
+static int ccm_inner_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct ccm_inner_desc_info *descinfo = desc->info;
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+
+ if (walk.nbytes == nbytes)
+ tail = 0;
+
+ ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), descinfo->mac,
+ descinfo->ctriv);
+
+ nbytes -= walk.nbytes - tail;
+ err = blkcipher_walk_done(desc, &walk, tail);
+ }
+ return err;
+}
+
+static int ccm_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_blkcipher *blk_tfm = ctx->blk_tfm;
+ struct ccm_inner_desc_info descinfo;
+ int err;
+
+ struct blkcipher_desc desc = {
+ .tfm = blk_tfm,
+ .info = &descinfo,
+ .flags = 0,
+ };
+
+ err = ccm_init_mac(req, descinfo.mac, req->cryptlen);
+ if (err)
+ return err;
+
+ kernel_neon_begin_partial(6);
+
+ if (req->assoclen)
+ ccm_calculate_auth_mac(req, descinfo.mac);
+
+ memcpy(descinfo.ctriv, req->iv, AES_BLOCK_SIZE);
+
+ /* call inner blkcipher to process the payload */
+ err = crypto_blkcipher_crt(blk_tfm)->encrypt(&desc, req->dst, req->src,
+ req->cryptlen);
+ if (!err)
+ ce_aes_ccm_final(descinfo.mac, req->iv, ctx->key->key_enc,
+ num_rounds(ctx->key));
+
+ kernel_neon_end();
+
+ if (err)
+ return err;
+
+ /* copy authtag to end of dst */
+ scatterwalk_map_and_copy(descinfo.mac, req->dst, req->cryptlen,
+ crypto_aead_authsize(aead), 1);
+
+ return 0;
+}
+
+static int ccm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_blkcipher *blk_tfm = ctx->blk_tfm;
+ struct ccm_inner_desc_info descinfo;
+ u8 atag[AES_BLOCK_SIZE];
+ u32 len;
+ int err;
+
+ struct blkcipher_desc desc = {
+ .tfm = blk_tfm,
+ .info = &descinfo,
+ .flags = 0,
+ };
+
+ len = req->cryptlen - crypto_aead_authsize(aead);
+ err = ccm_init_mac(req, descinfo.mac, len);
+ if (err)
+ return err;
+
+ if (req->assoclen)
+ ccm_calculate_auth_mac(req, descinfo.mac);
+
+ memcpy(descinfo.ctriv, req->iv, AES_BLOCK_SIZE);
+
+ kernel_neon_begin_partial(6);
+
+ /* call inner blkcipher to process the payload */
+ err = crypto_blkcipher_crt(blk_tfm)->decrypt(&desc, req->dst, req->src,
+ len);
+ if (!err)
+ ce_aes_ccm_final(descinfo.mac, req->iv, ctx->key->key_enc,
+ num_rounds(ctx->key));
+
+ kernel_neon_end();
+
+ if (err)
+ return err;
+
+ /* compare calculated auth tag with the stored one */
+ scatterwalk_map_and_copy(atag, req->src, len,
+ crypto_aead_authsize(aead), 0);
+
+ if (memcmp(descinfo.mac, atag, crypto_aead_authsize(aead)))
+ return -EBADMSG;
+ return 0;
+}
+
+static int ccm_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_blkcipher *blk_tfm;
+
+ blk_tfm = crypto_alloc_blkcipher("__driver-ccm-aesce-inner", 0, 0);
+ if (IS_ERR(blk_tfm))
+ return PTR_ERR(blk_tfm);
+
+ ctx->blk_tfm = blk_tfm;
+ ctx->key = crypto_blkcipher_ctx(blk_tfm);
+
+ return 0;
+}
+
+static void ccm_exit(struct crypto_tfm *tfm)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(ctx->blk_tfm);
+}
+
+static struct crypto_alg aes_algs[] = { {
+ .cra_name = "__ccm-aesce-inner",
+ .cra_driver_name = "__driver-ccm-aesce-inner",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = sizeof(struct ccm_inner_desc_info),
+ .setkey = crypto_aes_set_key,
+ .encrypt = ccm_inner_encrypt,
+ .decrypt = ccm_inner_decrypt,
+ },
+}, {
+ .cra_name = "ccm(aes)",
+ .cra_driver_name = "ccm-aes-ce",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_ccm_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ccm_init,
+ .cra_exit = ccm_exit,
+ .cra_aead = {
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = ccm_setkey,
+ .setauthsize = ccm_setauthsize,
+ .encrypt = ccm_encrypt,
+ .decrypt = ccm_decrypt,
+ }
+} };
+
+static int __init aes_mod_init(void)
+{
+ if (!(elf_hwcap & HWCAP_AES))
+ return -ENODEV;
+ return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs));
+}
+
+static void __exit aes_mod_exit(void)
+{
+ crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
+}
+
+module_init(aes_mod_init);
+module_exit(aes_mod_exit);
+
+MODULE_DESCRIPTION("Synchronous AES in CCM mode using ARMv8 Crypto Extensions");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ccm(aes)");
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-11 8:21 ` Ard Biesheuvel
0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-11 8:21 UTC (permalink / raw)
To: linux-arm-kernel
This adds support for a synchronous implementation of AES in CCM mode
using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
Hi all,
I am posting this for review/RFC. The main topic for feedback is the way
I have used an inner blkcipher instance to process the encrypted + authenticated
data.
The point of having a dedicated module for synchronous ccm(aes) is the fact that
mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
IRQ context. In this case, the performance improvement offered by dedicated AES
instructions is likely wasted on stacking and unstacking the NEON register file,
as the generic CCM operates on a single AES block at a time.
Instead, this implementation interleaves the CTR and CBC modes at the round
level, eliminating 50% of both the input and round key loads and (hopefully)
eliminating pipeline stalls by operating on two AES blocks at a time.
Tested with tcrypt, no performance numbers yet.
--
Ard.
arch/arm64/Makefile | 1 +
arch/arm64/crypto/Makefile | 12 ++
arch/arm64/crypto/aesce-ccm-core.S | 222 +++++++++++++++++++++
arch/arm64/crypto/aesce-ccm-glue.c | 387 +++++++++++++++++++++++++++++++++++++
4 files changed, 622 insertions(+)
create mode 100644 arch/arm64/crypto/Makefile
create mode 100644 arch/arm64/crypto/aesce-ccm-core.S
create mode 100644 arch/arm64/crypto/aesce-ccm-glue.c
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index e0b75464b7f1..a4b3e253557d 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -46,6 +46,7 @@ core-y += arch/arm64/emu/
core-y += arch/arm64/kernel/ arch/arm64/mm/
core-$(CONFIG_KVM) += arch/arm64/kvm/
core-$(CONFIG_XEN) += arch/arm64/xen/
+core-$(CONFIG_CRYPTO) += arch/arm64/crypto/
libs-y := arch/arm64/lib/ $(libs-y)
libs-y += $(LIBGCC)
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
new file mode 100644
index 000000000000..ba10ebb53e9e
--- /dev/null
+++ b/arch/arm64/crypto/Makefile
@@ -0,0 +1,12 @@
+#
+# linux/arch/arm64/crypto/Makefile
+#
+# Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+#
+# 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.
+#
+
+aesce-ccm-y := aesce-ccm-glue.o aesce-ccm-core.o
+obj-m += aesce-ccm.o
diff --git a/arch/arm64/crypto/aesce-ccm-core.S b/arch/arm64/crypto/aesce-ccm-core.S
new file mode 100644
index 000000000000..f808c17eac45
--- /dev/null
+++ b/arch/arm64/crypto/aesce-ccm-core.S
@@ -0,0 +1,222 @@
+/*
+ * linux/arch/arm64/crypto/aesce-ccm-core.S - AES-CCM transform for
+ * ARMv8 with Crypto Extensions
+ *
+ * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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/linkage.h>
+
+ .text
+ .arch armv8-a+crypto
+
+ /*
+ * void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
+ * u32 *macp, u8 const rk[], u32 rounds);
+ */
+ENTRY(ce_aes_ccm_auth_data)
+ ldr w8, [x3] /* leftover from prev round? */
+ ld1 {v0.2d}, [x0] /* load mac */
+ cbz w8, 1f
+ sub w8, w8, #16
+ eor v1.16b, v1.16b, v1.16b
+0: ldrb w7, [x1], #1 /* get 1 byte of input */
+ subs w2, w2, #1
+ add w8, w8, #1
+ ins v1.b[0], w7
+ ext v1.16b, v1.16b, v1.16b, #1 /* rotate in the input bytes */
+ beq 8f /* out of input? */
+ cbnz w8, 0b
+ eor v0.16b, v0.16b, v1.16b
+1: ld1 {v3.2d}, [x4] /* load first round key */
+ prfm pldl1strm, [x1]
+ cmp w5, #12 /* which key size? */
+ add x6, x4, #16
+ sub w7, w5, #2 /* modified # of rounds */
+ bmi 2f
+ bne 5f
+ mov v5.16b, v3.16b
+ b 4f
+2: mov v4.16b, v3.16b
+ ld1 {v5.2d}, [x6], #16 /* load 2nd round key */
+3: aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+4: ld1 {v3.2d}, [x6], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+5: ld1 {v4.2d}, [x6], #16 /* load next round key */
+ subs w7, w7, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ ld1 {v5.2d}, [x6], #16 /* load next round key */
+ bpl 3b
+ aese v0.16b, v4.16b
+ subs w2, w2, #16 /* last data? */
+ eor v0.16b, v0.16b, v5.16b /* final round */
+ bmi 6f
+ ld1 {v1.16b}, [x1], #16 /* load next input block */
+ eor v0.16b, v0.16b, v1.16b /* xor with mac */
+ bne 1b
+6: st1 {v0.2d}, [x0] /* store mac */
+ beq 10f
+ adds w2, w2, #16
+ beq 10f
+ mov w8, w2
+7: ldrb w7, [x1], #1
+ umov w6, v0.b[0]
+ eor w6, w6, w7
+ strb w6, [x0], #1
+ subs w2, w2, #1
+ beq 10f
+ ext v0.16b, v0.16b, v0.16b, #1 /* rotate out the mac bytes */
+ b 7b
+8: mov w7, w8
+ add w8, w8, #16
+9: ext v1.16b, v1.16b, v1.16b, #1
+ adds w7, w7, #1
+ bne 9b
+ eor v0.16b, v0.16b, v1.16b
+ st1 {v0.2d}, [x0]
+10: str w8, [x3]
+ ret
+ENDPROC(ce_aes_ccm_auth_data)
+
+ /*
+ * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[],
+ * u32 rounds);
+ */
+ENTRY(ce_aes_ccm_final)
+ ld1 {v3.2d}, [x2], #16 /* load first round key */
+ ld1 {v0.2d}, [x0] /* load mac */
+ cmp w3, #12 /* which key size? */
+ sub w3, w3, #2 /* modified # of rounds */
+ ld1 {v1.2d}, [x1] /* load 1st ctriv */
+ bmi 0f
+ bne 3f
+ mov v5.16b, v3.16b
+ b 2f
+0: mov v4.16b, v3.16b
+1: ld1 {v5.2d}, [x2], #16 /* load next round key */
+ aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v4.16b
+ aesmc v1.16b, v1.16b
+2: ld1 {v3.2d}, [x2], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v5.16b
+ aesmc v1.16b, v1.16b
+3: ld1 {v4.2d}, [x2], #16 /* load next round key */
+ subs w3, w3, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v3.16b
+ aesmc v1.16b, v1.16b
+ bpl 1b
+ aese v0.16b, v4.16b
+ aese v1.16b, v4.16b
+ /* final round key cancels out */
+ eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */
+ st1 {v0.2d}, [x0] /* store result */
+ ret
+ENDPROC(ce_aes_ccm_final)
+
+ .macro aes_ccm_do_crypt,enc
+ ldr x8, [x6, #8] /* load lower ctr */
+ ld1 {v0.2d}, [x5] /* load mac */
+ rev x8, x8 /* keep swabbed ctr in reg */
+0: /* outer loop */
+ ld1 {v1.1d}, [x6] /* load upper ctr */
+ prfm pldl1strm, [x1]
+ add x8, x8, #1
+ rev x9, x8
+ cmp w4, #12 /* which key size? */
+ sub w7, w4, #2 /* get modified # of rounds */
+ ins v1.d[1], x9 /* no carry in lower ctr */
+ ld1 {v3.2d}, [x3] /* load first round key */
+ add x10, x3, #16
+ bmi 1f
+ bne 4f
+ mov v5.16b, v3.16b
+ b 3f
+1: mov v4.16b, v3.16b
+ ld1 {v5.2d}, [x10], #16 /* load 2nd round key */
+2: /* inner loop: 3 rounds, 2x interleaved */
+ aese v0.16b, v4.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v4.16b
+ aesmc v1.16b, v1.16b
+3: ld1 {v3.2d}, [x10], #16 /* load next round key */
+ aese v0.16b, v5.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v5.16b
+ aesmc v1.16b, v1.16b
+4: ld1 {v4.2d}, [x10], #16 /* load next round key */
+ subs w7, w7, #3
+ aese v0.16b, v3.16b
+ aesmc v0.16b, v0.16b
+ aese v1.16b, v3.16b
+ aesmc v1.16b, v1.16b
+ ld1 {v5.2d}, [x10], #16 /* load next round key */
+ bpl 2b
+ aese v0.16b, v4.16b
+ aese v1.16b, v4.16b
+ subs w2, w2, #16
+ bmi 5f
+ ld1 {v2.16b}, [x1], #16 /* load next input block */
+ .if \enc == 1
+ eor v2.16b, v2.16b, v5.16b /* final round enc+mac */
+ eor v1.16b, v1.16b, v2.16b /* xor with crypted ctr */
+ .else
+ eor v2.16b, v2.16b, v1.16b /* xor with crypted ctr */
+ eor v1.16b, v2.16b, v5.16b /* final round enc */
+ .endif
+ eor v0.16b, v0.16b, v2.16b /* xor mac with pt ^ rk[last] */
+ st1 {v1.16b}, [x0], #16 /* write output block */
+ bne 0b
+5: eor v0.16b, v0.16b, v5.16b /* final round mac */
+ eor v1.16b, v1.16b, v5.16b /* final round enc */
+ st1 {v0.2d}, [x5] /* store mac */
+ beq 7f
+ add w2, w2, #16 /* process partial tail block */
+6: ldrb w9, [x1], #1 /* get 1 byte of input */
+ umov w6, v1.b[0] /* get top crypted ctr byte */
+ umov w7, v0.b[0] /* get top mac byte */
+ .if \enc == 1
+ eor w7, w7, w9
+ eor w9, w9, w6
+ .else
+ eor w9, w9, w6
+ eor w7, w7, w9
+ .endif
+ strb w9, [x0], #1 /* store out byte */
+ strb w7, [x5], #1 /* store mac byte */
+ subs w2, w2, #1
+ beq 8f
+ ext v0.16b, v0.16b, v0.16b, #1 /* shift out mac byte */
+ ext v1.16b, v1.16b, v1.16b, #1 /* shift out ctr byte */
+ b 6b
+7: rev x8, x8
+ str x8, [x6, #8] /* store lsb end of ctr (BE) */
+8: ret
+ .endm
+
+ /*
+ * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
+ * u8 const rk[], u32 rounds, u8 mac[],
+ * u8 ctr[]);
+ * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
+ * u8 const rk[], u32 rounds, u8 mac[],
+ * u8 ctr[]);
+ */
+ENTRY(ce_aes_ccm_encrypt)
+ aes_ccm_do_crypt 1
+ENDPROC(ce_aes_ccm_encrypt)
+
+ENTRY(ce_aes_ccm_decrypt)
+ aes_ccm_do_crypt 0
+ENDPROC(ce_aes_ccm_decrypt)
diff --git a/arch/arm64/crypto/aesce-ccm-glue.c b/arch/arm64/crypto/aesce-ccm-glue.c
new file mode 100644
index 000000000000..153a40f43a6e
--- /dev/null
+++ b/arch/arm64/crypto/aesce-ccm-glue.c
@@ -0,0 +1,387 @@
+/*
+ * linux/arch/arm64/crypto/aes-ccm-glue.c
+ *
+ * Copyright (C) 2013 - 2014 Linaro Ltd <ard.biesheuvel@linaro.org>
+ *
+ * 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 <asm/neon.h>
+#include <asm/unaligned.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/scatterwalk.h>
+#include <linux/crypto.h>
+#include <linux/module.h>
+
+struct crypto_ccm_aes_ctx {
+ struct crypto_aes_ctx *key;
+ struct crypto_blkcipher *blk_tfm;
+};
+
+static int num_rounds(struct crypto_aes_ctx *ctx)
+{
+ /*
+ * # of rounds specified by AES:
+ * 128 bit key 10 rounds
+ * 192 bit key 12 rounds
+ * 256 bit key 14 rounds
+ * => n byte key => 6 + (n/4) rounds
+ */
+ return 6 + ctx->key_length / 4;
+}
+
+asmlinkage void ce_aes_ccm_auth_data(u8 mac[], u8 const in[], u32 abytes,
+ u32 *macp, u32 const rk[], u32 rounds);
+
+asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes,
+ u32 const rk[], u32 rounds, u8 mac[],
+ u8 ctr[]);
+
+asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes,
+ u32 const rk[], u32 rounds, u8 mac[],
+ u8 ctr[]);
+
+asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[],
+ u32 rounds);
+
+static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key,
+ unsigned int key_len)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(tfm);
+ int ret;
+
+ ret = crypto_aes_expand_key(ctx->key, in_key, key_len);
+ if (!ret)
+ return 0;
+
+ tfm->base.crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
+ return -EINVAL;
+}
+
+static int ccm_setauthsize(struct crypto_aead *tfm, unsigned int authsize)
+{
+ if ((authsize & 1) || authsize < 4)
+ return -EINVAL;
+ return 0;
+}
+
+static int ccm_init_mac(struct aead_request *req, u8 maciv[], u32 msglen)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ __be32 *n = (__be32 *)&maciv[AES_BLOCK_SIZE - 8];
+ u32 l = req->iv[0] + 1;
+
+ /* verify that CCM dimension 'L' is set correctly in the IV */
+ if (l < 2 || l > 8)
+ return -EINVAL;
+
+ /* verify that msglen can in fact be represented in L bytes */
+ if (msglen >> (8 * l))
+ return -EOVERFLOW;
+
+ /*
+ * Even if the CCM spec allows L values of up to 8, the Linux cryptoapi
+ * uses a u32 type to represent msglen so the top 4 bytes are always 0.
+ */
+ n[0] = 0;
+ n[1] = cpu_to_be32(msglen);
+
+ memcpy(maciv, req->iv, AES_BLOCK_SIZE - l);
+
+ /*
+ * Meaning of byte 0 according to CCM spec (RFC 3610/NIST 800-38C)
+ * - bits 0..2 : max # of bytes required to represent msglen, minus 1
+ * (already set by caller)
+ * - bits 3..5 : size of auth tag (1 => 4 bytes, 2 => 6 bytes, etc)
+ * - bit 6 : indicates presence of authenticate-only data
+ */
+ maciv[0] |= (crypto_aead_authsize(aead) - 2) << 2;
+ if (req->assoclen)
+ maciv[0] |= 0x40;
+
+ memset(&req->iv[AES_BLOCK_SIZE - l], 0, l);
+ return 0;
+}
+
+static void ccm_calculate_auth_mac(struct aead_request *req, u8 mac[])
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct __packed { __be16 l; __be32 h; u16 len; } ltag;
+ struct scatter_walk walk;
+ u32 len = req->assoclen;
+ u32 macp = 0;
+
+ /* prepend the AAD with a length tag */
+ if (len < 0xff00) {
+ ltag.l = cpu_to_be16(len);
+ ltag.len = 2;
+ } else {
+ ltag.l = cpu_to_be16(0xfffe);
+ put_unaligned_be32(len, <ag.h);
+ ltag.len = 6;
+ }
+
+ ce_aes_ccm_auth_data(mac, (u8 *)<ag, ltag.len, &macp,
+ ctx->key->key_enc, num_rounds(ctx->key));
+ scatterwalk_start(&walk, req->assoc);
+
+ do {
+ u32 n = scatterwalk_clamp(&walk, len);
+ u8 *p;
+
+ if (!n) {
+ scatterwalk_start(&walk, sg_next(walk.sg));
+ n = scatterwalk_clamp(&walk, len);
+ }
+ p = scatterwalk_map(&walk);
+ ce_aes_ccm_auth_data(mac, p, n, &macp,
+ ctx->key->key_enc, num_rounds(ctx->key));
+ len -= n;
+
+ scatterwalk_unmap(p);
+ scatterwalk_advance(&walk, n);
+ scatterwalk_done(&walk, 0, len);
+ } while (len);
+}
+
+struct ccm_inner_desc_info {
+ u8 ctriv[AES_BLOCK_SIZE];
+ u8 mac[AES_BLOCK_SIZE];
+} __aligned(8);
+
+static int ccm_inner_encrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct ccm_inner_desc_info *descinfo = desc->info;
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+
+ if (walk.nbytes == nbytes)
+ tail = 0;
+
+ ce_aes_ccm_encrypt(walk.dst.virt.addr, walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), descinfo->mac,
+ descinfo->ctriv);
+
+ nbytes -= walk.nbytes - tail;
+ err = blkcipher_walk_done(desc, &walk, tail);
+ }
+ return err;
+}
+
+static int ccm_inner_decrypt(struct blkcipher_desc *desc,
+ struct scatterlist *dst, struct scatterlist *src,
+ unsigned int nbytes)
+{
+ struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
+ struct ccm_inner_desc_info *descinfo = desc->info;
+ struct blkcipher_walk walk;
+ int err;
+
+ blkcipher_walk_init(&walk, dst, src, nbytes);
+ err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE);
+
+ while (walk.nbytes) {
+ u32 tail = walk.nbytes % AES_BLOCK_SIZE;
+
+ if (walk.nbytes == nbytes)
+ tail = 0;
+
+ ce_aes_ccm_decrypt(walk.dst.virt.addr, walk.src.virt.addr,
+ walk.nbytes - tail, ctx->key_enc,
+ num_rounds(ctx), descinfo->mac,
+ descinfo->ctriv);
+
+ nbytes -= walk.nbytes - tail;
+ err = blkcipher_walk_done(desc, &walk, tail);
+ }
+ return err;
+}
+
+static int ccm_encrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_blkcipher *blk_tfm = ctx->blk_tfm;
+ struct ccm_inner_desc_info descinfo;
+ int err;
+
+ struct blkcipher_desc desc = {
+ .tfm = blk_tfm,
+ .info = &descinfo,
+ .flags = 0,
+ };
+
+ err = ccm_init_mac(req, descinfo.mac, req->cryptlen);
+ if (err)
+ return err;
+
+ kernel_neon_begin_partial(6);
+
+ if (req->assoclen)
+ ccm_calculate_auth_mac(req, descinfo.mac);
+
+ memcpy(descinfo.ctriv, req->iv, AES_BLOCK_SIZE);
+
+ /* call inner blkcipher to process the payload */
+ err = crypto_blkcipher_crt(blk_tfm)->encrypt(&desc, req->dst, req->src,
+ req->cryptlen);
+ if (!err)
+ ce_aes_ccm_final(descinfo.mac, req->iv, ctx->key->key_enc,
+ num_rounds(ctx->key));
+
+ kernel_neon_end();
+
+ if (err)
+ return err;
+
+ /* copy authtag to end of dst */
+ scatterwalk_map_and_copy(descinfo.mac, req->dst, req->cryptlen,
+ crypto_aead_authsize(aead), 1);
+
+ return 0;
+}
+
+static int ccm_decrypt(struct aead_request *req)
+{
+ struct crypto_aead *aead = crypto_aead_reqtfm(req);
+ struct crypto_ccm_aes_ctx *ctx = crypto_aead_ctx(aead);
+ struct crypto_blkcipher *blk_tfm = ctx->blk_tfm;
+ struct ccm_inner_desc_info descinfo;
+ u8 atag[AES_BLOCK_SIZE];
+ u32 len;
+ int err;
+
+ struct blkcipher_desc desc = {
+ .tfm = blk_tfm,
+ .info = &descinfo,
+ .flags = 0,
+ };
+
+ len = req->cryptlen - crypto_aead_authsize(aead);
+ err = ccm_init_mac(req, descinfo.mac, len);
+ if (err)
+ return err;
+
+ if (req->assoclen)
+ ccm_calculate_auth_mac(req, descinfo.mac);
+
+ memcpy(descinfo.ctriv, req->iv, AES_BLOCK_SIZE);
+
+ kernel_neon_begin_partial(6);
+
+ /* call inner blkcipher to process the payload */
+ err = crypto_blkcipher_crt(blk_tfm)->decrypt(&desc, req->dst, req->src,
+ len);
+ if (!err)
+ ce_aes_ccm_final(descinfo.mac, req->iv, ctx->key->key_enc,
+ num_rounds(ctx->key));
+
+ kernel_neon_end();
+
+ if (err)
+ return err;
+
+ /* compare calculated auth tag with the stored one */
+ scatterwalk_map_and_copy(atag, req->src, len,
+ crypto_aead_authsize(aead), 0);
+
+ if (memcmp(descinfo.mac, atag, crypto_aead_authsize(aead)))
+ return -EBADMSG;
+ return 0;
+}
+
+static int ccm_init(struct crypto_tfm *tfm)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+ struct crypto_blkcipher *blk_tfm;
+
+ blk_tfm = crypto_alloc_blkcipher("__driver-ccm-aesce-inner", 0, 0);
+ if (IS_ERR(blk_tfm))
+ return PTR_ERR(blk_tfm);
+
+ ctx->blk_tfm = blk_tfm;
+ ctx->key = crypto_blkcipher_ctx(blk_tfm);
+
+ return 0;
+}
+
+static void ccm_exit(struct crypto_tfm *tfm)
+{
+ struct crypto_ccm_aes_ctx *ctx = crypto_tfm_ctx(tfm);
+
+ crypto_free_blkcipher(ctx->blk_tfm);
+}
+
+static struct crypto_alg aes_algs[] = { {
+ .cra_name = "__ccm-aesce-inner",
+ .cra_driver_name = "__driver-ccm-aesce-inner",
+ .cra_priority = 0,
+ .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_blkcipher_type,
+ .cra_module = THIS_MODULE,
+ .cra_blkcipher = {
+ .min_keysize = AES_MIN_KEY_SIZE,
+ .max_keysize = AES_MAX_KEY_SIZE,
+ .ivsize = sizeof(struct ccm_inner_desc_info),
+ .setkey = crypto_aes_set_key,
+ .encrypt = ccm_inner_encrypt,
+ .decrypt = ccm_inner_decrypt,
+ },
+}, {
+ .cra_name = "ccm(aes)",
+ .cra_driver_name = "ccm-aes-ce",
+ .cra_priority = 300,
+ .cra_flags = CRYPTO_ALG_TYPE_AEAD,
+ .cra_blocksize = 1,
+ .cra_ctxsize = sizeof(struct crypto_ccm_aes_ctx),
+ .cra_alignmask = 7,
+ .cra_type = &crypto_aead_type,
+ .cra_module = THIS_MODULE,
+ .cra_init = ccm_init,
+ .cra_exit = ccm_exit,
+ .cra_aead = {
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = AES_BLOCK_SIZE,
+ .setkey = ccm_setkey,
+ .setauthsize = ccm_setauthsize,
+ .encrypt = ccm_encrypt,
+ .decrypt = ccm_decrypt,
+ }
+} };
+
+static int __init aes_mod_init(void)
+{
+ if (!(elf_hwcap & HWCAP_AES))
+ return -ENODEV;
+ return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs));
+}
+
+static void __exit aes_mod_exit(void)
+{
+ crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
+}
+
+module_init(aes_mod_init);
+module_exit(aes_mod_exit);
+
+MODULE_DESCRIPTION("Synchronous AES in CCM mode using ARMv8 Crypto Extensions");
+MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ccm(aes)");
--
1.8.3.2
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-11 8:21 ` Ard Biesheuvel
@ 2014-02-25 7:02 ` Herbert Xu
-1 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 7:02 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: linux-crypto, linux-arm-kernel, will.deacon, nico
On Tue, Feb 11, 2014 at 09:21:45AM +0100, Ard Biesheuvel wrote:
> This adds support for a synchronous implementation of AES in CCM mode
> using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> Hi all,
>
> I am posting this for review/RFC. The main topic for feedback is the way
> I have used an inner blkcipher instance to process the encrypted + authenticated
> data.
>
> The point of having a dedicated module for synchronous ccm(aes) is the fact that
> mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
> IRQ context. In this case, the performance improvement offered by dedicated AES
> instructions is likely wasted on stacking and unstacking the NEON register file,
> as the generic CCM operates on a single AES block at a time.
>
> Instead, this implementation interleaves the CTR and CBC modes at the round
> level, eliminating 50% of both the input and round key loads and (hopefully)
> eliminating pipeline stalls by operating on two AES blocks at a time.
>
> Tested with tcrypt, no performance numbers yet.
I think your idea definitely make sense, since we do the same
thing in aesni-intel.
It'll be interesting to see some numbers, especially if we could
compare this against the generic version that we talked about
earlier.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 7:02 ` Herbert Xu
0 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 7:02 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Feb 11, 2014 at 09:21:45AM +0100, Ard Biesheuvel wrote:
> This adds support for a synchronous implementation of AES in CCM mode
> using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> Hi all,
>
> I am posting this for review/RFC. The main topic for feedback is the way
> I have used an inner blkcipher instance to process the encrypted + authenticated
> data.
>
> The point of having a dedicated module for synchronous ccm(aes) is the fact that
> mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
> IRQ context. In this case, the performance improvement offered by dedicated AES
> instructions is likely wasted on stacking and unstacking the NEON register file,
> as the generic CCM operates on a single AES block at a time.
>
> Instead, this implementation interleaves the CTR and CBC modes at the round
> level, eliminating 50% of both the input and round key loads and (hopefully)
> eliminating pipeline stalls by operating on two AES blocks at a time.
>
> Tested with tcrypt, no performance numbers yet.
I think your idea definitely make sense, since we do the same
thing in aesni-intel.
It'll be interesting to see some numbers, especially if we could
compare this against the generic version that we talked about
earlier.
Thanks,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-25 7:02 ` Herbert Xu
@ 2014-02-25 7:12 ` Ard Biesheuvel
-1 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 7:12 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto, linux-arm-kernel, Will Deacon, Nicolas Pitre
On 25 February 2014 08:02, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 11, 2014 at 09:21:45AM +0100, Ard Biesheuvel wrote:
>> This adds support for a synchronous implementation of AES in CCM mode
>> using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> Hi all,
>>
>> I am posting this for review/RFC. The main topic for feedback is the way
>> I have used an inner blkcipher instance to process the encrypted + authenticated
>> data.
>>
>> The point of having a dedicated module for synchronous ccm(aes) is the fact that
>> mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
>> IRQ context. In this case, the performance improvement offered by dedicated AES
>> instructions is likely wasted on stacking and unstacking the NEON register file,
>> as the generic CCM operates on a single AES block at a time.
>>
>> Instead, this implementation interleaves the CTR and CBC modes at the round
>> level, eliminating 50% of both the input and round key loads and (hopefully)
>> eliminating pipeline stalls by operating on two AES blocks at a time.
>>
>> Tested with tcrypt, no performance numbers yet.
>
> I think your idea definitely make sense, since we do the same
> thing in aesni-intel.
>
> It'll be interesting to see some numbers, especially if we could
> compare this against the generic version that we talked about
> earlier.
>
Hi Herbert,
Thanks for taking a look.
I will definitely come back with performance numbers as soon as I
manage to produce any.
Do you have any comments specifically about using an inner blkcipher
instance to implement the aead?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 7:12 ` Ard Biesheuvel
0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 7:12 UTC (permalink / raw)
To: linux-arm-kernel
On 25 February 2014 08:02, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 11, 2014 at 09:21:45AM +0100, Ard Biesheuvel wrote:
>> This adds support for a synchronous implementation of AES in CCM mode
>> using ARMv8 Crypto Extensions, using NEON registers q0 - q5.
>>
>> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
>> ---
>> Hi all,
>>
>> I am posting this for review/RFC. The main topic for feedback is the way
>> I have used an inner blkcipher instance to process the encrypted + authenticated
>> data.
>>
>> The point of having a dedicated module for synchronous ccm(aes) is the fact that
>> mac80211 uses it for WPA2 CCMP en-/decryption, where it runs entirely in soft
>> IRQ context. In this case, the performance improvement offered by dedicated AES
>> instructions is likely wasted on stacking and unstacking the NEON register file,
>> as the generic CCM operates on a single AES block at a time.
>>
>> Instead, this implementation interleaves the CTR and CBC modes at the round
>> level, eliminating 50% of both the input and round key loads and (hopefully)
>> eliminating pipeline stalls by operating on two AES blocks at a time.
>>
>> Tested with tcrypt, no performance numbers yet.
>
> I think your idea definitely make sense, since we do the same
> thing in aesni-intel.
>
> It'll be interesting to see some numbers, especially if we could
> compare this against the generic version that we talked about
> earlier.
>
Hi Herbert,
Thanks for taking a look.
I will definitely come back with performance numbers as soon as I
manage to produce any.
Do you have any comments specifically about using an inner blkcipher
instance to implement the aead?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-25 7:12 ` Ard Biesheuvel
@ 2014-02-25 7:16 ` Herbert Xu
-1 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 7:16 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: linux-crypto, linux-arm-kernel, Will Deacon, Nicolas Pitre
On Tue, Feb 25, 2014 at 08:12:36AM +0100, Ard Biesheuvel wrote:
>
> Do you have any comments specifically about using an inner blkcipher
> instance to implement the aead?
Indeed, the inner block cipher looks superfluous since it's only
used once by ccm and there is no nesting similar to aesni-intel.
Inner algorithms are only needed if you want to nest it, e.g.,
through fpu(). Otherwise I don't see any difference vs. calling
the underlying functions directly, especially since you seem to
be calling them directly anyway.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 7:16 ` Herbert Xu
0 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 7:16 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Feb 25, 2014 at 08:12:36AM +0100, Ard Biesheuvel wrote:
>
> Do you have any comments specifically about using an inner blkcipher
> instance to implement the aead?
Indeed, the inner block cipher looks superfluous since it's only
used once by ccm and there is no nesting similar to aesni-intel.
Inner algorithms are only needed if you want to nest it, e.g.,
through fpu(). Otherwise I don't see any difference vs. calling
the underlying functions directly, especially since you seem to
be calling them directly anyway.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-25 7:16 ` Herbert Xu
@ 2014-02-25 7:21 ` Ard Biesheuvel
-1 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 7:21 UTC (permalink / raw)
To: Herbert Xu; +Cc: linux-crypto, linux-arm-kernel, Will Deacon, Nicolas Pitre
On 25 February 2014 08:16, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 25, 2014 at 08:12:36AM +0100, Ard Biesheuvel wrote:
>>
>> Do you have any comments specifically about using an inner blkcipher
>> instance to implement the aead?
>
> Indeed, the inner block cipher looks superfluous since it's only
> used once by ccm and there is no nesting similar to aesni-intel.
>
> Inner algorithms are only needed if you want to nest it, e.g.,
> through fpu(). Otherwise I don't see any difference vs. calling
> the underlying functions directly, especially since you seem to
> be calling them directly anyway.
>
Well, the problem is that aead does not provide the blkcipher walk
API, which means it is up to the caller to map/unmap the scatterlists
and keep track of the in and out pointers etc.
For the authenticate-only data, this is manageable as you are only
dealing with input, but when dealing with both in- and output, as in
the core of CCM, it becomes very tedious.
So instead, I have opted for an inner blkcipher instance which takes
care of all of that. Could you suggest another approach that if
preferable?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 7:21 ` Ard Biesheuvel
0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 7:21 UTC (permalink / raw)
To: linux-arm-kernel
On 25 February 2014 08:16, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 25, 2014 at 08:12:36AM +0100, Ard Biesheuvel wrote:
>>
>> Do you have any comments specifically about using an inner blkcipher
>> instance to implement the aead?
>
> Indeed, the inner block cipher looks superfluous since it's only
> used once by ccm and there is no nesting similar to aesni-intel.
>
> Inner algorithms are only needed if you want to nest it, e.g.,
> through fpu(). Otherwise I don't see any difference vs. calling
> the underlying functions directly, especially since you seem to
> be calling them directly anyway.
>
Well, the problem is that aead does not provide the blkcipher walk
API, which means it is up to the caller to map/unmap the scatterlists
and keep track of the in and out pointers etc.
For the authenticate-only data, this is manageable as you are only
dealing with input, but when dealing with both in- and output, as in
the core of CCM, it becomes very tedious.
So instead, I have opted for an inner blkcipher instance which takes
care of all of that. Could you suggest another approach that if
preferable?
Thanks,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-25 7:21 ` Ard Biesheuvel
@ 2014-02-25 9:08 ` Herbert Xu
-1 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 9:08 UTC (permalink / raw)
To: Ard Biesheuvel; +Cc: linux-crypto, linux-arm-kernel, Will Deacon, Nicolas Pitre
On Tue, Feb 25, 2014 at 08:21:22AM +0100, Ard Biesheuvel wrote:
>
> For the authenticate-only data, this is manageable as you are only
> dealing with input, but when dealing with both in- and output, as in
> the core of CCM, it becomes very tedious.
> So instead, I have opted for an inner blkcipher instance which takes
> care of all of that. Could you suggest another approach that if
> preferable?
I don't think the walk helper actually needs the tfm apart from
getting a couple of parameters out of it, so perhaps we can just
change the helper to not depend on a tfm.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 9:08 ` Herbert Xu
0 siblings, 0 replies; 14+ messages in thread
From: Herbert Xu @ 2014-02-25 9:08 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Feb 25, 2014 at 08:21:22AM +0100, Ard Biesheuvel wrote:
>
> For the authenticate-only data, this is manageable as you are only
> dealing with input, but when dealing with both in- and output, as in
> the core of CCM, it becomes very tedious.
> So instead, I have opted for an inner blkcipher instance which takes
> care of all of that. Could you suggest another approach that if
> preferable?
I don't think the walk helper actually needs the tfm apart from
getting a couple of parameters out of it, so perhaps we can just
change the helper to not depend on a tfm.
Cheers,
--
Email: Herbert Xu <herbert@gondor.apana.org.au>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
2014-02-25 9:08 ` Herbert Xu
@ 2014-02-25 10:11 ` Ard Biesheuvel
-1 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 10:11 UTC (permalink / raw)
To: Herbert Xu; +Cc: Will Deacon, linux-crypto, linux-arm-kernel, Nicolas Pitre
On 25 February 2014 10:08, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 25, 2014 at 08:21:22AM +0100, Ard Biesheuvel wrote:
>>
>> For the authenticate-only data, this is manageable as you are only
>> dealing with input, but when dealing with both in- and output, as in
>> the core of CCM, it becomes very tedious.
>> So instead, I have opted for an inner blkcipher instance which takes
>> care of all of that. Could you suggest another approach that if
>> preferable?
>
> I don't think the walk helper actually needs the tfm apart from
> getting a couple of parameters out of it, so perhaps we can just
> change the helper to not depend on a tfm.
>
That seems like a less hacky approach.
I'll cook something up and put it on the list.
Cheers,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
* [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions
@ 2014-02-25 10:11 ` Ard Biesheuvel
0 siblings, 0 replies; 14+ messages in thread
From: Ard Biesheuvel @ 2014-02-25 10:11 UTC (permalink / raw)
To: linux-arm-kernel
On 25 February 2014 10:08, Herbert Xu <herbert@gondor.apana.org.au> wrote:
> On Tue, Feb 25, 2014 at 08:21:22AM +0100, Ard Biesheuvel wrote:
>>
>> For the authenticate-only data, this is manageable as you are only
>> dealing with input, but when dealing with both in- and output, as in
>> the core of CCM, it becomes very tedious.
>> So instead, I have opted for an inner blkcipher instance which takes
>> care of all of that. Could you suggest another approach that if
>> preferable?
>
> I don't think the walk helper actually needs the tfm apart from
> getting a couple of parameters out of it, so perhaps we can just
> change the helper to not depend on a tfm.
>
That seems like a less hacky approach.
I'll cook something up and put it on the list.
Cheers,
Ard.
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2014-02-25 10:11 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-11 8:21 [RFC PATCH] arm64: add support for AES in CCM mode using Crypto Extensions Ard Biesheuvel
2014-02-11 8:21 ` Ard Biesheuvel
2014-02-25 7:02 ` Herbert Xu
2014-02-25 7:02 ` Herbert Xu
2014-02-25 7:12 ` Ard Biesheuvel
2014-02-25 7:12 ` Ard Biesheuvel
2014-02-25 7:16 ` Herbert Xu
2014-02-25 7:16 ` Herbert Xu
2014-02-25 7:21 ` Ard Biesheuvel
2014-02-25 7:21 ` Ard Biesheuvel
2014-02-25 9:08 ` Herbert Xu
2014-02-25 9:08 ` Herbert Xu
2014-02-25 10:11 ` Ard Biesheuvel
2014-02-25 10:11 ` Ard Biesheuvel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.