aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorMilan Broz <gmazyland@gmail.com>2013-10-28 18:21:03 -0400
committerMike Snitzer <snitzer@redhat.com>2013-11-09 18:20:20 -0500
commitda31a0787a2ac92dd219ce0d33322160b66d6a01 (patch)
tree01f47fbf8855b25ea85a7504dbb32569f712f293 /drivers/md
parent2c2263c93f70c6abdce90ad96a854760532aa52f (diff)
dm crypt: properly handle extra key string in initialization
Some encryption modes use extra keys (e.g. loopAES has IV seed) which are not used in block cipher initialization but are part of key string in table constructor. This patch adds an additional field which describes the length of the extra key(s) and substracts it before real key encryption setting. The key_size always includes the size, in bytes, of the key provided in mapping table. The key_parts describes how many parts (usually keys) are contained in the whole key buffer. And key_extra_size contains size in bytes of additional keys part (this number of bytes must be subtracted because it is processed by the IV generator). | K1 | K2 | .... | K64 | Kiv | |----------- key_size ----------------- | | |-key_extra_size-| | [64 keys] | [1 key] | => key_parts = 65 Example where key string contains main key K, whitening key Kw and IV seed Kiv: | K | Kiv | Kw | |--------------- key_size --------------| | |-----key_extra_size------| | [1 key] | [1 key] | [1 key] | => key_parts = 3 Because key_extra_size is calculated during IV mode setting, key initialization is moved after this step. For now, this change has no effect to supported modes (thanks to ilog2 rounding) but it is required by the following patch. Also, fix a sparse warning in crypt_iv_lmk_one(). Signed-off-by: Milan Broz <gmazyland@gmail.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-crypt.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 0fce0bc1a957..e0c61a326550 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -171,7 +171,8 @@ struct crypt_config {
171 171
172 unsigned long flags; 172 unsigned long flags;
173 unsigned int key_size; 173 unsigned int key_size;
174 unsigned int key_parts; 174 unsigned int key_parts; /* independent parts in key buffer */
175 unsigned int key_extra_size; /* additional keys length */
175 u8 key[0]; 176 u8 key[0];
176}; 177};
177 178
@@ -530,7 +531,7 @@ static int crypt_iv_lmk_one(struct crypt_config *cc, u8 *iv,
530 char ctx[crypto_shash_descsize(lmk->hash_tfm)]; 531 char ctx[crypto_shash_descsize(lmk->hash_tfm)];
531 } sdesc; 532 } sdesc;
532 struct md5_state md5state; 533 struct md5_state md5state;
533 u32 buf[4]; 534 __le32 buf[4];
534 int i, r; 535 int i, r;
535 536
536 sdesc.desc.tfm = lmk->hash_tfm; 537 sdesc.desc.tfm = lmk->hash_tfm;
@@ -1274,9 +1275,12 @@ static int crypt_alloc_tfms(struct crypt_config *cc, char *ciphermode)
1274 1275
1275static int crypt_setkey_allcpus(struct crypt_config *cc) 1276static int crypt_setkey_allcpus(struct crypt_config *cc)
1276{ 1277{
1277 unsigned subkey_size = cc->key_size >> ilog2(cc->tfms_count); 1278 unsigned subkey_size;
1278 int err = 0, i, r; 1279 int err = 0, i, r;
1279 1280
1281 /* Ignore extra keys (which are used for IV etc) */
1282 subkey_size = (cc->key_size - cc->key_extra_size) >> ilog2(cc->tfms_count);
1283
1280 for (i = 0; i < cc->tfms_count; i++) { 1284 for (i = 0; i < cc->tfms_count; i++) {
1281 r = crypto_ablkcipher_setkey(cc->tfms[i], 1285 r = crypto_ablkcipher_setkey(cc->tfms[i],
1282 cc->key + (i * subkey_size), 1286 cc->key + (i * subkey_size),
@@ -1409,6 +1413,7 @@ static int crypt_ctr_cipher(struct dm_target *ti,
1409 return -EINVAL; 1413 return -EINVAL;
1410 } 1414 }
1411 cc->key_parts = cc->tfms_count; 1415 cc->key_parts = cc->tfms_count;
1416 cc->key_extra_size = 0;
1412 1417
1413 cc->cipher = kstrdup(cipher, GFP_KERNEL); 1418 cc->cipher = kstrdup(cipher, GFP_KERNEL);
1414 if (!cc->cipher) 1419 if (!cc->cipher)
@@ -1460,13 +1465,6 @@ static int crypt_ctr_cipher(struct dm_target *ti,
1460 goto bad; 1465 goto bad;
1461 } 1466 }
1462 1467
1463 /* Initialize and set key */
1464 ret = crypt_set_key(cc, key);
1465 if (ret < 0) {
1466 ti->error = "Error decoding and setting key";
1467 goto bad;
1468 }
1469
1470 /* Initialize IV */ 1468 /* Initialize IV */
1471 cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc)); 1469 cc->iv_size = crypto_ablkcipher_ivsize(any_tfm(cc));
1472 if (cc->iv_size) 1470 if (cc->iv_size)
@@ -1497,14 +1495,23 @@ static int crypt_ctr_cipher(struct dm_target *ti,
1497 * to length of provided multi-key string. 1495 * to length of provided multi-key string.
1498 * If present (version 3), last key is used as IV seed. 1496 * If present (version 3), last key is used as IV seed.
1499 */ 1497 */
1500 if (cc->key_size % cc->key_parts) 1498 if (cc->key_size % cc->key_parts) {
1501 cc->key_parts++; 1499 cc->key_parts++;
1500 cc->key_extra_size = cc->key_size / cc->key_parts;
1501 }
1502 } else { 1502 } else {
1503 ret = -EINVAL; 1503 ret = -EINVAL;
1504 ti->error = "Invalid IV mode"; 1504 ti->error = "Invalid IV mode";
1505 goto bad; 1505 goto bad;
1506 } 1506 }
1507 1507
1508 /* Initialize and set key */
1509 ret = crypt_set_key(cc, key);
1510 if (ret < 0) {
1511 ti->error = "Error decoding and setting key";
1512 goto bad;
1513 }
1514
1508 /* Allocate IV */ 1515 /* Allocate IV */
1509 if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) { 1516 if (cc->iv_gen_ops && cc->iv_gen_ops->ctr) {
1510 ret = cc->iv_gen_ops->ctr(cc, ti, ivopts); 1517 ret = cc->iv_gen_ops->ctr(cc, ti, ivopts);