mirror of
https://gitlab.com/cryptsetup/cryptsetup.git
synced 2025-12-13 20:00:08 +01:00
* 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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
118
lib/setup.c
118
lib/setup.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
358
src/cryptsetup.c
358
src/cryptsetup.c
@@ -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,
|
||||
¶ms);
|
||||
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));
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user