162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Bit sliced AES using NEON instructions 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2016 - 2017 Linaro Ltd <ard.biesheuvel@linaro.org> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <asm/neon.h> 962306a36Sopenharmony_ci#include <asm/simd.h> 1062306a36Sopenharmony_ci#include <crypto/aes.h> 1162306a36Sopenharmony_ci#include <crypto/ctr.h> 1262306a36Sopenharmony_ci#include <crypto/internal/simd.h> 1362306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 1462306a36Sopenharmony_ci#include <crypto/scatterwalk.h> 1562306a36Sopenharmony_ci#include <crypto/xts.h> 1662306a36Sopenharmony_ci#include <linux/module.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ciMODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 1962306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("ecb(aes)"); 2262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("cbc(aes)"); 2362306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("ctr(aes)"); 2462306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("xts(aes)"); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciasmlinkage void aesbs_convert_key(u8 out[], u32 const rk[], int rounds); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ciasmlinkage void aesbs_ecb_encrypt(u8 out[], u8 const in[], u8 const rk[], 2962306a36Sopenharmony_ci int rounds, int blocks); 3062306a36Sopenharmony_ciasmlinkage void aesbs_ecb_decrypt(u8 out[], u8 const in[], u8 const rk[], 3162306a36Sopenharmony_ci int rounds, int blocks); 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ciasmlinkage void aesbs_cbc_decrypt(u8 out[], u8 const in[], u8 const rk[], 3462306a36Sopenharmony_ci int rounds, int blocks, u8 iv[]); 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ciasmlinkage void aesbs_ctr_encrypt(u8 out[], u8 const in[], u8 const rk[], 3762306a36Sopenharmony_ci int rounds, int blocks, u8 iv[]); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ciasmlinkage void aesbs_xts_encrypt(u8 out[], u8 const in[], u8 const rk[], 4062306a36Sopenharmony_ci int rounds, int blocks, u8 iv[]); 4162306a36Sopenharmony_ciasmlinkage void aesbs_xts_decrypt(u8 out[], u8 const in[], u8 const rk[], 4262306a36Sopenharmony_ci int rounds, int blocks, u8 iv[]); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/* borrowed from aes-neon-blk.ko */ 4562306a36Sopenharmony_ciasmlinkage void neon_aes_ecb_encrypt(u8 out[], u8 const in[], u32 const rk[], 4662306a36Sopenharmony_ci int rounds, int blocks); 4762306a36Sopenharmony_ciasmlinkage void neon_aes_cbc_encrypt(u8 out[], u8 const in[], u32 const rk[], 4862306a36Sopenharmony_ci int rounds, int blocks, u8 iv[]); 4962306a36Sopenharmony_ciasmlinkage void neon_aes_ctr_encrypt(u8 out[], u8 const in[], u32 const rk[], 5062306a36Sopenharmony_ci int rounds, int bytes, u8 ctr[]); 5162306a36Sopenharmony_ciasmlinkage void neon_aes_xts_encrypt(u8 out[], u8 const in[], 5262306a36Sopenharmony_ci u32 const rk1[], int rounds, int bytes, 5362306a36Sopenharmony_ci u32 const rk2[], u8 iv[], int first); 5462306a36Sopenharmony_ciasmlinkage void neon_aes_xts_decrypt(u8 out[], u8 const in[], 5562306a36Sopenharmony_ci u32 const rk1[], int rounds, int bytes, 5662306a36Sopenharmony_ci u32 const rk2[], u8 iv[], int first); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistruct aesbs_ctx { 5962306a36Sopenharmony_ci u8 rk[13 * (8 * AES_BLOCK_SIZE) + 32]; 6062306a36Sopenharmony_ci int rounds; 6162306a36Sopenharmony_ci} __aligned(AES_BLOCK_SIZE); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_cistruct aesbs_cbc_ctr_ctx { 6462306a36Sopenharmony_ci struct aesbs_ctx key; 6562306a36Sopenharmony_ci u32 enc[AES_MAX_KEYLENGTH_U32]; 6662306a36Sopenharmony_ci}; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistruct aesbs_xts_ctx { 6962306a36Sopenharmony_ci struct aesbs_ctx key; 7062306a36Sopenharmony_ci u32 twkey[AES_MAX_KEYLENGTH_U32]; 7162306a36Sopenharmony_ci struct crypto_aes_ctx cts; 7262306a36Sopenharmony_ci}; 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic int aesbs_setkey(struct crypto_skcipher *tfm, const u8 *in_key, 7562306a36Sopenharmony_ci unsigned int key_len) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); 7862306a36Sopenharmony_ci struct crypto_aes_ctx rk; 7962306a36Sopenharmony_ci int err; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci err = aes_expandkey(&rk, in_key, key_len); 8262306a36Sopenharmony_ci if (err) 8362306a36Sopenharmony_ci return err; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci ctx->rounds = 6 + key_len / 4; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci kernel_neon_begin(); 8862306a36Sopenharmony_ci aesbs_convert_key(ctx->rk, rk.key_enc, ctx->rounds); 8962306a36Sopenharmony_ci kernel_neon_end(); 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistatic int __ecb_crypt(struct skcipher_request *req, 9562306a36Sopenharmony_ci void (*fn)(u8 out[], u8 const in[], u8 const rk[], 9662306a36Sopenharmony_ci int rounds, int blocks)) 9762306a36Sopenharmony_ci{ 9862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 9962306a36Sopenharmony_ci struct aesbs_ctx *ctx = crypto_skcipher_ctx(tfm); 10062306a36Sopenharmony_ci struct skcipher_walk walk; 10162306a36Sopenharmony_ci int err; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci while (walk.nbytes >= AES_BLOCK_SIZE) { 10662306a36Sopenharmony_ci unsigned int blocks = walk.nbytes / AES_BLOCK_SIZE; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (walk.nbytes < walk.total) 10962306a36Sopenharmony_ci blocks = round_down(blocks, 11062306a36Sopenharmony_ci walk.stride / AES_BLOCK_SIZE); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci kernel_neon_begin(); 11362306a36Sopenharmony_ci fn(walk.dst.virt.addr, walk.src.virt.addr, ctx->rk, 11462306a36Sopenharmony_ci ctx->rounds, blocks); 11562306a36Sopenharmony_ci kernel_neon_end(); 11662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, 11762306a36Sopenharmony_ci walk.nbytes - blocks * AES_BLOCK_SIZE); 11862306a36Sopenharmony_ci } 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return err; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic int ecb_encrypt(struct skcipher_request *req) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci return __ecb_crypt(req, aesbs_ecb_encrypt); 12662306a36Sopenharmony_ci} 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_cistatic int ecb_decrypt(struct skcipher_request *req) 12962306a36Sopenharmony_ci{ 13062306a36Sopenharmony_ci return __ecb_crypt(req, aesbs_ecb_decrypt); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int aesbs_cbc_ctr_setkey(struct crypto_skcipher *tfm, const u8 *in_key, 13462306a36Sopenharmony_ci unsigned int key_len) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 13762306a36Sopenharmony_ci struct crypto_aes_ctx rk; 13862306a36Sopenharmony_ci int err; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci err = aes_expandkey(&rk, in_key, key_len); 14162306a36Sopenharmony_ci if (err) 14262306a36Sopenharmony_ci return err; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci ctx->key.rounds = 6 + key_len / 4; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci memcpy(ctx->enc, rk.key_enc, sizeof(ctx->enc)); 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci kernel_neon_begin(); 14962306a36Sopenharmony_ci aesbs_convert_key(ctx->key.rk, rk.key_enc, ctx->key.rounds); 15062306a36Sopenharmony_ci kernel_neon_end(); 15162306a36Sopenharmony_ci memzero_explicit(&rk, sizeof(rk)); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci return 0; 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cistatic int cbc_encrypt(struct skcipher_request *req) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 15962306a36Sopenharmony_ci struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 16062306a36Sopenharmony_ci struct skcipher_walk walk; 16162306a36Sopenharmony_ci int err; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci while (walk.nbytes >= AES_BLOCK_SIZE) { 16662306a36Sopenharmony_ci unsigned int blocks = walk.nbytes / AES_BLOCK_SIZE; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* fall back to the non-bitsliced NEON implementation */ 16962306a36Sopenharmony_ci kernel_neon_begin(); 17062306a36Sopenharmony_ci neon_aes_cbc_encrypt(walk.dst.virt.addr, walk.src.virt.addr, 17162306a36Sopenharmony_ci ctx->enc, ctx->key.rounds, blocks, 17262306a36Sopenharmony_ci walk.iv); 17362306a36Sopenharmony_ci kernel_neon_end(); 17462306a36Sopenharmony_ci err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci return err; 17762306a36Sopenharmony_ci} 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_cistatic int cbc_decrypt(struct skcipher_request *req) 18062306a36Sopenharmony_ci{ 18162306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 18262306a36Sopenharmony_ci struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 18362306a36Sopenharmony_ci struct skcipher_walk walk; 18462306a36Sopenharmony_ci int err; 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci while (walk.nbytes >= AES_BLOCK_SIZE) { 18962306a36Sopenharmony_ci unsigned int blocks = walk.nbytes / AES_BLOCK_SIZE; 19062306a36Sopenharmony_ci 19162306a36Sopenharmony_ci if (walk.nbytes < walk.total) 19262306a36Sopenharmony_ci blocks = round_down(blocks, 19362306a36Sopenharmony_ci walk.stride / AES_BLOCK_SIZE); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci kernel_neon_begin(); 19662306a36Sopenharmony_ci aesbs_cbc_decrypt(walk.dst.virt.addr, walk.src.virt.addr, 19762306a36Sopenharmony_ci ctx->key.rk, ctx->key.rounds, blocks, 19862306a36Sopenharmony_ci walk.iv); 19962306a36Sopenharmony_ci kernel_neon_end(); 20062306a36Sopenharmony_ci err = skcipher_walk_done(&walk, 20162306a36Sopenharmony_ci walk.nbytes - blocks * AES_BLOCK_SIZE); 20262306a36Sopenharmony_ci } 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci return err; 20562306a36Sopenharmony_ci} 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_cistatic int ctr_encrypt(struct skcipher_request *req) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 21062306a36Sopenharmony_ci struct aesbs_cbc_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 21162306a36Sopenharmony_ci struct skcipher_walk walk; 21262306a36Sopenharmony_ci int err; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci while (walk.nbytes > 0) { 21762306a36Sopenharmony_ci int blocks = (walk.nbytes / AES_BLOCK_SIZE) & ~7; 21862306a36Sopenharmony_ci int nbytes = walk.nbytes % (8 * AES_BLOCK_SIZE); 21962306a36Sopenharmony_ci const u8 *src = walk.src.virt.addr; 22062306a36Sopenharmony_ci u8 *dst = walk.dst.virt.addr; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci kernel_neon_begin(); 22362306a36Sopenharmony_ci if (blocks >= 8) { 22462306a36Sopenharmony_ci aesbs_ctr_encrypt(dst, src, ctx->key.rk, ctx->key.rounds, 22562306a36Sopenharmony_ci blocks, walk.iv); 22662306a36Sopenharmony_ci dst += blocks * AES_BLOCK_SIZE; 22762306a36Sopenharmony_ci src += blocks * AES_BLOCK_SIZE; 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci if (nbytes && walk.nbytes == walk.total) { 23062306a36Sopenharmony_ci u8 buf[AES_BLOCK_SIZE]; 23162306a36Sopenharmony_ci u8 *d = dst; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci if (unlikely(nbytes < AES_BLOCK_SIZE)) 23462306a36Sopenharmony_ci src = dst = memcpy(buf + sizeof(buf) - nbytes, 23562306a36Sopenharmony_ci src, nbytes); 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci neon_aes_ctr_encrypt(dst, src, ctx->enc, ctx->key.rounds, 23862306a36Sopenharmony_ci nbytes, walk.iv); 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (unlikely(nbytes < AES_BLOCK_SIZE)) 24162306a36Sopenharmony_ci memcpy(d, dst, nbytes); 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci nbytes = 0; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci kernel_neon_end(); 24662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci return err; 24962306a36Sopenharmony_ci} 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cistatic int aesbs_xts_setkey(struct crypto_skcipher *tfm, const u8 *in_key, 25262306a36Sopenharmony_ci unsigned int key_len) 25362306a36Sopenharmony_ci{ 25462306a36Sopenharmony_ci struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); 25562306a36Sopenharmony_ci struct crypto_aes_ctx rk; 25662306a36Sopenharmony_ci int err; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci err = xts_verify_key(tfm, in_key, key_len); 25962306a36Sopenharmony_ci if (err) 26062306a36Sopenharmony_ci return err; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci key_len /= 2; 26362306a36Sopenharmony_ci err = aes_expandkey(&ctx->cts, in_key, key_len); 26462306a36Sopenharmony_ci if (err) 26562306a36Sopenharmony_ci return err; 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci err = aes_expandkey(&rk, in_key + key_len, key_len); 26862306a36Sopenharmony_ci if (err) 26962306a36Sopenharmony_ci return err; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci memcpy(ctx->twkey, rk.key_enc, sizeof(ctx->twkey)); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return aesbs_setkey(tfm, in_key, key_len); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic int __xts_crypt(struct skcipher_request *req, bool encrypt, 27762306a36Sopenharmony_ci void (*fn)(u8 out[], u8 const in[], u8 const rk[], 27862306a36Sopenharmony_ci int rounds, int blocks, u8 iv[])) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 28162306a36Sopenharmony_ci struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); 28262306a36Sopenharmony_ci int tail = req->cryptlen % (8 * AES_BLOCK_SIZE); 28362306a36Sopenharmony_ci struct scatterlist sg_src[2], sg_dst[2]; 28462306a36Sopenharmony_ci struct skcipher_request subreq; 28562306a36Sopenharmony_ci struct scatterlist *src, *dst; 28662306a36Sopenharmony_ci struct skcipher_walk walk; 28762306a36Sopenharmony_ci int nbytes, err; 28862306a36Sopenharmony_ci int first = 1; 28962306a36Sopenharmony_ci u8 *out, *in; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci if (req->cryptlen < AES_BLOCK_SIZE) 29262306a36Sopenharmony_ci return -EINVAL; 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_ci /* ensure that the cts tail is covered by a single step */ 29562306a36Sopenharmony_ci if (unlikely(tail > 0 && tail < AES_BLOCK_SIZE)) { 29662306a36Sopenharmony_ci int xts_blocks = DIV_ROUND_UP(req->cryptlen, 29762306a36Sopenharmony_ci AES_BLOCK_SIZE) - 2; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci skcipher_request_set_tfm(&subreq, tfm); 30062306a36Sopenharmony_ci skcipher_request_set_callback(&subreq, 30162306a36Sopenharmony_ci skcipher_request_flags(req), 30262306a36Sopenharmony_ci NULL, NULL); 30362306a36Sopenharmony_ci skcipher_request_set_crypt(&subreq, req->src, req->dst, 30462306a36Sopenharmony_ci xts_blocks * AES_BLOCK_SIZE, 30562306a36Sopenharmony_ci req->iv); 30662306a36Sopenharmony_ci req = &subreq; 30762306a36Sopenharmony_ci } else { 30862306a36Sopenharmony_ci tail = 0; 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 31262306a36Sopenharmony_ci if (err) 31362306a36Sopenharmony_ci return err; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci while (walk.nbytes >= AES_BLOCK_SIZE) { 31662306a36Sopenharmony_ci int blocks = (walk.nbytes / AES_BLOCK_SIZE) & ~7; 31762306a36Sopenharmony_ci out = walk.dst.virt.addr; 31862306a36Sopenharmony_ci in = walk.src.virt.addr; 31962306a36Sopenharmony_ci nbytes = walk.nbytes; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci kernel_neon_begin(); 32262306a36Sopenharmony_ci if (blocks >= 8) { 32362306a36Sopenharmony_ci if (first == 1) 32462306a36Sopenharmony_ci neon_aes_ecb_encrypt(walk.iv, walk.iv, 32562306a36Sopenharmony_ci ctx->twkey, 32662306a36Sopenharmony_ci ctx->key.rounds, 1); 32762306a36Sopenharmony_ci first = 2; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci fn(out, in, ctx->key.rk, ctx->key.rounds, blocks, 33062306a36Sopenharmony_ci walk.iv); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci out += blocks * AES_BLOCK_SIZE; 33362306a36Sopenharmony_ci in += blocks * AES_BLOCK_SIZE; 33462306a36Sopenharmony_ci nbytes -= blocks * AES_BLOCK_SIZE; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci if (walk.nbytes == walk.total && nbytes > 0) { 33762306a36Sopenharmony_ci if (encrypt) 33862306a36Sopenharmony_ci neon_aes_xts_encrypt(out, in, ctx->cts.key_enc, 33962306a36Sopenharmony_ci ctx->key.rounds, nbytes, 34062306a36Sopenharmony_ci ctx->twkey, walk.iv, first); 34162306a36Sopenharmony_ci else 34262306a36Sopenharmony_ci neon_aes_xts_decrypt(out, in, ctx->cts.key_dec, 34362306a36Sopenharmony_ci ctx->key.rounds, nbytes, 34462306a36Sopenharmony_ci ctx->twkey, walk.iv, first); 34562306a36Sopenharmony_ci nbytes = first = 0; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci kernel_neon_end(); 34862306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes); 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (err || likely(!tail)) 35262306a36Sopenharmony_ci return err; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* handle ciphertext stealing */ 35562306a36Sopenharmony_ci dst = src = scatterwalk_ffwd(sg_src, req->src, req->cryptlen); 35662306a36Sopenharmony_ci if (req->dst != req->src) 35762306a36Sopenharmony_ci dst = scatterwalk_ffwd(sg_dst, req->dst, req->cryptlen); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci skcipher_request_set_crypt(req, src, dst, AES_BLOCK_SIZE + tail, 36062306a36Sopenharmony_ci req->iv); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, false); 36362306a36Sopenharmony_ci if (err) 36462306a36Sopenharmony_ci return err; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci out = walk.dst.virt.addr; 36762306a36Sopenharmony_ci in = walk.src.virt.addr; 36862306a36Sopenharmony_ci nbytes = walk.nbytes; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci kernel_neon_begin(); 37162306a36Sopenharmony_ci if (encrypt) 37262306a36Sopenharmony_ci neon_aes_xts_encrypt(out, in, ctx->cts.key_enc, ctx->key.rounds, 37362306a36Sopenharmony_ci nbytes, ctx->twkey, walk.iv, first); 37462306a36Sopenharmony_ci else 37562306a36Sopenharmony_ci neon_aes_xts_decrypt(out, in, ctx->cts.key_dec, ctx->key.rounds, 37662306a36Sopenharmony_ci nbytes, ctx->twkey, walk.iv, first); 37762306a36Sopenharmony_ci kernel_neon_end(); 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci return skcipher_walk_done(&walk, 0); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic int xts_encrypt(struct skcipher_request *req) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci return __xts_crypt(req, true, aesbs_xts_encrypt); 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic int xts_decrypt(struct skcipher_request *req) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci return __xts_crypt(req, false, aesbs_xts_decrypt); 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic struct skcipher_alg aes_algs[] = { { 39362306a36Sopenharmony_ci .base.cra_name = "ecb(aes)", 39462306a36Sopenharmony_ci .base.cra_driver_name = "ecb-aes-neonbs", 39562306a36Sopenharmony_ci .base.cra_priority = 250, 39662306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 39762306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct aesbs_ctx), 39862306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 40162306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 40262306a36Sopenharmony_ci .walksize = 8 * AES_BLOCK_SIZE, 40362306a36Sopenharmony_ci .setkey = aesbs_setkey, 40462306a36Sopenharmony_ci .encrypt = ecb_encrypt, 40562306a36Sopenharmony_ci .decrypt = ecb_decrypt, 40662306a36Sopenharmony_ci}, { 40762306a36Sopenharmony_ci .base.cra_name = "cbc(aes)", 40862306a36Sopenharmony_ci .base.cra_driver_name = "cbc-aes-neonbs", 40962306a36Sopenharmony_ci .base.cra_priority = 250, 41062306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 41162306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct aesbs_cbc_ctr_ctx), 41262306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 41562306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 41662306a36Sopenharmony_ci .walksize = 8 * AES_BLOCK_SIZE, 41762306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 41862306a36Sopenharmony_ci .setkey = aesbs_cbc_ctr_setkey, 41962306a36Sopenharmony_ci .encrypt = cbc_encrypt, 42062306a36Sopenharmony_ci .decrypt = cbc_decrypt, 42162306a36Sopenharmony_ci}, { 42262306a36Sopenharmony_ci .base.cra_name = "ctr(aes)", 42362306a36Sopenharmony_ci .base.cra_driver_name = "ctr-aes-neonbs", 42462306a36Sopenharmony_ci .base.cra_priority = 250, 42562306a36Sopenharmony_ci .base.cra_blocksize = 1, 42662306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct aesbs_cbc_ctr_ctx), 42762306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci .min_keysize = AES_MIN_KEY_SIZE, 43062306a36Sopenharmony_ci .max_keysize = AES_MAX_KEY_SIZE, 43162306a36Sopenharmony_ci .chunksize = AES_BLOCK_SIZE, 43262306a36Sopenharmony_ci .walksize = 8 * AES_BLOCK_SIZE, 43362306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 43462306a36Sopenharmony_ci .setkey = aesbs_cbc_ctr_setkey, 43562306a36Sopenharmony_ci .encrypt = ctr_encrypt, 43662306a36Sopenharmony_ci .decrypt = ctr_encrypt, 43762306a36Sopenharmony_ci}, { 43862306a36Sopenharmony_ci .base.cra_name = "xts(aes)", 43962306a36Sopenharmony_ci .base.cra_driver_name = "xts-aes-neonbs", 44062306a36Sopenharmony_ci .base.cra_priority = 250, 44162306a36Sopenharmony_ci .base.cra_blocksize = AES_BLOCK_SIZE, 44262306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct aesbs_xts_ctx), 44362306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci .min_keysize = 2 * AES_MIN_KEY_SIZE, 44662306a36Sopenharmony_ci .max_keysize = 2 * AES_MAX_KEY_SIZE, 44762306a36Sopenharmony_ci .walksize = 8 * AES_BLOCK_SIZE, 44862306a36Sopenharmony_ci .ivsize = AES_BLOCK_SIZE, 44962306a36Sopenharmony_ci .setkey = aesbs_xts_setkey, 45062306a36Sopenharmony_ci .encrypt = xts_encrypt, 45162306a36Sopenharmony_ci .decrypt = xts_decrypt, 45262306a36Sopenharmony_ci} }; 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic void aes_exit(void) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci crypto_unregister_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); 45762306a36Sopenharmony_ci} 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_cistatic int __init aes_init(void) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci if (!cpu_have_named_feature(ASIMD)) 46262306a36Sopenharmony_ci return -ENODEV; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci return crypto_register_skciphers(aes_algs, ARRAY_SIZE(aes_algs)); 46562306a36Sopenharmony_ci} 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cimodule_init(aes_init); 46862306a36Sopenharmony_cimodule_exit(aes_exit); 469