aes-ce-cipher.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. /*
  2. * aes-ce-cipher.c - core AES cipher using ARMv8 Crypto Extensions
  3. *
  4. * Copyright (C) 2013 - 2014 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. #include <asm/neon.h>
  11. #include <crypto/aes.h>
  12. #include <linux/cpufeature.h>
  13. #include <linux/crypto.h>
  14. #include <linux/module.h>
  15. #include "aes-ce-setkey.h"
  16. MODULE_DESCRIPTION("Synchronous AES cipher using ARMv8 Crypto Extensions");
  17. MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
  18. MODULE_LICENSE("GPL v2");
  19. struct aes_block {
  20. u8 b[AES_BLOCK_SIZE];
  21. };
  22. static int num_rounds(struct crypto_aes_ctx *ctx)
  23. {
  24. /*
  25. * # of rounds specified by AES:
  26. * 128 bit key 10 rounds
  27. * 192 bit key 12 rounds
  28. * 256 bit key 14 rounds
  29. * => n byte key => 6 + (n/4) rounds
  30. */
  31. return 6 + ctx->key_length / 4;
  32. }
  33. static void aes_cipher_encrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
  34. {
  35. struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
  36. struct aes_block *out = (struct aes_block *)dst;
  37. struct aes_block const *in = (struct aes_block *)src;
  38. void *dummy0;
  39. int dummy1;
  40. kernel_neon_begin_partial(4);
  41. __asm__(" ld1 {v0.16b}, %[in] ;"
  42. " ld1 {v1.16b}, [%[key]], #16 ;"
  43. " cmp %w[rounds], #10 ;"
  44. " bmi 0f ;"
  45. " bne 3f ;"
  46. " mov v3.16b, v1.16b ;"
  47. " b 2f ;"
  48. "0: mov v2.16b, v1.16b ;"
  49. " ld1 {v3.16b}, [%[key]], #16 ;"
  50. "1: aese v0.16b, v2.16b ;"
  51. " aesmc v0.16b, v0.16b ;"
  52. "2: ld1 {v1.16b}, [%[key]], #16 ;"
  53. " aese v0.16b, v3.16b ;"
  54. " aesmc v0.16b, v0.16b ;"
  55. "3: ld1 {v2.16b}, [%[key]], #16 ;"
  56. " subs %w[rounds], %w[rounds], #3 ;"
  57. " aese v0.16b, v1.16b ;"
  58. " aesmc v0.16b, v0.16b ;"
  59. " ld1 {v3.16b}, [%[key]], #16 ;"
  60. " bpl 1b ;"
  61. " aese v0.16b, v2.16b ;"
  62. " eor v0.16b, v0.16b, v3.16b ;"
  63. " st1 {v0.16b}, %[out] ;"
  64. : [out] "=Q"(*out),
  65. [key] "=r"(dummy0),
  66. [rounds] "=r"(dummy1)
  67. : [in] "Q"(*in),
  68. "1"(ctx->key_enc),
  69. "2"(num_rounds(ctx) - 2)
  70. : "cc");
  71. kernel_neon_end();
  72. }
  73. static void aes_cipher_decrypt(struct crypto_tfm *tfm, u8 dst[], u8 const src[])
  74. {
  75. struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
  76. struct aes_block *out = (struct aes_block *)dst;
  77. struct aes_block const *in = (struct aes_block *)src;
  78. void *dummy0;
  79. int dummy1;
  80. kernel_neon_begin_partial(4);
  81. __asm__(" ld1 {v0.16b}, %[in] ;"
  82. " ld1 {v1.16b}, [%[key]], #16 ;"
  83. " cmp %w[rounds], #10 ;"
  84. " bmi 0f ;"
  85. " bne 3f ;"
  86. " mov v3.16b, v1.16b ;"
  87. " b 2f ;"
  88. "0: mov v2.16b, v1.16b ;"
  89. " ld1 {v3.16b}, [%[key]], #16 ;"
  90. "1: aesd v0.16b, v2.16b ;"
  91. " aesimc v0.16b, v0.16b ;"
  92. "2: ld1 {v1.16b}, [%[key]], #16 ;"
  93. " aesd v0.16b, v3.16b ;"
  94. " aesimc v0.16b, v0.16b ;"
  95. "3: ld1 {v2.16b}, [%[key]], #16 ;"
  96. " subs %w[rounds], %w[rounds], #3 ;"
  97. " aesd v0.16b, v1.16b ;"
  98. " aesimc v0.16b, v0.16b ;"
  99. " ld1 {v3.16b}, [%[key]], #16 ;"
  100. " bpl 1b ;"
  101. " aesd v0.16b, v2.16b ;"
  102. " eor v0.16b, v0.16b, v3.16b ;"
  103. " st1 {v0.16b}, %[out] ;"
  104. : [out] "=Q"(*out),
  105. [key] "=r"(dummy0),
  106. [rounds] "=r"(dummy1)
  107. : [in] "Q"(*in),
  108. "1"(ctx->key_dec),
  109. "2"(num_rounds(ctx) - 2)
  110. : "cc");
  111. kernel_neon_end();
  112. }
  113. /*
  114. * aes_sub() - use the aese instruction to perform the AES sbox substitution
  115. * on each byte in 'input'
  116. */
  117. static u32 aes_sub(u32 input)
  118. {
  119. u32 ret;
  120. __asm__("dup v1.4s, %w[in] ;"
  121. "movi v0.16b, #0 ;"
  122. "aese v0.16b, v1.16b ;"
  123. "umov %w[out], v0.4s[0] ;"
  124. : [out] "=r"(ret)
  125. : [in] "r"(input)
  126. : "v0","v1");
  127. return ret;
  128. }
  129. int ce_aes_expandkey(struct crypto_aes_ctx *ctx, const u8 *in_key,
  130. unsigned int key_len)
  131. {
  132. /*
  133. * The AES key schedule round constants
  134. */
  135. static u8 const rcon[] = {
  136. 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36,
  137. };
  138. u32 kwords = key_len / sizeof(u32);
  139. struct aes_block *key_enc, *key_dec;
  140. int i, j;
  141. if (key_len != AES_KEYSIZE_128 &&
  142. key_len != AES_KEYSIZE_192 &&
  143. key_len != AES_KEYSIZE_256)
  144. return -EINVAL;
  145. memcpy(ctx->key_enc, in_key, key_len);
  146. ctx->key_length = key_len;
  147. kernel_neon_begin_partial(2);
  148. for (i = 0; i < sizeof(rcon); i++) {
  149. u32 *rki = ctx->key_enc + (i * kwords);
  150. u32 *rko = rki + kwords;
  151. #ifndef CONFIG_CPU_BIG_ENDIAN
  152. rko[0] = ror32(aes_sub(rki[kwords - 1]), 8) ^ rcon[i] ^ rki[0];
  153. #else
  154. rko[0] = rol32(aes_sub(rki[kwords - 1]), 8) ^ (rcon[i] << 24) ^
  155. rki[0];
  156. #endif
  157. rko[1] = rko[0] ^ rki[1];
  158. rko[2] = rko[1] ^ rki[2];
  159. rko[3] = rko[2] ^ rki[3];
  160. if (key_len == AES_KEYSIZE_192) {
  161. if (i >= 7)
  162. break;
  163. rko[4] = rko[3] ^ rki[4];
  164. rko[5] = rko[4] ^ rki[5];
  165. } else if (key_len == AES_KEYSIZE_256) {
  166. if (i >= 6)
  167. break;
  168. rko[4] = aes_sub(rko[3]) ^ rki[4];
  169. rko[5] = rko[4] ^ rki[5];
  170. rko[6] = rko[5] ^ rki[6];
  171. rko[7] = rko[6] ^ rki[7];
  172. }
  173. }
  174. /*
  175. * Generate the decryption keys for the Equivalent Inverse Cipher.
  176. * This involves reversing the order of the round keys, and applying
  177. * the Inverse Mix Columns transformation on all but the first and
  178. * the last one.
  179. */
  180. key_enc = (struct aes_block *)ctx->key_enc;
  181. key_dec = (struct aes_block *)ctx->key_dec;
  182. j = num_rounds(ctx);
  183. key_dec[0] = key_enc[j];
  184. for (i = 1, j--; j > 0; i++, j--)
  185. __asm__("ld1 {v0.16b}, %[in] ;"
  186. "aesimc v1.16b, v0.16b ;"
  187. "st1 {v1.16b}, %[out] ;"
  188. : [out] "=Q"(key_dec[i])
  189. : [in] "Q"(key_enc[j])
  190. : "v0","v1");
  191. key_dec[i] = key_enc[0];
  192. kernel_neon_end();
  193. return 0;
  194. }
  195. EXPORT_SYMBOL(ce_aes_expandkey);
  196. int ce_aes_setkey(struct crypto_tfm *tfm, const u8 *in_key,
  197. unsigned int key_len)
  198. {
  199. struct crypto_aes_ctx *ctx = crypto_tfm_ctx(tfm);
  200. int ret;
  201. ret = ce_aes_expandkey(ctx, in_key, key_len);
  202. if (!ret)
  203. return 0;
  204. tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
  205. return -EINVAL;
  206. }
  207. EXPORT_SYMBOL(ce_aes_setkey);
  208. static struct crypto_alg aes_alg = {
  209. .cra_name = "aes",
  210. .cra_driver_name = "aes-ce",
  211. .cra_priority = 250,
  212. .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
  213. .cra_blocksize = AES_BLOCK_SIZE,
  214. .cra_ctxsize = sizeof(struct crypto_aes_ctx),
  215. .cra_module = THIS_MODULE,
  216. .cra_cipher = {
  217. .cia_min_keysize = AES_MIN_KEY_SIZE,
  218. .cia_max_keysize = AES_MAX_KEY_SIZE,
  219. .cia_setkey = ce_aes_setkey,
  220. .cia_encrypt = aes_cipher_encrypt,
  221. .cia_decrypt = aes_cipher_decrypt
  222. }
  223. };
  224. static int __init aes_mod_init(void)
  225. {
  226. return crypto_register_alg(&aes_alg);
  227. }
  228. static void __exit aes_mod_exit(void)
  229. {
  230. crypto_unregister_alg(&aes_alg);
  231. }
  232. module_cpu_feature_match(AES, aes_mod_init);
  233. module_exit(aes_mod_exit);