* Add crypt_get_type(), crypt_resize(), crypt_keyslot_max()

and crypt_get_active_device() to API.
* Rewrite all implementations in cryptsetup to new API.
* Fix luksRemoveKey to behave as documented (do not ask
for remaining keyslot passphrase).
* Add more regression tests for commands.

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@360 36d66b0a-2a48-0410-832c-cd162a569da5
This commit is contained in:
Milan Broz
2010-11-05 11:27:47 +00:00
parent 7b42e0b99c
commit c9881f8c33
8 changed files with 497 additions and 128 deletions

View File

@@ -1,6 +1,12 @@
2010-11-01 Milan Broz <mbroz@redhat.com>
* No longer support luksDelKey, reload and --non-exclusive.
* Remove some obsolete info from man page.
* Add crypt_get_type(), crypt_resize(), crypt_keyslot_max()
and crypt_get_active_device() to API.
* Rewrite all implementations in cryptsetup to new API.
* Fix luksRemoveKey to behave as documented (do not ask
for remaining keyslot passphrase).
* Add more regression tests for commands.
2010-10-27 Milan Broz <mbroz@redhat.com>
* Rewrite cryptsetup luksFormat, luksOpen, luksAddKey to use new API

View File

@@ -144,6 +144,15 @@ int crypt_memory_lock(struct crypt_device *cd, int lock);
#define CRYPT_PLAIN "PLAIN" /* regular crypt device, no on-disk header */
#define CRYPT_LUKS1 "LUKS1" /* LUKS version 1 header on-disk */
/**
* Get device type
*
* @cd - crypt device handle
*
* Return string according to device type or NULL if not known.
*/
const char *crypt_get_type(struct crypt_device *cd);
struct crypt_params_plain {
const char *hash; /* password hash function */
uint64_t offset; /* offset in sectors */
@@ -206,6 +215,19 @@ int crypt_load(struct crypt_device *cd,
const char *requested_type,
void *params);
/**
* Resize crypt device
*
* Returns 0 on success or negative errno value otherwise.
*
* @cd - crypt device handle
* @name - name of device to resize
* @new_size - new device size in sectors or 0 to use underlying device size
*/
int crypt_resize(struct crypt_device *cd,
const char *name,
uint64_t new_size);
/**
* Suspends crypt device.
*
@@ -278,6 +300,16 @@ int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
const char *new_passphrase,
size_t new_passphrase_size);
/**
* Get number of keyslots supported for device type.
*
* Returns slot count or negative errno otherwise if device
* doesn't not support keyslots.
*
* @type - crypt device type
*/
int crypt_keyslot_max(const char *type);
/**
* Add key slot using provided key file path
*
@@ -336,6 +368,32 @@ int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
#define CRYPT_ACTIVATE_READONLY (1 << 0)
#define CRYPT_ACTIVATE_NO_UUID (1 << 1)
/**
* Active device runtime attributes
*/
struct crypt_active_device {
uint64_t offset; /* offset in sectors */
uint64_t iv_offset; /* IV initilisation sector */
uint64_t size; /* active device size */
uint32_t flags; /* activation flags */
};
/**
* Receives runtime attributes of active crypt device
*
* Returns 0 on success or negative errno value otherwise.
*
* @cd - crypt device handle
* @name - name of active device
* @cad - preallocated active device attributes to fill
*
* Note that this is old API function using global context.
* All error messages are reported also through log callback.
*/
int crypt_get_active_device(struct crypt_device *cd,
const char *name,
struct crypt_active_device *cad);
/**
* Activate device or check passphrase
*

View File

@@ -14,6 +14,7 @@ CRYPTSETUP_1.0 {
crypt_memory_lock;
crypt_format;
crypt_load;
crypt_resize;
crypt_suspend;
crypt_resume_by_passphrase;
crypt_resume_by_keyfile;
@@ -38,9 +39,13 @@ CRYPTSETUP_1.0 {
crypt_get_volume_key_size;
crypt_get_device_name;
crypt_get_type;
crypt_get_active_device;
crypt_set_rng_type;
crypt_get_rng_type;
crypt_keyslot_max;
crypt_keyslot_status;
crypt_get_error;
crypt_get_dir;

View File

@@ -990,8 +990,11 @@ int crypt_init(struct crypt_device **cd, const char *device)
int crypt_init_by_name(struct crypt_device **cd, const char *name)
{
crypt_status_info ci;
char *device = NULL;
int r;
struct crypt_active_device cad;
char *device = NULL, *cipher_full = NULL, *device_uuid = NULL;
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
int key_size = 0, r;
log_dbg("Allocating crypt device context by device %s.", name);
@@ -1004,8 +1007,9 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
return -ENODEV;
}
r = dm_query_device(name, &device, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL);
r = dm_query_device(name, &device, &cad.size, &cad.iv_offset, &cad.offset,
&cipher_full, &key_size, NULL, NULL, NULL,
&device_uuid);
/* Underlying device disappeared but mapping still active */
if (r >= 0 && !device)
@@ -1015,7 +1019,32 @@ int crypt_init_by_name(struct crypt_device **cd, const char *name)
if (r >= 0)
r = crypt_init(cd, device);
/* Try to initialise basic parameters from active device */
if (!r && *device_uuid) {
if (!strncmp(CRYPT_PLAIN, device_uuid, sizeof(CRYPT_PLAIN)-1)) {
(*cd)->type = strdup(CRYPT_PLAIN);
(*cd)->plain_uuid = strdup(device_uuid);
(*cd)->plain_hdr.hash = NULL; /* no way to get this */
(*cd)->plain_hdr.offset = cad.offset;
(*cd)->plain_hdr.skip = cad.iv_offset;
(*cd)->volume_key = crypt_alloc_volume_key(key_size, NULL);
if (!(*cd)->volume_key)
r = -ENOMEM;
r = crypt_parse_name_and_mode(cipher_full, cipher, cipher_mode);
if (!r) {
(*cd)->plain_cipher = strdup(cipher);
(*cd)->plain_cipher_mode = strdup(cipher_mode);
}
} else if (!strncmp(CRYPT_LUKS1, device_uuid, sizeof(CRYPT_LUKS1)-1)) {
if (device)
r = crypt_load(*cd, CRYPT_LUKS1, NULL);
}
}
free(device);
free(cipher_full);
free(device_uuid);
return r;
}
@@ -1186,6 +1215,53 @@ int crypt_load(struct crypt_device *cd,
return r;
}
int crypt_resize(struct crypt_device *cd, const char *name, uint64_t new_size)
{
char *device = NULL, *cipher = NULL, *uuid = NULL, *key = NULL;
uint64_t size, skip, offset;
int key_size, read_only, r;
/* Device context type must be initialised */
if (!cd->type || !crypt_get_uuid(cd))
return -EINVAL;
r = dm_query_device(name, &device, &size, &skip, &offset,
&cipher, &key_size, &key, &read_only, NULL, &uuid);
if (r < 0) {
log_err(NULL, _("Device %s is not active.\n"), name);
goto out;
}
if (!uuid) {
r = -EINVAL;
goto out;
}
r = device_check_and_adjust(cd, device, &new_size, &offset, &read_only);
if (r)
goto out;
if (new_size == size) {
log_dbg("Device has already requested size %" PRIu64
" sectors.", size);
r = 0;
goto out;
}
log_dbg("Resizing device %s to %" PRIu64 " sectors.", name, new_size);
r = dm_create_device(name, device, cipher, cd->type,
crypt_get_uuid(cd), new_size, skip, offset,
key_size, key, read_only, 1);
out:
crypt_safe_free(key);
free(cipher);
free(device);
free(uuid);
return r;
}
int crypt_set_uuid(struct crypt_device *cd, const char *uuid)
{
if (!isLUKS(cd->type)) {
@@ -2069,6 +2145,9 @@ const char *crypt_get_uuid(struct crypt_device *cd)
if (isLUKS(cd->type))
return cd->hdr.uuid;
if (isPLAIN(cd->type))
return cd->plain_uuid;
return NULL;
}
@@ -2079,7 +2158,7 @@ const char *crypt_get_device_name(struct crypt_device *cd)
int crypt_get_volume_key_size(struct crypt_device *cd)
{
if (isPLAIN(cd->type))
if (isPLAIN(cd->type) && cd->volume_key)
return cd->volume_key->keylength;
if (isLUKS(cd->type))
@@ -2108,3 +2187,32 @@ crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
return LUKS_keyslot_info(&cd->hdr, keyslot);
}
int crypt_keyslot_max(const char *type)
{
if (type && isLUKS(type))
return LUKS_NUMKEYS;
return -EINVAL;
}
const char *crypt_get_type(struct crypt_device *cd)
{
return cd->type;
}
int crypt_get_active_device(struct crypt_device *cd,
const char *name,
struct crypt_active_device *cad)
{
int r, readonly;
r = dm_query_device(name, NULL, &cad->size, &cad->iv_offset, &cad->offset,
NULL, NULL, NULL, &readonly, NULL, NULL);
if (r < 0)
return r;
cad->flags = readonly ? CRYPT_ACTIVATE_READONLY : 0;
return 0;
}

View File

@@ -22,11 +22,13 @@ int crypt_parse_name_and_mode(const char *s, char *cipher, char *cipher_mode)
{
if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]-%" MAX_CIPHER_LEN_STR "s",
cipher, cipher_mode) == 2) {
if (!strcmp(cipher_mode, "plain"))
strncpy(cipher_mode, "cbc-plain", 10);
return 0;
}
if (sscanf(s, "%" MAX_CIPHER_LEN_STR "[^-]", cipher) == 1) {
strncpy(cipher_mode, "cbc-plain", 9);
strncpy(cipher_mode, "cbc-plain", 10);
return 0;
}

