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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.10 367 lines 9.6 kB view raw
1/* 2 * linux/arch/arm/crypto/aesbs-glue.c - glue code for NEON bit sliced AES 3 * 4 * Copyright (C) 2013 Linaro Ltd <ard.biesheuvel@linaro.org> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10 11#include <asm/neon.h> 12#include <crypto/aes.h> 13#include <crypto/cbc.h> 14#include <crypto/internal/simd.h> 15#include <crypto/internal/skcipher.h> 16#include <linux/module.h> 17#include <crypto/xts.h> 18 19#include "aes_glue.h" 20 21#define BIT_SLICED_KEY_MAXSIZE (128 * (AES_MAXNR - 1) + 2 * AES_BLOCK_SIZE) 22 23struct BS_KEY { 24 struct AES_KEY rk; 25 int converted; 26 u8 __aligned(8) bs[BIT_SLICED_KEY_MAXSIZE]; 27} __aligned(8); 28 29asmlinkage void bsaes_enc_key_convert(u8 out[], struct AES_KEY const *in); 30asmlinkage void bsaes_dec_key_convert(u8 out[], struct AES_KEY const *in); 31 32asmlinkage void bsaes_cbc_encrypt(u8 const in[], u8 out[], u32 bytes, 33 struct BS_KEY *key, u8 iv[]); 34 35asmlinkage void bsaes_ctr32_encrypt_blocks(u8 const in[], u8 out[], u32 blocks, 36 struct BS_KEY *key, u8 const iv[]); 37 38asmlinkage void bsaes_xts_encrypt(u8 const in[], u8 out[], u32 bytes, 39 struct BS_KEY *key, u8 tweak[]); 40 41asmlinkage void bsaes_xts_decrypt(u8 const in[], u8 out[], u32 bytes, 42 struct BS_KEY *key, u8 tweak[]); 43 44struct aesbs_cbc_ctx { 45 struct AES_KEY enc; 46 struct BS_KEY dec; 47}; 48 49struct aesbs_ctr_ctx { 50 struct BS_KEY enc; 51}; 52 53struct aesbs_xts_ctx { 54 struct BS_KEY enc; 55 struct BS_KEY dec; 56 struct AES_KEY twkey; 57}; 58 59static int aesbs_cbc_set_key(struct crypto_skcipher *tfm, const u8 *in_key, 60 unsigned int key_len) 61{ 62 struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 63 int bits = key_len * 8; 64 65 if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc)) { 66 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 67 return -EINVAL; 68 } 69 ctx->dec.rk = ctx->enc; 70 private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk); 71 ctx->dec.converted = 0; 72 return 0; 73} 74 75static int aesbs_ctr_set_key(struct crypto_skcipher *tfm, const u8 *in_key, 76 unsigned int key_len) 77{ 78 struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 79 int bits = key_len * 8; 80 81 if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) { 82 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 83 return -EINVAL; 84 } 85 ctx->enc.converted = 0; 86 return 0; 87} 88 89static int aesbs_xts_set_key(struct crypto_skcipher *tfm, const u8 *in_key, 90 unsigned int key_len) 91{ 92 struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); 93 int bits = key_len * 4; 94 int err; 95 96 err = xts_verify_key(tfm, in_key, key_len); 97 if (err) 98 return err; 99 100 if (private_AES_set_encrypt_key(in_key, bits, &ctx->enc.rk)) { 101 crypto_skcipher_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); 102 return -EINVAL; 103 } 104 ctx->dec.rk = ctx->enc.rk; 105 private_AES_set_decrypt_key(in_key, bits, &ctx->dec.rk); 106 private_AES_set_encrypt_key(in_key + key_len / 2, bits, &ctx->twkey); 107 ctx->enc.converted = ctx->dec.converted = 0; 108 return 0; 109} 110 111static inline void aesbs_encrypt_one(struct crypto_skcipher *tfm, 112 const u8 *src, u8 *dst) 113{ 114 struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 115 116 AES_encrypt(src, dst, &ctx->enc); 117} 118 119static int aesbs_cbc_encrypt(struct skcipher_request *req) 120{ 121 return crypto_cbc_encrypt_walk(req, aesbs_encrypt_one); 122} 123 124static inline void aesbs_decrypt_one(struct crypto_skcipher *tfm, 125 const u8 *src, u8 *dst) 126{ 127 struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 128 129 AES_decrypt(src, dst, &ctx->dec.rk); 130} 131 132static int aesbs_cbc_decrypt(struct skcipher_request *req) 133{ 134 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 135 struct aesbs_cbc_ctx *ctx = crypto_skcipher_ctx(tfm); 136 struct skcipher_walk walk; 137 unsigned int nbytes; 138 int err; 139 140 for (err = skcipher_walk_virt(&walk, req, false); 141 (nbytes = walk.nbytes); err = skcipher_walk_done(&walk, nbytes)) { 142 u32 blocks = nbytes / AES_BLOCK_SIZE; 143 u8 *dst = walk.dst.virt.addr; 144 u8 *src = walk.src.virt.addr; 145 u8 *iv = walk.iv; 146 147 if (blocks >= 8) { 148 kernel_neon_begin(); 149 bsaes_cbc_encrypt(src, dst, nbytes, &ctx->dec, iv); 150 kernel_neon_end(); 151 nbytes %= AES_BLOCK_SIZE; 152 continue; 153 } 154 155 nbytes = crypto_cbc_decrypt_blocks(&walk, tfm, 156 aesbs_decrypt_one); 157 } 158 return err; 159} 160 161static void inc_be128_ctr(__be32 ctr[], u32 addend) 162{ 163 int i; 164 165 for (i = 3; i >= 0; i--, addend = 1) { 166 u32 n = be32_to_cpu(ctr[i]) + addend; 167 168 ctr[i] = cpu_to_be32(n); 169 if (n >= addend) 170 break; 171 } 172} 173 174static int aesbs_ctr_encrypt(struct skcipher_request *req) 175{ 176 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 177 struct aesbs_ctr_ctx *ctx = crypto_skcipher_ctx(tfm); 178 struct skcipher_walk walk; 179 u32 blocks; 180 int err; 181 182 err = skcipher_walk_virt(&walk, req, false); 183 184 while ((blocks = walk.nbytes / AES_BLOCK_SIZE)) { 185 u32 tail = walk.nbytes % AES_BLOCK_SIZE; 186 __be32 *ctr = (__be32 *)walk.iv; 187 u32 headroom = UINT_MAX - be32_to_cpu(ctr[3]); 188 189 /* avoid 32 bit counter overflow in the NEON code */ 190 if (unlikely(headroom < blocks)) { 191 blocks = headroom + 1; 192 tail = walk.nbytes - blocks * AES_BLOCK_SIZE; 193 } 194 kernel_neon_begin(); 195 bsaes_ctr32_encrypt_blocks(walk.src.virt.addr, 196 walk.dst.virt.addr, blocks, 197 &ctx->enc, walk.iv); 198 kernel_neon_end(); 199 inc_be128_ctr(ctr, blocks); 200 201 err = skcipher_walk_done(&walk, tail); 202 } 203 if (walk.nbytes) { 204 u8 *tdst = walk.dst.virt.addr + blocks * AES_BLOCK_SIZE; 205 u8 *tsrc = walk.src.virt.addr + blocks * AES_BLOCK_SIZE; 206 u8 ks[AES_BLOCK_SIZE]; 207 208 AES_encrypt(walk.iv, ks, &ctx->enc.rk); 209 if (tdst != tsrc) 210 memcpy(tdst, tsrc, walk.nbytes); 211 crypto_xor(tdst, ks, walk.nbytes); 212 err = skcipher_walk_done(&walk, 0); 213 } 214 return err; 215} 216 217static int aesbs_xts_encrypt(struct skcipher_request *req) 218{ 219 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 220 struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); 221 struct skcipher_walk walk; 222 int err; 223 224 err = skcipher_walk_virt(&walk, req, false); 225 226 /* generate the initial tweak */ 227 AES_encrypt(walk.iv, walk.iv, &ctx->twkey); 228 229 while (walk.nbytes) { 230 kernel_neon_begin(); 231 bsaes_xts_encrypt(walk.src.virt.addr, walk.dst.virt.addr, 232 walk.nbytes, &ctx->enc, walk.iv); 233 kernel_neon_end(); 234 err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); 235 } 236 return err; 237} 238 239static int aesbs_xts_decrypt(struct skcipher_request *req) 240{ 241 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 242 struct aesbs_xts_ctx *ctx = crypto_skcipher_ctx(tfm); 243 struct skcipher_walk walk; 244 int err; 245 246 err = skcipher_walk_virt(&walk, req, false); 247 248 /* generate the initial tweak */ 249 AES_encrypt(walk.iv, walk.iv, &ctx->twkey); 250 251 while (walk.nbytes) { 252 kernel_neon_begin(); 253 bsaes_xts_decrypt(walk.src.virt.addr, walk.dst.virt.addr, 254 walk.nbytes, &ctx->dec, walk.iv); 255 kernel_neon_end(); 256 err = skcipher_walk_done(&walk, walk.nbytes % AES_BLOCK_SIZE); 257 } 258 return err; 259} 260 261static struct skcipher_alg aesbs_algs[] = { { 262 .base = { 263 .cra_name = "__cbc(aes)", 264 .cra_driver_name = "__cbc-aes-neonbs", 265 .cra_priority = 300, 266 .cra_flags = CRYPTO_ALG_INTERNAL, 267 .cra_blocksize = AES_BLOCK_SIZE, 268 .cra_ctxsize = sizeof(struct aesbs_cbc_ctx), 269 .cra_alignmask = 7, 270 .cra_module = THIS_MODULE, 271 }, 272 .min_keysize = AES_MIN_KEY_SIZE, 273 .max_keysize = AES_MAX_KEY_SIZE, 274 .ivsize = AES_BLOCK_SIZE, 275 .setkey = aesbs_cbc_set_key, 276 .encrypt = aesbs_cbc_encrypt, 277 .decrypt = aesbs_cbc_decrypt, 278}, { 279 .base = { 280 .cra_name = "__ctr(aes)", 281 .cra_driver_name = "__ctr-aes-neonbs", 282 .cra_priority = 300, 283 .cra_flags = CRYPTO_ALG_INTERNAL, 284 .cra_blocksize = 1, 285 .cra_ctxsize = sizeof(struct aesbs_ctr_ctx), 286 .cra_alignmask = 7, 287 .cra_module = THIS_MODULE, 288 }, 289 .min_keysize = AES_MIN_KEY_SIZE, 290 .max_keysize = AES_MAX_KEY_SIZE, 291 .ivsize = AES_BLOCK_SIZE, 292 .chunksize = AES_BLOCK_SIZE, 293 .setkey = aesbs_ctr_set_key, 294 .encrypt = aesbs_ctr_encrypt, 295 .decrypt = aesbs_ctr_encrypt, 296}, { 297 .base = { 298 .cra_name = "__xts(aes)", 299 .cra_driver_name = "__xts-aes-neonbs", 300 .cra_priority = 300, 301 .cra_flags = CRYPTO_ALG_INTERNAL, 302 .cra_blocksize = AES_BLOCK_SIZE, 303 .cra_ctxsize = sizeof(struct aesbs_xts_ctx), 304 .cra_alignmask = 7, 305 .cra_module = THIS_MODULE, 306 }, 307 .min_keysize = 2 * AES_MIN_KEY_SIZE, 308 .max_keysize = 2 * AES_MAX_KEY_SIZE, 309 .ivsize = AES_BLOCK_SIZE, 310 .setkey = aesbs_xts_set_key, 311 .encrypt = aesbs_xts_encrypt, 312 .decrypt = aesbs_xts_decrypt, 313} }; 314 315struct simd_skcipher_alg *aesbs_simd_algs[ARRAY_SIZE(aesbs_algs)]; 316 317static void aesbs_mod_exit(void) 318{ 319 int i; 320 321 for (i = 0; i < ARRAY_SIZE(aesbs_simd_algs) && aesbs_simd_algs[i]; i++) 322 simd_skcipher_free(aesbs_simd_algs[i]); 323 324 crypto_unregister_skciphers(aesbs_algs, ARRAY_SIZE(aesbs_algs)); 325} 326 327static int __init aesbs_mod_init(void) 328{ 329 struct simd_skcipher_alg *simd; 330 const char *basename; 331 const char *algname; 332 const char *drvname; 333 int err; 334 int i; 335 336 if (!cpu_has_neon()) 337 return -ENODEV; 338 339 err = crypto_register_skciphers(aesbs_algs, ARRAY_SIZE(aesbs_algs)); 340 if (err) 341 return err; 342 343 for (i = 0; i < ARRAY_SIZE(aesbs_algs); i++) { 344 algname = aesbs_algs[i].base.cra_name + 2; 345 drvname = aesbs_algs[i].base.cra_driver_name + 2; 346 basename = aesbs_algs[i].base.cra_driver_name; 347 simd = simd_skcipher_create_compat(algname, drvname, basename); 348 err = PTR_ERR(simd); 349 if (IS_ERR(simd)) 350 goto unregister_simds; 351 352 aesbs_simd_algs[i] = simd; 353 } 354 355 return 0; 356 357unregister_simds: 358 aesbs_mod_exit(); 359 return err; 360} 361 362module_init(aesbs_mod_init); 363module_exit(aesbs_mod_exit); 364 365MODULE_DESCRIPTION("Bit sliced AES in CBC/CTR/XTS modes using NEON"); 366MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>"); 367MODULE_LICENSE("GPL");