* Add --header option for detached metadata (on-disk LUKS header) device.

* Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@575 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2011-07-20 17:39:26 +00:00
parent 1bf26b9a90
commit f7f9e291f4
6 changed files with 213 additions and 88 deletions

View File

@@ -3,6 +3,8 @@
* Do not allow key retrieval while suspended (key could be wiped).
* Do not allow suspend for non-LUKS devices.
* Support retries and timeout parameters for luksSuspend.
* Add --header option for detached metadata (on-disk LUKS header) device.
* Add crypt_init_by_name_and_header() and crypt_set_data_device() to API.
2011-07-07 Milan Broz <mbroz@redhat.com>
* Remove old API functions (all functions using crypt_options).

View File

@@ -22,14 +22,23 @@ struct crypt_device; /* crypt device handle */
int crypt_init(struct crypt_device **cd, const char *device);
/**
* Initialise crypt device handle from provided active device name
* Initialise crypt device handle from provided active device name,
* and, optionally, from separate metadata (header) device
* and check if provided device exists.
*
* Returns 0 on success or negative errno value otherwise.
*
* @cd - crypt device handle
* @name - name of active crypt device
* @header_device - optional device containing on-disk header
* (NULL if it the same as underlying device on there is no on-disk header)
*
* crypt_init_by_name is quivalent to calling
* crypt_init_by_name_and_header(cd, name, NULL);
*/
int crypt_init_by_name_and_header(struct crypt_device **cd,
const char *name,
const char *header_device);
int crypt_init_by_name(struct crypt_device **cd, const char *name);
/**
@@ -112,6 +121,13 @@ void crypt_set_password_retry(struct crypt_device *cd, int tries);
void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms);
void crypt_set_password_verify(struct crypt_device *cd, int password_verify);
/**
* Set data device (ciphertext device) if LUKS header is separated
* @cd - crypt device handle
* @device - path to device
*/
int crypt_set_data_device(struct crypt_device *cd, const char *device);
/**
* Set which RNG (random number generator) is used for generating long term key
* @cd - crypt device handle

View File

@@ -2,6 +2,7 @@ CRYPTSETUP_1.0 {
global:
crypt_init;
crypt_init_by_name;
crypt_init_by_name_and_header;
crypt_set_log_callback;
crypt_set_confirm_callback;
crypt_set_password_callback;
@@ -10,6 +11,7 @@ CRYPTSETUP_1.0 {
crypt_set_iterarion_time;
crypt_set_password_verify;
crypt_set_uuid;
crypt_set_data_device;
crypt_memory_lock;
crypt_format;

View File

@@ -36,6 +36,8 @@ struct crypt_device {
char *type;
char *device;
char *metadata_device;
char *backing_file;
int loop_fd;
struct volume_key *volume_key;
@@ -118,6 +120,11 @@ void logger(struct crypt_device *cd, int level, const char *file,
free(target);
}
static const char *mdata_device(struct crypt_device *cd)
{
return cd->metadata_device ?: cd->device;
}
static int init_crypto(struct crypt_device *ctx)
{
int r;
@@ -273,7 +280,7 @@ static int key_from_terminal(struct crypt_device *cd, char *msg, char **key,
*key = NULL;
if(!msg && asprintf(&prompt, _("Enter passphrase for %s: "),
cd->backing_file ?: cd->device) < 0)
cd->backing_file ?: crypt_get_device_name(cd)) < 0)
return -ENOMEM;
if (!msg)
@@ -317,7 +324,7 @@ static int volume_key_by_terminal_passphrase(struct crypt_device *cd, int keyslo
if(r < 0)
goto out;
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase_read,
passphrase_size_read, &cd->hdr, vk, cd);
if (r == -EPERM)
eperm = 1;
@@ -469,7 +476,42 @@ bad:
return r;
}
int crypt_init_by_name(struct crypt_device **cd, const char *name)
int crypt_set_data_device(struct crypt_device *cd, const char *device)
{
char *data_device;
int r;
log_dbg("Setting ciphertext data device to %s.", device ?: "(none)");
if (!isLUKS(cd->type)) {
log_err(cd, _("This operation is not supported for this device type.\n"));
return -EINVAL;
}
/* metadata device must be set */
if (!cd->device)
return -EINVAL;
r = device_ready(NULL, device, O_RDONLY);
if (r < 0)
return r;
if (!(data_device = strdup(device)))
return -ENOMEM;
if (!cd->metadata_device)
cd->metadata_device = cd->device;
else
free(cd->device);
cd->device = data_device;
return 0;
}
int crypt_init_by_name_and_header(struct crypt_device **cd,
const char *name,
const char *header_device)
{
crypt_status_info ci;
struct crypt_dm_active_device dmd;
@@ -494,23 +536,46 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
goto out;
*cd = NULL;
r = crypt_init(cd, dmd.device);
/* Underlying device disappeared but mapping still active */
if (!dmd.device || r == -ENOTBLK)
log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
name);
if (header_device) {
r = crypt_init(cd, header_device);
} else {
r = crypt_init(cd, dmd.device);
/* Underlying device is not readable but crypt mapping exists */
if (r == -ENOTBLK) {
free((char*)dmd.device);
dmd.device = NULL;
r = crypt_init(cd, NULL);
/* Underlying device disappeared but mapping still active */
if (!dmd.device || r == -ENOTBLK)
log_verbose(NULL, _("Underlying device for crypt device %s disappeared.\n"),
name);
/* Underlying device is not readable but crypt mapping exists */
if (r == -ENOTBLK) {
free((char*)dmd.device);
dmd.device = NULL;
r = crypt_init(cd, NULL);
}
}
if (r < 0)
goto out;
if (dmd.uuid) {
if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1))
(*cd)->type = strdup(CRYPT_PLAIN);
else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1))
(*cd)->type = strdup(CRYPT_LOOPAES);
else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1))
(*cd)->type = strdup(CRYPT_LUKS1);
else
log_dbg("Unknown UUID set, some parameters are not set.");
} else
log_dbg("Active device has no UUID set, some parameters are not set.");
if (header_device) {
r = crypt_set_data_device(*cd, dmd.device);
if (r < 0)
goto out;
}
/* Try to initialise basic parameters from active device */
if (!(*cd)->backing_file && dmd.device && crypt_loop_device(dmd.device) &&
@@ -519,46 +584,45 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
goto out;
}
if (dmd.uuid) {
if (!strncmp(CRYPT_PLAIN, dmd.uuid, sizeof(CRYPT_PLAIN)-1)) {
(*cd)->type = strdup(CRYPT_PLAIN);
(*cd)->plain_uuid = strdup(dmd.uuid);
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
(*cd)->plain_hdr.offset = dmd.offset;
(*cd)->plain_hdr.skip = dmd.iv_offset;
if (isPLAIN((*cd)->type)) {
(*cd)->type = strdup(CRYPT_PLAIN);
(*cd)->plain_uuid = strdup(dmd.uuid);
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
(*cd)->plain_hdr.offset = dmd.offset;
(*cd)->plain_hdr.skip = dmd.iv_offset;
r = crypt_parse_name_and_mode(dmd.cipher, cipher, NULL, cipher_mode);
if (!r) {
(*cd)->plain_cipher = strdup(cipher);
(*cd)->plain_cipher_mode = strdup(cipher_mode);
}
} else if (!strncmp(CRYPT_LOOPAES, dmd.uuid, sizeof(CRYPT_LOOPAES)-1)) {
(*cd)->type = strdup(CRYPT_LOOPAES);
(*cd)->loopaes_uuid = strdup(dmd.uuid);
(*cd)->loopaes_hdr.offset = dmd.offset;
r = crypt_parse_name_and_mode(dmd.cipher, cipher, NULL, cipher_mode);
if (!r) {
(*cd)->plain_cipher = strdup(cipher);
(*cd)->plain_cipher_mode = strdup(cipher_mode);
}
} else if (isLOOPAES((*cd)->type)) {
(*cd)->type = strdup(CRYPT_LOOPAES);
(*cd)->loopaes_uuid = strdup(dmd.uuid);
(*cd)->loopaes_hdr.offset = dmd.offset;
r = crypt_parse_name_and_mode(dmd.cipher, cipher,
&key_nums, cipher_mode);
if (!r) {
(*cd)->loopaes_cipher = strdup(cipher);
(*cd)->loopaes_cipher_mode = strdup(cipher_mode);
/* version 3 uses last key for IV */
if (dmd.vk->keylength % key_nums)
key_nums++;
(*cd)->loopaes_key_size = dmd.vk->keylength / key_nums;
}
} else if (!strncmp(CRYPT_LUKS1, dmd.uuid, sizeof(CRYPT_LUKS1)-1)) {
if (dmd.device) {
r = crypt_load(*cd, CRYPT_LUKS1, NULL);
if (r < 0) {
log_dbg("LUKS device header does not match active device.");
/* initialise empty context */
r = 0;
}
r = crypt_parse_name_and_mode(dmd.cipher, cipher,
&key_nums, cipher_mode);
if (!r) {
(*cd)->loopaes_cipher = strdup(cipher);
(*cd)->loopaes_cipher_mode = strdup(cipher_mode);
/* version 3 uses last key for IV */
if (dmd.vk->keylength % key_nums)
key_nums++;
(*cd)->loopaes_key_size = dmd.vk->keylength / key_nums;
}
} else if (isLUKS((*cd)->type)) {
if (mdata_device(*cd)) {
r = crypt_load(*cd, CRYPT_LUKS1, NULL);
if (r < 0) {
log_dbg("LUKS device header does not match active device.");
free((*cd)->type);
(*cd)->type = NULL;
r = 0;
goto out;
}
}
} else
log_dbg("Active device has no UUID set, some parameters are not set.");
}
out:
if (r < 0) {
@@ -572,6 +636,11 @@ out:
return r;
}
int crypt_init_by_name(struct crypt_device **cd, const char *name)
{
return crypt_init_by_name_and_header(cd, name, NULL);
}
static int _crypt_format_plain(struct crypt_device *cd,
const char *cipher,
const char *cipher_mode,
@@ -624,7 +693,7 @@ static int _crypt_format_luks1(struct crypt_device *cd,
unsigned long required_alignment = DEFAULT_DISK_ALIGNMENT;
unsigned long alignment_offset = 0;
if (!cd->device) {
if (!mdata_device(cd)) {
log_err(cd, _("Can't format LUKS without device.\n"));
return -EINVAL;
}
@@ -638,6 +707,7 @@ static int _crypt_format_luks1(struct crypt_device *cd,
if(!cd->volume_key)
return -ENOMEM;
//FIXME: external metadata, ignore alignment
if (params && params->data_alignment)
required_alignment = params->data_alignment * SECTOR_SIZE;
else
@@ -654,19 +724,19 @@ static int _crypt_format_luks1(struct crypt_device *cd,
return r;
/* Wipe first 8 sectors - fs magic numbers etc. */
r = wipe_device_header(cd->device, 8);
r = wipe_device_header(mdata_device(cd), 8);
if(r < 0) {
if (r == -EBUSY)
log_err(cd, _("Cannot format device %s which is still in use.\n"),
cd->device);
mdata_device(cd));
else
log_err(cd, _("Cannot wipe header on device %s.\n"),
cd->device);
mdata_device(cd));
return r;
}
r = LUKS_write_phdr(cd->device, &cd->hdr, cd);
r = LUKS_write_phdr(mdata_device(cd), &cd->hdr, cd);
return r;
}
@@ -677,7 +747,7 @@ static int _crypt_format_loopaes(struct crypt_device *cd,
size_t volume_key_size,
struct crypt_params_loopaes *params)
{
if (!cd->device) {
if (!mdata_device(cd)) {
log_err(cd, _("Can't format LOOPAES without device.\n"));
return -EINVAL;
}
@@ -717,7 +787,7 @@ int crypt_format(struct crypt_device *cd,
if (!type)
return -EINVAL;
log_dbg("Formatting device %s as type %s.", cd->device ?: "(none)", type);
log_dbg("Formatting device %s as type %s.", mdata_device(cd) ?: "(none)", type);
r = init_crypto(cd);
if (r < 0)
@@ -756,9 +826,9 @@ int crypt_load(struct crypt_device *cd,
int r;
log_dbg("Trying to load %s crypt type from device %s.",
requested_type ?: "any", cd->device ?: "(none)");
requested_type ?: "any", mdata_device(cd) ?: "(none)");
if (!cd->device)
if (!mdata_device(cd))
return -EINVAL;
if (requested_type && !isLUKS(requested_type))
@@ -768,10 +838,11 @@ int crypt_load(struct crypt_device *cd,
if (r < 0)
return r;
r = LUKS_read_phdr(cd->device, &hdr, 1, cd);
r = LUKS_read_phdr(mdata_device(cd), &hdr, 1, cd);
if (!r) {
memcpy(&cd->hdr, &hdr, sizeof(hdr));
free(cd->type);
cd->type = strdup(CRYPT_LUKS1);
if (!cd->type)
r = -ENOMEM;
@@ -834,19 +905,19 @@ int crypt_set_uuid(struct crypt_device *cd, const char *uuid)
if (uuid && !strncmp(uuid, cd->hdr.uuid, sizeof(cd->hdr.uuid))) {
log_dbg("UUID is the same as requested (%s) for device %s.",
uuid, cd->device);
uuid, mdata_device(cd));
return 0;
}
if (uuid)
log_dbg("Requested new UUID change to %s for %s.", uuid, cd->device);
log_dbg("Requested new UUID change to %s for %s.", uuid, mdata_device(cd));
else
log_dbg("Requested new UUID refresh for %s.", cd->device);
log_dbg("Requested new UUID refresh for %s.", mdata_device(cd));
if (!crypt_confirm(cd, _("Do you really want to change UUID of device?")))
return -EPERM;
return LUKS_hdr_uuid_set(cd->device, &cd->hdr, uuid, cd);
return LUKS_hdr_uuid_set(mdata_device(cd), &cd->hdr, uuid, cd);
}
int crypt_header_backup(struct crypt_device *cd,
@@ -863,9 +934,9 @@ int crypt_header_backup(struct crypt_device *cd,
return r;
log_dbg("Requested header backup of device %s (%s) to "
"file %s.", cd->device, requested_type, backup_file);
"file %s.", mdata_device(cd), requested_type, backup_file);
return LUKS_hdr_backup(backup_file, cd->device, &cd->hdr, cd);
return LUKS_hdr_backup(backup_file, mdata_device(cd), &cd->hdr, cd);
}
int crypt_header_restore(struct crypt_device *cd,
@@ -883,15 +954,15 @@ int crypt_header_restore(struct crypt_device *cd,
return r;
log_dbg("Requested header restore to device %s (%s) from "
"file %s.", cd->device, requested_type, backup_file);
"file %s.", mdata_device(cd), requested_type, backup_file);
return LUKS_hdr_restore(backup_file, cd->device, &cd->hdr, cd);
return LUKS_hdr_restore(backup_file, mdata_device(cd), &cd->hdr, cd);
}
void crypt_free(struct crypt_device *cd)
{
if (cd) {
log_dbg("Releasing crypt device %s context.", cd->device);
log_dbg("Releasing crypt device %s context.", mdata_device(cd));
if (cd->loop_fd != -1)
close(cd->loop_fd);
@@ -900,6 +971,7 @@ void crypt_free(struct crypt_device *cd)
crypt_free_volume_key(cd->volume_key);
free(cd->device);
free(cd->metadata_device);
free(cd->backing_file);
free(cd->type);
@@ -989,7 +1061,7 @@ int crypt_resume_by_passphrase(struct crypt_device *cd,
}
if (passphrase) {
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase,
passphrase_size, &cd->hdr, &vk, cd);
} else
r = volume_key_by_terminal_passphrase(cd, keyslot, &vk);
@@ -1044,7 +1116,7 @@ int crypt_resume_by_keyfile(struct crypt_device *cd,
if (r < 0)
goto out;
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase_read,
passphrase_size_read, &cd->hdr, &vk, cd);
if (r < 0)
goto out;
@@ -1096,7 +1168,7 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
}
} else if (passphrase) {
/* Passphrase provided, use it to unlock existing keyslot */
r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, passphrase,
r = LUKS_open_key_with_hdr(mdata_device(cd), CRYPT_ANY_SLOT, passphrase,
passphrase_size, &cd->hdr, &vk, cd);
} else {
/* Passphrase not provided, ask first and use it to unlock existing keyslot */
@@ -1105,7 +1177,7 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
if (r < 0)
goto out;
r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password,
r = LUKS_open_key_with_hdr(mdata_device(cd), CRYPT_ANY_SLOT, password,
passwordLen, &cd->hdr, &vk, cd);
crypt_safe_free(password);
}
@@ -1123,7 +1195,7 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
goto out;
}
r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
r = LUKS_set_key(mdata_device(cd), keyslot, new_password, new_passwordLen,
&cd->hdr, vk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
if(r < 0) goto out;
@@ -1180,7 +1252,7 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
if (r < 0)
goto out;
r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password, passwordLen,
r = LUKS_open_key_with_hdr(mdata_device(cd), CRYPT_ANY_SLOT, password, passwordLen,
&cd->hdr, &vk, cd);
}
@@ -1197,7 +1269,7 @@ int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
if (r < 0)
goto out;
r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
r = LUKS_set_key(mdata_device(cd), keyslot, new_password, new_passwordLen,
&cd->hdr, vk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
out:
crypt_safe_free(password);
@@ -1251,7 +1323,7 @@ int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
passphrase_size = new_passwordLen;
}
r = LUKS_set_key(cd->device, keyslot, passphrase, passphrase_size,
r = LUKS_set_key(mdata_device(cd), keyslot, passphrase, passphrase_size,
&cd->hdr, vk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
out:
crypt_safe_free(new_password);
@@ -1281,7 +1353,7 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
return -EINVAL;
}
return LUKS_del_key(cd->device, keyslot, &cd->hdr, cd);
return LUKS_del_key(mdata_device(cd), keyslot, &cd->hdr, cd);
}
// activation/deactivation of device mapping
@@ -1337,7 +1409,7 @@ int crypt_activate_by_passphrase(struct crypt_device *cd,
} else if (isLUKS(cd->type)) {
/* provided passphrase, do not retry */
if (passphrase) {
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase,
passphrase_size, &cd->hdr, &vk, cd);
} else
r = volume_key_by_terminal_passphrase(cd, keyslot, &vk);
@@ -1408,7 +1480,7 @@ int crypt_activate_by_keyfile(struct crypt_device *cd,
&passphrase_size_read, keyfile, keyfile_size);
if (r < 0)
goto out;
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase_read,
passphrase_size_read, &cd->hdr, &vk, cd);
if (r < 0)
goto out;
@@ -1567,7 +1639,7 @@ int crypt_volume_key_get(struct crypt_device *cd,
if (r < 0)
log_err(cd, _("Cannot retrieve volume key for plain device.\n"));
} else if (isLUKS(cd->type)) {
r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
r = LUKS_open_key_with_hdr(mdata_device(cd), keyslot, passphrase,
passphrase_size, &cd->hdr, &vk, cd);
} else
@@ -1695,7 +1767,7 @@ int crypt_dump(struct crypt_device *cd)
return -EINVAL;
}
log_std(cd, "LUKS header information for %s\n\n", cd->device);
log_std(cd, "LUKS header information for %s\n\n", mdata_device(cd));
log_std(cd, "Version: \t%d\n", cd->hdr.version);
log_std(cd, "Cipher name: \t%s\n", cd->hdr.cipherName);
log_std(cd, "Cipher mode: \t%s\n", cd->hdr.cipherMode);
@@ -1784,6 +1856,7 @@ const char *crypt_get_device_name(struct crypt_device *cd)
return cd->device;
}
int crypt_get_volume_key_size(struct crypt_device *cd)
{
if (isPLAIN(cd->type) && cd->volume_key)

View File

@@ -52,7 +52,8 @@ opens the LUKS partition <device> and sets up a mapping <name> after
successful verification of the supplied key material
(either via key file by \-\-key-file, or via prompting).
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size, \-\-readonly, \-\-allow-discards].
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size, \-\-readonly, \-\-allow-discards,
\-\-header].
.PP
\fIluksClose\fR <name>
.IP
@@ -67,13 +68,15 @@ After that operation you have to use \fIluksResume\fR to reinstate
encryption key (and resume device) or \fIluksClose\fR to remove mapped device.
\fBWARNING:\fR never try to suspend device where is the cryptsetup binary itself.
\fB<options>\fR can be [\-\-header].
.PP
\fIluksResume\fR <name>
.IP
Resumes suspended device and reinstates encryption key. You will need provide passphrase
identical to \fIluksOpen\fR command (using prompting or key file).
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size]
\fB<options>\fR can be [\-\-key-file, \-\-keyfile-size, \-\-header]
.PP
\fIluksAddKey\fR <device> [<new key file>]
.IP
@@ -374,6 +377,20 @@ if the discarded blocks can be located easily on the device later.
Kernel version 3.1 or more recent is required.
For older versions is the option ignored.
.TP
.B "\-\-header\fR"
Set detached (separated) metadata device or file with LUKS header.
This options allows separation of ciphertext device and on-disk metadata header.
This option is only relevant for LUKS devices and can be used in \fIluksOpen\fR,
\fIluksSuspend\fR, \fIluksResume\fR and \fIresize\fR commands.
For other commands with separated metadata device you have to always specify
path to metadata device (not to the ciphertext device).
\fBWARNING:\fR There is no possible check that specified ciphertext device
is correct if on-disk header is detached. Use with care.
.TP
.B "\-\-version"
Show the version.
.SH RETURN CODES

