aes.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
  4. * Copyright (C) 2015 International Business Machines Inc.
  5. * Copyright 2026 Google LLC
  6. */
  7. #include <asm/simd.h>
  8. #include <asm/switch_to.h>
  9. #include <linux/cpufeature.h>
  10. #include <linux/jump_label.h>
  11. #include <linux/preempt.h>
  12. #include <linux/uaccess.h>
  13. #ifdef CONFIG_SPE
  14. EXPORT_SYMBOL_GPL(ppc_expand_key_128);
  15. EXPORT_SYMBOL_GPL(ppc_expand_key_192);
  16. EXPORT_SYMBOL_GPL(ppc_expand_key_256);
  17. EXPORT_SYMBOL_GPL(ppc_generate_decrypt_key);
  18. EXPORT_SYMBOL_GPL(ppc_encrypt_ecb);
  19. EXPORT_SYMBOL_GPL(ppc_decrypt_ecb);
  20. EXPORT_SYMBOL_GPL(ppc_encrypt_cbc);
  21. EXPORT_SYMBOL_GPL(ppc_decrypt_cbc);
  22. EXPORT_SYMBOL_GPL(ppc_crypt_ctr);
  23. EXPORT_SYMBOL_GPL(ppc_encrypt_xts);
  24. EXPORT_SYMBOL_GPL(ppc_decrypt_xts);
  25. void ppc_encrypt_aes(u8 *out, const u8 *in, const u32 *key_enc, u32 rounds);
  26. void ppc_decrypt_aes(u8 *out, const u8 *in, const u32 *key_dec, u32 rounds);
  27. static void spe_begin(void)
  28. {
  29. /* disable preemption and save users SPE registers if required */
  30. preempt_disable();
  31. enable_kernel_spe();
  32. }
  33. static void spe_end(void)
  34. {
  35. disable_kernel_spe();
  36. /* reenable preemption */
  37. preempt_enable();
  38. }
  39. static void aes_preparekey_arch(union aes_enckey_arch *k,
  40. union aes_invkey_arch *inv_k,
  41. const u8 *in_key, int key_len, int nrounds)
  42. {
  43. if (key_len == AES_KEYSIZE_128)
  44. ppc_expand_key_128(k->spe_enc_key, in_key);
  45. else if (key_len == AES_KEYSIZE_192)
  46. ppc_expand_key_192(k->spe_enc_key, in_key);
  47. else
  48. ppc_expand_key_256(k->spe_enc_key, in_key);
  49. if (inv_k)
  50. ppc_generate_decrypt_key(inv_k->spe_dec_key, k->spe_enc_key,
  51. key_len);
  52. }
  53. static void aes_encrypt_arch(const struct aes_enckey *key,
  54. u8 out[AES_BLOCK_SIZE],
  55. const u8 in[AES_BLOCK_SIZE])
  56. {
  57. spe_begin();
  58. ppc_encrypt_aes(out, in, key->k.spe_enc_key, key->nrounds / 2 - 1);
  59. spe_end();
  60. }
  61. static void aes_decrypt_arch(const struct aes_key *key,
  62. u8 out[AES_BLOCK_SIZE],
  63. const u8 in[AES_BLOCK_SIZE])
  64. {
  65. spe_begin();
  66. ppc_decrypt_aes(out, in, key->inv_k.spe_dec_key, key->nrounds / 2 - 1);
  67. spe_end();
  68. }
  69. #else /* CONFIG_SPE */
  70. static __ro_after_init DEFINE_STATIC_KEY_FALSE(have_vec_crypto);
  71. EXPORT_SYMBOL_GPL(aes_p8_set_encrypt_key);
  72. EXPORT_SYMBOL_GPL(aes_p8_set_decrypt_key);
  73. EXPORT_SYMBOL_GPL(aes_p8_encrypt);
  74. EXPORT_SYMBOL_GPL(aes_p8_decrypt);
  75. EXPORT_SYMBOL_GPL(aes_p8_cbc_encrypt);
  76. EXPORT_SYMBOL_GPL(aes_p8_ctr32_encrypt_blocks);
  77. EXPORT_SYMBOL_GPL(aes_p8_xts_encrypt);
  78. EXPORT_SYMBOL_GPL(aes_p8_xts_decrypt);
  79. static inline bool is_vsx_format(const struct p8_aes_key *key)
  80. {
  81. return key->nrounds != 0;
  82. }
  83. /*
  84. * Convert a round key from VSX to generic format by reflecting all 16 bytes (if
  85. * little endian) or reflecting the bytes in each 4-byte word (if big endian),
  86. * and (if apply_inv_mix=true) applying InvMixColumn to each column.
  87. *
  88. * It would be nice if the VSX and generic key formats would be compatible. But
  89. * that's very difficult to do, with the assembly code having been borrowed from
  90. * OpenSSL and also targeted to POWER8 rather than POWER9.
  91. *
  92. * Fortunately, this conversion should only be needed in extremely rare cases,
  93. * possibly not at all in practice. It's just included for full correctness.
  94. */
  95. static void rndkey_from_vsx(u32 out[4], const u32 in[4], bool apply_inv_mix)
  96. {
  97. const bool be = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN);
  98. u32 k0 = swab32(in[0]);
  99. u32 k1 = swab32(in[1]);
  100. u32 k2 = swab32(in[2]);
  101. u32 k3 = swab32(in[3]);
  102. if (apply_inv_mix) {
  103. k0 = inv_mix_columns(k0);
  104. k1 = inv_mix_columns(k1);
  105. k2 = inv_mix_columns(k2);
  106. k3 = inv_mix_columns(k3);
  107. }
  108. out[0] = be ? k0 : k3;
  109. out[1] = be ? k1 : k2;
  110. out[2] = be ? k2 : k1;
  111. out[3] = be ? k3 : k0;
  112. }
  113. static void aes_preparekey_arch(union aes_enckey_arch *k,
  114. union aes_invkey_arch *inv_k,
  115. const u8 *in_key, int key_len, int nrounds)
  116. {
  117. const int keybits = 8 * key_len;
  118. int ret;
  119. if (static_branch_likely(&have_vec_crypto) && likely(may_use_simd())) {
  120. preempt_disable();
  121. pagefault_disable();
  122. enable_kernel_vsx();
  123. ret = aes_p8_set_encrypt_key(in_key, keybits, &k->p8);
  124. /*
  125. * aes_p8_set_encrypt_key() should never fail here, since the
  126. * key length was already validated.
  127. */
  128. WARN_ON_ONCE(ret);
  129. if (inv_k) {
  130. ret = aes_p8_set_decrypt_key(in_key, keybits,
  131. &inv_k->p8);
  132. /* ... and likewise for aes_p8_set_decrypt_key(). */
  133. WARN_ON_ONCE(ret);
  134. }
  135. disable_kernel_vsx();
  136. pagefault_enable();
  137. preempt_enable();
  138. } else {
  139. aes_expandkey_generic(k->rndkeys,
  140. inv_k ? inv_k->inv_rndkeys : NULL,
  141. in_key, key_len);
  142. /* Mark the key as using the generic format. */
  143. k->p8.nrounds = 0;
  144. if (inv_k)
  145. inv_k->p8.nrounds = 0;
  146. }
  147. }
  148. static void aes_encrypt_arch(const struct aes_enckey *key,
  149. u8 out[AES_BLOCK_SIZE],
  150. const u8 in[AES_BLOCK_SIZE])
  151. {
  152. if (static_branch_likely(&have_vec_crypto) &&
  153. likely(is_vsx_format(&key->k.p8) && may_use_simd())) {
  154. preempt_disable();
  155. pagefault_disable();
  156. enable_kernel_vsx();
  157. aes_p8_encrypt(in, out, &key->k.p8);
  158. disable_kernel_vsx();
  159. pagefault_enable();
  160. preempt_enable();
  161. } else if (unlikely(is_vsx_format(&key->k.p8))) {
  162. /*
  163. * This handles (the hopefully extremely rare) case where a key
  164. * was prepared using the VSX optimized format, then encryption
  165. * is done in a context that cannot use VSX instructions.
  166. */
  167. u32 rndkeys[AES_MAX_KEYLENGTH_U32];
  168. for (int i = 0; i < 4 * (key->nrounds + 1); i += 4)
  169. rndkey_from_vsx(&rndkeys[i],
  170. &key->k.p8.rndkeys[i], false);
  171. aes_encrypt_generic(rndkeys, key->nrounds, out, in);
  172. } else {
  173. aes_encrypt_generic(key->k.rndkeys, key->nrounds, out, in);
  174. }
  175. }
  176. static void aes_decrypt_arch(const struct aes_key *key, u8 out[AES_BLOCK_SIZE],
  177. const u8 in[AES_BLOCK_SIZE])
  178. {
  179. if (static_branch_likely(&have_vec_crypto) &&
  180. likely(is_vsx_format(&key->inv_k.p8) && may_use_simd())) {
  181. preempt_disable();
  182. pagefault_disable();
  183. enable_kernel_vsx();
  184. aes_p8_decrypt(in, out, &key->inv_k.p8);
  185. disable_kernel_vsx();
  186. pagefault_enable();
  187. preempt_enable();
  188. } else if (unlikely(is_vsx_format(&key->inv_k.p8))) {
  189. /*
  190. * This handles (the hopefully extremely rare) case where a key
  191. * was prepared using the VSX optimized format, then decryption
  192. * is done in a context that cannot use VSX instructions.
  193. */
  194. u32 inv_rndkeys[AES_MAX_KEYLENGTH_U32];
  195. int i;
  196. rndkey_from_vsx(&inv_rndkeys[0],
  197. &key->inv_k.p8.rndkeys[0], false);
  198. for (i = 4; i < 4 * key->nrounds; i += 4) {
  199. rndkey_from_vsx(&inv_rndkeys[i],
  200. &key->inv_k.p8.rndkeys[i], true);
  201. }
  202. rndkey_from_vsx(&inv_rndkeys[i],
  203. &key->inv_k.p8.rndkeys[i], false);
  204. aes_decrypt_generic(inv_rndkeys, key->nrounds, out, in);
  205. } else {
  206. aes_decrypt_generic(key->inv_k.inv_rndkeys, key->nrounds,
  207. out, in);
  208. }
  209. }
  210. #define aes_mod_init_arch aes_mod_init_arch
  211. static void aes_mod_init_arch(void)
  212. {
  213. if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
  214. (cur_cpu_spec->cpu_user_features2 & PPC_FEATURE2_VEC_CRYPTO))
  215. static_branch_enable(&have_vec_crypto);
  216. }
  217. #endif /* !CONFIG_SPE */