cryptoloop.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. Linux loop encryption enabling module
  3. Copyright (C) 2002 Herbert Valerio Riedel <hvr@gnu.org>
  4. Copyright (C) 2003 Fruhwirth Clemens <clemens@endorphin.org>
  5. This module is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This module is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this module; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include <linux/module.h>
  18. #include <linux/init.h>
  19. #include <linux/string.h>
  20. #include <linux/crypto.h>
  21. #include <linux/blkdev.h>
  22. #include <linux/loop.h>
  23. #include <linux/scatterlist.h>
  24. #include <asm/semaphore.h>
  25. #include <asm/uaccess.h>
  26. MODULE_LICENSE("GPL");
  27. MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI");
  28. MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>");
  29. #define LOOP_IV_SECTOR_BITS 9
  30. #define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS)
  31. static int
  32. cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
  33. {
  34. int err = -EINVAL;
  35. int cipher_len;
  36. int mode_len;
  37. char cms[LO_NAME_SIZE]; /* cipher-mode string */
  38. char *cipher;
  39. char *mode;
  40. char *cmsp = cms; /* c-m string pointer */
  41. struct crypto_blkcipher *tfm;
  42. /* encryption breaks for non sector aligned offsets */
  43. if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
  44. goto out;
  45. strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE);
  46. cms[LO_NAME_SIZE - 1] = 0;
  47. cipher = cmsp;
  48. cipher_len = strcspn(cmsp, "-");
  49. mode = cmsp + cipher_len;
  50. mode_len = 0;
  51. if (*mode) {
  52. mode++;
  53. mode_len = strcspn(mode, "-");
  54. }
  55. if (!mode_len) {
  56. mode = "cbc";
  57. mode_len = 3;
  58. }
  59. if (cipher_len + mode_len + 3 > LO_NAME_SIZE)
  60. return -EINVAL;
  61. memmove(cms, mode, mode_len);
  62. cmsp = cms + mode_len;
  63. *cmsp++ = '(';
  64. memcpy(cmsp, info->lo_crypt_name, cipher_len);
  65. cmsp += cipher_len;
  66. *cmsp++ = ')';
  67. *cmsp = 0;
  68. tfm = crypto_alloc_blkcipher(cms, 0, CRYPTO_ALG_ASYNC);
  69. if (IS_ERR(tfm))
  70. return PTR_ERR(tfm);
  71. err = crypto_blkcipher_setkey(tfm, info->lo_encrypt_key,
  72. info->lo_encrypt_key_size);
  73. if (err != 0)
  74. goto out_free_tfm;
  75. lo->key_data = tfm;
  76. return 0;
  77. out_free_tfm:
  78. crypto_free_blkcipher(tfm);
  79. out:
  80. return err;
  81. }
  82. typedef int (*encdec_cbc_t)(struct blkcipher_desc *desc,
  83. struct scatterlist *sg_out,
  84. struct scatterlist *sg_in,
  85. unsigned int nsg);
  86. static int
  87. cryptoloop_transfer(struct loop_device *lo, int cmd,
  88. struct page *raw_page, unsigned raw_off,
  89. struct page *loop_page, unsigned loop_off,
  90. int size, sector_t IV)
  91. {
  92. struct crypto_blkcipher *tfm = lo->key_data;
  93. struct blkcipher_desc desc = {
  94. .tfm = tfm,
  95. .flags = CRYPTO_TFM_REQ_MAY_SLEEP,
  96. };
  97. struct scatterlist sg_out;
  98. struct scatterlist sg_in;
  99. encdec_cbc_t encdecfunc;
  100. struct page *in_page, *out_page;
  101. unsigned in_offs, out_offs;
  102. int err;
  103. sg_init_table(&sg_out, 1);
  104. sg_init_table(&sg_in, 1);
  105. if (cmd == READ) {
  106. in_page = raw_page;
  107. in_offs = raw_off;
  108. out_page = loop_page;
  109. out_offs = loop_off;
  110. encdecfunc = crypto_blkcipher_crt(tfm)->decrypt;
  111. } else {
  112. in_page = loop_page;
  113. in_offs = loop_off;
  114. out_page = raw_page;
  115. out_offs = raw_off;
  116. encdecfunc = crypto_blkcipher_crt(tfm)->encrypt;
  117. }
  118. while (size > 0) {
  119. const int sz = min(size, LOOP_IV_SECTOR_SIZE);
  120. u32 iv[4] = { 0, };
  121. iv[0] = cpu_to_le32(IV & 0xffffffff);
  122. sg_set_page(&sg_in, in_page, sz, in_offs);
  123. sg_set_page(&sg_out, out_page, sz, out_offs);
  124. desc.info = iv;
  125. err = encdecfunc(&desc, &sg_out, &sg_in, sz);
  126. if (err)
  127. return err;
  128. IV++;
  129. size -= sz;
  130. in_offs += sz;
  131. out_offs += sz;
  132. }
  133. return 0;
  134. }
  135. static int
  136. cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)
  137. {
  138. return -EINVAL;
  139. }
  140. static int
  141. cryptoloop_release(struct loop_device *lo)
  142. {
  143. struct crypto_blkcipher *tfm = lo->key_data;
  144. if (tfm != NULL) {
  145. crypto_free_blkcipher(tfm);
  146. lo->key_data = NULL;
  147. return 0;
  148. }
  149. printk(KERN_ERR "cryptoloop_release(): tfm == NULL?\n");
  150. return -EINVAL;
  151. }
  152. static struct loop_func_table cryptoloop_funcs = {
  153. .number = LO_CRYPT_CRYPTOAPI,
  154. .init = cryptoloop_init,
  155. .ioctl = cryptoloop_ioctl,
  156. .transfer = cryptoloop_transfer,
  157. .release = cryptoloop_release,
  158. .owner = THIS_MODULE
  159. };
  160. static int __init
  161. init_cryptoloop(void)
  162. {
  163. int rc = loop_register_transfer(&cryptoloop_funcs);
  164. if (rc)
  165. printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
  166. return rc;
  167. }
  168. static void __exit
  169. cleanup_cryptoloop(void)
  170. {
  171. if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI))
  172. printk(KERN_ERR
  173. "cryptoloop: loop_unregister_transfer failed\n");
  174. }
  175. module_init(init_cryptoloop);
  176. module_exit(cleanup_cryptoloop);