diff options
author | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 12:05:15 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-07 12:05:15 -0500 |
commit | 2685b267bce34c9b66626cb11664509c32a761a5 (patch) | |
tree | ce8b4ad47b4a1aa1b0e7634298d63c4cb0ca46c5 /drivers/md/dm-crypt.c | |
parent | 4522d58275f124105819723e24e912c8e5bf3cdd (diff) | |
parent | 272491ef423b6976a230a998b10f46976aa91342 (diff) |
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: (48 commits)
[NETFILTER]: Fix non-ANSI func. decl.
[TG3]: Identify Serdes devices more clearly.
[TG3]: Use msleep.
[TG3]: Use netif_msg_*.
[TG3]: Allow partial speed advertisement.
[TG3]: Add TG3_FLG2_IS_NIC flag.
[TG3]: Add 5787F device ID.
[TG3]: Fix Phy loopback.
[WANROUTER]: Kill kmalloc debugging code.
[TCP] inet_twdr_hangman: Delete unnecessary memory barrier().
[NET]: Memory barrier cleanups
[IPSEC]: Fix inetpeer leak in ipv4 xfrm dst entries.
audit: disable ipsec auditing when CONFIG_AUDITSYSCALL=n
audit: Add auditing to ipsec
[IRDA] irlan: Fix compile warning when CONFIG_PROC_FS=n
[IrDA]: Incorrect TTP header reservation
[IrDA]: PXA FIR code device model conversion
[GENETLINK]: Fix misplaced command flags.
[NETLIK]: Add a pointer to the Generic Netlink wiki page.
[IPV6] RAW: Don't release unlocked sock.
...
Diffstat (limited to 'drivers/md/dm-crypt.c')
-rw-r--r-- | drivers/md/dm-crypt.c | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index c7bee4f2eedb..a1086ee8cccd 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 | ||
@@ -85,7 +86,10 @@ struct crypt_config { | |||
85 | */ | 86 | */ |
86 | struct crypt_iv_operations *iv_gen_ops; | 87 | struct crypt_iv_operations *iv_gen_ops; |
87 | char *iv_mode; | 88 | char *iv_mode; |
88 | struct crypto_cipher *iv_gen_private; | 89 | union { |
90 | struct crypto_cipher *essiv_tfm; | ||
91 | int benbi_shift; | ||
92 | } iv_gen_private; | ||
89 | sector_t iv_offset; | 93 | sector_t iv_offset; |
90 | unsigned int iv_size; | 94 | unsigned int iv_size; |
91 | 95 | ||
@@ -113,6 +117,9 @@ static struct kmem_cache *_crypt_io_pool; | |||
113 | * encrypted with the bulk cipher using a salt as key. The salt | 117 | * encrypted with the bulk cipher using a salt as key. The salt |
114 | * should be derived from the bulk cipher's key via hashing. | 118 | * should be derived from the bulk cipher's key via hashing. |
115 | * | 119 | * |
120 | * benbi: the 64-bit "big-endian 'narrow block'-count", starting at 1 | ||
121 | * (needed for LRW-32-AES and possible other narrow block modes) | ||
122 | * | ||
116 | * plumb: unimplemented, see: | 123 | * plumb: unimplemented, see: |
117 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 | 124 | * http://article.gmane.org/gmane.linux.kernel.device-mapper.dm-crypt/454 |
118 | */ | 125 | */ |
@@ -191,21 +198,61 @@ static int crypt_iv_essiv_ctr(struct crypt_config *cc, struct dm_target *ti, | |||
191 | } | 198 | } |
192 | kfree(salt); | 199 | kfree(salt); |
193 | 200 | ||
194 | cc->iv_gen_private = essiv_tfm; | 201 | cc->iv_gen_private.essiv_tfm = essiv_tfm; |
195 | return 0; | 202 | return 0; |
196 | } | 203 | } |
197 | 204 | ||
198 | static void crypt_iv_essiv_dtr(struct crypt_config *cc) | 205 | static void crypt_iv_essiv_dtr(struct crypt_config *cc) |
199 | { | 206 | { |
200 | crypto_free_cipher(cc->iv_gen_private); | 207 | crypto_free_cipher(cc->iv_gen_private.essiv_tfm); |
201 | cc->iv_gen_private = NULL; | 208 | cc->iv_gen_private.essiv_tfm = NULL; |
202 | } | 209 | } |
203 | 210 | ||
204 | static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | 211 | static int crypt_iv_essiv_gen(struct crypt_config *cc, u8 *iv, sector_t sector) |
205 | { | 212 | { |
206 | memset(iv, 0, cc->iv_size); | 213 | memset(iv, 0, cc->iv_size); |
207 | *(u64 *)iv = cpu_to_le64(sector); | 214 | *(u64 *)iv = cpu_to_le64(sector); |
208 | crypto_cipher_encrypt_one(cc->iv_gen_private, iv, iv); | 215 | crypto_cipher_encrypt_one(cc->iv_gen_private.essiv_tfm, iv, iv); |
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int crypt_iv_benbi_ctr(struct crypt_config *cc, struct dm_target *ti, | ||
220 | const char *opts) | ||
221 | { | ||
222 | unsigned int bs = crypto_blkcipher_blocksize(cc->tfm); | ||
223 | int log = long_log2(bs); | ||
224 | |||
225 | /* we need to calculate how far we must shift the sector count | ||
226 | * to get the cipher block count, we use this shift in _gen */ | ||
227 | |||
228 | if (1 << log != bs) { | ||
229 | ti->error = "cypher blocksize is not a power of 2"; | ||
230 | return -EINVAL; | ||
231 | } | ||
232 | |||
233 | if (log > 9) { | ||
234 | ti->error = "cypher blocksize is > 512"; | ||
235 | return -EINVAL; | ||
236 | } | ||
237 | |||
238 | cc->iv_gen_private.benbi_shift = 9 - log; | ||
239 | |||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static void crypt_iv_benbi_dtr(struct crypt_config *cc) | ||
244 | { | ||
245 | } | ||
246 | |||
247 | static int crypt_iv_benbi_gen(struct crypt_config *cc, u8 *iv, sector_t sector) | ||
248 | { | ||
249 | __be64 val; | ||
250 | |||
251 | memset(iv, 0, cc->iv_size - sizeof(u64)); /* rest is cleared below */ | ||
252 | |||
253 | val = cpu_to_be64(((u64)sector << cc->iv_gen_private.benbi_shift) + 1); | ||
254 | put_unaligned(val, (__be64 *)(iv + cc->iv_size - sizeof(u64))); | ||
255 | |||
209 | return 0; | 256 | return 0; |
210 | } | 257 | } |
211 | 258 | ||
@@ -219,13 +266,18 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { | |||
219 | .generator = crypt_iv_essiv_gen | 266 | .generator = crypt_iv_essiv_gen |
220 | }; | 267 | }; |
221 | 268 | ||
269 | static struct crypt_iv_operations crypt_iv_benbi_ops = { | ||
270 | .ctr = crypt_iv_benbi_ctr, | ||
271 | .dtr = crypt_iv_benbi_dtr, | ||
272 | .generator = crypt_iv_benbi_gen | ||
273 | }; | ||
222 | 274 | ||
223 | static int | 275 | static int |
224 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, | 276 | crypt_convert_scatterlist(struct crypt_config *cc, struct scatterlist *out, |
225 | struct scatterlist *in, unsigned int length, | 277 | struct scatterlist *in, unsigned int length, |
226 | int write, sector_t sector) | 278 | int write, sector_t sector) |
227 | { | 279 | { |
228 | u8 iv[cc->iv_size]; | 280 | u8 iv[cc->iv_size] __attribute__ ((aligned(__alignof__(u64)))); |
229 | struct blkcipher_desc desc = { | 281 | struct blkcipher_desc desc = { |
230 | .tfm = cc->tfm, | 282 | .tfm = cc->tfm, |
231 | .info = iv, | 283 | .info = iv, |
@@ -768,7 +820,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
768 | cc->tfm = tfm; | 820 | cc->tfm = tfm; |
769 | 821 | ||
770 | /* | 822 | /* |
771 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>". | 823 | * Choose ivmode. Valid modes: "plain", "essiv:<esshash>", "benbi". |
772 | * See comments at iv code | 824 | * See comments at iv code |
773 | */ | 825 | */ |
774 | 826 | ||
@@ -778,6 +830,8 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
778 | cc->iv_gen_ops = &crypt_iv_plain_ops; | 830 | cc->iv_gen_ops = &crypt_iv_plain_ops; |
779 | else if (strcmp(ivmode, "essiv") == 0) | 831 | else if (strcmp(ivmode, "essiv") == 0) |
780 | cc->iv_gen_ops = &crypt_iv_essiv_ops; | 832 | cc->iv_gen_ops = &crypt_iv_essiv_ops; |
833 | else if (strcmp(ivmode, "benbi") == 0) | ||
834 | cc->iv_gen_ops = &crypt_iv_benbi_ops; | ||
781 | else { | 835 | else { |
782 | ti->error = "Invalid IV mode"; | 836 | ti->error = "Invalid IV mode"; |
783 | goto bad2; | 837 | goto bad2; |