View File

@@ -43,6 +43,7 @@ static const char *opt_key_file = NULL;
static const char *opt_master_key_file = NULL;
static const char *opt_header_backup_file = NULL;
static const char *opt_uuid = NULL;
static const char *opt_header_device = NULL;
static int opt_key_size = 0;
static long opt_keyfile_size = 0;
static long opt_new_keyfile_size = 0;
@@ -356,7 +357,7 @@ static int action_resize(int arg __attribute__((unused)))
struct crypt_device *cd = NULL;
int r;
r = crypt_init_by_name(&cd, action_argv[0]);
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
if (r == 0)
r = crypt_resize(cd, action_argv[0], opt_size);
@@ -520,15 +521,28 @@ out:
static int action_luksOpen(int arg __attribute__((unused)))
{
struct crypt_device *cd = NULL;
const char *data_device, *header_device;
uint32_t flags = 0;
int r;
if ((r = crypt_init(&cd, action_argv[0])))
if (opt_header_device) {
header_device = opt_header_device;
data_device = action_argv[0];
} else {
header_device = action_argv[0];
data_device = NULL;
}
if ((r = crypt_init(&cd, header_device)))
goto out;
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
if (data_device &&
(r = crypt_set_data_device(cd, data_device)))
goto out;
crypt_set_timeout(cd, opt_timeout);
crypt_set_password_retry(cd, opt_tries);
@@ -942,7 +956,7 @@ static int action_luksSuspend(int arg __attribute__((unused)))
struct crypt_device *cd = NULL;
int r;
r = crypt_init_by_name(&cd, action_argv[0]);
r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device);
if (!r)
r = crypt_suspend(cd, action_argv[0]);
@@ -955,7 +969,7 @@ static int action_luksResume(int arg __attribute__((unused)))
struct crypt_device *cd = NULL;
int r;
if ((r = crypt_init_by_name(&cd, action_argv[0])))
if ((r = crypt_init_by_name_and_header(&cd, action_argv[0], opt_header_device)))
goto out;
crypt_set_timeout(cd, opt_timeout);
@@ -1156,6 +1170,7 @@ int main(int argc, const char **argv)
{ "shared", '\0', POPT_ARG_NONE, &opt_shared, 0, N_("Share device with another non-overlapping crypt segment."), NULL },
{ "uuid", '\0', POPT_ARG_STRING, &opt_uuid, 0, N_("UUID for device to use."), NULL },
{ "allow-discards", '\0', POPT_ARG_NONE, &opt_allow_discards, 0, N_("Allow discards (aka TRIM) requests for device."), NULL },
{ "header", '\0', POPT_ARG_STRING, &opt_header_device, 0, N_("Device or file with separated LUKS header."), NULL },
POPT_TABLEEND
};
poptContext popt_context;