View File

@@ -664,7 +664,7 @@ static int LUKS_open_key(const char *device,
if(r < 0) goto out;
r = LUKS_verify_volume_key(hdr, vk);
if (r >= 0)
if (!r)
log_verbose(ctx, _("Key slot %d unlocked.\n"), keyIndex);
out:
free(AfKey);
@@ -684,8 +684,10 @@ int LUKS_open_key_with_hdr(const char *device,
*vk = crypt_alloc_volume_key(hdr->keyBytes, NULL);
if (keyIndex >= 0)
return LUKS_open_key(device, keyIndex, password, passwordLen, hdr, *vk, ctx);
if (keyIndex >= 0) {
r = LUKS_open_key(device, keyIndex, password, passwordLen, hdr, *vk, ctx);
return (r < 0) ? r : keyIndex;
}
for(i = 0; i < LUKS_NUMKEYS; i++) {
r = LUKS_open_key(device, i, password, passwordLen, hdr, *vk, ctx);

View File

@@ -52,7 +52,6 @@ static int action_status(int arg);
static int action_luksFormat(int arg);
static int action_luksOpen(int arg);
static int action_luksAddKey(int arg);
static int action_luksDelKey(int arg);
static int action_luksKillSlot(int arg);
static int action_luksRemoveKey(int arg);
static int action_isLuks(int arg);
@@ -116,8 +115,7 @@ static void clogger(struct crypt_device *cd, int level, const char *file,
free(target);
}
/* Interface Callbacks */
static int yesDialog(char *msg)
static int _yesDialog(const char *msg, void *usrptr)
{
char *answer = NULL;
size_t size = 0;
@@ -139,7 +137,8 @@ static int yesDialog(char *msg)
return r;
}
static void cmdLineLog(int level, char *msg) {
static void _log(int level, const char *msg, void *usrptr)
{
switch(level) {
case CRYPT_LOG_NORMAL:
@@ -158,33 +157,6 @@ static void cmdLineLog(int level, char *msg) {
}
}
static struct interface_callbacks cmd_icb = {
.yesDialog = yesDialog,
.log = cmdLineLog,
};
static void _log(int level, const char *msg, void *usrptr)
{
cmdLineLog(level, (char *)msg);
}
static int _yesDialog(const char *msg, void *usrptr)
{
return yesDialog((char*)msg);
}
/* End ICBs */
static int check_slot(int key_slot)
{
/* FIXME: use per format define here */
if (key_slot != CRYPT_ANY_SLOT && (key_slot < 0 || key_slot > 8))
return 0;
return 1;
}
static void show_status(int errcode)
{
char error[256], *error_;
@@ -216,85 +188,125 @@ static void show_status(int errcode)
static int action_create(int arg)
{
struct crypt_options options = {
.name = action_argv[0],
.device = action_argv[1],
.cipher = opt_cipher ? opt_cipher : DEFAULT_CIPHER(PLAIN),
struct crypt_device *cd = NULL;
char cipher[MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
struct crypt_params_plain params = {
.hash = opt_hash ?: DEFAULT_PLAIN_HASH,
.key_file = opt_key_file,
.key_size = (opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8,
.key_slot = opt_key_slot,
.flags = 0,
.size = opt_size,
.offset = opt_offset,
.skip = opt_skip,
.timeout = opt_timeout,
.tries = opt_tries,
.icb = &cmd_icb,
.offset = opt_offset,
};
char *password = NULL;
unsigned int passwordLen;
int r;
if (options.hash && strcmp(options.hash, "plain") == 0)
options.hash = NULL;
if (opt_verify_passphrase)
options.flags |= CRYPT_FLAG_VERIFY;
if (opt_readonly)
options.flags |= CRYPT_FLAG_READONLY;
if (params.hash && !strcmp(params.hash, "plain"))
params.hash = NULL;
return crypt_create_device(&options);
r = crypt_parse_name_and_mode(opt_cipher ?: DEFAULT_CIPHER(PLAIN),
cipher, cipher_mode);
if (r < 0) {
log_err("No known cipher specification pattern detected.\n");
goto out;
}
if ((r = crypt_init(&cd, action_argv[1])))
goto out;
crypt_set_timeout(cd, opt_timeout);
crypt_set_password_retry(cd, opt_tries);
r = crypt_format(cd, CRYPT_PLAIN,
cipher, cipher_mode,
NULL, NULL,
(opt_key_size ?: DEFAULT_PLAIN_KEYBITS) / 8,
&params);
if (r < 0)
goto out;
crypt_get_key(_("Enter passphrase: "),
&password, &passwordLen,
opt_keyfile_size, opt_key_file,
opt_timeout,
opt_batch_mode ? 0 : opt_verify_passphrase,
cd);
r = crypt_activate_by_passphrase(cd, action_argv[0], CRYPT_ANY_SLOT,
password, passwordLen,
opt_readonly ? CRYPT_ACTIVATE_READONLY : 0);
out:
crypt_free(cd);
crypt_safe_free(password);
return (r < 0) ? r : 0;
}
static int action_remove(int arg)
{
struct crypt_options options = {
.name = action_argv[0],
.icb = &cmd_icb,
};
struct crypt_device *cd = NULL;
int r;
return crypt_remove_device(&options);
r = crypt_init_by_name(&cd, action_argv[0]);
if (r == 0)
r = crypt_deactivate(cd, action_argv[0]);
crypt_free(cd);
return r;
}
static int action_resize(int arg)
{
struct crypt_options options = {
.name = action_argv[0],
.size = opt_size,
.icb = &cmd_icb,
};
struct crypt_device *cd = NULL;
int r;
return crypt_resize_device(&options);
r = crypt_init_by_name(&cd, action_argv[0]);
if (r == 0)
r = crypt_resize(cd, action_argv[0], opt_size);
crypt_free(cd);
return r;
}
static int action_status(int arg)
{
struct crypt_options options = {
.name = action_argv[0],
.icb = &cmd_icb,
};
int r;
crypt_status_info ci;
struct crypt_active_device cad;
struct crypt_device *cd = NULL;
int r = 0;
r = crypt_query_device(&options);
ci = crypt_status(NULL, action_argv[0]);
switch (ci) {
case CRYPT_INVALID:
r = -ENODEV;
break;
case CRYPT_INACTIVE:
log_std("%s/%s is inactive.\n", crypt_get_dir(), action_argv[0]);
break;
case CRYPT_ACTIVE:
case CRYPT_BUSY:
log_std("%s/%s is active%s.\n", crypt_get_dir(), action_argv[0],
ci == CRYPT_BUSY ? " and is in use" : "");
r = crypt_init_by_name(&cd, action_argv[0]);
if (r < 0 || !crypt_get_type(cd))
goto out;
log_std(" type: %s\n", crypt_get_type(cd));
r = crypt_get_active_device(cd, action_argv[0], &cad);
if (r < 0)
return r;
goto out;
if (r == 0) {
/* inactive */
log_std("%s/%s is inactive.\n", crypt_get_dir(), options.name);
r = 1;
} else {
/* active */
log_std("%s/%s is active:\n", crypt_get_dir(), options.name);
log_std(" cipher: %s\n", options.cipher);
log_std(" keysize: %d bits\n", options.key_size * 8);
log_std(" device: %s\n", options.device ?: "");
log_std(" offset: %" PRIu64 " sectors\n", options.offset);
log_std(" size: %" PRIu64 " sectors\n", options.size);
if (options.skip)
log_std(" skipped: %" PRIu64 " sectors\n", options.skip);
log_std(" mode: %s\n", (options.flags & CRYPT_FLAG_READONLY)
? "readonly" : "read/write");
crypt_put_options(&options);
r = 0;
log_std(" cipher: %s-%s\n", crypt_get_cipher(cd), crypt_get_cipher_mode(cd));
log_std(" keysize: %d bits\n", crypt_get_volume_key_size(cd) * 8);
log_std(" device: %s\n", crypt_get_device_name(cd));
log_std(" offset: %" PRIu64 " sectors\n", cad.offset);
log_std(" size: %" PRIu64 " sectors\n", cad.size);
if (cad.iv_offset)
log_std(" skipped: %" PRIu64 " sectors\n", cad.iv_offset);
log_std(" mode: %s\n", cad.flags & CRYPT_ACTIVATE_READONLY ?
"readonly" : "read/write");
}
out:
crypt_free(cd);
return r;
}
@@ -328,7 +340,6 @@ static int action_luksFormat(int arg)
{
int r = -EINVAL, keysize;
char *msg = NULL, *key = NULL, cipher [MAX_CIPHER_LEN], cipher_mode[MAX_CIPHER_LEN];
const char *key_file = NULL;
char *password = NULL;
unsigned int passwordLen;
struct crypt_device *cd = NULL;
@@ -337,19 +348,12 @@ static int action_luksFormat(int arg)
.data_alignment = opt_align_payload,
};
if (action_argc > 1) {
key_file = action_argv[1];
if (opt_key_file)
log_err(_("Option --key-file takes precedence over specified key file argument.\n"));
} else
key_file = opt_key_file;
if(asprintf(&msg, _("This will overwrite data on %s irrevocably."), action_argv[0]) == -1) {
log_err(_("memory allocation error in action_luksFormat"));
r = -ENOMEM;
goto out;
}
r = yesDialog(msg) ? 0 : -EINVAL;
r = _yesDialog(msg, NULL) ? 0 : -EINVAL;
free(msg);
if (r < 0)
goto out;
@@ -379,7 +383,7 @@ static int action_luksFormat(int arg)
r = -EINVAL;
crypt_get_key(_("Enter LUKS passphrase: "),
&password, &passwordLen,
opt_keyfile_size, key_file,
opt_keyfile_size, opt_key_file,
opt_timeout,
opt_batch_mode ? 0 : 1, /* always verify */
cd);
@@ -441,33 +445,143 @@ out:
return (r < 0) ? r : 0;
}
/* FIXME: keyslot operation needs better get_key() implementation. Use old API for now */
static int verify_keyslot(struct crypt_device *cd, int key_slot,
char *msg_last, char *msg_pass,
const char *key_file, int keyfile_size)
{
crypt_keyslot_info ki;
char *password = NULL;
unsigned int passwordLen, i;
int r = -EPERM;
ki = crypt_keyslot_status(cd, key_slot);
if (ki == CRYPT_SLOT_ACTIVE_LAST && msg_last && !_yesDialog(msg_last, NULL))
return -EPERM;
crypt_get_key(msg_pass, &password, &passwordLen,
keyfile_size, key_file,
opt_timeout,
opt_batch_mode ? 0 : opt_verify_passphrase,
cd);
if(!password)
return -EINVAL;
if (ki == CRYPT_SLOT_ACTIVE_LAST) {
/* check the last keyslot */
r = crypt_activate_by_passphrase(cd, NULL, key_slot,
password, passwordLen, 0);
} else {
/* try all other keyslots */
for (i = 0; i < crypt_keyslot_max(CRYPT_LUKS1); i++) {
if (i == key_slot)
continue;
ki = crypt_keyslot_status(cd, key_slot);
if (ki == CRYPT_SLOT_ACTIVE)
r = crypt_activate_by_passphrase(cd, NULL, i,
password, passwordLen, 0);
if (r == i)
break;
}
}
if (r < 0)
log_err(_("No key available with this passphrase.\n"));
crypt_safe_free(password);
return r;
}
static int action_luksKillSlot(int arg)
{
struct crypt_options options = {
.device = action_argv[0],
.key_slot = opt_key_slot,
.key_file = opt_key_file,
.timeout = opt_timeout,
.flags = !opt_batch_mode?CRYPT_FLAG_VERIFY_ON_DELKEY : 0,
.icb = &cmd_icb,
};
struct crypt_device *cd = NULL;
int r;
return crypt_luksKillSlot(&options);
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
crypt_set_confirm_callback(cd, _yesDialog, NULL);
crypt_set_timeout(cd, opt_timeout);
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
switch (crypt_keyslot_status(cd, opt_key_slot)) {
case CRYPT_SLOT_ACTIVE_LAST:
case CRYPT_SLOT_ACTIVE:
log_verbose(_("Key slot %d selected for deletion.\n"), opt_key_slot);
break;
case CRYPT_SLOT_INACTIVE:
log_err(_("Key %d not active. Can't wipe.\n"), opt_key_slot);
case CRYPT_SLOT_INVALID:
goto out;
}
if (!opt_batch_mode) {
r = verify_keyslot(cd, opt_key_slot,
_("This is the last keyslot. Device will become unusable after purging this key."),
_("Enter any remaining LUKS passphrase: "),
opt_key_file, opt_keyfile_size);
if (r < 0)
goto out;
}
r = crypt_keyslot_destroy(cd, opt_key_slot);
out:
crypt_free(cd);
return (r < 0) ? r : 0;
}
static int action_luksRemoveKey(int arg)
{
struct crypt_options options = {
.device = action_argv[0],
.new_key_file = action_argc>1?action_argv[1]:NULL,
.key_file = opt_key_file,
.timeout = opt_timeout,
.flags = !opt_batch_mode?CRYPT_FLAG_VERIFY_ON_DELKEY : 0,
.icb = &cmd_icb,
};
struct crypt_device *cd = NULL;
crypt_keyslot_info ki;
char *password = NULL;
unsigned int passwordLen;
int r;
return crypt_luksRemoveKey(&options);
if ((r = crypt_init(&cd, action_argv[0])))
goto out;
crypt_set_confirm_callback(cd, _yesDialog, NULL);
crypt_set_timeout(cd, opt_timeout);
if ((r = crypt_load(cd, CRYPT_LUKS1, NULL)))
goto out;
crypt_get_key(_("Enter LUKS passphrase to be deleted: "),
&password, &passwordLen,
opt_keyfile_size, opt_key_file,
opt_timeout,
opt_batch_mode ? 0 : opt_verify_passphrase,
cd);
if(!password) {
r = -EINVAL;
goto out;
}
r = crypt_activate_by_passphrase(cd, NULL, CRYPT_ANY_SLOT,
password, passwordLen, 0);
if (r < 0)
goto out;
opt_key_slot = r;
log_verbose(_("Key slot %d selected for deletion.\n"), opt_key_slot);
if (crypt_keyslot_status(cd, opt_key_slot) == CRYPT_SLOT_ACTIVE_LAST &&
!_yesDialog(_("This is the last keyslot. "
"Device will become unusable after purging this key."),
NULL)) {
r = -EPERM;
goto out;
}
r = crypt_keyslot_destroy(cd, opt_key_slot);
out:
crypt_safe_free(password);
crypt_free(cd);
return (r < 0) ? r : 0;
}
static int action_luksAddKey(int arg)
@@ -853,10 +967,20 @@ int main(int argc, char **argv)
if (!strcmp(aname, "luksKillSlot"))
opt_key_slot = atoi(action_argv[1]);
if (!check_slot(opt_key_slot))
if (opt_key_slot != CRYPT_ANY_SLOT &&
(opt_key_slot < 0 || opt_key_slot > crypt_keyslot_max(CRYPT_LUKS1)))
usage(popt_context, 1, _("Key slot is invalid."),
poptGetInvocationName(popt_context));
if ((!strcmp(aname, "luksRemoveKey") ||
!strcmp(aname, "luksFormat")) &&
action_argc > 1) {
if (opt_key_file)
log_err(_("Option --key-file takes precedence over specified key file argument.\n"));
else
opt_key_file = (char*)action_argv[1];
}
if (opt_random && opt_urandom)
usage(popt_context, 1, _("Only one of --use-[u]random options is allowed."),
poptGetInvocationName(popt_context));

View File

@@ -8,6 +8,7 @@ DEV_NAME2=dummy2
ORIG_IMG=luks-test-orig
IMG=luks-test
KEY1=key1
KEY2=key2
LUKS_HEADER="S0-5 S6-7 S8-39 S40-71 S72-103 S104-107 S108-111 R112-131 R132-163 S164-167 S168-207 A0-591"
KEY_SLOT0="S208-211 S212-215 R216-247 A248-251 A251-255"
@@ -25,7 +26,7 @@ function remove_mapping()
[ -b /dev/mapper/$DEV_NAME2 ] && dmsetup remove $DEV_NAME2
[ -b /dev/mapper/$DEV_NAME ] && dmsetup remove $DEV_NAME
losetup -d $LOOPDEV >/dev/null 2>&1
rm -f $ORIG_IMG $IMG $KEY1 >/dev/null 2>&1
rm -f $ORIG_IMG $IMG $KEY1 $KEY2 >/dev/null 2>&1
}
function fail()
@@ -63,6 +64,10 @@ function prepare()
dd if=/dev/urandom of=$KEY1 count=1 bs=32 >/dev/null 2>&1
fi
if [ ! -e $KEY2 ]; then
dd if=/dev/urandom of=$KEY2 count=1 bs=16 >/dev/null 2>&1
fi
cp $IMG $ORIG_IMG
[ -n "$1" ] && echo "CASE: $1"
}
@@ -192,5 +197,64 @@ $CRYPTSETUP -q luksFormat --master-key-file /dev/urandom -s 128 --uuid $TEST_UUI
$CRYPTSETUP luksOpen -d $KEY1 $LOOPDEV $DEV_NAME || fail
$CRYPTSETUP -q luksClose $DEV_NAME || fail
prepare "[17] AddKey passphrase and keyfile" wipe
# [0]key0 [1]key1 [2]$KEY1/1 [3]$KEY1 [4]$KEY2
$CRYPTSETUP -q luksFormat $LOOPDEV $KEY1 --key-slot 3 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: ENABLED" || fail
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 3 2>/dev/null && fail
# keyfile/keyfile
$CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 $KEY2 --key-slot 4 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: ENABLED" || fail
# passphrase/keyfile
echo "key0" | $CRYPTSETUP luksAddKey $LOOPDEV -d $KEY1 --key-slot 0 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: ENABLED" || fail
# passphrase/passphrase
echo -e "key0\nkey1\n" | $CRYPTSETUP luksAddKey $LOOPDEV --key-slot 1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: ENABLED" || fail
# keyfile/passphrase
echo -e "key1\n" | $CRYPTSETUP luksAddKey $LOOPDEV $KEY1 --key-slot 2 --new-keyfile-size 1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: ENABLED" || fail
prepare "[18] RemoveKey passphrase and keyfile" reuse
$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 3: DISABLED" || fail
$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY1 2>/dev/null && fail
$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 --keyfile-size 1 2>/dev/null && fail
$CRYPTSETUP luksRemoveKey $LOOPDEV $KEY2 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 4: DISABLED" || fail
# kill slot using passphrase from 1
echo "key1" | $CRYPTSETUP luksKillSlot $LOOPDEV 2 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 2: DISABLED" || fail
# remove key0 / slot 0
echo "key0" | $CRYPTSETUP luksRemoveKey $LOOPDEV || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 0: DISABLED" || fail
# last keyslot, in batch mode no passphrase needed...
$CRYPTSETUP luksKillSlot -q $LOOPDEV 1 || fail
$CRYPTSETUP luksDump $LOOPDEV | grep -q "Key Slot 1: DISABLED" || fail
prepare "[19] create & status & resize" wipe
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash xxx 2>/dev/null && fail
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --hash sha1 --cipher aes-cbc-essiv:sha256 --offset 3 --skip 4 --readonly || fail
$CRYPTSETUP -q status $DEV_NAME | grep "offset:" | grep -q "3 sectors" || fail
$CRYPTSETUP -q status $DEV_NAME | grep "skipped:" | grep -q "4 sectors" || fail
$CRYPTSETUP -q status $DEV_NAME | grep "mode:" | grep -q "readonly" || fail
$CRYPTSETUP -q resize $DEV_NAME --size 100 || fail
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "100 sectors" || fail
$CRYPTSETUP -q resize $DEV_NAME || fail
$CRYPTSETUP -q status $DEV_NAME | grep "size:" | grep -q "19997 sectors" || fail
$CRYPTSETUP -q remove $DEV_NAME || fail
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV || fail
$CRYPTSETUP -q remove $DEV_NAME || fail
echo "key0" | $CRYPTSETUP -q create $DEV_NAME $LOOPDEV || fail
$CRYPTSETUP -q remove $DEV_NAME || fail
# verify is ignored on non-tty input
echo "key0" | $CRYPTSETUP create $DEV_NAME $LOOPDEV --verify-passphrase || fail
$CRYPTSETUP -q remove $DEV_NAME || fail
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 --key-size 255 2>/dev/null && fail
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 || fail
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d $KEY1 2>/dev/null && fail
$CRYPTSETUP create $DEV_NAME $LOOPDEV -d blah 2>/dev/null && fail
$CRYPTSETUP -q remove $DEV_NAME || fail
remove_mapping
exit 0