serpent_avx2_glue.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Glue Code for x86_64/AVX2 assembler optimized version of Serpent
  3. *
  4. * Copyright © 2012-2013 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  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 as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. */
  12. #include <linux/module.h>
  13. #include <linux/types.h>
  14. #include <linux/crypto.h>
  15. #include <linux/err.h>
  16. #include <crypto/algapi.h>
  17. #include <crypto/internal/simd.h>
  18. #include <crypto/serpent.h>
  19. #include <crypto/xts.h>
  20. #include <asm/crypto/glue_helper.h>
  21. #include <asm/crypto/serpent-avx.h>
  22. #define SERPENT_AVX2_PARALLEL_BLOCKS 16
  23. /* 16-way AVX2 parallel cipher functions */
  24. asmlinkage void serpent_ecb_enc_16way(struct serpent_ctx *ctx, u8 *dst,
  25. const u8 *src);
  26. asmlinkage void serpent_ecb_dec_16way(struct serpent_ctx *ctx, u8 *dst,
  27. const u8 *src);
  28. asmlinkage void serpent_cbc_dec_16way(void *ctx, u128 *dst, const u128 *src);
  29. asmlinkage void serpent_ctr_16way(void *ctx, u128 *dst, const u128 *src,
  30. le128 *iv);
  31. asmlinkage void serpent_xts_enc_16way(struct serpent_ctx *ctx, u8 *dst,
  32. const u8 *src, le128 *iv);
  33. asmlinkage void serpent_xts_dec_16way(struct serpent_ctx *ctx, u8 *dst,
  34. const u8 *src, le128 *iv);
  35. static int serpent_setkey_skcipher(struct crypto_skcipher *tfm,
  36. const u8 *key, unsigned int keylen)
  37. {
  38. return __serpent_setkey(crypto_skcipher_ctx(tfm), key, keylen);
  39. }
  40. static const struct common_glue_ctx serpent_enc = {
  41. .num_funcs = 3,
  42. .fpu_blocks_limit = 8,
  43. .funcs = { {
  44. .num_blocks = 16,
  45. .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_16way) }
  46. }, {
  47. .num_blocks = 8,
  48. .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_enc_8way_avx) }
  49. }, {
  50. .num_blocks = 1,
  51. .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_encrypt) }
  52. } }
  53. };
  54. static const struct common_glue_ctx serpent_ctr = {
  55. .num_funcs = 3,
  56. .fpu_blocks_limit = 8,
  57. .funcs = { {
  58. .num_blocks = 16,
  59. .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_16way) }
  60. }, {
  61. .num_blocks = 8,
  62. .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(serpent_ctr_8way_avx) }
  63. }, {
  64. .num_blocks = 1,
  65. .fn_u = { .ctr = GLUE_CTR_FUNC_CAST(__serpent_crypt_ctr) }
  66. } }
  67. };
  68. static const struct common_glue_ctx serpent_enc_xts = {
  69. .num_funcs = 3,
  70. .fpu_blocks_limit = 8,
  71. .funcs = { {
  72. .num_blocks = 16,
  73. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc_16way) }
  74. }, {
  75. .num_blocks = 8,
  76. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc_8way_avx) }
  77. }, {
  78. .num_blocks = 1,
  79. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_enc) }
  80. } }
  81. };
  82. static const struct common_glue_ctx serpent_dec = {
  83. .num_funcs = 3,
  84. .fpu_blocks_limit = 8,
  85. .funcs = { {
  86. .num_blocks = 16,
  87. .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_16way) }
  88. }, {
  89. .num_blocks = 8,
  90. .fn_u = { .ecb = GLUE_FUNC_CAST(serpent_ecb_dec_8way_avx) }
  91. }, {
  92. .num_blocks = 1,
  93. .fn_u = { .ecb = GLUE_FUNC_CAST(__serpent_decrypt) }
  94. } }
  95. };
  96. static const struct common_glue_ctx serpent_dec_cbc = {
  97. .num_funcs = 3,
  98. .fpu_blocks_limit = 8,
  99. .funcs = { {
  100. .num_blocks = 16,
  101. .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_16way) }
  102. }, {
  103. .num_blocks = 8,
  104. .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(serpent_cbc_dec_8way_avx) }
  105. }, {
  106. .num_blocks = 1,
  107. .fn_u = { .cbc = GLUE_CBC_FUNC_CAST(__serpent_decrypt) }
  108. } }
  109. };
  110. static const struct common_glue_ctx serpent_dec_xts = {
  111. .num_funcs = 3,
  112. .fpu_blocks_limit = 8,
  113. .funcs = { {
  114. .num_blocks = 16,
  115. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec_16way) }
  116. }, {
  117. .num_blocks = 8,
  118. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec_8way_avx) }
  119. }, {
  120. .num_blocks = 1,
  121. .fn_u = { .xts = GLUE_XTS_FUNC_CAST(serpent_xts_dec) }
  122. } }
  123. };
  124. static int ecb_encrypt(struct skcipher_request *req)
  125. {
  126. return glue_ecb_req_128bit(&serpent_enc, req);
  127. }
  128. static int ecb_decrypt(struct skcipher_request *req)
  129. {
  130. return glue_ecb_req_128bit(&serpent_dec, req);
  131. }
  132. static int cbc_encrypt(struct skcipher_request *req)
  133. {
  134. return glue_cbc_encrypt_req_128bit(GLUE_FUNC_CAST(__serpent_encrypt),
  135. req);
  136. }
  137. static int cbc_decrypt(struct skcipher_request *req)
  138. {
  139. return glue_cbc_decrypt_req_128bit(&serpent_dec_cbc, req);
  140. }
  141. static int ctr_crypt(struct skcipher_request *req)
  142. {
  143. return glue_ctr_req_128bit(&serpent_ctr, req);
  144. }
  145. static int xts_encrypt(struct skcipher_request *req)
  146. {
  147. struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  148. struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
  149. return glue_xts_req_128bit(&serpent_enc_xts, req,
  150. XTS_TWEAK_CAST(__serpent_encrypt),
  151. &ctx->tweak_ctx, &ctx->crypt_ctx);
  152. }
  153. static int xts_decrypt(struct skcipher_request *req)
  154. {
  155. struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  156. struct serpent_xts_ctx *ctx = crypto_skcipher_ctx(tfm);
  157. return glue_xts_req_128bit(&serpent_dec_xts, req,
  158. XTS_TWEAK_CAST(__serpent_encrypt),
  159. &ctx->tweak_ctx, &ctx->crypt_ctx);
  160. }
  161. static struct skcipher_alg serpent_algs[] = {
  162. {
  163. .base.cra_name = "__ecb(serpent)",
  164. .base.cra_driver_name = "__ecb-serpent-avx2",
  165. .base.cra_priority = 600,
  166. .base.cra_flags = CRYPTO_ALG_INTERNAL,
  167. .base.cra_blocksize = SERPENT_BLOCK_SIZE,
  168. .base.cra_ctxsize = sizeof(struct serpent_ctx),
  169. .base.cra_module = THIS_MODULE,
  170. .min_keysize = SERPENT_MIN_KEY_SIZE,
  171. .max_keysize = SERPENT_MAX_KEY_SIZE,
  172. .setkey = serpent_setkey_skcipher,
  173. .encrypt = ecb_encrypt,
  174. .decrypt = ecb_decrypt,
  175. }, {
  176. .base.cra_name = "__cbc(serpent)",
  177. .base.cra_driver_name = "__cbc-serpent-avx2",
  178. .base.cra_priority = 600,
  179. .base.cra_flags = CRYPTO_ALG_INTERNAL,
  180. .base.cra_blocksize = SERPENT_BLOCK_SIZE,
  181. .base.cra_ctxsize = sizeof(struct serpent_ctx),
  182. .base.cra_module = THIS_MODULE,
  183. .min_keysize = SERPENT_MIN_KEY_SIZE,
  184. .max_keysize = SERPENT_MAX_KEY_SIZE,
  185. .ivsize = SERPENT_BLOCK_SIZE,
  186. .setkey = serpent_setkey_skcipher,
  187. .encrypt = cbc_encrypt,
  188. .decrypt = cbc_decrypt,
  189. }, {
  190. .base.cra_name = "__ctr(serpent)",
  191. .base.cra_driver_name = "__ctr-serpent-avx2",
  192. .base.cra_priority = 600,
  193. .base.cra_flags = CRYPTO_ALG_INTERNAL,
  194. .base.cra_blocksize = 1,
  195. .base.cra_ctxsize = sizeof(struct serpent_ctx),
  196. .base.cra_module = THIS_MODULE,
  197. .min_keysize = SERPENT_MIN_KEY_SIZE,
  198. .max_keysize = SERPENT_MAX_KEY_SIZE,
  199. .ivsize = SERPENT_BLOCK_SIZE,
  200. .chunksize = SERPENT_BLOCK_SIZE,
  201. .setkey = serpent_setkey_skcipher,
  202. .encrypt = ctr_crypt,
  203. .decrypt = ctr_crypt,
  204. }, {
  205. .base.cra_name = "__xts(serpent)",
  206. .base.cra_driver_name = "__xts-serpent-avx2",
  207. .base.cra_priority = 600,
  208. .base.cra_flags = CRYPTO_ALG_INTERNAL,
  209. .base.cra_blocksize = SERPENT_BLOCK_SIZE,
  210. .base.cra_ctxsize = sizeof(struct serpent_xts_ctx),
  211. .base.cra_module = THIS_MODULE,
  212. .min_keysize = 2 * SERPENT_MIN_KEY_SIZE,
  213. .max_keysize = 2 * SERPENT_MAX_KEY_SIZE,
  214. .ivsize = SERPENT_BLOCK_SIZE,
  215. .setkey = xts_serpent_setkey,
  216. .encrypt = xts_encrypt,
  217. .decrypt = xts_decrypt,
  218. },
  219. };
  220. static struct simd_skcipher_alg *serpent_simd_algs[ARRAY_SIZE(serpent_algs)];
  221. static int __init init(void)
  222. {
  223. const char *feature_name;
  224. if (!boot_cpu_has(X86_FEATURE_AVX2) || !boot_cpu_has(X86_FEATURE_OSXSAVE)) {
  225. pr_info("AVX2 instructions are not detected.\n");
  226. return -ENODEV;
  227. }
  228. if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
  229. &feature_name)) {
  230. pr_info("CPU feature '%s' is not supported.\n", feature_name);
  231. return -ENODEV;
  232. }
  233. return simd_register_skciphers_compat(serpent_algs,
  234. ARRAY_SIZE(serpent_algs),
  235. serpent_simd_algs);
  236. }
  237. static void __exit fini(void)
  238. {
  239. simd_unregister_skciphers(serpent_algs, ARRAY_SIZE(serpent_algs),
  240. serpent_simd_algs);
  241. }
  242. module_init(init);
  243. module_exit(fini);
  244. MODULE_LICENSE("GPL");
  245. MODULE_DESCRIPTION("Serpent Cipher Algorithm, AVX2 optimized");
  246. MODULE_ALIAS_CRYPTO("serpent");
  247. MODULE_ALIAS_CRYPTO("serpent-asm");