mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-11 19:00:02 +01:00
* Allow to activate by internally cached volume key
(format/activate without keyslots active - used for temporary devices). * Initialize volume key from active device in crypt_init_by_name() git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@365 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
@@ -2,6 +2,9 @@
|
|||||||
* Fix password callback call.
|
* Fix password callback call.
|
||||||
* Fix default plain password entry from terminal in activate_by_passphrase.
|
* Fix default plain password entry from terminal in activate_by_passphrase.
|
||||||
* Add --dump-master-key option for luksDump to allow volume key dump.
|
* Add --dump-master-key option for luksDump to allow volume key dump.
|
||||||
|
* Allow to activate by internally cached volume key
|
||||||
|
(format/activate without keyslots active - used for temporary devices).
|
||||||
|
* Initialize volume key from active device in crypt_init_by_name()
|
||||||
|
|
||||||
2010-11-01 Milan Broz <mbroz@redhat.com>
|
2010-11-01 Milan Broz <mbroz@redhat.com>
|
||||||
* No longer support luksDelKey, reload and --non-exclusive.
|
* No longer support luksDelKey, reload and --non-exclusive.
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ struct crypt_params_luks1 {
|
|||||||
* @cipher_mode - including IV specification (e.g. "xts-plain")
|
* @cipher_mode - including IV specification (e.g. "xts-plain")
|
||||||
* @uuid - requested UUID or NULL if it should be generated
|
* @uuid - requested UUID or NULL if it should be generated
|
||||||
* @volume_key - pre-generated volume key or NULL if it should be generated (only for LUKS)
|
* @volume_key - pre-generated volume key or NULL if it should be generated (only for LUKS)
|
||||||
* @volume_key_size - size og volume key in bytes.
|
* @volume_key_size - size of volume key in bytes.
|
||||||
* @params - crypt type specific parameters
|
* @params - crypt type specific parameters
|
||||||
*
|
*
|
||||||
* Note that crypt_format do not enable any keyslot, but it stores volume key internally
|
* Note that crypt_format do not enable any keyslot, but it stores volume key internally
|
||||||
@@ -439,9 +439,12 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
|
|||||||
*
|
*
|
||||||
* @cd - crypt device handle
|
* @cd - crypt device handle
|
||||||
* @name - name of device to create, if NULL only check volume key
|
* @name - name of device to create, if NULL only check volume key
|
||||||
* @volume_key - provided volume key
|
* @volume_key - provided volume key (or NULL to use internal)
|
||||||
* @volume_key_size - size of @volume_key
|
* @volume_key_size - size of @volume_key
|
||||||
* @flags - activation flags
|
* @flags - activation flags
|
||||||
|
*
|
||||||
|
* If NULL is used for volume_key, device has to be initialized
|
||||||
|
* by previous operation (like crypt_format() or crypt_init_by_name())
|
||||||
*/
|
*/
|
||||||
int crypt_activate_by_volume_key(struct crypt_device *cd,
|
int crypt_activate_by_volume_key(struct crypt_device *cd,
|
||||||
const char *name,
|
const char *name,
|
||||||
|
|||||||
78
lib/setup.c
78
lib/setup.c
@@ -482,8 +482,7 @@ static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslo
|
|||||||
|
|
||||||
*vk = NULL;
|
*vk = NULL;
|
||||||
do {
|
do {
|
||||||
if (*vk)
|
crypt_free_volume_key(*vk);
|
||||||
crypt_free_volume_key(*vk);
|
|
||||||
*vk = NULL;
|
*vk = NULL;
|
||||||
|
|
||||||
r = key_from_terminal(cd, NULL, &passphrase_read,
|
r = key_from_terminal(cd, NULL, &passphrase_read,
|
||||||
@@ -1019,6 +1018,7 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
|
|||||||
struct crypt_active_device cad;
|
struct crypt_active_device cad;
|
||||||
char *device = NULL, *cipher_full = NULL, *device_uuid = NULL;
|
char *device = NULL, *cipher_full = NULL, *device_uuid = NULL;
|
||||||
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
|
||||||
|
char *key = NULL;
|
||||||
int key_size = 0, r;
|
int key_size = 0, r;
|
||||||
|
|
||||||
|
|
||||||
@@ -1034,28 +1034,34 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
r = dm_query_device(name, &device, &cad.size, &cad.iv_offset, &cad.offset,
|
r = dm_query_device(name, &device, &cad.size, &cad.iv_offset, &cad.offset,
|
||||||
&cipher_full, &key_size, NULL, NULL, NULL,
|
&cipher_full, &key_size, &key, NULL, NULL,
|
||||||
&device_uuid);
|
&device_uuid);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Underlying device disappeared but mapping still active */
|
/* Underlying device disappeared but mapping still active */
|
||||||
if (r >= 0 && !device)
|
if (!device)
|
||||||
log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
|
log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
|
||||||
name);
|
name);
|
||||||
|
|
||||||
if (r >= 0)
|
*cd = NULL;
|
||||||
r = crypt_init(cd, device);
|
r = crypt_init(cd, device);
|
||||||
|
if (r < 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
/* Try to initialise basic parameters from active device */
|
/* Try to initialise basic parameters from active device */
|
||||||
if (!r && *device_uuid) {
|
if (device_uuid) {
|
||||||
if (!strncmp(CRYPT_PLAIN, device_uuid, sizeof(CRYPT_PLAIN)-1)) {
|
if (!strncmp(CRYPT_PLAIN, device_uuid, sizeof(CRYPT_PLAIN)-1)) {
|
||||||
(*cd)->type = strdup(CRYPT_PLAIN);
|
(*cd)->type = strdup(CRYPT_PLAIN);
|
||||||
(*cd)->plain_uuid = strdup(device_uuid);
|
(*cd)->plain_uuid = strdup(device_uuid);
|
||||||
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
|
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
|
||||||
(*cd)->plain_hdr.offset = cad.offset;
|
(*cd)->plain_hdr.offset = cad.offset;
|
||||||
(*cd)->plain_hdr.skip = cad.iv_offset;
|
(*cd)->plain_hdr.skip = cad.iv_offset;
|
||||||
(*cd)->volume_key = crypt_alloc_volume_key(key_size, NULL);
|
(*cd)->volume_key = crypt_alloc_volume_key(key_size, key);
|
||||||
if (!(*cd)->volume_key)
|
if (!(*cd)->volume_key) {
|
||||||
r = -ENOMEM;
|
r = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
r = crypt_parse_name_and_mode(cipher_full, cipher, cipher_mode);
|
r = crypt_parse_name_and_mode(cipher_full, cipher, cipher_mode);
|
||||||
if (!r) {
|
if (!r) {
|
||||||
@@ -1063,11 +1069,29 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
|
|||||||
(*cd)->plain_cipher_mode = strdup(cipher_mode);
|
(*cd)->plain_cipher_mode = strdup(cipher_mode);
|
||||||
}
|
}
|
||||||
} else if (!strncmp(CRYPT_LUKS1, device_uuid, sizeof(CRYPT_LUKS1)-1)) {
|
} else if (!strncmp(CRYPT_LUKS1, device_uuid, sizeof(CRYPT_LUKS1)-1)) {
|
||||||
if (device)
|
if (device) {
|
||||||
r = crypt_load(*cd, CRYPT_LUKS1, NULL);
|
if (crypt_load(*cd, CRYPT_LUKS1, NULL) < 0 ||
|
||||||
}
|
crypt_volume_key_verify(*cd, key, key_size) < 0) {
|
||||||
}
|
log_dbg("LUKS device header does not match active device.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*cd)->volume_key = crypt_alloc_volume_key(key_size, key);
|
||||||
|
if (!(*cd)->volume_key) {
|
||||||
|
r = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
log_dbg("Active device has no UUID set, some parameters are not set.");
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (r < 0) {
|
||||||
|
crypt_free(*cd);
|
||||||
|
*cd = NULL;
|
||||||
|
}
|
||||||
|
crypt_safe_free(key);
|
||||||
free(device);
|
free(device);
|
||||||
free(cipher_full);
|
free(cipher_full);
|
||||||
free(device_uuid);
|
free(device_uuid);
|
||||||
@@ -1363,8 +1387,7 @@ void crypt_free(struct crypt_device *cd)
|
|||||||
log_dbg("Releasing crypt device %s context.", cd->device);
|
log_dbg("Releasing crypt device %s context.", cd->device);
|
||||||
|
|
||||||
dm_exit();
|
dm_exit();
|
||||||
if (cd->volume_key)
|
crypt_free_volume_key(cd->volume_key);
|
||||||
crypt_free_volume_key(cd->volume_key);
|
|
||||||
|
|
||||||
free(cd->device);
|
free(cd->device);
|
||||||
free(cd->type);
|
free(cd->type);
|
||||||
@@ -1874,18 +1897,22 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
|
|||||||
|
|
||||||
log_dbg("Activating volume %s by volume key.", name);
|
log_dbg("Activating volume %s by volume key.", name);
|
||||||
|
|
||||||
if (!volume_key_size)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
/* use key directly, no hash */
|
/* use key directly, no hash */
|
||||||
if (isPLAIN(cd->type))
|
if (isPLAIN(cd->type)) {
|
||||||
|
if (!volume_key || !volume_key_size || !cd->volume_key ||
|
||||||
|
volume_key_size != cd->volume_key->keylength) {
|
||||||
|
log_err(cd, _("Incorrect volume key specified for plain device.\n"));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return create_device_helper(cd, name, NULL,
|
return create_device_helper(cd, name, NULL,
|
||||||
cd->plain_cipher, cd->plain_cipher_mode, NULL, volume_key, volume_key_size,
|
cd->plain_cipher, cd->plain_cipher_mode, NULL, volume_key, volume_key_size,
|
||||||
cd->volume_key->keylength, 0, cd->plain_hdr.skip,
|
cd->volume_key->keylength, 0, cd->plain_hdr.skip,
|
||||||
cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
|
cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!isLUKS(cd->type)) {
|
if (!isLUKS(cd->type)) {
|
||||||
log_err(cd, _("This operation is supported only for LUKS device.\n"));
|
log_err(cd, _("Device type is not properly initialised.\n"));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1899,6 +1926,16 @@ int crypt_activate_by_volume_key(struct crypt_device *cd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If key is not provided, try to use internal key */
|
||||||
|
if (!volume_key) {
|
||||||
|
if (!cd->volume_key) {
|
||||||
|
log_err(cd, _("Volume key does not match the volume.\n"));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
volume_key_size = cd->volume_key->keylength;
|
||||||
|
volume_key = cd->volume_key->key;
|
||||||
|
}
|
||||||
|
|
||||||
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
|
vk = crypt_alloc_volume_key(volume_key_size, volume_key);
|
||||||
if (!vk)
|
if (!vk)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -1950,7 +1987,6 @@ int crypt_deactivate(struct crypt_device *cd, const char *name)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
// misc helper functions
|
|
||||||
int crypt_volume_key_get(struct crypt_device *cd,
|
int crypt_volume_key_get(struct crypt_device *cd,
|
||||||
int keyslot,
|
int keyslot,
|
||||||
char *volume_key,
|
char *volume_key,
|
||||||
|
|||||||
@@ -811,6 +811,68 @@ static void AddDeviceLuks(void)
|
|||||||
crypt_free(cd);
|
crypt_free(cd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void UseTempVolumes(void)
|
||||||
|
{
|
||||||
|
struct crypt_device *cd;
|
||||||
|
struct crypt_params_plain params = {
|
||||||
|
.hash = "sha1",
|
||||||
|
.skip = 0,
|
||||||
|
.offset = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tepmporary device without keyslot but with on-disk LUKS header
|
||||||
|
OK_(crypt_init(&cd, DEVICE_2));
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "not yet formatted");
|
||||||
|
OK_(crypt_format(cd, CRYPT_LUKS1, "aes", "cbc-essiv:sha256", NULL, NULL, 16, NULL));
|
||||||
|
OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0));
|
||||||
|
EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
// Volume key is properly initialised from active device
|
||||||
|
OK_(crypt_init_by_name(&cd, CDEVICE_2));
|
||||||
|
OK_(crypt_deactivate(cd, CDEVICE_2));
|
||||||
|
OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0));
|
||||||
|
OK_(crypt_deactivate(cd, CDEVICE_2));
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
// Dirty checks: device without UUID
|
||||||
|
// we should be able to remove it but not manuipulate with it
|
||||||
|
system("dmsetup create " CDEVICE_2 " --table \""
|
||||||
|
"0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
|
||||||
|
DEVICE_2 " 2048\"");
|
||||||
|
OK_(crypt_init_by_name(&cd, CDEVICE_2));
|
||||||
|
OK_(crypt_deactivate(cd, CDEVICE_2));
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "No known device type");
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
// Dirty checks: device with UUID but LUKS header key fingerprint must fail)
|
||||||
|
system("dmsetup create " CDEVICE_2 " --table \""
|
||||||
|
"0 100 crypt aes-cbc-essiv:sha256 deadbabedeadbabedeadbabedeadbabe 0 "
|
||||||
|
DEVICE_2 " 2048\" "
|
||||||
|
"-u CRYPT-LUKS1-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa-ctest1");
|
||||||
|
OK_(crypt_init_by_name(&cd, CDEVICE_2));
|
||||||
|
OK_(crypt_deactivate(cd, CDEVICE_2));
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "wrong volume key");
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
// No slots
|
||||||
|
OK_(crypt_init(&cd, DEVICE_2));
|
||||||
|
OK_(crypt_load(cd, CRYPT_LUKS1, NULL));
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, NULL, 0, 0), "volume key is lost");
|
||||||
|
crypt_free(cd);
|
||||||
|
|
||||||
|
// Plain device
|
||||||
|
OK_(crypt_init(&cd, DEVICE_2));
|
||||||
|
OK_(crypt_format(cd, CRYPT_PLAIN, "aes", "cbc-essiv:sha256", NULL, NULL, 16, NULL));
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, NULL, "xxx", 3, 0), "cannot verify key with plain");
|
||||||
|
FAIL_(crypt_volume_key_verify(cd, "xxx", 3), "cannot verify key with plain");
|
||||||
|
FAIL_(crypt_activate_by_volume_key(cd, CDEVICE_2, "xxx", 3, 0), "wrong key lenght");
|
||||||
|
OK_(crypt_activate_by_volume_key(cd, CDEVICE_2, "volumekeyvolumek", 16, 0));
|
||||||
|
EQ_(crypt_status(cd, CDEVICE_2), CRYPT_ACTIVE);
|
||||||
|
OK_(crypt_deactivate(cd, CDEVICE_2));
|
||||||
|
crypt_free(cd);
|
||||||
|
}
|
||||||
|
|
||||||
// Check that gcrypt is properly initialised in format
|
// Check that gcrypt is properly initialised in format
|
||||||
static void NonFIPSAlg(void)
|
static void NonFIPSAlg(void)
|
||||||
{
|
{
|
||||||
@@ -892,6 +954,7 @@ int main (int argc, char *argv[])
|
|||||||
RUN_(AddDeviceLuks, "Format and use LUKS device");
|
RUN_(AddDeviceLuks, "Format and use LUKS device");
|
||||||
RUN_(UseLuksDevice, "Use pre-formated LUKS device");
|
RUN_(UseLuksDevice, "Use pre-formated LUKS device");
|
||||||
RUN_(SuspendDevice, "Suspend/Resume test");
|
RUN_(SuspendDevice, "Suspend/Resume test");
|
||||||
|
RUN_(UseTempVolumes, "Format and use temporary encrypted device");
|
||||||
|
|
||||||
RUN_(CallbacksTest, "API callbacks test");
|
RUN_(CallbacksTest, "API callbacks test");
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user