diff options
author | Rik Snel <rsnel@cube.dyndns.org> | 2006-09-02 18:56:39 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-06 21:38:47 -0500 |
commit | 48527fa7cf7fefb84e9fe03cddd08ddafc9f15f3 (patch) | |
tree | 38062656a96888f3f5dbbf2d74073a0159a39f69 /drivers/md/dm-crypt.c | |
parent | 9fe757b0cfcee0724027a675c533077287a21b96 (diff) |
[BLOCK] dm-crypt: benbi IV, big endian narrow block count for LRW-32-AES
LRW-32-AES needs a certain IV. This IV should be provided dm-crypt.
The block cipher mode could, in principle generate the correct IV from
the plain IV, but I think that it is cleaner to supply the right IV
directly.
The sector -> narrow block calculation uses a shift for performance reasons.
This shift is computed in .ctr and stored in cc->iv_gen_private (as a void *).
Signed-off-by: Rik Snel <rsnel@cube.dyndns.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ed2d4ef27fd8..6dbaeee48ced 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <asm/atomic.h> | 20 | #include <asm/atomic.h> |
21 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
22 | #include <asm/page.h> | 22 | #include <asm/page.h> |
23 | #include <asm/unaligned.h> | ||
23 | 24 | ||
24 | #include "dm.h" | 25 | #include "dm.h" |
25 | 26 | ||
@@ -113,6 +114,9 @@ static kmem_cache_t *_crypt_io_pool; | |||
113 | * encrypted with the bulk cipher using a salt as key. The salt | 114 | * encrypted with the bulk cipher using a salt as key. The salt |
114 | * should be derived from the bulk cipher's key via hashing. | 115 | * should be derived from the bulk cipher's key via hashing. |
115 | * | 116 | * |
117 | * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1 | ||
118 | * (needed for LRW-32-AES and possible other narrow block modes) | ||
119 | * | ||
116 | * plumb: unimplemented, see: | 120 | * plumb: unimplemented, see: |
117 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 | 121 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 |
118 | */ | 122 | */ |
@@ -209,6 +213,44 @@ static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | |||
209 | return 0; | 213 | return 0; |
210 | } | 214 | } |
211 | 215 | ||
216 | static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, | ||
217 | const char *opts) | ||
218 | { | ||
219 | unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); | ||
220 | int log = long_log2(bs); | ||
221 | |||
222 | /* we need to calculate how far we must shift the sector count | ||
223 | * to get the cipher block count, we use this shift in _gen */ | ||
224 | |||
225 | if (1 << log != bs) { | ||
226 | ti->error = "cypher blocksize is not a power of 2"; | ||
227 | return -EINVAL; | ||
228 | } | ||
229 | |||
230 | if (log > 9) { | ||
231 | ti->error = "cypher blocksize is > 512"; | ||
232 | return -EINVAL; | ||
233 | } | ||
234 | |||
235 | cc->iv_gen_private = (void *)(9 - log); | ||
236 | |||
237 | return 0; | ||
238 | } | ||
239 | |||
240 | static void crypt_iv_benbi_dtr(struct crypt_config *cc) | ||
241 | { | ||
242 | cc->iv_gen_private = NULL; | ||
243 | } | ||
244 | |||
245 | static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | ||
246 | { | ||
247 | memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ | ||
248 | put_unaligned(cpu_to_be64(((u64)sector << (u32)cc->iv_gen_private) + 1), | ||
249 | (__be64 *)(iv + cc->iv_size - sizeof(u64))); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
212 | static struct crypt_iv_operations crypt_iv_plain_ops = { | 254 | static struct crypt_iv_operations crypt_iv_plain_ops = { |
213 | .generator = crypt_iv_plain_gen | 255 | .generator = crypt_iv_plain_gen |
214 | }; | 256 | }; |
@@ -219,6 +261,11 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { | |||
219 | .generator = crypt_iv_essiv_gen | 261 | .generator = crypt_iv_essiv_gen |
220 | }; | 262 | }; |
221 | 263 | ||
264 | static struct crypt_iv_operations crypt_iv_benbi_ops = { | ||
265 | .ctr = crypt_iv_benbi_ctr, | ||
266 | .dtr = crypt_iv_benbi_dtr, | ||
267 | .generator = crypt_iv_benbi_gen | ||
268 | }; | ||
222 | 269 | ||
223 | static int | 270 | static int |
224 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, | 271 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, |
@@ -768,7 +815,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
768 | cc->tfm = tfm; | 815 | cc->tfm = tfm; |
769 | 816 | ||
770 | /* | 817 | /* |
771 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>". | 818 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi". |
772 | * See comments at iv code | 819 | * See comments at iv code |
773 | */ | 820 | */ |
774 | 821 | ||
@@ -778,6 +825,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
778 | cc->iv_gen_ops = &crypt_iv_plain_ops; | 825 | cc->iv_gen_ops = &crypt_iv_plain_ops; |
779 | else if (strcmp(ivmode, "essiv") == 0) | 826 | else if (strcmp(ivmode, "essiv") == 0) |
780 | cc->iv_gen_ops = &crypt_iv_essiv_ops; | 827 | cc->iv_gen_ops = &crypt_iv_essiv_ops; |
828 | else if (strcmp(ivmode, "benbi") == 0) | ||
829 | cc->iv_gen_ops = &crypt_iv_benbi_ops; | ||
781 | else { | 830 | else { |
782 | ti->error = "Invalid IV mode"; | 831 | ti->error = "Invalid IV mode"; |
783 | goto bad2; | 832 | goto bad2; |