camellia_glue.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
  2. *
  3. * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
  4. */
  5. #include <linux/crypto.h>
  6. #include <linux/init.h>
  7. #include <linux/module.h>
  8. #include <linux/mm.h>
  9. #include <linux/types.h>
  10. #include <crypto/algapi.h>
  11. #include <asm/fpumacro.h>
  12. #include <asm/pstate.h>
  13. #include <asm/elf.h>
  14. #define CAMELLIA_MIN_KEY_SIZE 16
  15. #define CAMELLIA_MAX_KEY_SIZE 32
  16. #define CAMELLIA_BLOCK_SIZE 16
  17. #define CAMELLIA_TABLE_BYTE_LEN 272
  18. struct camellia_sparc64_ctx {
  19. u64 encrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
  20. u64 decrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
  21. int key_len;
  22. };
  23. extern void camellia_sparc64_key_expand(const u32 *in_key, u64 *encrypt_key,
  24. unsigned int key_len, u64 *decrypt_key);
  25. static int camellia_set_key(struct crypto_tfm *tfm, const u8 *_in_key,
  26. unsigned int key_len)
  27. {
  28. struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
  29. const u32 *in_key = (const u32 *) _in_key;
  30. u32 *flags = &tfm->crt_flags;
  31. if (key_len != 16 && key_len != 24 && key_len != 32) {
  32. *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
  33. return -EINVAL;
  34. }
  35. ctx->key_len = key_len;
  36. camellia_sparc64_key_expand(in_key, &ctx->encrypt_key[0],
  37. key_len, &ctx->decrypt_key[0]);
  38. return 0;
  39. }
  40. extern void camellia_sparc64_crypt(const u64 *key, const u32 *input,
  41. u32 *output, unsigned int key_len);
  42. static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  43. {
  44. struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
  45. camellia_sparc64_crypt(&ctx->encrypt_key[0],
  46. (const u32 *) src,
  47. (u32 *) dst, ctx->key_len);
  48. }
  49. static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
  50. {
  51. struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
  52. camellia_sparc64_crypt(&ctx->decrypt_key[0],
  53. (const u32 *) src,
  54. (u32 *) dst, ctx->key_len);
  55. }
  56. extern void camellia_sparc64_load_keys(const u64 *key, unsigned int key_len);
  57. typedef void ecb_crypt_op(const u64 *input, u64 *output, unsigned int len,
  58. const u64 *key);
  59. extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds;
  60. extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds;
  61. #define CAMELLIA_BLOCK_MASK (~(CAMELLIA_BLOCK_SIZE - 1))
  62. static int __ecb_crypt(struct blkcipher_desc *desc,
  63. struct scatterlist *dst, struct scatterlist *src,
  64. unsigned int nbytes, bool encrypt)
  65. {
  66. struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  67. struct blkcipher_walk walk;
  68. ecb_crypt_op *op;
  69. const u64 *key;
  70. int err;
  71. op = camellia_sparc64_ecb_crypt_3_grand_rounds;
  72. if (ctx->key_len != 16)
  73. op = camellia_sparc64_ecb_crypt_4_grand_rounds;
  74. blkcipher_walk_init(&walk, dst, src, nbytes);
  75. err = blkcipher_walk_virt(desc, &walk);
  76. if (encrypt)
  77. key = &ctx->encrypt_key[0];
  78. else
  79. key = &ctx->decrypt_key[0];
  80. camellia_sparc64_load_keys(key, ctx->key_len);
  81. while ((nbytes = walk.nbytes)) {
  82. unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
  83. if (likely(block_len)) {
  84. const u64 *src64;
  85. u64 *dst64;
  86. src64 = (const u64 *)walk.src.virt.addr;
  87. dst64 = (u64 *) walk.dst.virt.addr;
  88. op(src64, dst64, block_len, key);
  89. }
  90. nbytes &= CAMELLIA_BLOCK_SIZE - 1;
  91. err = blkcipher_walk_done(desc, &walk, nbytes);
  92. }
  93. fprs_write(0);
  94. return err;
  95. }
  96. static int ecb_encrypt(struct blkcipher_desc *desc,
  97. struct scatterlist *dst, struct scatterlist *src,
  98. unsigned int nbytes)
  99. {
  100. return __ecb_crypt(desc, dst, src, nbytes, true);
  101. }
  102. static int ecb_decrypt(struct blkcipher_desc *desc,
  103. struct scatterlist *dst, struct scatterlist *src,
  104. unsigned int nbytes)
  105. {
  106. return __ecb_crypt(desc, dst, src, nbytes, false);
  107. }
  108. typedef void cbc_crypt_op(const u64 *input, u64 *output, unsigned int len,
  109. const u64 *key, u64 *iv);
  110. extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds;
  111. extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds;
  112. extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds;
  113. extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds;
  114. static int cbc_encrypt(struct blkcipher_desc *desc,
  115. struct scatterlist *dst, struct scatterlist *src,
  116. unsigned int nbytes)
  117. {
  118. struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  119. struct blkcipher_walk walk;
  120. cbc_crypt_op *op;
  121. const u64 *key;
  122. int err;
  123. op = camellia_sparc64_cbc_encrypt_3_grand_rounds;
  124. if (ctx->key_len != 16)
  125. op = camellia_sparc64_cbc_encrypt_4_grand_rounds;
  126. blkcipher_walk_init(&walk, dst, src, nbytes);
  127. err = blkcipher_walk_virt(desc, &walk);
  128. key = &ctx->encrypt_key[0];
  129. camellia_sparc64_load_keys(key, ctx->key_len);
  130. while ((nbytes = walk.nbytes)) {
  131. unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
  132. if (likely(block_len)) {
  133. const u64 *src64;
  134. u64 *dst64;
  135. src64 = (const u64 *)walk.src.virt.addr;
  136. dst64 = (u64 *) walk.dst.virt.addr;
  137. op(src64, dst64, block_len, key,
  138. (u64 *) walk.iv);
  139. }
  140. nbytes &= CAMELLIA_BLOCK_SIZE - 1;
  141. err = blkcipher_walk_done(desc, &walk, nbytes);
  142. }
  143. fprs_write(0);
  144. return err;
  145. }
  146. static int cbc_decrypt(struct blkcipher_desc *desc,
  147. struct scatterlist *dst, struct scatterlist *src,
  148. unsigned int nbytes)
  149. {
  150. struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  151. struct blkcipher_walk walk;
  152. cbc_crypt_op *op;
  153. const u64 *key;
  154. int err;
  155. op = camellia_sparc64_cbc_decrypt_3_grand_rounds;
  156. if (ctx->key_len != 16)
  157. op = camellia_sparc64_cbc_decrypt_4_grand_rounds;
  158. blkcipher_walk_init(&walk, dst, src, nbytes);
  159. err = blkcipher_walk_virt(desc, &walk);
  160. key = &ctx->decrypt_key[0];
  161. camellia_sparc64_load_keys(key, ctx->key_len);
  162. while ((nbytes = walk.nbytes)) {
  163. unsigned int block_len = nbytes & CAMELLIA_BLOCK_MASK;
  164. if (likely(block_len)) {
  165. const u64 *src64;
  166. u64 *dst64;
  167. src64 = (const u64 *)walk.src.virt.addr;
  168. dst64 = (u64 *) walk.dst.virt.addr;
  169. op(src64, dst64, block_len, key,
  170. (u64 *) walk.iv);
  171. }
  172. nbytes &= CAMELLIA_BLOCK_SIZE - 1;
  173. err = blkcipher_walk_done(desc, &walk, nbytes);
  174. }
  175. fprs_write(0);
  176. return err;
  177. }
  178. static struct crypto_alg algs[] = { {
  179. .cra_name = "camellia",
  180. .cra_driver_name = "camellia-sparc64",
  181. .cra_priority = 150,
  182. .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
  183. .cra_blocksize = CAMELLIA_BLOCK_SIZE,
  184. .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
  185. .cra_alignmask = 3,
  186. .cra_module = THIS_MODULE,
  187. .cra_u = {
  188. .cipher = {
  189. .cia_min_keysize = CAMELLIA_MIN_KEY_SIZE,
  190. .cia_max_keysize = CAMELLIA_MAX_KEY_SIZE,
  191. .cia_setkey = camellia_set_key,
  192. .cia_encrypt = camellia_encrypt,
  193. .cia_decrypt = camellia_decrypt
  194. }
  195. }
  196. }, {
  197. .cra_name = "ecb(camellia)",
  198. .cra_driver_name = "ecb-camellia-sparc64",
  199. .cra_priority = 150,
  200. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  201. .cra_blocksize = CAMELLIA_BLOCK_SIZE,
  202. .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
  203. .cra_alignmask = 7,
  204. .cra_type = &crypto_blkcipher_type,
  205. .cra_module = THIS_MODULE,
  206. .cra_u = {
  207. .blkcipher = {
  208. .min_keysize = CAMELLIA_MIN_KEY_SIZE,
  209. .max_keysize = CAMELLIA_MAX_KEY_SIZE,
  210. .setkey = camellia_set_key,
  211. .encrypt = ecb_encrypt,
  212. .decrypt = ecb_decrypt,
  213. },
  214. },
  215. }, {
  216. .cra_name = "cbc(camellia)",
  217. .cra_driver_name = "cbc-camellia-sparc64",
  218. .cra_priority = 150,
  219. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  220. .cra_blocksize = CAMELLIA_BLOCK_SIZE,
  221. .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
  222. .cra_alignmask = 7,
  223. .cra_type = &crypto_blkcipher_type,
  224. .cra_module = THIS_MODULE,
  225. .cra_u = {
  226. .blkcipher = {
  227. .min_keysize = CAMELLIA_MIN_KEY_SIZE,
  228. .max_keysize = CAMELLIA_MAX_KEY_SIZE,
  229. .setkey = camellia_set_key,
  230. .encrypt = cbc_encrypt,
  231. .decrypt = cbc_decrypt,
  232. },
  233. },
  234. }
  235. };
  236. static bool __init sparc64_has_camellia_opcode(void)
  237. {
  238. unsigned long cfr;
  239. if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
  240. return false;
  241. __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
  242. if (!(cfr & CFR_CAMELLIA))
  243. return false;
  244. return true;
  245. }
  246. static int __init camellia_sparc64_mod_init(void)
  247. {
  248. int i;
  249. for (i = 0; i < ARRAY_SIZE(algs); i++)
  250. INIT_LIST_HEAD(&algs[i].cra_list);
  251. if (sparc64_has_camellia_opcode()) {
  252. pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
  253. return crypto_register_algs(algs, ARRAY_SIZE(algs));
  254. }
  255. pr_info("sparc64 camellia opcodes not available.\n");
  256. return -ENODEV;
  257. }
  258. static void __exit camellia_sparc64_mod_fini(void)
  259. {
  260. crypto_unregister_algs(algs, ARRAY_SIZE(algs));
  261. }
  262. module_init(camellia_sparc64_mod_init);
  263. module_exit(camellia_sparc64_mod_fini);
  264. MODULE_LICENSE("GPL");
  265. MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
  266. MODULE_ALIAS("aes");