Commit 542da317 authored by Milan Broz's avatar Milan Broz Committed by Alasdair G Kergon

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: default avatarMilan Broz <mbroz@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent b95bf2d3
/* /*
* Copyright (C) 2003 Christophe Saout <christophe@saout.de> * Copyright (C) 2003 Christophe Saout <christophe@saout.de>
* Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org> * Copyright (C) 2004 Clemens Fruhwirth <clemens@endorphin.org>
* Copyright (C) 2006-2008 Red Hat, Inc. All rights reserved. * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved.
* *
* This file is released under the GPL. * This file is released under the GPL.
*/ */
...@@ -72,6 +72,7 @@ struct crypt_iv_operations { ...@@ -72,6 +72,7 @@ struct crypt_iv_operations {
const char *opts); const char *opts);
void (*dtr)(struct crypt_config *cc); void (*dtr)(struct crypt_config *cc);
int (*init)(struct crypt_config *cc); int (*init)(struct crypt_config *cc);
int (*wipe)(struct crypt_config *cc);
int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector); int (*generator)(struct crypt_config *cc, u8 *iv, sector_t sector);
}; };
...@@ -199,6 +200,17 @@ static int crypt_iv_essiv_init(struct crypt_config *cc) ...@@ -199,6 +200,17 @@ static int crypt_iv_essiv_init(struct crypt_config *cc)
crypto_hash_digestsize(essiv->hash_tfm)); crypto_hash_digestsize(essiv->hash_tfm));
} }
/* Wipe salt and reset key derived from volume key */
static int crypt_iv_essiv_wipe(struct crypt_config *cc)
{
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
unsigned salt_size = crypto_hash_digestsize(essiv->hash_tfm);
memset(essiv->salt, 0, salt_size);
return crypto_cipher_setkey(essiv->tfm, essiv->salt, salt_size);
}
static void crypt_iv_essiv_dtr(struct crypt_config *cc) static void crypt_iv_essiv_dtr(struct crypt_config *cc)
{ {
struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv; struct iv_essiv_private *essiv = &cc->iv_gen_private.essiv;
...@@ -334,6 +346,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = { ...@@ -334,6 +346,7 @@ static struct crypt_iv_operations crypt_iv_essiv_ops = {
.ctr = crypt_iv_essiv_ctr, .ctr = crypt_iv_essiv_ctr,
.dtr = crypt_iv_essiv_dtr, .dtr = crypt_iv_essiv_dtr,
.init = crypt_iv_essiv_init, .init = crypt_iv_essiv_init,
.wipe = crypt_iv_essiv_wipe,
.generator = crypt_iv_essiv_gen .generator = crypt_iv_essiv_gen
}; };
...@@ -1305,6 +1318,7 @@ static void crypt_resume(struct dm_target *ti) ...@@ -1305,6 +1318,7 @@ static void crypt_resume(struct dm_target *ti)
static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
{ {
struct crypt_config *cc = ti->private; struct crypt_config *cc = ti->private;
int ret = -EINVAL;
if (argc < 2) if (argc < 2)
goto error; goto error;
...@@ -1314,10 +1328,22 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv) ...@@ -1314,10 +1328,22 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
DMWARN("not suspended during key manipulation."); DMWARN("not suspended during key manipulation.");
return -EINVAL; return -EINVAL;
} }
if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) if (argc == 3 && !strnicmp(argv[1], MESG_STR("set"))) {
return crypt_set_key(cc, argv[2]); ret = crypt_set_key(cc, argv[2]);
if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) if (ret)
return ret;
if (cc->iv_gen_ops && cc->iv_gen_ops->init)
ret = cc->iv_gen_ops->init(cc);
return ret;
}
if (argc == 2 && !strnicmp(argv[1], MESG_STR("wipe"))) {
if (cc->iv_gen_ops && cc->iv_gen_ops->wipe) {
ret = cc->iv_gen_ops->wipe(cc);
if (ret)
return ret;
}
return crypt_wipe_key(cc); return crypt_wipe_key(cc);
}
} }
error: error:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment