Commit 542da317668c35036e8471822a564b609d05af66

Authored by Milan Broz
Committed by Alasdair G Kergon
1 parent b95bf2d3d5

dm crypt: make wipe message also wipe essiv key

The "wipe key" message is used to wipe the volume key from memory
temporarily, for example when suspending to RAM.

But the initialisation vector in ESSIV mode is calculated from the
hashed volume key, so the wipe message should wipe this IV key too and
reinitialise it when the volume key is reinstated.

This patch adds an IV wipe method called from a wipe message callback.
ESSIV is then reinitialised using the init function added by the
last patch.

Cc: stable@kernel.org
Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

Showing 1 changed file with 30 additions and 4 deletions Side-by-side Diff

drivers/md/dm-crypt.c
1 1 /*
2 2 * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
3 3 * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
4   - * Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved.
  4 + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
5 5 *
6 6 * This file is released under the GPL.
7 7 */
... ... @@ -72,6 +72,7 @@
72 72 const char *opts);
73 73 void (*dtr)(struct crypt_config *cc);
74 74 int (*init)(struct crypt_config *cc);
  75 + int (*wipe)(struct crypt_config *cc);
75 76 int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
76 77 };
77 78  
... ... @@ -199,6 +200,17 @@
199 200 crypto_hash_digestsize(essiv->hash_tfm));
200 201 }
201 202  
  203 +/* Wipe salt and reset key derived from volume key */
  204 +static int crypt_iv_essiv_wipe(struct crypt_config *cc)
  205 +{
  206 + struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
  207 + unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
  208 +
  209 + memset(essiv->salt, 0, salt_size);
  210 +
  211 + return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size);
  212 +}
  213 +
202 214 static void crypt_iv_essiv_dtr(struct crypt_config *cc)
203 215 {
204 216 struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
... ... @@ -334,6 +346,7 @@
334 346 .ctr = crypt_iv_essiv_ctr,
335 347 .dtr = crypt_iv_essiv_dtr,
336 348 .init = crypt_iv_essiv_init,
  349 + .wipe = crypt_iv_essiv_wipe,
337 350 .generator = crypt_iv_essiv_gen
338 351 };
339 352  
... ... @@ -1305,6 +1318,7 @@
1305 1318 static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
1306 1319 {
1307 1320 struct crypt_config *cc = ti->private;
  1321 + int ret = -EINVAL;
1308 1322  
1309 1323 if (argc < 2)
1310 1324 goto error;
1311 1325  
... ... @@ -1314,10 +1328,22 @@
1314 1328 DMWARN("not suspended during key manipulation.");
1315 1329 return -EINVAL;
1316 1330 }
1317   - if (argc == 3 && !strnicmp(argv[1], MESG_STR("set")))
1318   - return crypt_set_key(cc, argv[2]);
1319   - if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe")))
  1331 + if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
  1332 + ret = crypt_set_key(cc, argv[2]);
  1333 + if (ret)
  1334 + return ret;
  1335 + if (cc->iv_gen_ops && cc->iv_gen_ops->init)
  1336 + ret = cc->iv_gen_ops->init(cc);
  1337 + return ret;
  1338 + }
  1339 + if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
  1340 + if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
  1341 + ret = cc->iv_gen_ops->wipe(cc);
  1342 + if (ret)
  1343 + return ret;
  1344 + }
1320 1345 return crypt_wipe_key(cc);
  1346 + }
1321 1347 }
1322 1348  
1323 1349 error: