Add crypt_get_old_volume_key_size API.

It allows to get former (old) volume key size
from LUKS2 device in reencryption state when
there's at least one keyslot containing encrypted
volume key.
This commit is contained in:
Ondrej Kozina
2025-05-16 13:49:37 +02:00
committed by Milan Broz
parent 3dcb532bd3
commit 4e94c8d809
6 changed files with 73 additions and 0 deletions

View File

@@ -2034,6 +2034,19 @@ uint64_t crypt_get_iv_offset(struct crypt_device *cd);
*/ */
int crypt_get_volume_key_size(struct crypt_device *cd); int crypt_get_volume_key_size(struct crypt_device *cd);
/**
* Get size (in bytes) of old volume key for LUKS2 device in reencryption.
*
* @param cd crypt LUKS2 device handle
*
* @return old volume key size when device is in reencryption state
*
* @note For LUKS2, this function can be used only if there is at least
* one keyslot assigned to old data segment. Also with reencryption
* mode 'encrypt' there's no old volume key.
*/
int crypt_get_old_volume_key_size(struct crypt_device *cd);
/** /**
* Get size (in bytes) of encryption sector for crypt device. * Get size (in bytes) of encryption sector for crypt device.
* *

View File

@@ -192,4 +192,5 @@ CRYPTSETUP_2.8 {
crypt_keyslot_context_init_by_keyring; crypt_keyslot_context_init_by_keyring;
crypt_keyslot_context_init_by_vk_in_keyring; crypt_keyslot_context_init_by_vk_in_keyring;
crypt_reencrypt_init_by_keyslot_context; crypt_reencrypt_init_by_keyslot_context;
crypt_get_old_volume_key_size;
} CRYPTSETUP_2.7; } CRYPTSETUP_2.7;

View File

@@ -411,6 +411,7 @@ const char *LUKS2_get_integrity(struct luks2_hdr *hdr, int segment);
int LUKS2_get_integrity_key_size(struct luks2_hdr *hdr, int segment); int LUKS2_get_integrity_key_size(struct luks2_hdr *hdr, int segment);
int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr, int LUKS2_keyslot_params_default(struct crypt_device *cd, struct luks2_hdr *hdr,
struct luks2_keyslot_params *params); struct luks2_keyslot_params *params);
int LUKS2_get_old_volume_key_size(struct luks2_hdr *hdr);
int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment); int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment);
int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot); int LUKS2_get_keyslot_stored_key_size(struct luks2_hdr *hdr, int keyslot);
const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size); const char *LUKS2_get_keyslot_cipher(struct luks2_hdr *hdr, int keyslot, size_t *key_size);

View File

@@ -2461,6 +2461,19 @@ int LUKS2_get_volume_key_size(struct luks2_hdr *hdr, int segment)
return -1; return -1;
} }
int LUKS2_get_old_volume_key_size(struct luks2_hdr *hdr)
{
int old_segment;
assert(hdr);
old_segment = LUKS2_reencrypt_segment_old(hdr);
if (old_segment < 0)
return old_segment;
return LUKS2_get_volume_key_size(hdr, old_segment);
}
uint32_t LUKS2_get_sector_size(struct luks2_hdr *hdr) uint32_t LUKS2_get_sector_size(struct luks2_hdr *hdr)
{ {
return json_segment_get_sector_size(LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT)); return json_segment_get_sector_size(LUKS2_get_segment_jobj(hdr, CRYPT_DEFAULT_SEGMENT));

View File

@@ -6413,6 +6413,19 @@ int crypt_get_volume_key_size(struct crypt_device *cd)
return 0; return 0;
} }
int crypt_get_old_volume_key_size(struct crypt_device *cd)
{
int r = _onlyLUKS2(cd, CRYPT_CD_QUIET,
CRYPT_REQUIREMENT_ONLINE_REENCRYPT | CRYPT_REQUIREMENT_OPAL);
if (r < 0)
return 0;
r = LUKS2_get_old_volume_key_size(&cd->u.luks2.hdr);
return r < 0 ? 0 : r;
}
int crypt_get_hw_encryption_key_size(struct crypt_device *cd) int crypt_get_hw_encryption_key_size(struct crypt_device *cd)
{ {
if (!cd || !isLUKS2(cd->type)) if (!cd || !isLUKS2(cd->type))

View File

@@ -4201,6 +4201,7 @@ static void Luks2Reencryption(void)
EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT); EQ_(getflags & CRYPT_REQUIREMENT_ONLINE_REENCRYPT, CRYPT_REQUIREMENT_ONLINE_REENCRYPT);
/* some parameters are expected to change immediately after reencryption initialization */ /* some parameters are expected to change immediately after reencryption initialization */
EQ_(crypt_get_old_volume_key_size(cd), 32);
EQ_(crypt_get_volume_key_size(cd), 64); EQ_(crypt_get_volume_key_size(cd), 64);
OK_(strcmp(crypt_get_cipher_mode(cd), "xts-plain64")); OK_(strcmp(crypt_get_cipher_mode(cd), "xts-plain64"));
EQ_(crypt_get_sector_size(cd), 4096); EQ_(crypt_get_sector_size(cd), 4096);
@@ -4402,6 +4403,34 @@ static void Luks2Reencryption(void)
CRYPT_FREE(cd); CRYPT_FREE(cd);
CRYPT_FREE(cd2); CRYPT_FREE(cd2);
/* same key size reencryption */
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
OK_(crypt_set_pbkdf_type(cd, &pbkdf));
EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
EQ_(crypt_keyslot_add_by_key(cd, 10, NULL, 32, PASSPHRASE, strlen(PASSPHRASE), CRYPT_VOLUME_KEY_NO_SEGMENT), 10);
rparams = (struct crypt_params_reencrypt) {
.mode = CRYPT_REENCRYPT_REENCRYPT,
.direction = CRYPT_REENCRYPT_FORWARD,
.resilience = "none",
.flags = CRYPT_REENCRYPT_INITIALIZE_ONLY
};
rparams.luks2 = &(struct crypt_params_luks2){ .sector_size = 512 };
NOTFAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 10, "aes", "xts-plain64", &rparams), "Failed to initialize reencryption");
EQ_(crypt_get_volume_key_size(cd), 32);
EQ_(crypt_get_old_volume_key_size(cd), 32);
CRYPT_FREE(cd);
/* same key reencryption */
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
OK_(crypt_format(cd, CRYPT_LUKS2, "aes", "cbc-essiv:sha256", NULL, NULL, 32, &params2));
OK_(crypt_set_pbkdf_type(cd, &pbkdf));
EQ_(crypt_keyslot_add_by_volume_key(cd, 0, NULL, 32, PASSPHRASE, strlen(PASSPHRASE)), 0);
NOTFAIL_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 0, 0, "aes", "xts-plain64", &rparams), "Failed to initialize reencryption");
EQ_(crypt_get_volume_key_size(cd), 32);
EQ_(crypt_get_old_volume_key_size(cd), 32);
CRYPT_FREE(cd);
/* data shift related tests */ /* data shift related tests */
params2.sector_size = 512; params2.sector_size = 512;
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
@@ -4517,6 +4546,8 @@ static void Luks2Reencryption(void)
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));
OK_(crypt_load(cd, CRYPT_LUKS2, NULL)); OK_(crypt_load(cd, CRYPT_LUKS2, NULL));
EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN); EQ_(crypt_reencrypt_status(cd, &retparams), CRYPT_REENCRYPT_CLEAN);
/* With encryption there's no old volume key */
EQ_(crypt_get_old_volume_key_size(cd), 0);
EQ_(retparams.mode, CRYPT_REENCRYPT_ENCRYPT); EQ_(retparams.mode, CRYPT_REENCRYPT_ENCRYPT);
OK_(strcmp(retparams.resilience, "datashift")); OK_(strcmp(retparams.resilience, "datashift"));
EQ_(retparams.data_shift, 8192); EQ_(retparams.data_shift, 8192);
@@ -4632,6 +4663,7 @@ static void Luks2Reencryption(void)
rparams.resilience = "none"; rparams.resilience = "none";
rparams.max_hotzone_size = 2048; rparams.max_hotzone_size = 2048;
OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams)); OK_(crypt_reencrypt_init_by_passphrase(cd, NULL, PASSPHRASE, strlen(PASSPHRASE), 6, CRYPT_ANY_SLOT, NULL, NULL, &rparams));
EQ_(crypt_get_old_volume_key_size(cd), 32);
OK_(crypt_reencrypt_run(cd, NULL, NULL)); OK_(crypt_reencrypt_run(cd, NULL, NULL));
CRYPT_FREE(cd); CRYPT_FREE(cd);
OK_(crypt_init(&cd, DMDIR L_DEVICE_OK)); OK_(crypt_init(&cd, DMDIR L_DEVICE_OK));