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 <crypto/skcipher.h>
  19. #include <linux/init.h>
  20. #include <linux/string.h>
  21. #include <linux/blkdev.h>
  22. #include <linux/scatterlist.h>
  23. #include <linux/uaccess.h>
  24. #include "loop.h"
  25. MODULE_LICENSE("GPL");
  26. MODULE_DESCRIPTION("loop blockdevice transferfunction adaptor / CryptoAPI");
  27. MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>");
  28. #define LOOP_IV_SECTOR_BITS 9
  29. #define LOOP_IV_SECTOR_SIZE (1 << LOOP_IV_SECTOR_BITS)
  30. static int
  31. cryptoloop_init(struct loop_device *lo, const struct loop_info64 *info)
  32. {
  33. int err = -EINVAL;
  34. int cipher_len;
  35. int mode_len;
  36. char cms[LO_NAME_SIZE]; /* cipher-mode string */
  37. char *mode;
  38. char *cmsp = cms; /* c-m string pointer */
  39. struct crypto_skcipher *tfm;
  40. /* encryption breaks for non sector aligned offsets */
  41. if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
  42. goto out;
  43. strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE);
  44. cms[LO_NAME_SIZE - 1] = 0;
  45. cipher_len = strcspn(cmsp, "-");
  46. mode = cmsp + cipher_len;
  47. mode_len = 0;
  48. if (*mode) {
  49. mode++;
  50. mode_len = strcspn(mode, "-");
  51. }
  52. if (!mode_len) {
  53. mode = "cbc";
  54. mode_len = 3;
  55. }
  56. if (cipher_len + mode_len + 3 > LO_NAME_SIZE)
  57. return -EINVAL;
  58. memmove(cms, mode, mode_len);
  59. cmsp = cms + mode_len;
  60. *cmsp++ = '(';
  61. memcpy(cmsp, info->lo_crypt_name, cipher_len);
  62. cmsp += cipher_len;
  63. *cmsp++ = ')';
  64. *cmsp = 0;
  65. tfm = crypto_alloc_skcipher(cms, 0, CRYPTO_ALG_ASYNC);
  66. if (IS_ERR(tfm))
  67. return PTR_ERR(tfm);
  68. err = crypto_skcipher_setkey(tfm, info->lo_encrypt_key,
  69. info->lo_encrypt_key_size);
  70. if (err != 0)
  71. goto out_free_tfm;
  72. lo->key_data = tfm;
  73. return 0;
  74. out_free_tfm:
  75. crypto_free_skcipher(tfm);
  76. out:
  77. return err;
  78. }
  79. typedef int (*encdec_cbc_t)(struct skcipher_request *req);
  80. static int
  81. cryptoloop_transfer(struct loop_device *lo, int cmd,
  82. struct page *raw_page, unsigned raw_off,
  83. struct page *loop_page, unsigned loop_off,
  84. int size, sector_t IV)
  85. {
  86. struct crypto_skcipher *tfm = lo->key_data;
  87. SKCIPHER_REQUEST_ON_STACK(req, tfm);
  88. struct scatterlist sg_out;
  89. struct scatterlist sg_in;
  90. encdec_cbc_t encdecfunc;
  91. struct page *in_page, *out_page;
  92. unsigned in_offs, out_offs;
  93. int err;
  94. skcipher_request_set_tfm(req, tfm);
  95. skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
  96. NULL, NULL);
  97. sg_init_table(&sg_out, 1);
  98. sg_init_table(&sg_in, 1);
  99. if (cmd == READ) {
  100. in_page = raw_page;
  101. in_offs = raw_off;
  102. out_page = loop_page;
  103. out_offs = loop_off;
  104. encdecfunc = crypto_skcipher_decrypt;
  105. } else {
  106. in_page = loop_page;
  107. in_offs = loop_off;
  108. out_page = raw_page;
  109. out_offs = raw_off;
  110. encdecfunc = crypto_skcipher_encrypt;
  111. }
  112. while (size > 0) {
  113. const int sz = min(size, LOOP_IV_SECTOR_SIZE);
  114. u32 iv[4] = { 0, };
  115. iv[0] = cpu_to_le32(IV & 0xffffffff);
  116. sg_set_page(&sg_in, in_page, sz, in_offs);
  117. sg_set_page(&sg_out, out_page, sz, out_offs);
  118. skcipher_request_set_crypt(req, &sg_in, &sg_out, sz, iv);
  119. err = encdecfunc(req);
  120. if (err)
  121. goto out;
  122. IV++;
  123. size -= sz;
  124. in_offs += sz;
  125. out_offs += sz;
  126. }
  127. err = 0;
  128. out:
  129. skcipher_request_zero(req);
  130. return err;
  131. }
  132. static int
  133. cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)
  134. {
  135. return -EINVAL;
  136. }
  137. static int
  138. cryptoloop_release(struct loop_device *lo)
  139. {
  140. struct crypto_skcipher *tfm = lo->key_data;
  141. if (tfm != NULL) {
  142. crypto_free_skcipher(tfm);
  143. lo->key_data = NULL;
  144. return 0;
  145. }
  146. printk(KERN_ERR "cryptoloop_release(): tfm == NULL?\n");
  147. return -EINVAL;
  148. }
  149. static struct loop_func_table cryptoloop_funcs = {
  150. .number = LO_CRYPT_CRYPTOAPI,
  151. .init = cryptoloop_init,
  152. .ioctl = cryptoloop_ioctl,
  153. .transfer = cryptoloop_transfer,
  154. .release = cryptoloop_release,
  155. .owner = THIS_MODULE
  156. };
  157. static int __init
  158. init_cryptoloop(void)
  159. {
  160. int rc = loop_register_transfer(&cryptoloop_funcs);
  161. if (rc)
  162. printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
  163. return rc;
  164. }
  165. static void __exit
  166. cleanup_cryptoloop(void)
  167. {
  168. if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI))
  169. printk(KERN_ERR
  170. "cryptoloop: loop_unregister_transfer failed\n");
  171. }
  172. module_init(init_cryptoloop);
  173. module_exit(cleanup_cryptoloop);