serpent_sse2_glue.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. /*
  2. * Glue Code for SSE2 assembler versions of Serpent Cipher
  3. *
  4. * Copyright (c) 2011 Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
  5. *
  6. * Glue code based on aesni-intel_glue.c by:
  7. * Copyright (C) 2008, Intel Corp.
  8. * Author: Huang Ying <ying.huang@intel.com>
  9. *
  10. * CBC & ECB parts based on code (crypto/cbc.c,ecb.c) by:
  11. * Copyright (c) 2006 Herbert Xu <herbert@gondor.apana.org.au>
  12. * CTR part based on code (crypto/ctr.c) by:
  13. * (C) Copyright IBM Corp. 2007 - Joy Latten <latten@us.ibm.com>
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 2 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program; if not, write to the Free Software
  27. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  28. * USA
  29. *
  30. */
  31. #include <linux/module.h>
  32. #include <linux/hardirq.h>
  33. #include <linux/types.h>
  34. #include <linux/crypto.h>
  35. #include <linux/err.h>
  36. #include <crypto/algapi.h>
  37. #include <crypto/serpent.h>
  38. #include <crypto/cryptd.h>
  39. #include <crypto/b128ops.h>
  40. #include <crypto/ctr.h>
  41. #include <crypto/lrw.h>
  42. #include <asm/i387.h>
  43. #include <asm/serpent.h>
  44. #include <crypto/scatterwalk.h>
  45. #include <linux/workqueue.h>
  46. #include <linux/spinlock.h>
  47. #if defined(CONFIG_CRYPTO_LRW) || defined(CONFIG_CRYPTO_LRW_MODULE)
  48. #define HAS_LRW
  49. #endif
  50. struct async_serpent_ctx {
  51. struct cryptd_ablkcipher *cryptd_tfm;
  52. };
  53. static inline bool serpent_fpu_begin(bool fpu_enabled, unsigned int nbytes)
  54. {
  55. if (fpu_enabled)
  56. return true;
  57. /* SSE2 is only used when chunk to be processed is large enough, so
  58. * do not enable FPU until it is necessary.
  59. */
  60. if (nbytes < SERPENT_BLOCK_SIZE * SERPENT_PARALLEL_BLOCKS)
  61. return false;
  62. kernel_fpu_begin();
  63. return true;
  64. }
  65. static inline void serpent_fpu_end(bool fpu_enabled)
  66. {
  67. if (fpu_enabled)
  68. kernel_fpu_end();
  69. }
  70. static int ecb_crypt(struct blkcipher_desc *desc, struct blkcipher_walk *walk,
  71. bool enc)
  72. {
  73. bool fpu_enabled = false;
  74. struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  75. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  76. unsigned int nbytes;
  77. int err;
  78. err = blkcipher_walk_virt(desc, walk);
  79. desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
  80. while ((nbytes = walk->nbytes)) {
  81. u8 *wsrc = walk->src.virt.addr;
  82. u8 *wdst = walk->dst.virt.addr;
  83. fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
  84. /* Process multi-block batch */
  85. if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
  86. do {
  87. if (enc)
  88. serpent_enc_blk_xway(ctx, wdst, wsrc);
  89. else
  90. serpent_dec_blk_xway(ctx, wdst, wsrc);
  91. wsrc += bsize * SERPENT_PARALLEL_BLOCKS;
  92. wdst += bsize * SERPENT_PARALLEL_BLOCKS;
  93. nbytes -= bsize * SERPENT_PARALLEL_BLOCKS;
  94. } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
  95. if (nbytes < bsize)
  96. goto done;
  97. }
  98. /* Handle leftovers */
  99. do {
  100. if (enc)
  101. __serpent_encrypt(ctx, wdst, wsrc);
  102. else
  103. __serpent_decrypt(ctx, wdst, wsrc);
  104. wsrc += bsize;
  105. wdst += bsize;
  106. nbytes -= bsize;
  107. } while (nbytes >= bsize);
  108. done:
  109. err = blkcipher_walk_done(desc, walk, nbytes);
  110. }
  111. serpent_fpu_end(fpu_enabled);
  112. return err;
  113. }
  114. static int ecb_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  115. struct scatterlist *src, unsigned int nbytes)
  116. {
  117. struct blkcipher_walk walk;
  118. blkcipher_walk_init(&walk, dst, src, nbytes);
  119. return ecb_crypt(desc, &walk, true);
  120. }
  121. static int ecb_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  122. struct scatterlist *src, unsigned int nbytes)
  123. {
  124. struct blkcipher_walk walk;
  125. blkcipher_walk_init(&walk, dst, src, nbytes);
  126. return ecb_crypt(desc, &walk, false);
  127. }
  128. static struct crypto_alg blk_ecb_alg = {
  129. .cra_name = "__ecb-serpent-sse2",
  130. .cra_driver_name = "__driver-ecb-serpent-sse2",
  131. .cra_priority = 0,
  132. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  133. .cra_blocksize = SERPENT_BLOCK_SIZE,
  134. .cra_ctxsize = sizeof(struct serpent_ctx),
  135. .cra_alignmask = 0,
  136. .cra_type = &crypto_blkcipher_type,
  137. .cra_module = THIS_MODULE,
  138. .cra_list = LIST_HEAD_INIT(blk_ecb_alg.cra_list),
  139. .cra_u = {
  140. .blkcipher = {
  141. .min_keysize = SERPENT_MIN_KEY_SIZE,
  142. .max_keysize = SERPENT_MAX_KEY_SIZE,
  143. .setkey = serpent_setkey,
  144. .encrypt = ecb_encrypt,
  145. .decrypt = ecb_decrypt,
  146. },
  147. },
  148. };
  149. static unsigned int __cbc_encrypt(struct blkcipher_desc *desc,
  150. struct blkcipher_walk *walk)
  151. {
  152. struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  153. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  154. unsigned int nbytes = walk->nbytes;
  155. u128 *src = (u128 *)walk->src.virt.addr;
  156. u128 *dst = (u128 *)walk->dst.virt.addr;
  157. u128 *iv = (u128 *)walk->iv;
  158. do {
  159. u128_xor(dst, src, iv);
  160. __serpent_encrypt(ctx, (u8 *)dst, (u8 *)dst);
  161. iv = dst;
  162. src += 1;
  163. dst += 1;
  164. nbytes -= bsize;
  165. } while (nbytes >= bsize);
  166. u128_xor((u128 *)walk->iv, (u128 *)walk->iv, iv);
  167. return nbytes;
  168. }
  169. static int cbc_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  170. struct scatterlist *src, unsigned int nbytes)
  171. {
  172. struct blkcipher_walk walk;
  173. int err;
  174. blkcipher_walk_init(&walk, dst, src, nbytes);
  175. err = blkcipher_walk_virt(desc, &walk);
  176. while ((nbytes = walk.nbytes)) {
  177. nbytes = __cbc_encrypt(desc, &walk);
  178. err = blkcipher_walk_done(desc, &walk, nbytes);
  179. }
  180. return err;
  181. }
  182. static unsigned int __cbc_decrypt(struct blkcipher_desc *desc,
  183. struct blkcipher_walk *walk)
  184. {
  185. struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  186. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  187. unsigned int nbytes = walk->nbytes;
  188. u128 *src = (u128 *)walk->src.virt.addr;
  189. u128 *dst = (u128 *)walk->dst.virt.addr;
  190. u128 ivs[SERPENT_PARALLEL_BLOCKS - 1];
  191. u128 last_iv;
  192. int i;
  193. /* Start of the last block. */
  194. src += nbytes / bsize - 1;
  195. dst += nbytes / bsize - 1;
  196. last_iv = *src;
  197. /* Process multi-block batch */
  198. if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
  199. do {
  200. nbytes -= bsize * (SERPENT_PARALLEL_BLOCKS - 1);
  201. src -= SERPENT_PARALLEL_BLOCKS - 1;
  202. dst -= SERPENT_PARALLEL_BLOCKS - 1;
  203. for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++)
  204. ivs[i] = src[i];
  205. serpent_dec_blk_xway(ctx, (u8 *)dst, (u8 *)src);
  206. for (i = 0; i < SERPENT_PARALLEL_BLOCKS - 1; i++)
  207. u128_xor(dst + (i + 1), dst + (i + 1), ivs + i);
  208. nbytes -= bsize;
  209. if (nbytes < bsize)
  210. goto done;
  211. u128_xor(dst, dst, src - 1);
  212. src -= 1;
  213. dst -= 1;
  214. } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
  215. if (nbytes < bsize)
  216. goto done;
  217. }
  218. /* Handle leftovers */
  219. for (;;) {
  220. __serpent_decrypt(ctx, (u8 *)dst, (u8 *)src);
  221. nbytes -= bsize;
  222. if (nbytes < bsize)
  223. break;
  224. u128_xor(dst, dst, src - 1);
  225. src -= 1;
  226. dst -= 1;
  227. }
  228. done:
  229. u128_xor(dst, dst, (u128 *)walk->iv);
  230. *(u128 *)walk->iv = last_iv;
  231. return nbytes;
  232. }
  233. static int cbc_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  234. struct scatterlist *src, unsigned int nbytes)
  235. {
  236. bool fpu_enabled = false;
  237. struct blkcipher_walk walk;
  238. int err;
  239. blkcipher_walk_init(&walk, dst, src, nbytes);
  240. err = blkcipher_walk_virt(desc, &walk);
  241. desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
  242. while ((nbytes = walk.nbytes)) {
  243. fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
  244. nbytes = __cbc_decrypt(desc, &walk);
  245. err = blkcipher_walk_done(desc, &walk, nbytes);
  246. }
  247. serpent_fpu_end(fpu_enabled);
  248. return err;
  249. }
  250. static struct crypto_alg blk_cbc_alg = {
  251. .cra_name = "__cbc-serpent-sse2",
  252. .cra_driver_name = "__driver-cbc-serpent-sse2",
  253. .cra_priority = 0,
  254. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  255. .cra_blocksize = SERPENT_BLOCK_SIZE,
  256. .cra_ctxsize = sizeof(struct serpent_ctx),
  257. .cra_alignmask = 0,
  258. .cra_type = &crypto_blkcipher_type,
  259. .cra_module = THIS_MODULE,
  260. .cra_list = LIST_HEAD_INIT(blk_cbc_alg.cra_list),
  261. .cra_u = {
  262. .blkcipher = {
  263. .min_keysize = SERPENT_MIN_KEY_SIZE,
  264. .max_keysize = SERPENT_MAX_KEY_SIZE,
  265. .setkey = serpent_setkey,
  266. .encrypt = cbc_encrypt,
  267. .decrypt = cbc_decrypt,
  268. },
  269. },
  270. };
  271. static inline void u128_to_be128(be128 *dst, const u128 *src)
  272. {
  273. dst->a = cpu_to_be64(src->a);
  274. dst->b = cpu_to_be64(src->b);
  275. }
  276. static inline void be128_to_u128(u128 *dst, const be128 *src)
  277. {
  278. dst->a = be64_to_cpu(src->a);
  279. dst->b = be64_to_cpu(src->b);
  280. }
  281. static inline void u128_inc(u128 *i)
  282. {
  283. i->b++;
  284. if (!i->b)
  285. i->a++;
  286. }
  287. static void ctr_crypt_final(struct blkcipher_desc *desc,
  288. struct blkcipher_walk *walk)
  289. {
  290. struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  291. u8 *ctrblk = walk->iv;
  292. u8 keystream[SERPENT_BLOCK_SIZE];
  293. u8 *src = walk->src.virt.addr;
  294. u8 *dst = walk->dst.virt.addr;
  295. unsigned int nbytes = walk->nbytes;
  296. __serpent_encrypt(ctx, keystream, ctrblk);
  297. crypto_xor(keystream, src, nbytes);
  298. memcpy(dst, keystream, nbytes);
  299. crypto_inc(ctrblk, SERPENT_BLOCK_SIZE);
  300. }
  301. static unsigned int __ctr_crypt(struct blkcipher_desc *desc,
  302. struct blkcipher_walk *walk)
  303. {
  304. struct serpent_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  305. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  306. unsigned int nbytes = walk->nbytes;
  307. u128 *src = (u128 *)walk->src.virt.addr;
  308. u128 *dst = (u128 *)walk->dst.virt.addr;
  309. u128 ctrblk;
  310. be128 ctrblocks[SERPENT_PARALLEL_BLOCKS];
  311. int i;
  312. be128_to_u128(&ctrblk, (be128 *)walk->iv);
  313. /* Process multi-block batch */
  314. if (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS) {
  315. do {
  316. /* create ctrblks for parallel encrypt */
  317. for (i = 0; i < SERPENT_PARALLEL_BLOCKS; i++) {
  318. if (dst != src)
  319. dst[i] = src[i];
  320. u128_to_be128(&ctrblocks[i], &ctrblk);
  321. u128_inc(&ctrblk);
  322. }
  323. serpent_enc_blk_xway_xor(ctx, (u8 *)dst,
  324. (u8 *)ctrblocks);
  325. src += SERPENT_PARALLEL_BLOCKS;
  326. dst += SERPENT_PARALLEL_BLOCKS;
  327. nbytes -= bsize * SERPENT_PARALLEL_BLOCKS;
  328. } while (nbytes >= bsize * SERPENT_PARALLEL_BLOCKS);
  329. if (nbytes < bsize)
  330. goto done;
  331. }
  332. /* Handle leftovers */
  333. do {
  334. if (dst != src)
  335. *dst = *src;
  336. u128_to_be128(&ctrblocks[0], &ctrblk);
  337. u128_inc(&ctrblk);
  338. __serpent_encrypt(ctx, (u8 *)ctrblocks, (u8 *)ctrblocks);
  339. u128_xor(dst, dst, (u128 *)ctrblocks);
  340. src += 1;
  341. dst += 1;
  342. nbytes -= bsize;
  343. } while (nbytes >= bsize);
  344. done:
  345. u128_to_be128((be128 *)walk->iv, &ctrblk);
  346. return nbytes;
  347. }
  348. static int ctr_crypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  349. struct scatterlist *src, unsigned int nbytes)
  350. {
  351. bool fpu_enabled = false;
  352. struct blkcipher_walk walk;
  353. int err;
  354. blkcipher_walk_init(&walk, dst, src, nbytes);
  355. err = blkcipher_walk_virt_block(desc, &walk, SERPENT_BLOCK_SIZE);
  356. desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
  357. while ((nbytes = walk.nbytes) >= SERPENT_BLOCK_SIZE) {
  358. fpu_enabled = serpent_fpu_begin(fpu_enabled, nbytes);
  359. nbytes = __ctr_crypt(desc, &walk);
  360. err = blkcipher_walk_done(desc, &walk, nbytes);
  361. }
  362. serpent_fpu_end(fpu_enabled);
  363. if (walk.nbytes) {
  364. ctr_crypt_final(desc, &walk);
  365. err = blkcipher_walk_done(desc, &walk, 0);
  366. }
  367. return err;
  368. }
  369. static struct crypto_alg blk_ctr_alg = {
  370. .cra_name = "__ctr-serpent-sse2",
  371. .cra_driver_name = "__driver-ctr-serpent-sse2",
  372. .cra_priority = 0,
  373. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  374. .cra_blocksize = 1,
  375. .cra_ctxsize = sizeof(struct serpent_ctx),
  376. .cra_alignmask = 0,
  377. .cra_type = &crypto_blkcipher_type,
  378. .cra_module = THIS_MODULE,
  379. .cra_list = LIST_HEAD_INIT(blk_ctr_alg.cra_list),
  380. .cra_u = {
  381. .blkcipher = {
  382. .min_keysize = SERPENT_MIN_KEY_SIZE,
  383. .max_keysize = SERPENT_MAX_KEY_SIZE,
  384. .ivsize = SERPENT_BLOCK_SIZE,
  385. .setkey = serpent_setkey,
  386. .encrypt = ctr_crypt,
  387. .decrypt = ctr_crypt,
  388. },
  389. },
  390. };
  391. #ifdef HAS_LRW
  392. struct crypt_priv {
  393. struct serpent_ctx *ctx;
  394. bool fpu_enabled;
  395. };
  396. static void encrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
  397. {
  398. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  399. struct crypt_priv *ctx = priv;
  400. int i;
  401. ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
  402. if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
  403. serpent_enc_blk_xway(ctx->ctx, srcdst, srcdst);
  404. return;
  405. }
  406. for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
  407. __serpent_encrypt(ctx->ctx, srcdst, srcdst);
  408. }
  409. static void decrypt_callback(void *priv, u8 *srcdst, unsigned int nbytes)
  410. {
  411. const unsigned int bsize = SERPENT_BLOCK_SIZE;
  412. struct crypt_priv *ctx = priv;
  413. int i;
  414. ctx->fpu_enabled = serpent_fpu_begin(ctx->fpu_enabled, nbytes);
  415. if (nbytes == bsize * SERPENT_PARALLEL_BLOCKS) {
  416. serpent_dec_blk_xway(ctx->ctx, srcdst, srcdst);
  417. return;
  418. }
  419. for (i = 0; i < nbytes / bsize; i++, srcdst += bsize)
  420. __serpent_decrypt(ctx->ctx, srcdst, srcdst);
  421. }
  422. struct serpent_lrw_ctx {
  423. struct lrw_table_ctx lrw_table;
  424. struct serpent_ctx serpent_ctx;
  425. };
  426. static int lrw_serpent_setkey(struct crypto_tfm *tfm, const u8 *key,
  427. unsigned int keylen)
  428. {
  429. struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
  430. int err;
  431. err = __serpent_setkey(&ctx->serpent_ctx, key, keylen -
  432. SERPENT_BLOCK_SIZE);
  433. if (err)
  434. return err;
  435. return lrw_init_table(&ctx->lrw_table, key + keylen -
  436. SERPENT_BLOCK_SIZE);
  437. }
  438. static int lrw_encrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  439. struct scatterlist *src, unsigned int nbytes)
  440. {
  441. struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  442. be128 buf[SERPENT_PARALLEL_BLOCKS];
  443. struct crypt_priv crypt_ctx = {
  444. .ctx = &ctx->serpent_ctx,
  445. .fpu_enabled = false,
  446. };
  447. struct lrw_crypt_req req = {
  448. .tbuf = buf,
  449. .tbuflen = sizeof(buf),
  450. .table_ctx = &ctx->lrw_table,
  451. .crypt_ctx = &crypt_ctx,
  452. .crypt_fn = encrypt_callback,
  453. };
  454. int ret;
  455. ret = lrw_crypt(desc, dst, src, nbytes, &req);
  456. serpent_fpu_end(crypt_ctx.fpu_enabled);
  457. return ret;
  458. }
  459. static int lrw_decrypt(struct blkcipher_desc *desc, struct scatterlist *dst,
  460. struct scatterlist *src, unsigned int nbytes)
  461. {
  462. struct serpent_lrw_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
  463. be128 buf[SERPENT_PARALLEL_BLOCKS];
  464. struct crypt_priv crypt_ctx = {
  465. .ctx = &ctx->serpent_ctx,
  466. .fpu_enabled = false,
  467. };
  468. struct lrw_crypt_req req = {
  469. .tbuf = buf,
  470. .tbuflen = sizeof(buf),
  471. .table_ctx = &ctx->lrw_table,
  472. .crypt_ctx = &crypt_ctx,
  473. .crypt_fn = decrypt_callback,
  474. };
  475. int ret;
  476. ret = lrw_crypt(desc, dst, src, nbytes, &req);
  477. serpent_fpu_end(crypt_ctx.fpu_enabled);
  478. return ret;
  479. }
  480. static void lrw_exit_tfm(struct crypto_tfm *tfm)
  481. {
  482. struct serpent_lrw_ctx *ctx = crypto_tfm_ctx(tfm);
  483. lrw_free_table(&ctx->lrw_table);
  484. }
  485. static struct crypto_alg blk_lrw_alg = {
  486. .cra_name = "__lrw-serpent-sse2",
  487. .cra_driver_name = "__driver-lrw-serpent-sse2",
  488. .cra_priority = 0,
  489. .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
  490. .cra_blocksize = SERPENT_BLOCK_SIZE,
  491. .cra_ctxsize = sizeof(struct serpent_lrw_ctx),
  492. .cra_alignmask = 0,
  493. .cra_type = &crypto_blkcipher_type,
  494. .cra_module = THIS_MODULE,
  495. .cra_list = LIST_HEAD_INIT(blk_lrw_alg.cra_list),
  496. .cra_exit = lrw_exit_tfm,
  497. .cra_u = {
  498. .blkcipher = {
  499. .min_keysize = SERPENT_MIN_KEY_SIZE +
  500. SERPENT_BLOCK_SIZE,
  501. .max_keysize = SERPENT_MAX_KEY_SIZE +
  502. SERPENT_BLOCK_SIZE,
  503. .ivsize = SERPENT_BLOCK_SIZE,
  504. .setkey = lrw_serpent_setkey,
  505. .encrypt = lrw_encrypt,
  506. .decrypt = lrw_decrypt,
  507. },
  508. },
  509. };
  510. #endif
  511. static int ablk_set_key(struct crypto_ablkcipher *tfm, const u8 *key,
  512. unsigned int key_len)
  513. {
  514. struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  515. struct crypto_ablkcipher *child = &ctx->cryptd_tfm->base;
  516. int err;
  517. crypto_ablkcipher_clear_flags(child, CRYPTO_TFM_REQ_MASK);
  518. crypto_ablkcipher_set_flags(child, crypto_ablkcipher_get_flags(tfm)
  519. & CRYPTO_TFM_REQ_MASK);
  520. err = crypto_ablkcipher_setkey(child, key, key_len);
  521. crypto_ablkcipher_set_flags(tfm, crypto_ablkcipher_get_flags(child)
  522. & CRYPTO_TFM_RES_MASK);
  523. return err;
  524. }
  525. static int __ablk_encrypt(struct ablkcipher_request *req)
  526. {
  527. struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
  528. struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  529. struct blkcipher_desc desc;
  530. desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
  531. desc.info = req->info;
  532. desc.flags = 0;
  533. return crypto_blkcipher_crt(desc.tfm)->encrypt(
  534. &desc, req->dst, req->src, req->nbytes);
  535. }
  536. static int ablk_encrypt(struct ablkcipher_request *req)
  537. {
  538. struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
  539. struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  540. if (!irq_fpu_usable()) {
  541. struct ablkcipher_request *cryptd_req =
  542. ablkcipher_request_ctx(req);
  543. memcpy(cryptd_req, req, sizeof(*req));
  544. ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
  545. return crypto_ablkcipher_encrypt(cryptd_req);
  546. } else {
  547. return __ablk_encrypt(req);
  548. }
  549. }
  550. static int ablk_decrypt(struct ablkcipher_request *req)
  551. {
  552. struct crypto_ablkcipher *tfm = crypto_ablkcipher_reqtfm(req);
  553. struct async_serpent_ctx *ctx = crypto_ablkcipher_ctx(tfm);
  554. if (!irq_fpu_usable()) {
  555. struct ablkcipher_request *cryptd_req =
  556. ablkcipher_request_ctx(req);
  557. memcpy(cryptd_req, req, sizeof(*req));
  558. ablkcipher_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
  559. return crypto_ablkcipher_decrypt(cryptd_req);
  560. } else {
  561. struct blkcipher_desc desc;
  562. desc.tfm = cryptd_ablkcipher_child(ctx->cryptd_tfm);
  563. desc.info = req->info;
  564. desc.flags = 0;
  565. return crypto_blkcipher_crt(desc.tfm)->decrypt(
  566. &desc, req->dst, req->src, req->nbytes);
  567. }
  568. }
  569. static void ablk_exit(struct crypto_tfm *tfm)
  570. {
  571. struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm);
  572. cryptd_free_ablkcipher(ctx->cryptd_tfm);
  573. }
  574. static void ablk_init_common(struct crypto_tfm *tfm,
  575. struct cryptd_ablkcipher *cryptd_tfm)
  576. {
  577. struct async_serpent_ctx *ctx = crypto_tfm_ctx(tfm);
  578. ctx->cryptd_tfm = cryptd_tfm;
  579. tfm->crt_ablkcipher.reqsize = sizeof(struct ablkcipher_request) +
  580. crypto_ablkcipher_reqsize(&cryptd_tfm->base);
  581. }
  582. static int ablk_ecb_init(struct crypto_tfm *tfm)
  583. {
  584. struct cryptd_ablkcipher *cryptd_tfm;
  585. cryptd_tfm = cryptd_alloc_ablkcipher("__driver-ecb-serpent-sse2", 0, 0);
  586. if (IS_ERR(cryptd_tfm))
  587. return PTR_ERR(cryptd_tfm);
  588. ablk_init_common(tfm, cryptd_tfm);
  589. return 0;
  590. }
  591. static struct crypto_alg ablk_ecb_alg = {
  592. .cra_name = "ecb(serpent)",
  593. .cra_driver_name = "ecb-serpent-sse2",
  594. .cra_priority = 400,
  595. .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  596. .cra_blocksize = SERPENT_BLOCK_SIZE,
  597. .cra_ctxsize = sizeof(struct async_serpent_ctx),
  598. .cra_alignmask = 0,
  599. .cra_type = &crypto_ablkcipher_type,
  600. .cra_module = THIS_MODULE,
  601. .cra_list = LIST_HEAD_INIT(ablk_ecb_alg.cra_list),
  602. .cra_init = ablk_ecb_init,
  603. .cra_exit = ablk_exit,
  604. .cra_u = {
  605. .ablkcipher = {
  606. .min_keysize = SERPENT_MIN_KEY_SIZE,
  607. .max_keysize = SERPENT_MAX_KEY_SIZE,
  608. .setkey = ablk_set_key,
  609. .encrypt = ablk_encrypt,
  610. .decrypt = ablk_decrypt,
  611. },
  612. },
  613. };
  614. static int ablk_cbc_init(struct crypto_tfm *tfm)
  615. {
  616. struct cryptd_ablkcipher *cryptd_tfm;
  617. cryptd_tfm = cryptd_alloc_ablkcipher("__driver-cbc-serpent-sse2", 0, 0);
  618. if (IS_ERR(cryptd_tfm))
  619. return PTR_ERR(cryptd_tfm);
  620. ablk_init_common(tfm, cryptd_tfm);
  621. return 0;
  622. }
  623. static struct crypto_alg ablk_cbc_alg = {
  624. .cra_name = "cbc(serpent)",
  625. .cra_driver_name = "cbc-serpent-sse2",
  626. .cra_priority = 400,
  627. .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  628. .cra_blocksize = SERPENT_BLOCK_SIZE,
  629. .cra_ctxsize = sizeof(struct async_serpent_ctx),
  630. .cra_alignmask = 0,
  631. .cra_type = &crypto_ablkcipher_type,
  632. .cra_module = THIS_MODULE,
  633. .cra_list = LIST_HEAD_INIT(ablk_cbc_alg.cra_list),
  634. .cra_init = ablk_cbc_init,
  635. .cra_exit = ablk_exit,
  636. .cra_u = {
  637. .ablkcipher = {
  638. .min_keysize = SERPENT_MIN_KEY_SIZE,
  639. .max_keysize = SERPENT_MAX_KEY_SIZE,
  640. .ivsize = SERPENT_BLOCK_SIZE,
  641. .setkey = ablk_set_key,
  642. .encrypt = __ablk_encrypt,
  643. .decrypt = ablk_decrypt,
  644. },
  645. },
  646. };
  647. static int ablk_ctr_init(struct crypto_tfm *tfm)
  648. {
  649. struct cryptd_ablkcipher *cryptd_tfm;
  650. cryptd_tfm = cryptd_alloc_ablkcipher("__driver-ctr-serpent-sse2", 0, 0);
  651. if (IS_ERR(cryptd_tfm))
  652. return PTR_ERR(cryptd_tfm);
  653. ablk_init_common(tfm, cryptd_tfm);
  654. return 0;
  655. }
  656. static struct crypto_alg ablk_ctr_alg = {
  657. .cra_name = "ctr(serpent)",
  658. .cra_driver_name = "ctr-serpent-sse2",
  659. .cra_priority = 400,
  660. .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  661. .cra_blocksize = 1,
  662. .cra_ctxsize = sizeof(struct async_serpent_ctx),
  663. .cra_alignmask = 0,
  664. .cra_type = &crypto_ablkcipher_type,
  665. .cra_module = THIS_MODULE,
  666. .cra_list = LIST_HEAD_INIT(ablk_ctr_alg.cra_list),
  667. .cra_init = ablk_ctr_init,
  668. .cra_exit = ablk_exit,
  669. .cra_u = {
  670. .ablkcipher = {
  671. .min_keysize = SERPENT_MIN_KEY_SIZE,
  672. .max_keysize = SERPENT_MAX_KEY_SIZE,
  673. .ivsize = SERPENT_BLOCK_SIZE,
  674. .setkey = ablk_set_key,
  675. .encrypt = ablk_encrypt,
  676. .decrypt = ablk_encrypt,
  677. .geniv = "chainiv",
  678. },
  679. },
  680. };
  681. #ifdef HAS_LRW
  682. static int ablk_lrw_init(struct crypto_tfm *tfm)
  683. {
  684. struct cryptd_ablkcipher *cryptd_tfm;
  685. cryptd_tfm = cryptd_alloc_ablkcipher("__driver-lrw-serpent-sse2", 0, 0);
  686. if (IS_ERR(cryptd_tfm))
  687. return PTR_ERR(cryptd_tfm);
  688. ablk_init_common(tfm, cryptd_tfm);
  689. return 0;
  690. }
  691. static struct crypto_alg ablk_lrw_alg = {
  692. .cra_name = "lrw(serpent)",
  693. .cra_driver_name = "lrw-serpent-sse2",
  694. .cra_priority = 400,
  695. .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
  696. .cra_blocksize = SERPENT_BLOCK_SIZE,
  697. .cra_ctxsize = sizeof(struct async_serpent_ctx),
  698. .cra_alignmask = 0,
  699. .cra_type = &crypto_ablkcipher_type,
  700. .cra_module = THIS_MODULE,
  701. .cra_list = LIST_HEAD_INIT(ablk_lrw_alg.cra_list),
  702. .cra_init = ablk_lrw_init,
  703. .cra_exit = ablk_exit,
  704. .cra_u = {
  705. .ablkcipher = {
  706. .min_keysize = SERPENT_MIN_KEY_SIZE +
  707. SERPENT_BLOCK_SIZE,
  708. .max_keysize = SERPENT_MAX_KEY_SIZE +
  709. SERPENT_BLOCK_SIZE,
  710. .ivsize = SERPENT_BLOCK_SIZE,
  711. .setkey = ablk_set_key,
  712. .encrypt = ablk_encrypt,
  713. .decrypt = ablk_decrypt,
  714. },
  715. },
  716. };
  717. #endif
  718. static int __init serpent_sse2_init(void)
  719. {
  720. int err;
  721. if (!cpu_has_xmm2) {
  722. printk(KERN_INFO "SSE2 instructions are not detected.\n");
  723. return -ENODEV;
  724. }
  725. err = crypto_register_alg(&blk_ecb_alg);
  726. if (err)
  727. goto blk_ecb_err;
  728. err = crypto_register_alg(&blk_cbc_alg);
  729. if (err)
  730. goto blk_cbc_err;
  731. err = crypto_register_alg(&blk_ctr_alg);
  732. if (err)
  733. goto blk_ctr_err;
  734. err = crypto_register_alg(&ablk_ecb_alg);
  735. if (err)
  736. goto ablk_ecb_err;
  737. err = crypto_register_alg(&ablk_cbc_alg);
  738. if (err)
  739. goto ablk_cbc_err;
  740. err = crypto_register_alg(&ablk_ctr_alg);
  741. if (err)
  742. goto ablk_ctr_err;
  743. #ifdef HAS_LRW
  744. err = crypto_register_alg(&blk_lrw_alg);
  745. if (err)
  746. goto blk_lrw_err;
  747. err = crypto_register_alg(&ablk_lrw_alg);
  748. if (err)
  749. goto ablk_lrw_err;
  750. #endif
  751. return err;
  752. #ifdef HAS_LRW
  753. ablk_lrw_err:
  754. crypto_unregister_alg(&blk_lrw_alg);
  755. blk_lrw_err:
  756. crypto_unregister_alg(&ablk_ctr_alg);
  757. #endif
  758. ablk_ctr_err:
  759. crypto_unregister_alg(&ablk_cbc_alg);
  760. ablk_cbc_err:
  761. crypto_unregister_alg(&ablk_ecb_alg);
  762. ablk_ecb_err:
  763. crypto_unregister_alg(&blk_ctr_alg);
  764. blk_ctr_err:
  765. crypto_unregister_alg(&blk_cbc_alg);
  766. blk_cbc_err:
  767. crypto_unregister_alg(&blk_ecb_alg);
  768. blk_ecb_err:
  769. return err;
  770. }
  771. static void __exit serpent_sse2_exit(void)
  772. {
  773. #ifdef HAS_LRW
  774. crypto_unregister_alg(&ablk_lrw_alg);
  775. crypto_unregister_alg(&blk_lrw_alg);
  776. #endif
  777. crypto_unregister_alg(&ablk_ctr_alg);
  778. crypto_unregister_alg(&ablk_cbc_alg);
  779. crypto_unregister_alg(&ablk_ecb_alg);
  780. crypto_unregister_alg(&blk_ctr_alg);
  781. crypto_unregister_alg(&blk_cbc_alg);
  782. crypto_unregister_alg(&blk_ecb_alg);
  783. }
  784. module_init(serpent_sse2_init);
  785. module_exit(serpent_sse2_exit);
  786. MODULE_DESCRIPTION("Serpent Cipher Algorithm, SSE2 optimized");
  787. MODULE_LICENSE("GPL");
  788. MODULE_ALIAS("serpent");