1*86464859SArd Biesheuvel /* 2*86464859SArd Biesheuvel * aes-ce-glue.c - wrapper code for ARMv8 AES 3*86464859SArd Biesheuvel * 4*86464859SArd Biesheuvel * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> 5*86464859SArd Biesheuvel * 6*86464859SArd Biesheuvel * This program is free software; you can redistribute it and/or modify 7*86464859SArd Biesheuvel * it under the terms of the GNU General Public License version 2 as 8*86464859SArd Biesheuvel * published by the Free Software Foundation. 9*86464859SArd Biesheuvel */ 10*86464859SArd Biesheuvel 11*86464859SArd Biesheuvel #include <asm/hwcap.h> 12*86464859SArd Biesheuvel #include <asm/neon.h> 13*86464859SArd Biesheuvel #include <asm/hwcap.h> 14*86464859SArd Biesheuvel #include <crypto/aes.h> 15*86464859SArd Biesheuvel #include <crypto/ablk_helper.h> 16*86464859SArd Biesheuvel #include <crypto/algapi.h> 17*86464859SArd Biesheuvel #include <linux/module.h> 18*86464859SArd Biesheuvel 19*86464859SArd Biesheuvel MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions"); 20*86464859SArd Biesheuvel MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 21*86464859SArd Biesheuvel MODULE_LICENSE("GPL v2"); 22*86464859SArd Biesheuvel 23*86464859SArd Biesheuvel /* defined in aes-ce-core.S */ 24*86464859SArd Biesheuvel asmlinkage u32 ce_aes_sub(u32 input); 25*86464859SArd Biesheuvel asmlinkage void ce_aes_invert(void *dst, void *src); 26*86464859SArd Biesheuvel 27*86464859SArd Biesheuvel asmlinkage void ce_aes_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], 28*86464859SArd Biesheuvel int rounds, int blocks); 29*86464859SArd Biesheuvel asmlinkage void ce_aes_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], 30*86464859SArd Biesheuvel int rounds, int blocks); 31*86464859SArd Biesheuvel 32*86464859SArd Biesheuvel asmlinkage void ce_aes_cbc_encrypt(u8 out[], u8 const in[], u8 const rk[], 33*86464859SArd Biesheuvel int rounds, int blocks, u8 iv[]); 34*86464859SArd Biesheuvel asmlinkage void ce_aes_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], 35*86464859SArd Biesheuvel int rounds, int blocks, u8 iv[]); 36*86464859SArd Biesheuvel 37*86464859SArd Biesheuvel asmlinkage void ce_aes_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], 38*86464859SArd Biesheuvel int rounds, int blocks, u8 ctr[]); 39*86464859SArd Biesheuvel 40*86464859SArd Biesheuvel asmlinkage void ce_aes_xts_encrypt(u8 out[], u8 const in[], u8 const rk1[], 41*86464859SArd Biesheuvel int rounds, int blocks, u8 iv[], 42*86464859SArd Biesheuvel u8 const rk2[], int first); 43*86464859SArd Biesheuvel asmlinkage void ce_aes_xts_decrypt(u8 out[], u8 const in[], u8 const rk1[], 44*86464859SArd Biesheuvel int rounds, int blocks, u8 iv[], 45*86464859SArd Biesheuvel u8 const rk2[], int first); 46*86464859SArd Biesheuvel 47*86464859SArd Biesheuvel struct aes_block { 48*86464859SArd Biesheuvel u8 b[AES_BLOCK_SIZE]; 49*86464859SArd Biesheuvel }; 50*86464859SArd Biesheuvel 51*86464859SArd Biesheuvel static int num_rounds(struct crypto_aes_ctx *ctx) 52*86464859SArd Biesheuvel { 53*86464859SArd Biesheuvel /* 54*86464859SArd Biesheuvel * # of rounds specified by AES: 55*86464859SArd Biesheuvel * 128 bit key 10 rounds 56*86464859SArd Biesheuvel * 192 bit key 12 rounds 57*86464859SArd Biesheuvel * 256 bit key 14 rounds 58*86464859SArd Biesheuvel * => n byte key => 6 + (n/4) rounds 59*86464859SArd Biesheuvel */ 60*86464859SArd Biesheuvel return 6 + ctx->key_length / 4; 61*86464859SArd Biesheuvel } 62*86464859SArd Biesheuvel 63*86464859SArd Biesheuvel static int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key, 64*86464859SArd Biesheuvel unsigned int key_len) 65*86464859SArd Biesheuvel { 66*86464859SArd Biesheuvel /* 67*86464859SArd Biesheuvel * The AES key schedule round constants 68*86464859SArd Biesheuvel */ 69*86464859SArd Biesheuvel static u8 const rcon[] = { 70*86464859SArd Biesheuvel 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 71*86464859SArd Biesheuvel }; 72*86464859SArd Biesheuvel 73*86464859SArd Biesheuvel u32 kwords = key_len / sizeof(u32); 74*86464859SArd Biesheuvel struct aes_block *key_enc, *key_dec; 75*86464859SArd Biesheuvel int i, j; 76*86464859SArd Biesheuvel 77*86464859SArd Biesheuvel if (key_len != AES_KEYSIZE_128 && 78*86464859SArd Biesheuvel key_len != AES_KEYSIZE_192 && 79*86464859SArd Biesheuvel key_len != AES_KEYSIZE_256) 80*86464859SArd Biesheuvel return -EINVAL; 81*86464859SArd Biesheuvel 82*86464859SArd Biesheuvel memcpy(ctx->key_enc, in_key, key_len); 83*86464859SArd Biesheuvel ctx->key_length = key_len; 84*86464859SArd Biesheuvel 85*86464859SArd Biesheuvel kernel_neon_begin(); 86*86464859SArd Biesheuvel for (i = 0; i < sizeof(rcon); i++) { 87*86464859SArd Biesheuvel u32 *rki = ctx->key_enc + (i * kwords); 88*86464859SArd Biesheuvel u32 *rko = rki + kwords; 89*86464859SArd Biesheuvel 90*86464859SArd Biesheuvel rko[0] = ror32(ce_aes_sub(rki[kwords - 1]), 8); 91*86464859SArd Biesheuvel rko[0] = rko[0] ^ rki[0] ^ rcon[i]; 92*86464859SArd Biesheuvel rko[1] = rko[0] ^ rki[1]; 93*86464859SArd Biesheuvel rko[2] = rko[1] ^ rki[2]; 94*86464859SArd Biesheuvel rko[3] = rko[2] ^ rki[3]; 95*86464859SArd Biesheuvel 96*86464859SArd Biesheuvel if (key_len == AES_KEYSIZE_192) { 97*86464859SArd Biesheuvel if (i >= 7) 98*86464859SArd Biesheuvel break; 99*86464859SArd Biesheuvel rko[4] = rko[3] ^ rki[4]; 100*86464859SArd Biesheuvel rko[5] = rko[4] ^ rki[5]; 101*86464859SArd Biesheuvel } else if (key_len == AES_KEYSIZE_256) { 102*86464859SArd Biesheuvel if (i >= 6) 103*86464859SArd Biesheuvel break; 104*86464859SArd Biesheuvel rko[4] = ce_aes_sub(rko[3]) ^ rki[4]; 105*86464859SArd Biesheuvel rko[5] = rko[4] ^ rki[5]; 106*86464859SArd Biesheuvel rko[6] = rko[5] ^ rki[6]; 107*86464859SArd Biesheuvel rko[7] = rko[6] ^ rki[7]; 108*86464859SArd Biesheuvel } 109*86464859SArd Biesheuvel } 110*86464859SArd Biesheuvel 111*86464859SArd Biesheuvel /* 112*86464859SArd Biesheuvel * Generate the decryption keys for the Equivalent Inverse Cipher. 113*86464859SArd Biesheuvel * This involves reversing the order of the round keys, and applying 114*86464859SArd Biesheuvel * the Inverse Mix Columns transformation on all but the first and 115*86464859SArd Biesheuvel * the last one. 116*86464859SArd Biesheuvel */ 117*86464859SArd Biesheuvel key_enc = (struct aes_block *)ctx->key_enc; 118*86464859SArd Biesheuvel key_dec = (struct aes_block *)ctx->key_dec; 119*86464859SArd Biesheuvel j = num_rounds(ctx); 120*86464859SArd Biesheuvel 121*86464859SArd Biesheuvel key_dec[0] = key_enc[j]; 122*86464859SArd Biesheuvel for (i = 1, j--; j > 0; i++, j--) 123*86464859SArd Biesheuvel ce_aes_invert(key_dec + i, key_enc + j); 124*86464859SArd Biesheuvel key_dec[i] = key_enc[0]; 125*86464859SArd Biesheuvel 126*86464859SArd Biesheuvel kernel_neon_end(); 127*86464859SArd Biesheuvel return 0; 128*86464859SArd Biesheuvel } 129*86464859SArd Biesheuvel 130*86464859SArd Biesheuvel static int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key, 131*86464859SArd Biesheuvel unsigned int key_len) 132*86464859SArd Biesheuvel { 133*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm); 134*86464859SArd Biesheuvel int ret; 135*86464859SArd Biesheuvel 136*86464859SArd Biesheuvel ret = ce_aes_expandkey(ctx, in_key, key_len); 137*86464859SArd Biesheuvel if (!ret) 138*86464859SArd Biesheuvel return 0; 139*86464859SArd Biesheuvel 140*86464859SArd Biesheuvel tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 141*86464859SArd Biesheuvel return -EINVAL; 142*86464859SArd Biesheuvel } 143*86464859SArd Biesheuvel 144*86464859SArd Biesheuvel struct crypto_aes_xts_ctx { 145*86464859SArd Biesheuvel struct crypto_aes_ctx key1; 146*86464859SArd Biesheuvel struct crypto_aes_ctx __aligned(8) key2; 147*86464859SArd Biesheuvel }; 148*86464859SArd Biesheuvel 149*86464859SArd Biesheuvel static int xts_set_key(struct crypto_tfm *tfm, const u8 *in_key, 150*86464859SArd Biesheuvel unsigned int key_len) 151*86464859SArd Biesheuvel { 152*86464859SArd Biesheuvel struct crypto_aes_xts_ctx *ctx = crypto_tfm_ctx(tfm); 153*86464859SArd Biesheuvel int ret; 154*86464859SArd Biesheuvel 155*86464859SArd Biesheuvel ret = ce_aes_expandkey(&ctx->key1, in_key, key_len / 2); 156*86464859SArd Biesheuvel if (!ret) 157*86464859SArd Biesheuvel ret = ce_aes_expandkey(&ctx->key2, &in_key[key_len / 2], 158*86464859SArd Biesheuvel key_len / 2); 159*86464859SArd Biesheuvel if (!ret) 160*86464859SArd Biesheuvel return 0; 161*86464859SArd Biesheuvel 162*86464859SArd Biesheuvel tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; 163*86464859SArd Biesheuvel return -EINVAL; 164*86464859SArd Biesheuvel } 165*86464859SArd Biesheuvel 166*86464859SArd Biesheuvel static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 167*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 168*86464859SArd Biesheuvel { 169*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 170*86464859SArd Biesheuvel struct blkcipher_walk walk; 171*86464859SArd Biesheuvel unsigned int blocks; 172*86464859SArd Biesheuvel int err; 173*86464859SArd Biesheuvel 174*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 175*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 176*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 177*86464859SArd Biesheuvel 178*86464859SArd Biesheuvel kernel_neon_begin(); 179*86464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { 180*86464859SArd Biesheuvel ce_aes_ecb_encrypt(walk.dst.virt.addr, walk.src.virt.addr, 181*86464859SArd Biesheuvel (u8 *)ctx->key_enc, num_rounds(ctx), blocks); 182*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 183*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 184*86464859SArd Biesheuvel } 185*86464859SArd Biesheuvel kernel_neon_end(); 186*86464859SArd Biesheuvel return err; 187*86464859SArd Biesheuvel } 188*86464859SArd Biesheuvel 189*86464859SArd Biesheuvel static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 190*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 191*86464859SArd Biesheuvel { 192*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 193*86464859SArd Biesheuvel struct blkcipher_walk walk; 194*86464859SArd Biesheuvel unsigned int blocks; 195*86464859SArd Biesheuvel int err; 196*86464859SArd Biesheuvel 197*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 198*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 199*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 200*86464859SArd Biesheuvel 201*86464859SArd Biesheuvel kernel_neon_begin(); 202*86464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { 203*86464859SArd Biesheuvel ce_aes_ecb_decrypt(walk.dst.virt.addr, walk.src.virt.addr, 204*86464859SArd Biesheuvel (u8 *)ctx->key_dec, num_rounds(ctx), blocks); 205*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 206*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 207*86464859SArd Biesheuvel } 208*86464859SArd Biesheuvel kernel_neon_end(); 209*86464859SArd Biesheuvel return err; 210*86464859SArd Biesheuvel } 211*86464859SArd Biesheuvel 212*86464859SArd Biesheuvel static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 213*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 214*86464859SArd Biesheuvel { 215*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 216*86464859SArd Biesheuvel struct blkcipher_walk walk; 217*86464859SArd Biesheuvel unsigned int blocks; 218*86464859SArd Biesheuvel int err; 219*86464859SArd Biesheuvel 220*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 221*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 222*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 223*86464859SArd Biesheuvel 224*86464859SArd Biesheuvel kernel_neon_begin(); 225*86464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { 226*86464859SArd Biesheuvel ce_aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, 227*86464859SArd Biesheuvel (u8 *)ctx->key_enc, num_rounds(ctx), blocks, 228*86464859SArd Biesheuvel walk.iv); 229*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 230*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 231*86464859SArd Biesheuvel } 232*86464859SArd Biesheuvel kernel_neon_end(); 233*86464859SArd Biesheuvel return err; 234*86464859SArd Biesheuvel } 235*86464859SArd Biesheuvel 236*86464859SArd Biesheuvel static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 237*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 238*86464859SArd Biesheuvel { 239*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 240*86464859SArd Biesheuvel struct blkcipher_walk walk; 241*86464859SArd Biesheuvel unsigned int blocks; 242*86464859SArd Biesheuvel int err; 243*86464859SArd Biesheuvel 244*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 245*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 246*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 247*86464859SArd Biesheuvel 248*86464859SArd Biesheuvel kernel_neon_begin(); 249*86464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { 250*86464859SArd Biesheuvel ce_aes_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, 251*86464859SArd Biesheuvel (u8 *)ctx->key_dec, num_rounds(ctx), blocks, 252*86464859SArd Biesheuvel walk.iv); 253*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 254*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 255*86464859SArd Biesheuvel } 256*86464859SArd Biesheuvel kernel_neon_end(); 257*86464859SArd Biesheuvel return err; 258*86464859SArd Biesheuvel } 259*86464859SArd Biesheuvel 260*86464859SArd Biesheuvel static int ctr_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 261*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 262*86464859SArd Biesheuvel { 263*86464859SArd Biesheuvel struct crypto_aes_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 264*86464859SArd Biesheuvel struct blkcipher_walk walk; 265*86464859SArd Biesheuvel int err, blocks; 266*86464859SArd Biesheuvel 267*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 268*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 269*86464859SArd Biesheuvel err = blkcipher_walk_virt_block(desc, &walk, AES_BLOCK_SIZE); 270*86464859SArd Biesheuvel 271*86464859SArd Biesheuvel kernel_neon_begin(); 272*86464859SArd Biesheuvel while ((blocks = (walk.nbytes / AES_BLOCK_SIZE))) { 273*86464859SArd Biesheuvel ce_aes_ctr_encrypt(walk.dst.virt.addr, walk.src.virt.addr, 274*86464859SArd Biesheuvel (u8 *)ctx->key_enc, num_rounds(ctx), blocks, 275*86464859SArd Biesheuvel walk.iv); 276*86464859SArd Biesheuvel nbytes -= blocks * AES_BLOCK_SIZE; 277*86464859SArd Biesheuvel if (nbytes && nbytes == walk.nbytes % AES_BLOCK_SIZE) 278*86464859SArd Biesheuvel break; 279*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 280*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 281*86464859SArd Biesheuvel } 282*86464859SArd Biesheuvel if (nbytes) { 283*86464859SArd Biesheuvel u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; 284*86464859SArd Biesheuvel u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; 285*86464859SArd Biesheuvel u8 __aligned(8) tail[AES_BLOCK_SIZE]; 286*86464859SArd Biesheuvel 287*86464859SArd Biesheuvel /* 288*86464859SArd Biesheuvel * Minimum alignment is 8 bytes, so if nbytes is <= 8, we need 289*86464859SArd Biesheuvel * to tell aes_ctr_encrypt() to only read half a block. 290*86464859SArd Biesheuvel */ 291*86464859SArd Biesheuvel blocks = (nbytes <= 8) ? -1 : 1; 292*86464859SArd Biesheuvel 293*86464859SArd Biesheuvel ce_aes_ctr_encrypt(tail, tsrc, (u8 *)ctx->key_enc, 294*86464859SArd Biesheuvel num_rounds(ctx), blocks, walk.iv); 295*86464859SArd Biesheuvel memcpy(tdst, tail, nbytes); 296*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 0); 297*86464859SArd Biesheuvel } 298*86464859SArd Biesheuvel kernel_neon_end(); 299*86464859SArd Biesheuvel 300*86464859SArd Biesheuvel return err; 301*86464859SArd Biesheuvel } 302*86464859SArd Biesheuvel 303*86464859SArd Biesheuvel static int xts_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 304*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 305*86464859SArd Biesheuvel { 306*86464859SArd Biesheuvel struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 307*86464859SArd Biesheuvel int err, first, rounds = num_rounds(&ctx->key1); 308*86464859SArd Biesheuvel struct blkcipher_walk walk; 309*86464859SArd Biesheuvel unsigned int blocks; 310*86464859SArd Biesheuvel 311*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 312*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 313*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 314*86464859SArd Biesheuvel 315*86464859SArd Biesheuvel kernel_neon_begin(); 316*86464859SArd Biesheuvel for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { 317*86464859SArd Biesheuvel ce_aes_xts_encrypt(walk.dst.virt.addr, walk.src.virt.addr, 318*86464859SArd Biesheuvel (u8 *)ctx->key1.key_enc, rounds, blocks, 319*86464859SArd Biesheuvel walk.iv, (u8 *)ctx->key2.key_enc, first); 320*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 321*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 322*86464859SArd Biesheuvel } 323*86464859SArd Biesheuvel kernel_neon_end(); 324*86464859SArd Biesheuvel 325*86464859SArd Biesheuvel return err; 326*86464859SArd Biesheuvel } 327*86464859SArd Biesheuvel 328*86464859SArd Biesheuvel static int xts_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst, 329*86464859SArd Biesheuvel struct scatterlist *src, unsigned int nbytes) 330*86464859SArd Biesheuvel { 331*86464859SArd Biesheuvel struct crypto_aes_xts_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 332*86464859SArd Biesheuvel int err, first, rounds = num_rounds(&ctx->key1); 333*86464859SArd Biesheuvel struct blkcipher_walk walk; 334*86464859SArd Biesheuvel unsigned int blocks; 335*86464859SArd Biesheuvel 336*86464859SArd Biesheuvel desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP; 337*86464859SArd Biesheuvel blkcipher_walk_init(&walk, dst, src, nbytes); 338*86464859SArd Biesheuvel err = blkcipher_walk_virt(desc, &walk); 339*86464859SArd Biesheuvel 340*86464859SArd Biesheuvel kernel_neon_begin(); 341*86464859SArd Biesheuvel for (first = 1; (blocks = (walk.nbytes / AES_BLOCK_SIZE)); first = 0) { 342*86464859SArd Biesheuvel ce_aes_xts_decrypt(walk.dst.virt.addr, walk.src.virt.addr, 343*86464859SArd Biesheuvel (u8 *)ctx->key1.key_dec, rounds, blocks, 344*86464859SArd Biesheuvel walk.iv, (u8 *)ctx->key2.key_enc, first); 345*86464859SArd Biesheuvel err = blkcipher_walk_done(desc, &walk, 346*86464859SArd Biesheuvel walk.nbytes % AES_BLOCK_SIZE); 347*86464859SArd Biesheuvel } 348*86464859SArd Biesheuvel kernel_neon_end(); 349*86464859SArd Biesheuvel 350*86464859SArd Biesheuvel return err; 351*86464859SArd Biesheuvel } 352*86464859SArd Biesheuvel 353*86464859SArd Biesheuvel static struct crypto_alg aes_algs[] = { { 354*86464859SArd Biesheuvel .cra_name = "__ecb-aes-ce", 355*86464859SArd Biesheuvel .cra_driver_name = "__driver-ecb-aes-ce", 356*86464859SArd Biesheuvel .cra_priority = 0, 357*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 358*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 359*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct crypto_aes_ctx), 360*86464859SArd Biesheuvel .cra_alignmask = 7, 361*86464859SArd Biesheuvel .cra_type = &crypto_blkcipher_type, 362*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 363*86464859SArd Biesheuvel .cra_blkcipher = { 364*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 365*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 366*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 367*86464859SArd Biesheuvel .setkey = ce_aes_setkey, 368*86464859SArd Biesheuvel .encrypt = ecb_encrypt, 369*86464859SArd Biesheuvel .decrypt = ecb_decrypt, 370*86464859SArd Biesheuvel }, 371*86464859SArd Biesheuvel }, { 372*86464859SArd Biesheuvel .cra_name = "__cbc-aes-ce", 373*86464859SArd Biesheuvel .cra_driver_name = "__driver-cbc-aes-ce", 374*86464859SArd Biesheuvel .cra_priority = 0, 375*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 376*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 377*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct crypto_aes_ctx), 378*86464859SArd Biesheuvel .cra_alignmask = 7, 379*86464859SArd Biesheuvel .cra_type = &crypto_blkcipher_type, 380*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 381*86464859SArd Biesheuvel .cra_blkcipher = { 382*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 383*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 384*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 385*86464859SArd Biesheuvel .setkey = ce_aes_setkey, 386*86464859SArd Biesheuvel .encrypt = cbc_encrypt, 387*86464859SArd Biesheuvel .decrypt = cbc_decrypt, 388*86464859SArd Biesheuvel }, 389*86464859SArd Biesheuvel }, { 390*86464859SArd Biesheuvel .cra_name = "__ctr-aes-ce", 391*86464859SArd Biesheuvel .cra_driver_name = "__driver-ctr-aes-ce", 392*86464859SArd Biesheuvel .cra_priority = 0, 393*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 394*86464859SArd Biesheuvel .cra_blocksize = 1, 395*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct crypto_aes_ctx), 396*86464859SArd Biesheuvel .cra_alignmask = 7, 397*86464859SArd Biesheuvel .cra_type = &crypto_blkcipher_type, 398*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 399*86464859SArd Biesheuvel .cra_blkcipher = { 400*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 401*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 402*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 403*86464859SArd Biesheuvel .setkey = ce_aes_setkey, 404*86464859SArd Biesheuvel .encrypt = ctr_encrypt, 405*86464859SArd Biesheuvel .decrypt = ctr_encrypt, 406*86464859SArd Biesheuvel }, 407*86464859SArd Biesheuvel }, { 408*86464859SArd Biesheuvel .cra_name = "__xts-aes-ce", 409*86464859SArd Biesheuvel .cra_driver_name = "__driver-xts-aes-ce", 410*86464859SArd Biesheuvel .cra_priority = 0, 411*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 412*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 413*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct crypto_aes_xts_ctx), 414*86464859SArd Biesheuvel .cra_alignmask = 7, 415*86464859SArd Biesheuvel .cra_type = &crypto_blkcipher_type, 416*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 417*86464859SArd Biesheuvel .cra_blkcipher = { 418*86464859SArd Biesheuvel .min_keysize = 2 * AES_MIN_KEY_SIZE, 419*86464859SArd Biesheuvel .max_keysize = 2 * AES_MAX_KEY_SIZE, 420*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 421*86464859SArd Biesheuvel .setkey = xts_set_key, 422*86464859SArd Biesheuvel .encrypt = xts_encrypt, 423*86464859SArd Biesheuvel .decrypt = xts_decrypt, 424*86464859SArd Biesheuvel }, 425*86464859SArd Biesheuvel }, { 426*86464859SArd Biesheuvel .cra_name = "ecb(aes)", 427*86464859SArd Biesheuvel .cra_driver_name = "ecb-aes-ce", 428*86464859SArd Biesheuvel .cra_priority = 300, 429*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, 430*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 431*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct async_helper_ctx), 432*86464859SArd Biesheuvel .cra_alignmask = 7, 433*86464859SArd Biesheuvel .cra_type = &crypto_ablkcipher_type, 434*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 435*86464859SArd Biesheuvel .cra_init = ablk_init, 436*86464859SArd Biesheuvel .cra_exit = ablk_exit, 437*86464859SArd Biesheuvel .cra_ablkcipher = { 438*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 439*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 440*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 441*86464859SArd Biesheuvel .setkey = ablk_set_key, 442*86464859SArd Biesheuvel .encrypt = ablk_encrypt, 443*86464859SArd Biesheuvel .decrypt = ablk_decrypt, 444*86464859SArd Biesheuvel } 445*86464859SArd Biesheuvel }, { 446*86464859SArd Biesheuvel .cra_name = "cbc(aes)", 447*86464859SArd Biesheuvel .cra_driver_name = "cbc-aes-ce", 448*86464859SArd Biesheuvel .cra_priority = 300, 449*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, 450*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 451*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct async_helper_ctx), 452*86464859SArd Biesheuvel .cra_alignmask = 7, 453*86464859SArd Biesheuvel .cra_type = &crypto_ablkcipher_type, 454*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 455*86464859SArd Biesheuvel .cra_init = ablk_init, 456*86464859SArd Biesheuvel .cra_exit = ablk_exit, 457*86464859SArd Biesheuvel .cra_ablkcipher = { 458*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 459*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 460*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 461*86464859SArd Biesheuvel .setkey = ablk_set_key, 462*86464859SArd Biesheuvel .encrypt = ablk_encrypt, 463*86464859SArd Biesheuvel .decrypt = ablk_decrypt, 464*86464859SArd Biesheuvel } 465*86464859SArd Biesheuvel }, { 466*86464859SArd Biesheuvel .cra_name = "ctr(aes)", 467*86464859SArd Biesheuvel .cra_driver_name = "ctr-aes-ce", 468*86464859SArd Biesheuvel .cra_priority = 300, 469*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, 470*86464859SArd Biesheuvel .cra_blocksize = 1, 471*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct async_helper_ctx), 472*86464859SArd Biesheuvel .cra_alignmask = 7, 473*86464859SArd Biesheuvel .cra_type = &crypto_ablkcipher_type, 474*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 475*86464859SArd Biesheuvel .cra_init = ablk_init, 476*86464859SArd Biesheuvel .cra_exit = ablk_exit, 477*86464859SArd Biesheuvel .cra_ablkcipher = { 478*86464859SArd Biesheuvel .min_keysize = AES_MIN_KEY_SIZE, 479*86464859SArd Biesheuvel .max_keysize = AES_MAX_KEY_SIZE, 480*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 481*86464859SArd Biesheuvel .setkey = ablk_set_key, 482*86464859SArd Biesheuvel .encrypt = ablk_encrypt, 483*86464859SArd Biesheuvel .decrypt = ablk_decrypt, 484*86464859SArd Biesheuvel } 485*86464859SArd Biesheuvel }, { 486*86464859SArd Biesheuvel .cra_name = "xts(aes)", 487*86464859SArd Biesheuvel .cra_driver_name = "xts-aes-ce", 488*86464859SArd Biesheuvel .cra_priority = 300, 489*86464859SArd Biesheuvel .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER|CRYPTO_ALG_ASYNC, 490*86464859SArd Biesheuvel .cra_blocksize = AES_BLOCK_SIZE, 491*86464859SArd Biesheuvel .cra_ctxsize = sizeof(struct async_helper_ctx), 492*86464859SArd Biesheuvel .cra_alignmask = 7, 493*86464859SArd Biesheuvel .cra_type = &crypto_ablkcipher_type, 494*86464859SArd Biesheuvel .cra_module = THIS_MODULE, 495*86464859SArd Biesheuvel .cra_init = ablk_init, 496*86464859SArd Biesheuvel .cra_exit = ablk_exit, 497*86464859SArd Biesheuvel .cra_ablkcipher = { 498*86464859SArd Biesheuvel .min_keysize = 2 * AES_MIN_KEY_SIZE, 499*86464859SArd Biesheuvel .max_keysize = 2 * AES_MAX_KEY_SIZE, 500*86464859SArd Biesheuvel .ivsize = AES_BLOCK_SIZE, 501*86464859SArd Biesheuvel .setkey = ablk_set_key, 502*86464859SArd Biesheuvel .encrypt = ablk_encrypt, 503*86464859SArd Biesheuvel .decrypt = ablk_decrypt, 504*86464859SArd Biesheuvel } 505*86464859SArd Biesheuvel } }; 506*86464859SArd Biesheuvel 507*86464859SArd Biesheuvel static int __init aes_init(void) 508*86464859SArd Biesheuvel { 509*86464859SArd Biesheuvel if (!(elf_hwcap2 & HWCAP2_AES)) 510*86464859SArd Biesheuvel return -ENODEV; 511*86464859SArd Biesheuvel return crypto_register_algs(aes_algs, ARRAY_SIZE(aes_algs)); 512*86464859SArd Biesheuvel } 513*86464859SArd Biesheuvel 514*86464859SArd Biesheuvel static void __exit aes_exit(void) 515*86464859SArd Biesheuvel { 516*86464859SArd Biesheuvel crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs)); 517*86464859SArd Biesheuvel } 518*86464859SArd Biesheuvel 519*86464859SArd Biesheuvel module_init(aes_init); 520*86464859SArd Biesheuvel module_exit(aes_exit); 521