cryptoloop.c
上传用户:ajay2009
上传日期:2009-05-22
资源大小:495k
文件大小:7k
源码类别:

驱动编程

开发平台:

Unix_Linux

  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 <asm/semaphore.h>
  24. #include <asm/uaccess.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. char cms[LO_NAME_SIZE]; /* cipher-mode string */
  35. char *cipher;
  36. char *mode;
  37. char *cmsp = cms; /* c-m string pointer */
  38. struct crypto_tfm *tfm = NULL;
  39. /* encryption breaks for non sector aligned offsets */
  40. if (info->lo_offset % LOOP_IV_SECTOR_SIZE)
  41. goto out;
  42. strncpy(cms, info->lo_crypt_name, LO_NAME_SIZE);
  43. cms[LO_NAME_SIZE - 1] = 0;
  44. cipher = strsep(&cmsp, "-");
  45. mode = strsep(&cmsp, "-");
  46. if (mode == NULL || strcmp(mode, "cbc") == 0)
  47. tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_CBC |
  48.        CRYPTO_TFM_REQ_MAY_SLEEP);
  49. else if (strcmp(mode, "ecb") == 0)
  50. tfm = crypto_alloc_tfm(cipher, CRYPTO_TFM_MODE_ECB |
  51.        CRYPTO_TFM_REQ_MAY_SLEEP);
  52. if (tfm == NULL)
  53. return -EINVAL;
  54. err = tfm->crt_u.cipher.cit_setkey(tfm, info->lo_encrypt_key,
  55.    info->lo_encrypt_key_size);
  56. if (err != 0)
  57. goto out_free_tfm;
  58. lo->key_data = tfm;
  59. return 0;
  60.  out_free_tfm:
  61. crypto_free_tfm(tfm);
  62.  out:
  63. return err;
  64. }
  65. typedef int (*encdec_ecb_t)(struct crypto_tfm *tfm,
  66. struct scatterlist *sg_out,
  67. struct scatterlist *sg_in,
  68. unsigned int nsg);
  69. static int
  70. cryptoloop_transfer_ecb(struct loop_device *lo, int cmd,
  71. struct page *raw_page, unsigned raw_off,
  72. struct page *loop_page, unsigned loop_off,
  73. int size, sector_t IV)
  74. {
  75. struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
  76. struct scatterlist sg_out = { NULL, };
  77. struct scatterlist sg_in = { NULL, };
  78. encdec_ecb_t encdecfunc;
  79. struct page *in_page, *out_page;
  80. unsigned in_offs, out_offs;
  81. if (cmd == READ) {
  82. in_page = raw_page;
  83. in_offs = raw_off;
  84. out_page = loop_page;
  85. out_offs = loop_off;
  86. encdecfunc = tfm->crt_u.cipher.cit_decrypt;
  87. } else {
  88. in_page = loop_page;
  89. in_offs = loop_off;
  90. out_page = raw_page;
  91. out_offs = raw_off;
  92. encdecfunc = tfm->crt_u.cipher.cit_encrypt;
  93. }
  94. while (size > 0) {
  95. const int sz = min(size, LOOP_IV_SECTOR_SIZE);
  96. sg_in.page = in_page;
  97. sg_in.offset = in_offs;
  98. sg_in.length = sz;
  99. sg_out.page = out_page;
  100. sg_out.offset = out_offs;
  101. sg_out.length = sz;
  102. encdecfunc(tfm, &sg_out, &sg_in, sz);
  103. size -= sz;
  104. in_offs += sz;
  105. out_offs += sz;
  106. }
  107. return 0;
  108. }
  109. typedef int (*encdec_cbc_t)(struct crypto_tfm *tfm,
  110. struct scatterlist *sg_out,
  111. struct scatterlist *sg_in,
  112. unsigned int nsg, u8 *iv);
  113. static int
  114. cryptoloop_transfer_cbc(struct loop_device *lo, int cmd,
  115. struct page *raw_page, unsigned raw_off,
  116. struct page *loop_page, unsigned loop_off,
  117. int size, sector_t IV)
  118. {
  119. struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
  120. struct scatterlist sg_out = { NULL, };
  121. struct scatterlist sg_in = { NULL, };
  122. encdec_cbc_t encdecfunc;
  123. struct page *in_page, *out_page;
  124. unsigned in_offs, out_offs;
  125. if (cmd == READ) {
  126. in_page = raw_page;
  127. in_offs = raw_off;
  128. out_page = loop_page;
  129. out_offs = loop_off;
  130. encdecfunc = tfm->crt_u.cipher.cit_decrypt_iv;
  131. } else {
  132. in_page = loop_page;
  133. in_offs = loop_off;
  134. out_page = raw_page;
  135. out_offs = raw_off;
  136. encdecfunc = tfm->crt_u.cipher.cit_encrypt_iv;
  137. }
  138. while (size > 0) {
  139. const int sz = min(size, LOOP_IV_SECTOR_SIZE);
  140. u32 iv[4] = { 0, };
  141. iv[0] = cpu_to_le32(IV & 0xffffffff);
  142. sg_in.page = in_page;
  143. sg_in.offset = in_offs;
  144. sg_in.length = sz;
  145. sg_out.page = out_page;
  146. sg_out.offset = out_offs;
  147. sg_out.length = sz;
  148. encdecfunc(tfm, &sg_out, &sg_in, sz, (u8 *)iv);
  149. IV++;
  150. size -= sz;
  151. in_offs += sz;
  152. out_offs += sz;
  153. }
  154. return 0;
  155. }
  156. static int
  157. cryptoloop_transfer(struct loop_device *lo, int cmd,
  158.     struct page *raw_page, unsigned raw_off,
  159.     struct page *loop_page, unsigned loop_off,
  160.     int size, sector_t IV)
  161. {
  162. struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
  163. if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_ECB)
  164. {
  165. lo->transfer = cryptoloop_transfer_ecb;
  166. return cryptoloop_transfer_ecb(lo, cmd, raw_page, raw_off,
  167.        loop_page, loop_off, size, IV);
  168. }
  169. if(tfm->crt_cipher.cit_mode == CRYPTO_TFM_MODE_CBC)
  170. {
  171. lo->transfer = cryptoloop_transfer_cbc;
  172. return cryptoloop_transfer_cbc(lo, cmd, raw_page, raw_off,
  173.        loop_page, loop_off, size, IV);
  174. }
  175. /*  This is not supposed to happen */
  176. printk( KERN_ERR "cryptoloop: unsupported cipher mode in cryptoloop_transfer!n");
  177. return -EINVAL;
  178. }
  179. static int
  180. cryptoloop_ioctl(struct loop_device *lo, int cmd, unsigned long arg)
  181. {
  182. return -EINVAL;
  183. }
  184. static int
  185. cryptoloop_release(struct loop_device *lo)
  186. {
  187. struct crypto_tfm *tfm = (struct crypto_tfm *) lo->key_data;
  188. if (tfm != NULL) {
  189. crypto_free_tfm(tfm);
  190. lo->key_data = NULL;
  191. return 0;
  192. }
  193. printk(KERN_ERR "cryptoloop_release(): tfm == NULL?n");
  194. return -EINVAL;
  195. }
  196. static struct loop_func_table cryptoloop_funcs = {
  197. .number = LO_CRYPT_CRYPTOAPI,
  198. .init = cryptoloop_init,
  199. .ioctl = cryptoloop_ioctl,
  200. .transfer = cryptoloop_transfer,
  201. .release = cryptoloop_release,
  202. .owner = THIS_MODULE
  203. };
  204. static int __init
  205. init_cryptoloop(void)
  206. {
  207. int rc = loop_register_transfer(&cryptoloop_funcs);
  208. if (rc)
  209. printk(KERN_ERR "cryptoloop: loop_register_transfer failedn");
  210. return rc;
  211. }
  212. static void __exit
  213. cleanup_cryptoloop(void)
  214. {
  215. if (loop_unregister_transfer(LO_CRYPT_CRYPTOAPI))
  216. printk(KERN_ERR
  217. "cryptoloop: loop_unregister_transfer failedn");
  218. }
  219. module_init(init_cryptoloop);
  220. module_exit(cleanup_cryptoloop);