simd.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. /*
  2. * Shared crypto simd helpers
  3. *
  4. * Copyright (c) 2012 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  5. * Copyright (c) 2016 Herbert Xu <herbert@gondor.apana.org.au>
  6. *
  7. * Based on aesni-intel_glue.c by:
  8. * Copyright (C) 2008, Intel Corp.
  9. * Author: Huang Ying <ying.huang@intel.com>
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation; either version 2 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. *
  24. */
  25. #include <crypto/cryptd.h>
  26. #include <crypto/internal/simd.h>
  27. #include <crypto/internal/skcipher.h>
  28. #include <linux/kernel.h>
  29. #include <linux/module.h>
  30. #include <linux/preempt.h>
  31. #include <asm/simd.h>
  32. struct simd_skcipher_alg {
  33. const char *ialg_name;
  34. struct skcipher_alg alg;
  35. };
  36. struct simd_skcipher_ctx {
  37. struct cryptd_skcipher *cryptd_tfm;
  38. };
  39. static int simd_skcipher_setkey(struct crypto_skcipher *tfm, const u8 *key,
  40. unsigned int key_len)
  41. {
  42. struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
  43. struct crypto_skcipher *child = &ctx->cryptd_tfm->base;
  44. int err;
  45. crypto_skcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  46. crypto_skcipher_set_flags(child, crypto_skcipher_get_flags(tfm) &
  47. CRYPTO_TFM_REQ_MASK);
  48. err = crypto_skcipher_setkey(child, key, key_len);
  49. crypto_skcipher_set_flags(tfm, crypto_skcipher_get_flags(child) &
  50. CRYPTO_TFM_RES_MASK);
  51. return err;
  52. }
  53. static int simd_skcipher_encrypt(struct skcipher_request *req)
  54. {
  55. struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  56. struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
  57. struct skcipher_request *subreq;
  58. struct crypto_skcipher *child;
  59. subreq = skcipher_request_ctx(req);
  60. *subreq = *req;
  61. if (!may_use_simd() ||
  62. (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm)))
  63. child = &ctx->cryptd_tfm->base;
  64. else
  65. child = cryptd_skcipher_child(ctx->cryptd_tfm);
  66. skcipher_request_set_tfm(subreq, child);
  67. return crypto_skcipher_encrypt(subreq);
  68. }
  69. static int simd_skcipher_decrypt(struct skcipher_request *req)
  70. {
  71. struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
  72. struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
  73. struct skcipher_request *subreq;
  74. struct crypto_skcipher *child;
  75. subreq = skcipher_request_ctx(req);
  76. *subreq = *req;
  77. if (!may_use_simd() ||
  78. (in_atomic() && cryptd_skcipher_queued(ctx->cryptd_tfm)))
  79. child = &ctx->cryptd_tfm->base;
  80. else
  81. child = cryptd_skcipher_child(ctx->cryptd_tfm);
  82. skcipher_request_set_tfm(subreq, child);
  83. return crypto_skcipher_decrypt(subreq);
  84. }
  85. static void simd_skcipher_exit(struct crypto_skcipher *tfm)
  86. {
  87. struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
  88. cryptd_free_skcipher(ctx->cryptd_tfm);
  89. }
  90. static int simd_skcipher_init(struct crypto_skcipher *tfm)
  91. {
  92. struct simd_skcipher_ctx *ctx = crypto_skcipher_ctx(tfm);
  93. struct cryptd_skcipher *cryptd_tfm;
  94. struct simd_skcipher_alg *salg;
  95. struct skcipher_alg *alg;
  96. unsigned reqsize;
  97. alg = crypto_skcipher_alg(tfm);
  98. salg = container_of(alg, struct simd_skcipher_alg, alg);
  99. cryptd_tfm = cryptd_alloc_skcipher(salg->ialg_name,
  100. CRYPTO_ALG_INTERNAL,
  101. CRYPTO_ALG_INTERNAL);
  102. if (IS_ERR(cryptd_tfm))
  103. return PTR_ERR(cryptd_tfm);
  104. ctx->cryptd_tfm = cryptd_tfm;
  105. reqsize = sizeof(struct skcipher_request);
  106. reqsize += crypto_skcipher_reqsize(&cryptd_tfm->base);
  107. crypto_skcipher_set_reqsize(tfm, reqsize);
  108. return 0;
  109. }
  110. struct simd_skcipher_alg *simd_skcipher_create_compat(const char *algname,
  111. const char *drvname,
  112. const char *basename)
  113. {
  114. struct simd_skcipher_alg *salg;
  115. struct crypto_skcipher *tfm;
  116. struct skcipher_alg *ialg;
  117. struct skcipher_alg *alg;
  118. int err;
  119. tfm = crypto_alloc_skcipher(basename, CRYPTO_ALG_INTERNAL,
  120. CRYPTO_ALG_INTERNAL | CRYPTO_ALG_ASYNC);
  121. if (IS_ERR(tfm))
  122. return ERR_CAST(tfm);
  123. ialg = crypto_skcipher_alg(tfm);
  124. salg = kzalloc(sizeof(*salg), GFP_KERNEL);
  125. if (!salg) {
  126. salg = ERR_PTR(-ENOMEM);
  127. goto out_put_tfm;
  128. }
  129. salg->ialg_name = basename;
  130. alg = &salg->alg;
  131. err = -ENAMETOOLONG;
  132. if (snprintf(alg->base.cra_name, CRYPTO_MAX_ALG_NAME, "%s", algname) >=
  133. CRYPTO_MAX_ALG_NAME)
  134. goto out_free_salg;
  135. if (snprintf(alg->base.cra_driver_name, CRYPTO_MAX_ALG_NAME, "%s",
  136. drvname) >= CRYPTO_MAX_ALG_NAME)
  137. goto out_free_salg;
  138. alg->base.cra_flags = CRYPTO_ALG_ASYNC;
  139. alg->base.cra_priority = ialg->base.cra_priority;
  140. alg->base.cra_blocksize = ialg->base.cra_blocksize;
  141. alg->base.cra_alignmask = ialg->base.cra_alignmask;
  142. alg->base.cra_module = ialg->base.cra_module;
  143. alg->base.cra_ctxsize = sizeof(struct simd_skcipher_ctx);
  144. alg->ivsize = ialg->ivsize;
  145. alg->chunksize = ialg->chunksize;
  146. alg->min_keysize = ialg->min_keysize;
  147. alg->max_keysize = ialg->max_keysize;
  148. alg->init = simd_skcipher_init;
  149. alg->exit = simd_skcipher_exit;
  150. alg->setkey = simd_skcipher_setkey;
  151. alg->encrypt = simd_skcipher_encrypt;
  152. alg->decrypt = simd_skcipher_decrypt;
  153. err = crypto_register_skcipher(alg);
  154. if (err)
  155. goto out_free_salg;
  156. out_put_tfm:
  157. crypto_free_skcipher(tfm);
  158. return salg;
  159. out_free_salg:
  160. kfree(salg);
  161. salg = ERR_PTR(err);
  162. goto out_put_tfm;
  163. }
  164. EXPORT_SYMBOL_GPL(simd_skcipher_create_compat);
  165. struct simd_skcipher_alg *simd_skcipher_create(const char *algname,
  166. const char *basename)
  167. {
  168. char drvname[CRYPTO_MAX_ALG_NAME];
  169. if (snprintf(drvname, CRYPTO_MAX_ALG_NAME, "simd-%s", basename) >=
  170. CRYPTO_MAX_ALG_NAME)
  171. return ERR_PTR(-ENAMETOOLONG);
  172. return simd_skcipher_create_compat(algname, drvname, basename);
  173. }
  174. EXPORT_SYMBOL_GPL(simd_skcipher_create);
  175. void simd_skcipher_free(struct simd_skcipher_alg *salg)
  176. {
  177. crypto_unregister_skcipher(&salg->alg);
  178. kfree(salg);
  179. }
  180. EXPORT_SYMBOL_GPL(simd_skcipher_free);
  181. MODULE_LICENSE("GPL");