mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-13 20:00:08 +01:00
Add support for verity in crypt_volume_key_get and use it in status
Other APIs use the root hash in place of keys when using verity devices, so do the same for crypt_volume_key_get to allow users to retrieve the root hash of an active verity device. Use it in veritysetup status to print the root hash. [Patch slightly modified by Milan Broz]
This commit is contained in:
committed by
Milan Broz
parent
35c49ababf
commit
188cb114af
@@ -1360,6 +1360,7 @@ int crypt_deactivate(struct crypt_device *cd, const char *name);
|
|||||||
*
|
*
|
||||||
* @note For TCRYPT cipher chain is the volume key concatenated
|
* @note For TCRYPT cipher chain is the volume key concatenated
|
||||||
* for all ciphers in chain.
|
* for all ciphers in chain.
|
||||||
|
* @note For VERITY the volume key means root hash used for activation.
|
||||||
*/
|
*/
|
||||||
int crypt_volume_key_get(struct crypt_device *cd,
|
int crypt_volume_key_get(struct crypt_device *cd,
|
||||||
int keyslot,
|
int keyslot,
|
||||||
|
|||||||
29
lib/setup.c
29
lib/setup.c
@@ -97,7 +97,7 @@ struct crypt_device {
|
|||||||
} loopaes;
|
} loopaes;
|
||||||
struct { /* used in CRYPT_VERITY */
|
struct { /* used in CRYPT_VERITY */
|
||||||
struct crypt_params_verity hdr;
|
struct crypt_params_verity hdr;
|
||||||
char *root_hash;
|
const char *root_hash;
|
||||||
unsigned int root_hash_size;
|
unsigned int root_hash_size;
|
||||||
char *uuid;
|
char *uuid;
|
||||||
struct device *fec_device;
|
struct device *fec_device;
|
||||||
@@ -1126,7 +1126,7 @@ static void crypt_free_type(struct crypt_device *cd)
|
|||||||
free(CONST_CAST(void*)cd->u.verity.hdr.hash_device);
|
free(CONST_CAST(void*)cd->u.verity.hdr.hash_device);
|
||||||
free(CONST_CAST(void*)cd->u.verity.hdr.fec_device);
|
free(CONST_CAST(void*)cd->u.verity.hdr.fec_device);
|
||||||
free(CONST_CAST(void*)cd->u.verity.hdr.salt);
|
free(CONST_CAST(void*)cd->u.verity.hdr.salt);
|
||||||
free(cd->u.verity.root_hash);
|
free(CONST_CAST(void*)cd->u.verity.root_hash);
|
||||||
free(cd->u.verity.uuid);
|
free(cd->u.verity.uuid);
|
||||||
device_free(cd, cd->u.verity.fec_device);
|
device_free(cd, cd->u.verity.fec_device);
|
||||||
} else if (isINTEGRITY(cd->type)) {
|
} else if (isINTEGRITY(cd->type)) {
|
||||||
@@ -1314,6 +1314,7 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
|
|||||||
r = dm_query_device(cd, name,
|
r = dm_query_device(cd, name,
|
||||||
DM_ACTIVE_DEVICE |
|
DM_ACTIVE_DEVICE |
|
||||||
DM_ACTIVE_VERITY_HASH_DEVICE |
|
DM_ACTIVE_VERITY_HASH_DEVICE |
|
||||||
|
DM_ACTIVE_VERITY_ROOT_HASH |
|
||||||
DM_ACTIVE_VERITY_PARAMS, &dmd);
|
DM_ACTIVE_VERITY_PARAMS, &dmd);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
@@ -1345,6 +1346,7 @@ static int _init_by_name_verity(struct crypt_device *cd, const char *name)
|
|||||||
cd->u.verity.hdr.fec_roots = tgt->u.verity.vp->fec_roots;
|
cd->u.verity.hdr.fec_roots = tgt->u.verity.vp->fec_roots;
|
||||||
MOVE_REF(cd->u.verity.fec_device, tgt->u.verity.fec_device);
|
MOVE_REF(cd->u.verity.fec_device, tgt->u.verity.fec_device);
|
||||||
MOVE_REF(cd->metadata_device, tgt->u.verity.hash_device);
|
MOVE_REF(cd->metadata_device, tgt->u.verity.hash_device);
|
||||||
|
MOVE_REF(cd->u.verity.root_hash, tgt->u.verity.root_hash);
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
dm_targets_free(cd, &dmd);
|
dm_targets_free(cd, &dmd);
|
||||||
@@ -4333,18 +4335,17 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(CONST_CAST(void*)cd->u.verity.root_hash);
|
||||||
|
cd->u.verity.root_hash = NULL;
|
||||||
|
|
||||||
r = VERITY_activate(cd, name, volume_key, volume_key_size, cd->u.verity.fec_device,
|
r = VERITY_activate(cd, name, volume_key, volume_key_size, cd->u.verity.fec_device,
|
||||||
&cd->u.verity.hdr, flags|CRYPT_ACTIVATE_READONLY);
|
&cd->u.verity.hdr, flags|CRYPT_ACTIVATE_READONLY);
|
||||||
|
|
||||||
if (r == -EPERM) {
|
if (!r) {
|
||||||
free(cd->u.verity.root_hash);
|
|
||||||
cd->u.verity.root_hash = NULL;
|
|
||||||
} if (!r) {
|
|
||||||
cd->u.verity.root_hash_size = volume_key_size;
|
cd->u.verity.root_hash_size = volume_key_size;
|
||||||
if (!cd->u.verity.root_hash)
|
|
||||||
cd->u.verity.root_hash = malloc(volume_key_size);
|
cd->u.verity.root_hash = malloc(volume_key_size);
|
||||||
if (cd->u.verity.root_hash)
|
if (cd->u.verity.root_hash)
|
||||||
memcpy(cd->u.verity.root_hash, volume_key, volume_key_size);
|
memcpy(CONST_CAST(void*)cd->u.verity.root_hash, volume_key, volume_key_size);
|
||||||
}
|
}
|
||||||
} else if (isTCRYPT(cd->type)) {
|
} else if (isTCRYPT(cd->type)) {
|
||||||
if (!name)
|
if (!name)
|
||||||
@@ -4534,7 +4535,7 @@ int crypt_volume_key_get(struct crypt_device *cd,
|
|||||||
struct volume_key *vk = NULL;
|
struct volume_key *vk = NULL;
|
||||||
int key_len, r = -EINVAL;
|
int key_len, r = -EINVAL;
|
||||||
|
|
||||||
if (!cd || !volume_key || !volume_key_size || (!isTCRYPT(cd->type) && !passphrase))
|
if (!cd || !volume_key || !volume_key_size || (!isTCRYPT(cd->type) && !isVERITY(cd->type) && !passphrase))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (isLUKS2(cd->type) && keyslot != CRYPT_ANY_SLOT)
|
if (isLUKS2(cd->type) && keyslot != CRYPT_ANY_SLOT)
|
||||||
@@ -4564,10 +4565,18 @@ int crypt_volume_key_get(struct crypt_device *cd,
|
|||||||
passphrase, passphrase_size, &vk);
|
passphrase, passphrase_size, &vk);
|
||||||
} else if (isTCRYPT(cd->type)) {
|
} else if (isTCRYPT(cd->type)) {
|
||||||
r = TCRYPT_get_volume_key(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, &vk);
|
r = TCRYPT_get_volume_key(cd, &cd->u.tcrypt.hdr, &cd->u.tcrypt.params, &vk);
|
||||||
|
} else if (isVERITY(cd->type)) {
|
||||||
|
/* volume_key == root hash */
|
||||||
|
if (cd->u.verity.root_hash) {
|
||||||
|
memcpy(volume_key, cd->u.verity.root_hash, cd->u.verity.root_hash_size);
|
||||||
|
*volume_key_size = cd->u.verity.root_hash_size;
|
||||||
|
r = 0;
|
||||||
|
} else
|
||||||
|
log_err(cd, _("Cannot retrieve root hash for verity device."));
|
||||||
} else
|
} else
|
||||||
log_err(cd, _("This operation is not supported for %s crypt device."), cd->type ?: "(none)");
|
log_err(cd, _("This operation is not supported for %s crypt device."), cd->type ?: "(none)");
|
||||||
|
|
||||||
if (r >= 0) {
|
if (r >= 0 && vk) {
|
||||||
memcpy(volume_key, vk->key, vk->keylength);
|
memcpy(volume_key, vk->key, vk->keylength);
|
||||||
*volume_key_size = vk->keylength;
|
*volume_key_size = vk->keylength;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ int VERITY_verify(struct crypt_device *cd,
|
|||||||
|
|
||||||
int VERITY_create(struct crypt_device *cd,
|
int VERITY_create(struct crypt_device *cd,
|
||||||
struct crypt_params_verity *verity_hdr,
|
struct crypt_params_verity *verity_hdr,
|
||||||
char *root_hash,
|
const char *root_hash,
|
||||||
size_t root_hash_size);
|
size_t root_hash_size);
|
||||||
|
|
||||||
int VERITY_FEC_process(struct crypt_device *cd,
|
int VERITY_FEC_process(struct crypt_device *cd,
|
||||||
|
|||||||
@@ -418,7 +418,7 @@ int VERITY_verify(struct crypt_device *cd,
|
|||||||
/* Create verity hash */
|
/* Create verity hash */
|
||||||
int VERITY_create(struct crypt_device *cd,
|
int VERITY_create(struct crypt_device *cd,
|
||||||
struct crypt_params_verity *verity_hdr,
|
struct crypt_params_verity *verity_hdr,
|
||||||
char *root_hash,
|
const char *root_hash,
|
||||||
size_t root_hash_size)
|
size_t root_hash_size)
|
||||||
{
|
{
|
||||||
unsigned pgsize = (unsigned)crypt_getpagesize();
|
unsigned pgsize = (unsigned)crypt_getpagesize();
|
||||||
@@ -439,7 +439,7 @@ int VERITY_create(struct crypt_device *cd,
|
|||||||
verity_hdr->data_block_size,
|
verity_hdr->data_block_size,
|
||||||
verity_hdr->data_size,
|
verity_hdr->data_size,
|
||||||
VERITY_hash_offset_block(verity_hdr),
|
VERITY_hash_offset_block(verity_hdr),
|
||||||
root_hash,
|
CONST_CAST(char*)root_hash,
|
||||||
root_hash_size,
|
root_hash_size,
|
||||||
verity_hdr->salt,
|
verity_hdr->salt,
|
||||||
verity_hdr->salt_size);
|
verity_hdr->salt_size);
|
||||||
|
|||||||
@@ -225,7 +225,8 @@ static int action_status(int arg)
|
|||||||
struct crypt_params_verity vp = {};
|
struct crypt_params_verity vp = {};
|
||||||
struct crypt_device *cd = NULL;
|
struct crypt_device *cd = NULL;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
char *backing_file;
|
char *backing_file, *root_hash;
|
||||||
|
size_t root_hash_size;
|
||||||
unsigned i, path = 0;
|
unsigned i, path = 0;
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
@@ -311,6 +312,19 @@ static int action_status(int arg)
|
|||||||
vp.fec_area_offset * vp.hash_block_size / 512);
|
vp.fec_area_offset * vp.hash_block_size / 512);
|
||||||
log_std(" FEC roots: %u\n", vp.fec_roots);
|
log_std(" FEC roots: %u\n", vp.fec_roots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
root_hash_size = crypt_get_volume_key_size(cd);
|
||||||
|
if (root_hash_size > 0 && (root_hash = malloc(root_hash_size))) {
|
||||||
|
r = crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash, &root_hash_size, NULL, 0);
|
||||||
|
if (!r) {
|
||||||
|
log_std(" root hash: ");
|
||||||
|
for (i = 0; i < root_hash_size; i++)
|
||||||
|
log_std("%02hhx", (const char)root_hash[i]);
|
||||||
|
log_std("\n");
|
||||||
|
}
|
||||||
|
free(root_hash);
|
||||||
|
}
|
||||||
|
|
||||||
if (cad.flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
|
if (cad.flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
|
||||||
CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
|
CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
|
||||||
CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
|
CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
|
||||||
|
|||||||
@@ -1570,7 +1570,8 @@ static void VerityTest(void)
|
|||||||
{
|
{
|
||||||
const char *salt_hex = "20c28ffc129c12360ba6ceea2b6cf04e89c2b41cfe6b8439eb53c1897f50df7b";
|
const char *salt_hex = "20c28ffc129c12360ba6ceea2b6cf04e89c2b41cfe6b8439eb53c1897f50df7b";
|
||||||
const char *root_hex = "ab018b003a967fc782effb293b6dccb60b4f40c06bf80d16391acf686d28b5d6";
|
const char *root_hex = "ab018b003a967fc782effb293b6dccb60b4f40c06bf80d16391acf686d28b5d6";
|
||||||
char salt[256], root_hash[256];
|
char salt[256], root_hash[256], root_hash_out[256];
|
||||||
|
size_t root_hash_out_size = 256;
|
||||||
struct crypt_active_device cad;
|
struct crypt_active_device cad;
|
||||||
struct crypt_params_verity params = {
|
struct crypt_params_verity params = {
|
||||||
.data_device = DEVICE_EMPTY,
|
.data_device = DEVICE_EMPTY,
|
||||||
@@ -1657,6 +1658,10 @@ static void VerityTest(void)
|
|||||||
CRYPT_FREE(cd);
|
CRYPT_FREE(cd);
|
||||||
|
|
||||||
OK_(crypt_init_by_name(&cd, CDEVICE_1));
|
OK_(crypt_init_by_name(&cd, CDEVICE_1));
|
||||||
|
memset(root_hash_out, 0, root_hash_out_size);
|
||||||
|
OK_(crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_out, &root_hash_out_size, NULL, 0));
|
||||||
|
EQ_(32, root_hash_out_size);
|
||||||
|
OK_(memcmp(root_hash, root_hash_out, root_hash_out_size));
|
||||||
OK_(crypt_deactivate(cd, CDEVICE_1));
|
OK_(crypt_deactivate(cd, CDEVICE_1));
|
||||||
|
|
||||||
/* hash fail */
|
/* hash fail */
|
||||||
|
|||||||
Reference in New Issue
Block a user