[dm-devel] [PATCH] dm crypt: wipe kernel key copy after IV initialization
Milan Broz
gmazyland at gmail.com
Mon Jan 15 09:58:12 UTC 2018
On 01/12/2018 04:30 PM, Ondrej Kozina wrote:
> Loading key via kernel keyring service we erase internal
> key copy immediately after we pass it in crypto layer. This is
> wrong because IV is initialised later and we use wrong key
> for the initialization (instead of real key there's just zeroed
> block).
>
> The bug may cause data corruption if key is loaded via kernel keyring
> service first and later same crypt device is reactivated using exactly
> same key in hexbyte representation, or vice versa. The bug (and fix)
> affects only ciphers using following IVs: essiv, lmk and tcw.
>
> Fixes: c538f6ec9f56 ("dm crypt: add ability to use keys from the kernel
> key retention service")
> Signed-off-by: Ondrej Kozina <okozina at redhat.com>
Reviewed-by: Milan Broz <gmazyland at gmail.com>
Mike, this patch should go into 4.15 final.
Actually I think this is the second most serious data corruption fix for dm-crypt
in the last years (the first one was wonderful RAID readahead bug we fixed "by mistake"
just by reordering code :-)
Once it is in mainline, we can release cryptsetup2 that disables using of keyring
for older kernels.
Thanks,
Milan
> ---
> drivers/md/dm-crypt.c | 12 ++++++++----
> 1 file changed, 8 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index 9fc12f5..334b0a3 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -2053,9 +2053,6 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string
>
> ret = crypt_setkey(cc);
>
> - /* wipe the kernel key payload copy in each case */
> - memset(cc->key, 0, cc->key_size * sizeof(u8));
> -
> if (!ret) {
> set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
> kzfree(cc->key_string);
> @@ -2523,6 +2520,10 @@ static int crypt_ctr_cipher(struct dm_target *ti, char *cipher_in, char *key)
> }
> }
>
> + /* wipe the kernel key payload copy */
> + if (cc->key_string)
> + memset(cc->key, 0, cc->key_size * sizeof(u8));
> +
> return ret;
> }
>
> @@ -2961,6 +2962,9 @@ static int crypt_message(struct dm_target *ti, unsigned argc, char **argv)
> return ret;
> if (cc->iv_gen_ops && cc->iv_gen_ops->init)
> ret = cc->iv_gen_ops->init(cc);
> + /* wipe the kernel key payload copy */
> + if (cc->key_string)
> + memset(cc->key, 0, cc->key_size * sizeof(u8));
> return ret;
> }
> if (argc == 2 && !strcasecmp(argv[1], "wipe")) {
> @@ -3007,7 +3011,7 @@ static void crypt_io_hints(struct dm_target *ti, struct queue_limits *limits)
>
> static struct target_type crypt_target = {
> .name = "crypt",
> - .version = {1, 18, 0},
> + .version = {1, 18, 1},
> .module = THIS_MODULE,
> .ctr = crypt_ctr,
> .dtr = crypt_dtr,
>
More information about the dm-devel
mailing list