Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: arm64/aes-ccm - Merge finalization into en/decrypt asm helpers

The C glue code already infers whether or not the current iteration is
the final one, by comparing walk.nbytes with walk.total. This means we
can easily inform the asm helpers of this as well, by conditionally
passing a pointer to the original IV, which is used in the finalization
of the MAC. This removes the need for a separate call into the asm code
to perform the finalization.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ard Biesheuvel and committed by
Herbert Xu
f691d444 71505288

+29 -38
+17 -23
arch/arm64/crypto/aes-ce-ccm-core.S
··· 44 44 aese \vb\().16b, v4.16b 45 45 .endm 46 46 47 - /* 48 - * void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u8 const rk[], 49 - * u32 rounds); 50 - */ 51 - SYM_FUNC_START(ce_aes_ccm_final) 52 - ld1 {v0.16b}, [x0] /* load mac */ 53 - ld1 {v1.16b}, [x1] /* load 1st ctriv */ 54 - 55 - aes_encrypt v0, v1, w3 56 - 57 - /* final round key cancels out */ 58 - eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */ 59 - st1 {v0.16b}, [x0] /* store result */ 60 - ret 61 - SYM_FUNC_END(ce_aes_ccm_final) 62 - 63 47 .macro aes_ccm_do_crypt,enc 64 48 load_round_keys x3, w4, x10 65 49 66 - cbz x2, 5f 67 - ldr x8, [x6, #8] /* load lower ctr */ 68 50 ld1 {v0.16b}, [x5] /* load mac */ 51 + cbz x2, ce_aes_ccm_final 52 + ldr x8, [x6, #8] /* load lower ctr */ 69 53 CPU_LE( rev x8, x8 ) /* keep swabbed ctr in reg */ 70 54 0: /* outer loop */ 71 55 ld1 {v1.8b}, [x6] /* load upper ctr */ ··· 74 90 st1 {v6.16b}, [x0], #16 /* write output block */ 75 91 bne 0b 76 92 CPU_LE( rev x8, x8 ) 77 - st1 {v0.16b}, [x5] /* store mac */ 78 93 str x8, [x6, #8] /* store lsb end of ctr (BE) */ 79 - 5: ret 94 + cbnz x7, ce_aes_ccm_final 95 + st1 {v0.16b}, [x5] /* store mac */ 96 + ret 80 97 .endm 81 98 82 99 SYM_FUNC_START_LOCAL(ce_aes_ccm_crypt_tail) ··· 101 116 tbl v2.16b, {v2.16b}, v9.16b /* copy plaintext to start of v2 */ 102 117 eor v0.16b, v0.16b, v2.16b /* fold plaintext into mac */ 103 118 104 - st1 {v0.16b}, [x5] /* store mac */ 105 119 st1 {v7.16b}, [x0] /* store output block */ 120 + cbz x7, 0f 121 + 122 + SYM_INNER_LABEL(ce_aes_ccm_final, SYM_L_LOCAL) 123 + ld1 {v1.16b}, [x7] /* load 1st ctriv */ 124 + 125 + aes_encrypt v0, v1, w4 126 + 127 + /* final round key cancels out */ 128 + eor v0.16b, v0.16b, v1.16b /* en-/decrypt the mac */ 129 + 0: st1 {v0.16b}, [x5] /* store result */ 106 130 ret 107 131 SYM_FUNC_END(ce_aes_ccm_crypt_tail) 108 132 109 133 /* 110 134 * void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes, 111 135 * u8 const rk[], u32 rounds, u8 mac[], 112 - * u8 ctr[]); 136 + * u8 ctr[], u8 const final_iv[]); 113 137 * void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, 114 138 * u8 const rk[], u32 rounds, u8 mac[], 115 - * u8 ctr[]); 139 + * u8 ctr[], u8 const final_iv[]); 116 140 */ 117 141 SYM_FUNC_START(ce_aes_ccm_encrypt) 118 142 movi v22.16b, #255
+12 -15
arch/arm64/crypto/aes-ce-ccm-glue.c
··· 38 38 39 39 asmlinkage void ce_aes_ccm_encrypt(u8 out[], u8 const in[], u32 cbytes, 40 40 u32 const rk[], u32 rounds, u8 mac[], 41 - u8 ctr[]); 41 + u8 ctr[], u8 const final_iv[]); 42 42 43 43 asmlinkage void ce_aes_ccm_decrypt(u8 out[], u8 const in[], u32 cbytes, 44 44 u32 const rk[], u32 rounds, u8 mac[], 45 - u8 ctr[]); 46 - 47 - asmlinkage void ce_aes_ccm_final(u8 mac[], u8 const ctr[], u32 const rk[], 48 - u32 rounds); 45 + u8 ctr[], u8 const final_iv[]); 49 46 50 47 static int ccm_setkey(struct crypto_aead *tfm, const u8 *in_key, 51 48 unsigned int key_len) ··· 207 210 const u8 *src = walk.src.virt.addr; 208 211 u8 *dst = walk.dst.virt.addr; 209 212 u8 buf[AES_BLOCK_SIZE]; 213 + u8 *final_iv = NULL; 210 214 211 - if (walk.nbytes == walk.total) 215 + if (walk.nbytes == walk.total) { 212 216 tail = 0; 217 + final_iv = orig_iv; 218 + } 213 219 214 220 if (unlikely(walk.nbytes < AES_BLOCK_SIZE)) 215 221 src = dst = memcpy(&buf[sizeof(buf) - walk.nbytes], ··· 220 220 221 221 ce_aes_ccm_encrypt(dst, src, walk.nbytes - tail, 222 222 ctx->key_enc, num_rounds(ctx), 223 - mac, walk.iv); 223 + mac, walk.iv, final_iv); 224 224 225 225 if (unlikely(walk.nbytes < AES_BLOCK_SIZE)) 226 226 memcpy(walk.dst.virt.addr, dst, walk.nbytes); 227 - 228 - if (walk.nbytes == walk.total) 229 - ce_aes_ccm_final(mac, orig_iv, ctx->key_enc, num_rounds(ctx)); 230 227 231 228 if (walk.nbytes) { 232 229 err = skcipher_walk_done(&walk, tail); ··· 274 277 const u8 *src = walk.src.virt.addr; 275 278 u8 *dst = walk.dst.virt.addr; 276 279 u8 buf[AES_BLOCK_SIZE]; 280 + u8 *final_iv = NULL; 277 281 278 - if (walk.nbytes == walk.total) 282 + if (walk.nbytes == walk.total) { 279 283 tail = 0; 284 + final_iv = orig_iv; 285 + } 280 286 281 287 if (unlikely(walk.nbytes < AES_BLOCK_SIZE)) 282 288 src = dst = memcpy(&buf[sizeof(buf) - walk.nbytes], ··· 287 287 288 288 ce_aes_ccm_decrypt(dst, src, walk.nbytes - tail, 289 289 ctx->key_enc, num_rounds(ctx), 290 - mac, walk.iv); 290 + mac, walk.iv, final_iv); 291 291 292 292 if (unlikely(walk.nbytes < AES_BLOCK_SIZE)) 293 293 memcpy(walk.dst.virt.addr, dst, walk.nbytes); 294 - 295 - if (walk.nbytes == walk.total) 296 - ce_aes_ccm_final(mac, orig_iv, ctx->key_enc, num_rounds(ctx)); 297 294 298 295 if (walk.nbytes) { 299 296 err = skcipher_walk_done(&walk, tail);