From 5eda5f6a387c3c13ea4342874c73768e4e5e1f16 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Tue, 26 Nov 2024 22:34:15 +0100 Subject: [PATCH] Fix compatibility for older dmcrypt without integrity_key_size For older kernel an default HMAC key size we must not set integrity_key_size option. --- lib/internal.h | 2 +- lib/luks2/luks2_json_metadata.c | 2 +- lib/setup.c | 18 +++++++++++------- lib/utils_dm.h | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/lib/internal.h b/lib/internal.h index d959e34e..d10b8c95 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -221,7 +221,7 @@ int crypt_wipe_device(struct crypt_device *cd, /* Internal integrity helpers */ const char *crypt_get_integrity(struct crypt_device *cd); -int crypt_get_integrity_key_size(struct crypt_device *cd); +int crypt_get_integrity_key_size(struct crypt_device *cd, bool dm_compat); int crypt_get_integrity_tag_size(struct crypt_device *cd); int crypt_key_in_keyring(struct crypt_device *cd); diff --git a/lib/luks2/luks2_json_metadata.c b/lib/luks2/luks2_json_metadata.c index ebd4f0fe..13e04f31 100644 --- a/lib/luks2/luks2_json_metadata.c +++ b/lib/luks2/luks2_json_metadata.c @@ -2737,7 +2737,7 @@ int LUKS2_activate(struct crypt_device *cd, crypt_key, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), crypt_get_data_offset(cd), crypt_get_integrity(cd) ?: "none", - crypt_get_integrity_key_size(cd), crypt_get_integrity_tag_size(cd), + crypt_get_integrity_key_size(cd, true), crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); } else r = dm_linear_target_set(&dmd.segment, 0, diff --git a/lib/setup.c b/lib/setup.c index d52aa635..5da5f507 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -1562,7 +1562,7 @@ static int _init_by_name_integrity(struct crypt_device *cd, const char *name) if (tgt->u.integrity.journal_integrity_key) cd->u.integrity.params.journal_integrity_key_size = tgt->u.integrity.journal_integrity_key->keylength; if (tgt->u.integrity.journal_crypt_key) - cd->u.integrity.params.integrity_key_size = tgt->u.integrity.journal_crypt_key->keylength; + cd->u.integrity.params.journal_crypt_key_size = tgt->u.integrity.journal_crypt_key->keylength; MOVE_REF(cd->metadata_device, tgt->u.integrity.meta_device); } out: @@ -3756,7 +3756,7 @@ int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size) r = dm_crypt_target_set(&dmd.segment, 0, new_size, crypt_data_device(cd), tgt->u.crypt.vk, crypt_get_cipher_spec(cd), crypt_get_iv_offset(cd), crypt_get_data_offset(cd), - crypt_get_integrity(cd), crypt_get_integrity_key_size(cd), crypt_get_integrity_tag_size(cd), + crypt_get_integrity(cd), crypt_get_integrity_key_size(cd, true), crypt_get_integrity_tag_size(cd), crypt_get_sector_size(cd)); if (r < 0) goto out; @@ -6215,13 +6215,17 @@ const char *crypt_get_integrity(struct crypt_device *cd) } /* INTERNAL only */ -int crypt_get_integrity_key_size(struct crypt_device *cd) +int crypt_get_integrity_key_size(struct crypt_device *cd, bool dm_compat) { int key_size = 0; - if (isLUKS2(cd->type)) + if (isLUKS2(cd->type)) { key_size = INTEGRITY_key_size(crypt_get_integrity(cd), LUKS2_get_integrity_key_size(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT)); + if (dm_compat && key_size > 0 && + key_size == INTEGRITY_key_size(crypt_get_integrity(cd), 0)) + return 0; + } if (isINTEGRITY(cd->type) || !cd->type) key_size = INTEGRITY_key_size(crypt_get_integrity(cd), 0); @@ -6703,7 +6707,7 @@ int crypt_get_integrity_info(struct crypt_device *cd, ip->buffer_sectors = cd->u.integrity.params.buffer_sectors; ip->integrity = cd->u.integrity.params.integrity; - ip->integrity_key_size = crypt_get_integrity_key_size(cd); + ip->integrity_key_size = crypt_get_integrity_key_size(cd, false); ip->journal_integrity = cd->u.integrity.params.journal_integrity; ip->journal_integrity_key_size = cd->u.integrity.params.journal_integrity_key_size; @@ -6722,7 +6726,7 @@ int crypt_get_integrity_info(struct crypt_device *cd, ip->buffer_sectors = 0; // FIXME ip->integrity = LUKS2_get_integrity(&cd->u.luks2.hdr, CRYPT_DEFAULT_SEGMENT); - ip->integrity_key_size = crypt_get_integrity_key_size(cd); + ip->integrity_key_size = crypt_get_integrity_key_size(cd, false); ip->tag_size = INTEGRITY_tag_size(ip->integrity, crypt_get_cipher(cd), crypt_get_cipher_mode(cd)); ip->journal_integrity = NULL; @@ -6736,7 +6740,7 @@ int crypt_get_integrity_info(struct crypt_device *cd, } else if (!cd->type) { memset(ip, 0, sizeof(*ip)); ip->integrity = crypt_get_integrity(cd); - ip->integrity_key_size = crypt_get_integrity_key_size(cd); + ip->integrity_key_size = crypt_get_integrity_key_size(cd, false); ip->tag_size = crypt_get_integrity_tag_size(cd); } diff --git a/lib/utils_dm.h b/lib/utils_dm.h index 62d2227c..cdccb42e 100644 --- a/lib/utils_dm.h +++ b/lib/utils_dm.h @@ -110,7 +110,7 @@ struct dm_target { uint64_t iv_offset; /* IV initialisation sector */ uint32_t tag_size; /* additional on-disk tag size */ uint32_t sector_size; /* encryption sector size */ - uint32_t integrity_key_size; /* for wrapped key HMAC */ + uint32_t integrity_key_size; /* explicit integrity key size (HMAC), 0 for default */ } crypt; struct { struct device *hash_device;