* Require device device-mapper to build and do not use backend wrapper for dm calls.
* Move memory locking and dm initialization to command layer.
* Increase priority of process if memory is locked.
+ * Add log macros and make logging modre consitent.
+ * Move command successful messages to verbose level.
+ * Introduce --debug parameter.
2009-08-17 Milan Broz <mbroz@redhat.com>
* Fix PBKDF2 speed calculation for large passhrases.
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
#define DEFAULT_ALIGNMENT 4096
+#define MAX_TTY_PASSWORD_LEN 512
+
/* private struct crypt_options flags */
#define CRYPT_FLAG_FREE_DEVICE (1 << 24)
void safe_free(void *data);
void *safe_realloc(void *data, size_t size);
char *safe_strdup(const char *s);
+void set_debug_level(int level);
struct hash_backend *get_hash_backend(const char *name);
void put_hash_backend(struct hash_backend *backend);
int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
- const char *key_file, int passphrase_fd, int timeout, int how2verify);
+ const char *key_file, int passphrase_fd, int timeout, int how2verify, struct crypt_device *cd);
+
+void set_default_log(void (*log)(int class, char *msg));
+void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
+#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
+#define log_std(c, x...) logger(c, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
+#define log_err(c, x...) do { \
+ logger(c, CRYPT_LOG_ERROR, __FILE__, __LINE__, x); \
+ set_error(x); } while(0)
int memlock_inc(struct crypt_device *ctx);
int memlock_dec(struct crypt_device *ctx);
#define CRYPT_LOG_NORMAL 0
#define CRYPT_LOG_ERROR 1
+#define CRYPT_LOG_DEBUG -1 /* always on stdout */
struct interface_callbacks {
int (*yesDialog)(char *msg);
static void set_dm_error(int level, const char *file, int line,
const char *f, ...)
{
+ char *msg = NULL;
va_list va;
- if (level > 3)
- return;
-
va_start(va, f);
- set_error_va(f, va);
+ if (vasprintf(&msg, f, va) > 0) {
+ if (level < 4) {
+ log_err(_context, msg);
+ log_err(_context, "\n");
+ } else
+ log_dbg(msg);
+ }
+ free(msg);
va_end(va);
}
int dm_init(struct crypt_device *context, int check_kernel)
{
if (!_dm_use_count++) {
+ log_dbg("Initialising device-mapper backend%s.",
+ check_kernel ? "" : " (NO kernel check requested)");
if (check_kernel && !_dm_simple(DM_DEVICE_LIST_VERSIONS, NULL))
return -1;
dm_log_init(set_dm_error);
void dm_exit(void)
{
if (_dm_use_count && (!--_dm_use_count)) {
+ log_dbg("Releasing device-mapper backend.");
dm_log_init_verbose(0);
dm_log_init(NULL);
dm_lib_release();
do {
r = _dm_simple(DM_DEVICE_REMOVE, name) ? 0 : -EINVAL;
if (--retries && r) {
+ log_dbg("WARNING: other process locked internal device %s, %s.",
+ name, retries ? "retrying remove" : "giving up");
sleep(1);
}
} while (r == -EINVAL && retries);
#include "internal.h"
#include "blockdev.h"
#include "luks.h"
+#include "internal.h"
+
+struct crypt_device {
+ /* callbacks definitions */
+ void (*log)(int class, const char *msg, void *usrptr);
+ void *log_usrptr;
+};
struct device_infos {
uint64_t size;
#define at_least_one(a) ({ __typeof__(a) __at_least_one=(a); (__at_least_one)?__at_least_one:1; })
-static void logger(struct crypt_options *options, int class, char *format, ...) {
+/* Log helper */
+static void (*_default_log)(int class, char *msg) = NULL;
+static int _debug_level = 0;
+
+void crypt_set_debug_level(int level)
+{
+ _debug_level = level;
+}
+
+void set_default_log(void (*log)(int class, char *msg))
+{
+ _default_log = log;
+}
+
+void logger(struct crypt_device *cd, int class, const char *file,
+ int line, const char *format, ...)
+{
va_list argp;
char *target = NULL;
va_start(argp, format);
- if (vasprintf(&target, format, argp) > 0)
- options->icb->log(class, target);
+ if (vasprintf(&target, format, argp) > 0) {
+ if (class >= 0) {
+ if (cd && cd->log)
+ cd->log(class, target, cd->log_usrptr);
+ else if (_default_log)
+ _default_log(class, target);
+#ifdef CRYPT_DEBUG
+ } else if (_debug_level)
+ printf("# %s:%d %s\n", file ?: "?", line, target);
+#else
+ } else if (_debug_level)
+ printf("# %s\n", target);
+#endif
+ }
va_end(argp);
free(target);
}
-static void hexprintICB(struct crypt_options *options, int class, char *d, int n)
+static void hexprintICB(struct crypt_device *cd, char *d, int n)
{
int i;
for(i = 0; i < n; i++)
- logger(options, class, "%02hhx ", (char)d[i]);
+ log_std(cd, "%02hhx ", (char)d[i]);
}
/*
* from binary file: check if there is sufficently large key material
* interactive & from fd: hash if requested, otherwise crop or pad with '0'
*/
-
-static char *process_key(struct crypt_options *options, char *pass, int passLen) {
+static char *process_key(struct crypt_device *cd,
+ struct crypt_options *options,
+ const char *pass, size_t passLen)
+{
char *key = safe_alloc(options->key_size);
memset(key, 0, options->key_size);
/* key is coming from binary file */
if (options->key_file && strcmp(options->key_file, "-")) {
if(passLen < options->key_size) {
- set_error("Could not read %d bytes from key file",
- options->key_size);
+ log_err(cd, _("Cannot not read %d bytes from key file %s.\n"),
+ options->key_size, options->key_file);
safe_free(key);
return NULL;
- }
+ }
memcpy(key,pass,options->key_size);
return key;
}
key, options->key_size,
pass, passLen) < 0)
{
+ log_err(cd, _("Key processing error.\n"));
safe_free(key);
return NULL;
}
return r;
}
-static int parse_into_name_and_mode(const char *nameAndMode, char *name,
- char *mode)
+static int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode)
{
/* Token content stringification, see info cpp/stringification */
#define str(s) #s
int r;
if(sscanf(nameAndMode,scanpattern1, name, mode) != 2) {
- if((r = sscanf(nameAndMode,scanpattern2,name)) == 1) {
+ if((r = sscanf(nameAndMode,scanpattern2,name)) == 1)
strncpy(mode,"cbc-plain",10);
- }
- else {
- set_error("no known cipher-spec pattern detected");
+ else
return -EINVAL;
- }
}
return 0;
-#undef sp1
-#undef sp2
+#undef scanpattern1
+#undef scanpattern2
#undef str
#undef xstr
}
-static int keyslot_is_valid(int keySlotIndex, struct crypt_options *options)
+static int keyslot_is_valid(struct crypt_device *cd, int keySlotIndex)
{
if(keySlotIndex >= LUKS_NUMKEYS || keySlotIndex < 0) {
- logger(options,CRYPT_LOG_ERROR,"Key slot %d is invalid, please pick between 0 and %d.\n", keySlotIndex, LUKS_NUMKEYS - 1);
+ log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"),
+ keySlotIndex, LUKS_NUMKEYS - 1);
return 0;
}
}
/* Select free keyslot or verifies that the one specified is empty */
-static int keyslot_from_option(int keySlotOption, struct luks_phdr *hdr, struct crypt_options *options) {
+static int keyslot_from_option(struct crypt_device *cd, int keySlotOption, struct luks_phdr *hdr) {
if(keySlotOption >= 0) {
- if(!keyslot_is_valid(keySlotOption, options))
+ if(!keyslot_is_valid(cd, keySlotOption))
return -EINVAL;
else if(hdr->keyblock[keySlotOption].active != LUKS_KEY_DISABLED) {
- logger(options,CRYPT_LOG_ERROR,"Key slot %d is full, please pick another one", keySlotOption);
+ log_err(cd, _("Key slot %d is full, please select another one.\n"),
+ keySlotOption);
return -EINVAL;
} else {
return keySlotOption;
if(hdr->keyblock[i].active == LUKS_KEY_DISABLED) break;
}
if(i==LUKS_NUMKEYS) {
- logger(options,CRYPT_LOG_ERROR,"All slots full");
+ log_err(cd, _("All key slots full.\n"));
return -EINVAL;
}
return i;
}
}
-static int __crypt_create_device(int reload, struct crypt_options *options)
+static int create_device_helper(int reload, struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
struct device_infos infos;
char *key = NULL;
unsigned int keyLen;
return r;
} else {
if (r >= 0) {
- set_error("Device %s already exists.", options->name);
+ log_err(cd, _("Device %s already exists.\n"), options->name);
return -EEXIST;
}
if (r != -ENODEV)
}
if (options->key_size < 0 || options->key_size > 1024) {
- set_error("Invalid key size");
+ log_err(cd, _("Invalid key size %d.\n"), options->key_size);
return -EINVAL;
}
if (!options->size) {
options->size = infos.size;
if (!options->size) {
- set_error("Not a block device");
+ log_err(cd, "Not a block device");
return -ENOTBLK;
}
if (options->size <= options->offset) {
- set_error("Invalid offset");
+ log_err(cd, "Invalid offset");
return -EINVAL;
}
options->size -= options->offset;
if (infos.readonly)
options->flags |= CRYPT_FLAG_READONLY;
- get_key("Enter passphrase: ", &key, &keyLen, options->key_size, options->key_file, options->passphrase_fd, options->timeout, options->flags);
+ get_key("Enter passphrase: ", &key, &keyLen, options->key_size,
+ options->key_file, options->passphrase_fd, options->timeout, options->flags, NULL);
if (!key) {
- set_error("Key reading error");
+ log_err(cd, "Key reading error");
return -ENOENT;
}
- processed_key = process_key(options,key,keyLen);
+ processed_key = process_key(cd, options, key, keyLen);
safe_free(key);
- if (!processed_key) {
- const char *error=get_error();
- if(error) {
- char *c_error_handling_sucks = NULL;
- if (asprintf(&c_error_handling_sucks,"Key processing error: %s",error) > 0)
- set_error(c_error_handling_sucks);
- free(c_error_handling_sucks);
- } else
- set_error("Key processing error");
+ if (!processed_key)
return -ENOENT;
- }
r = dm_create_device(options->name, options->device, options->cipher,
NULL, options->size, options->skip, options->offset,
return r;
}
-static int __crypt_query_device(int details, struct crypt_options *options)
+static int luks_remove_helper(struct crypt_device *cd,
+ struct crypt_options *options, int supply_it)
{
- int read_only, r;
+ struct luks_masterkey *mk;
+ struct luks_phdr hdr;
+ char *password=NULL;
+ unsigned int passwordLen;
+ const char *device = options->device;
+ int keyIndex;
+ int openedIndex;
+ int r, last_slot;
- r = dm_status_device(options->name);
- if (r == -ENODEV)
- return 0;
+ if (!LUKS_device_ready(options->device, O_RDWR))
+ return -ENOTBLK;
- r = dm_query_device(options->name, (char **)&options->device, &options->size,
- &options->skip, &options->offset, (char **)&options->cipher,
- &options->key_size, NULL, &read_only);
+ if(supply_it) {
+ get_key("Enter LUKS passphrase to be deleted: ",&password,&passwordLen, 0, options->new_key_file,
+ options->passphrase_fd, options->timeout, options->flags, cd);
+ if(!password) {
+ r = -EINVAL; goto out;
+ }
- if (r < 0)
- return r;
+ keyIndex = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk, cd);
+ if(keyIndex < 0) {
+ log_err(cd, "No remaining key available with this passphrase.\n");
+ r = -EPERM; goto out;
+ } else
+ log_std(cd ,"key slot %d selected for deletion.\n", keyIndex);
- if (read_only)
- options->flags |= CRYPT_FLAG_READONLY;
+ safe_free(password);
+ password = NULL;
+ } else {
+ keyIndex = options->key_slot;
+ if (!keyslot_is_valid(cd, keyIndex)) {
+ r = -EINVAL; goto out;
+ }
+ }
- options->flags |= CRYPT_FLAG_FREE_DEVICE;
- options->flags |= CRYPT_FLAG_FREE_CIPHER;
+ last_slot = LUKS_is_last_keyslot(options->device, keyIndex);
+ if(last_slot && !(options->icb->yesDialog(_("This is the last keyslot. Device will become unusable after purging this key.")))) {
+ r = -EINVAL; goto out;
+ }
- return 1;
+ if(options->flags & CRYPT_FLAG_VERIFY_ON_DELKEY) {
+ options->flags &= ~CRYPT_FLAG_VERIFY_ON_DELKEY;
+ get_key("Enter any remaining LUKS passphrase: ",&password,&passwordLen, 0, options->key_file,
+ options->passphrase_fd, options->timeout, options->flags, cd);
+ if(!password) {
+ r = -EINVAL; goto out;
+ }
+
+ r = LUKS_read_phdr(device, &hdr, 1, cd);
+ if(r < 0) {
+ options->icb->log(CRYPT_LOG_ERROR,"Failed to access device.\n");
+ r = -EIO; goto out;
+ }
+
+ if(!last_slot)
+ hdr.keyblock[keyIndex].active = LUKS_KEY_DISABLED;
+
+ openedIndex = LUKS_open_any_key_with_hdr(device, password, passwordLen, &hdr, &mk, cd);
+ /* Clean up */
+ if (openedIndex >= 0) {
+ LUKS_dealloc_masterkey(mk);
+ mk = NULL;
+ }
+ if(openedIndex < 0) {
+ log_err(cd, "No remaining key available with this passphrase.\n");
+ r = -EPERM; goto out;
+ } else
+ log_std(cd, "key slot %d verified.\n", openedIndex);
+ }
+ r = LUKS_del_key(device, keyIndex, cd);
+ if(r < 0) goto out;
+
+ r = 0;
+out:
+ safe_free(password);
+ return r;
+}
+
+/* OPTIONS: name, cipher, device, hash, key_file, key_size, key_slot,
+ * offset, size, skip, timeout, tries, passphrase_fd (ignored),
+ * flags, icb */
+int crypt_create_device(struct crypt_options *options)
+{
+ return create_device_helper(0, options);
+}
+
+/* OPTIONS: same as create above */
+int crypt_update_device(struct crypt_options *options)
+{
+ return create_device_helper(1, options);
}
-static int __crypt_resize_device(int details, struct crypt_options *options)
+/* OPTIONS: name, size, icb */
+int crypt_resize_device(struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
char *device, *cipher, *key = NULL;
uint64_t size, skip, offset;
int key_size, read_only, r;
if (!options->size) {
options->size = infos.size;
if (!options->size) {
- set_error("Not a block device");
+ log_err(cd, "Not a block device");
return -ENOTBLK;
}
if (options->size <= offset) {
- set_error("Invalid offset");
+ log_err(cd, "Invalid offset");
return -EINVAL;
}
options->size -= offset;
return r;
}
-static int __crypt_remove_device(int arg, struct crypt_options *options)
+/* OPTIONS: name, icb */
+int crypt_query_device(struct crypt_options *options)
+{
+ int read_only, r;
+
+ r = dm_status_device(options->name);
+ if (r == -ENODEV)
+ return 0;
+
+ r = dm_query_device(options->name, (char **)&options->device, &options->size,
+ &options->skip, &options->offset, (char **)&options->cipher,
+ &options->key_size, NULL, &read_only);
+
+ if (r < 0)
+ return r;
+
+ if (read_only)
+ options->flags |= CRYPT_FLAG_READONLY;
+
+ options->flags |= CRYPT_FLAG_FREE_DEVICE;
+ options->flags |= CRYPT_FLAG_FREE_CIPHER;
+
+ return 1;
+}
+
+/* OPTIONS: name, icb */
+int crypt_remove_device(struct crypt_options *options)
{
int r;
if (r < 0)
return r;
if (r > 0) {
- set_error("Device busy");
+ log_err(NULL, "Device busy");
return -EBUSY;
}
return dm_remove_device(options->name, 0, 0);
}
-static int __crypt_luks_format(int arg, struct crypt_options *options)
+/* OPTIONS: device, cipher, hash, align_payload, key_size (master key), key_slot
+ * new_key_file, iteration_time, timeout, flags, icb */
+int crypt_luksFormat(struct crypt_options *options)
{
- int r;
-
+ struct crypt_device *cd = NULL;
struct luks_phdr header;
struct luks_masterkey *mk=NULL;
char *password=NULL;
char cipherMode[LUKS_CIPHERMODE_L];
unsigned int passwordLen;
unsigned int PBKDF2perSecond = 0;
- int keyIndex;
+ int r, keyIndex;
if (!LUKS_device_ready(options->device, O_RDWR | O_EXCL))
return -ENOTBLK;
logger(options, CRYPT_LOG_ERROR, \
"offset of " #entry " = %d\n", (char *)(&header.entry)-(char *)(&header))
- logger(options, CRYPT_LOG_ERROR,
- "sizeof phdr %d, sizeof key slot %d\n",
+ log_err("sizeof phdr %d, sizeof key slot %d\n",
sizeof(struct luks_phdr),
sizeof(header.keyblock[0]));
#endif
r = parse_into_name_and_mode(options->cipher, cipherName, cipherMode);
- if(r < 0) return r;
+ if(r < 0) {
+ log_err(cd, _("No known cipher specification pattern detected.\n"));
+ return r;
+ }
- r = LUKS_generate_phdr(&header, mk, cipherName, cipherMode, options->hash, LUKS_STRIPES, options->align_payload);
+ r = LUKS_generate_phdr(&header, mk, cipherName, cipherMode, options->hash, LUKS_STRIPES, options->align_payload, NULL);
if(r < 0) return r;
- keyIndex = keyslot_from_option(options->key_slot, &header, options);
+ keyIndex = keyslot_from_option(NULL, options->key_slot, &header);
if(keyIndex == -EINVAL) {
r = -EINVAL; goto out;
}
#ifdef LUKS_DEBUG
logger(options, CRYPT_LOG_ERROR, "pitr %d\n", header.keyblock[0].passwordIterations);
#endif
- get_key("Enter LUKS passphrase: ",&password,&passwordLen, 0, options->new_key_file, options->passphrase_fd, options->timeout, options->flags);
+ get_key("Enter LUKS passphrase: ",&password,&passwordLen, 0, options->new_key_file,
+ options->passphrase_fd, options->timeout, options->flags, NULL);
if(!password) {
r = -EINVAL; goto out;
}
if(r < 0) goto out;
/* Set key, also writes phdr */
- r = LUKS_set_key(options->device, keyIndex, password, passwordLen, &header, mk);
+ r = LUKS_set_key(options->device, keyIndex, password, passwordLen, &header, mk, NULL);
if(r < 0) goto out;
r = 0;
return r;
}
-static int __crypt_luks_open(int arg, struct crypt_options *options)
+/* OPTIONS: name, device, key_size, key_file, timeout, tries, flags, icb */
+int crypt_luksOpen(struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
struct luks_masterkey *mk=NULL;
struct luks_phdr hdr;
char *prompt = NULL;
r = dm_status_device(options->name);
if (r >= 0) {
- set_error("Device %s already exists.", options->name);
+ log_err(cd, "Device %s already exists.", options->name);
return -EEXIST;
}
return -ENOTBLK;
if (get_device_infos(options->device, &infos) < 0) {
- set_error("Can't get device information.\n");
+ log_err(cd, "Can't get device information.\n");
return -ENOTBLK;
}
password = safe_alloc(passwordLen + 1);
strncpy(password, options->passphrase, passwordLen + 1);
tries = 0;
- } else if(get_key(prompt, &password, &passwordLen, options->key_size, options->key_file, options->passphrase_fd, options->timeout, options->flags))
+ } else if(get_key(prompt, &password, &passwordLen, options->key_size, options->key_file,
+ options->passphrase_fd, options->timeout, options->flags, cd))
tries--;
else
tries = 0;
r = -EINVAL; goto out;
}
- r = LUKS_open_any_key(options->device, password, passwordLen, &hdr, &mk);
+ r = LUKS_open_any_key(options->device, password, passwordLen, &hdr, &mk, cd);
if (r == -EPERM)
- set_error("No key available with this passphrase.\n");
+ log_err(cd, "No key available with this passphrase.\n");
if (r < 0)
goto out1;
- logger(options, CRYPT_LOG_NORMAL,"key slot %d unlocked.\n", r);
+ log_err(NULL, "key slot %d unlocked.\n", r);
options->offset = hdr.payloadOffset;
options->size = infos.size;
if (!options->size) {
- set_error("Not a block device.\n");
+ log_err(cd, "Not a block device.\n");
r = -ENOTBLK; goto out2;
}
if (options->size <= options->offset) {
- set_error("Invalid offset");
+ log_err(cd, "Invalid offset");
r = -EINVAL; goto out2;
}
options->size -= options->offset;
return r;
}
-static int __crypt_luks_add_key(int arg, struct crypt_options *options)
+/* OPTIONS: device, keys_slot, key_file, timeout, flags, icb */
+int crypt_luksKillSlot(struct crypt_options *options)
{
+ return luks_remove_helper(NULL, options, 0);
+}
+
+/* OPTIONS: device, new_key_file, key_file, timeout, flags, icb */
+int crypt_luksRemoveKey(struct crypt_options *options)
+{
+ return luks_remove_helper(NULL, options, 1);
+}
+
+/* OPTIONS: device, new_key_file, key_file, key_slot, flags,
+ iteration_time, timeout, icb */
+int crypt_luksAddKey(struct crypt_options *options)
+{
+ struct crypt_device *cd = NULL;
struct luks_masterkey *mk=NULL;
struct luks_phdr hdr;
char *password=NULL; unsigned int passwordLen;
if (!LUKS_device_ready(options->device, O_RDWR))
return -ENOTBLK;
- r = LUKS_read_phdr(device, &hdr);
+ r = LUKS_read_phdr(device, &hdr, 1, cd);
if(r < 0) return r;
- keyIndex = keyslot_from_option(options->key_slot, &hdr, options);
+ keyIndex = keyslot_from_option(cd, options->key_slot, &hdr);
if(keyIndex == -EINVAL) {
r = -EINVAL; goto out;
}
options->key_file,
options->passphrase_fd,
options->timeout,
- options->flags & ~(CRYPT_FLAG_VERIFY | CRYPT_FLAG_VERIFY_IF_POSSIBLE));
+ options->flags & ~(CRYPT_FLAG_VERIFY | CRYPT_FLAG_VERIFY_IF_POSSIBLE), cd);
if(!password) {
r = -EINVAL; goto out;
}
- r = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk);
+ r = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk, cd);
if(r < 0) {
options->icb->log(CRYPT_LOG_ERROR,"No key available with this passphrase.\n");
r = -EPERM; goto out;
- } else
- logger(options, CRYPT_LOG_NORMAL,"key slot %d unlocked.\n", r);
-
+ }
safe_free(password);
get_key("Enter new passphrase for key slot: ",
options->new_key_file,
options->passphrase_fd,
options->timeout,
- options->flags);
+ options->flags, cd);
if(!password) {
r = -EINVAL; goto out;
}
if (r < 0) goto out;
hdr.keyblock[keyIndex].passwordIterations = at_least_one(PBKDF2perSecond * ((float)options->iteration_time / 1000));
- r = LUKS_set_key(device, keyIndex, password, passwordLen, &hdr, mk);
+ r = LUKS_set_key(device, keyIndex, password, passwordLen, &hdr, mk, cd);
if(r < 0) goto out;
r = 0;
return r;
}
-static int luks_remove_helper(int arg, struct crypt_options *options, int supply_it)
-{
- struct luks_masterkey *mk;
- struct luks_phdr hdr;
- char *password=NULL;
- unsigned int passwordLen;
- const char *device = options->device;
- int keyIndex;
- int openedIndex;
- int r, last_slot;
-
- if (!LUKS_device_ready(options->device, O_RDWR))
- return -ENOTBLK;
-
- if(supply_it) {
- get_key("Enter LUKS passphrase to be deleted: ",&password,&passwordLen, 0, options->new_key_file,
- options->passphrase_fd, options->timeout, options->flags);
- if(!password) {
- r = -EINVAL; goto out;
- }
-
- keyIndex = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk);
- if(keyIndex < 0) {
- options->icb->log(CRYPT_LOG_ERROR,"No remaining key available with this passphrase.\n");
- r = -EPERM; goto out;
- } else
- logger(options, CRYPT_LOG_NORMAL,"key slot %d selected for deletion.\n", keyIndex);
-
- safe_free(password);
- password = NULL;
- } else {
- keyIndex = options->key_slot;
- if (!keyslot_is_valid(keyIndex, options)) {
- r = -EINVAL; goto out;
- }
- }
-
- last_slot = LUKS_is_last_keyslot(options->device, keyIndex);
- if(last_slot && !(options->icb->yesDialog(_("This is the last keyslot. Device will become unusable after purging this key.")))) {
- r = -EINVAL; goto out;
- }
-
- if(options->flags & CRYPT_FLAG_VERIFY_ON_DELKEY) {
- options->flags &= ~CRYPT_FLAG_VERIFY_ON_DELKEY;
- get_key("Enter any remaining LUKS passphrase: ",&password,&passwordLen, 0, options->key_file, options->passphrase_fd, options->timeout, options->flags);
- if(!password) {
- r = -EINVAL; goto out;
- }
-
- r = LUKS_read_phdr(device, &hdr);
- if(r < 0) {
- options->icb->log(CRYPT_LOG_ERROR,"Failed to access device.\n");
- r = -EIO; goto out;
- }
-
- if(!last_slot)
- hdr.keyblock[keyIndex].active = LUKS_KEY_DISABLED;
-
- openedIndex = LUKS_open_any_key_with_hdr(device, password, passwordLen, &hdr, &mk);
- /* Clean up */
- if (openedIndex >= 0) {
- LUKS_dealloc_masterkey(mk);
- mk = NULL;
- }
- if(openedIndex < 0) {
- options->icb->log(CRYPT_LOG_ERROR,"No remaining key available with this passphrase.\n");
- r = -EPERM; goto out;
- } else
- logger(options, CRYPT_LOG_NORMAL,"key slot %d verified.\n", openedIndex);
- }
- r = LUKS_del_key(device, keyIndex);
- if(r < 0) goto out;
-
- r = 0;
-out:
- safe_free(password);
- return r;
-}
-
-static int __crypt_luks_kill_slot(int arg, struct crypt_options *options) {
- return luks_remove_helper(arg, options, 0);
-}
-
-static int __crypt_luks_remove_key(int arg, struct crypt_options *options) {
- return luks_remove_helper(arg, options, 1);
-}
-
-static int crypt_job(int (*job)(int arg, struct crypt_options *options),
- int arg, struct crypt_options *options)
-{
- int r;
-
- r = job(arg, options);
-
- if (r >= 0)
- set_error(NULL);
-
- return r;
-}
-
-int crypt_create_device(struct crypt_options *options)
-{
- return crypt_job(__crypt_create_device, 0, options);
-}
-
-int crypt_update_device(struct crypt_options *options)
-{
- return crypt_job(__crypt_create_device, 1, options);
-}
-
-int crypt_resize_device(struct crypt_options *options)
-{
- return crypt_job(__crypt_resize_device, 0, options);
-}
-
-int crypt_query_device(struct crypt_options *options)
-{
- return crypt_job(__crypt_query_device, 1, options);
-}
-
-int crypt_remove_device(struct crypt_options *options)
-{
- return crypt_job(__crypt_remove_device, 0, options);
-
-}
-
-int crypt_luksFormat(struct crypt_options *options)
-{
- return crypt_job(__crypt_luks_format, 0, options);
-}
-
-int crypt_luksOpen(struct crypt_options *options)
-{
- return crypt_job(__crypt_luks_open, 0, options);
-}
-
-int crypt_luksKillSlot(struct crypt_options *options)
-{
- return crypt_job(__crypt_luks_kill_slot, 0, options);
-}
-
-int crypt_luksRemoveKey(struct crypt_options *options)
-{
- return crypt_job(__crypt_luks_remove_key, 0, options);
-}
-
-int crypt_luksAddKey(struct crypt_options *options)
-{
- return crypt_job(__crypt_luks_add_key, 0, options);
-}
-
+/* OPTIONS: device, icb */
int crypt_luksUUID(struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
struct luks_phdr hdr;
int r;
- r = LUKS_read_phdr(options->device,&hdr);
+ r = LUKS_read_phdr(options->device, &hdr, 1, cd);
if(r < 0) return r;
options->icb->log(CRYPT_LOG_NORMAL,hdr.uuid);
return 0;
}
+/* OPTIONS: device, icb */
int crypt_isLuks(struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
struct luks_phdr hdr;
- return LUKS_read_phdr(options->device,&hdr);
+ return LUKS_read_phdr(options->device, &hdr, 0, cd);
}
+/* OPTIONS: device, icb */
int crypt_luksDump(struct crypt_options *options)
{
+ struct crypt_device *cd = NULL;
struct luks_phdr hdr;
int r,i;
- r = LUKS_read_phdr(options->device,&hdr);
+ r = LUKS_read_phdr(options->device, &hdr, 1, cd);
if(r < 0) return r;
- logger(options, CRYPT_LOG_NORMAL, "LUKS header information for %s\n\n",options->device);
- logger(options, CRYPT_LOG_NORMAL, "Version: \t%d\n",hdr.version);
- logger(options, CRYPT_LOG_NORMAL, "Cipher name: \t%s\n",hdr.cipherName);
- logger(options, CRYPT_LOG_NORMAL, "Cipher mode: \t%s\n",hdr.cipherMode);
- logger(options, CRYPT_LOG_NORMAL, "Hash spec: \t%s\n",hdr.hashSpec);
- logger(options, CRYPT_LOG_NORMAL, "Payload offset:\t%d\n",hdr.payloadOffset);
- logger(options, CRYPT_LOG_NORMAL, "MK bits: \t%d\n",hdr.keyBytes*8);
- logger(options, CRYPT_LOG_NORMAL, "MK digest: \t");
- hexprintICB(options, CRYPT_LOG_NORMAL, hdr.mkDigest,LUKS_DIGESTSIZE);
- logger(options, CRYPT_LOG_NORMAL, "\n");
- logger(options, CRYPT_LOG_NORMAL, "MK salt: \t");
- hexprintICB(options, CRYPT_LOG_NORMAL, hdr.mkDigestSalt,LUKS_SALTSIZE/2);
- logger(options, CRYPT_LOG_NORMAL, "\n \t");
- hexprintICB(options, CRYPT_LOG_NORMAL, hdr.mkDigestSalt+LUKS_SALTSIZE/2,LUKS_SALTSIZE/2);
- logger(options, CRYPT_LOG_NORMAL, "\n");
- logger(options, CRYPT_LOG_NORMAL, "MK iterations: \t%d\n",hdr.mkDigestIterations);
- logger(options, CRYPT_LOG_NORMAL, "UUID: \t%s\n\n",hdr.uuid);
- for(i=0;i<LUKS_NUMKEYS;i++) {
+ log_std(cd, "LUKS header information for %s\n\n", options->device);
+ log_std(cd, "Version: \t%d\n", hdr.version);
+ log_std(cd, "Cipher name: \t%s\n", hdr.cipherName);
+ log_std(cd, "Cipher mode: \t%s\n", hdr.cipherMode);
+ log_std(cd, "Hash spec: \t%s\n", hdr.hashSpec);
+ log_std(cd, "Payload offset:\t%d\n", hdr.payloadOffset);
+ log_std(cd, "MK bits: \t%d\n", hdr.keyBytes * 8);
+ log_std(cd, "MK digest: \t");
+ hexprintICB(cd, hdr.mkDigest, LUKS_DIGESTSIZE);
+ log_std(cd, "\n");
+ log_std(cd, "MK salt: \t");
+ hexprintICB(cd, hdr.mkDigestSalt, LUKS_SALTSIZE/2);
+ log_std(cd, "\n \t");
+ hexprintICB(cd, hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
+ log_std(cd, "\n");
+ log_std(cd, "MK iterations: \t%d\n", hdr.mkDigestIterations);
+ log_std(cd, "UUID: \t%s\n\n", hdr.uuid);
+ for(i = 0; i < LUKS_NUMKEYS; i++) {
if(hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
- logger(options, CRYPT_LOG_NORMAL, "Key Slot %d: ENABLED\n",i);
- logger(options, CRYPT_LOG_NORMAL, "\tIterations: \t%d\n",hdr.keyblock[i].passwordIterations);
- logger(options, CRYPT_LOG_NORMAL, "\tSalt: \t");
- hexprintICB(options, CRYPT_LOG_NORMAL, hdr.keyblock[i].passwordSalt,LUKS_SALTSIZE/2);
- logger(options, CRYPT_LOG_NORMAL, "\n\t \t");
- hexprintICB(options, CRYPT_LOG_NORMAL, hdr.keyblock[i].passwordSalt+LUKS_SALTSIZE/2,LUKS_SALTSIZE/2);
- logger(options, CRYPT_LOG_NORMAL, "\n");
-
- logger(options, CRYPT_LOG_NORMAL, "\tKey material offset:\t%d\n",hdr.keyblock[i].keyMaterialOffset);
- logger(options, CRYPT_LOG_NORMAL, "\tAF stripes: \t%d\n",hdr.keyblock[i].stripes);
+ log_std(cd, "Key Slot %d: ENABLED\n",i);
+ log_std(cd, "\tIterations: \t%d\n",
+ hdr.keyblock[i].passwordIterations);
+ log_std(cd, "\tSalt: \t");
+ hexprintICB(cd, hdr.keyblock[i].passwordSalt,
+ LUKS_SALTSIZE/2);
+ log_std(cd, "\n\t \t");
+ hexprintICB(cd, hdr.keyblock[i].passwordSalt +
+ LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
+ log_std(cd, "\n");
+
+ log_std(cd, "\tKey material offset:\t%d\n",
+ hdr.keyblock[i].keyMaterialOffset);
+ log_std(cd, "\tAF stripes: \t%d\n",
+ hdr.keyblock[i].stripes);
}
else
- logger(options, CRYPT_LOG_NORMAL, "Key Slot %d: DISABLED\n",i);
+ log_std(cd, "Key Slot %d: DISABLED\n", i);
}
return 0;
}
-
void crypt_get_error(char *buf, size_t size)
{
const char *error = get_error();
#include "libcryptsetup.h"
#include "internal.h"
-
struct safe_allocation {
size_t size;
char data[1];
void set_error_va(const char *fmt, va_list va)
{
+ int r;
if(error) {
- free(error);
- error=NULL;
+ free(error);
+ error = NULL;
}
if(!fmt) return;
- if (vasprintf(&error, fmt, va) < 0) {
+ r = vasprintf(&error, fmt, va);
+ if (r < 0) {
free(error);
error = NULL;
+ return;
}
+
+ if (r && error[r - 1] == '\n')
+ error[r - 1] = '\0';
}
void set_error(const char *fmt, ...)
buf = orig_buf;
r = read(fd, buf, solid);
- if(r < 0 || r != solid) {
- set_error("read failed in read_blockwise.\n");
+ if(r < 0 || r != solid)
goto out;
- }
if (hangover) {
hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
if (select(fd+1, &fds, NULL, NULL, &t) > 0)
failed = untimed_read(fd, pass, maxlen);
- else
- set_error("Operation timed out");
+
return failed;
}
outfd = STDERR_FILENO;
}
- if (tcgetattr(infd, &orig)) {
- set_error("Unable to get terminal");
+ if (tcgetattr(infd, &orig))
goto out_err;
- }
+
memcpy(&tmp, &orig, sizeof(tmp));
tmp.c_lflag &= ~ECHO;
*/
int get_key(char *prompt, char **key, unsigned int *passLen, int key_size,
- const char *key_file, int passphrase_fd, int timeout, int how2verify)
+ const char *key_file, int passphrase_fd, int timeout, int how2verify, struct crypt_device *cd)
{
int fd;
const int verify = how2verify & CRYPT_FLAG_VERIFY;
} else if (key_file) {
fd = open(key_file, O_RDONLY);
if (fd < 0) {
- char buf[128];
- set_error("Error opening key file: %s",
- strerror_r(errno, buf, 128));
+ log_err(cd, "Failed to open key file %s.\n", key_file);
goto out_err;
}
newline_stop = 0;
* of key bytes (default or passed by -s) */
read_horizon = key_size;
} else {
- fd = passphrase_fd;
+ fd = STDIN_FILENO;
newline_stop = 1;
read_horizon = 0; /* Infinite, if read from terminal or fd */
}
if(isatty(fd)) {
int i;
- pass = safe_alloc(512);
- if (!pass || (i = interactive_pass(prompt, pass, 512, timeout))) {
- set_error("Error reading passphrase");
+ pass = safe_alloc(MAX_TTY_PASSWORD_LEN);
+ if (!pass || (i = interactive_pass(prompt, pass, MAX_TTY_PASSWORD_LEN, timeout))) {
+ log_err(cd, "Error reading passphrase from terminal.\n");
goto out_err;
}
if (verify || verify_if_possible) {
- char pass_verify[512];
+ char pass_verify[MAX_TTY_PASSWORD_LEN];
i = interactive_pass("Verify passphrase: ", pass_verify, sizeof(pass_verify), timeout);
if (i || strcmp(pass, pass_verify) != 0) {
- set_error("Passphrases do not match");
+ log_err(cd, "Passphrases do not match.\n");
goto out_err;
}
memset(pass_verify, 0, sizeof(pass_verify));
int buflen, i;
if(verify) {
- set_error("Can't do passphrase verification on non-tty inputs");
+ log_err(cd, "Can't do passphrase verification on non-tty inputs.\n");
goto out_err;
}
/* The following for control loop does an exhausting
if(key_file && strcmp(key_file, "-") && read_horizon == 0) {
struct stat st;
if(stat(key_file, &st) < 0) {
- set_error("Can't stat key file");
+ log_err(cd, "Failed to stat key file %s.\n", key_file);
goto out_err;
}
if(!S_ISREG(st.st_mode)) {
- // set_error("Can't do exhausting read on non regular files");
- // goto out_err;
- fprintf(stderr,"Warning: exhausting read requested, but key file is not a regular file, function might never return.\n");
+ log_err(cd, "Warning: exhausting read requested, but key file %s"
+ " is not a regular file, function might never return.\n",
+ key_file);
}
}
buflen = 0;
buflen += 128;
pass = safe_realloc(pass, buflen);
if (!pass) {
- set_error("Not enough memory while "
- "reading passphrase");
+ log_err(cd, "Out of memory while reading passphrase.\n");
goto out_err;
}
}
int memlock_inc(struct crypt_device *ctx)
{
if (!_memlock_count++) {
+ log_dbg("Locking memory.");
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
- set_error(_("WARNING!!! Possibly insecure memory. Are you root?\n"));
+ log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
_memlock_count--;
return 0;
}
errno = 0;
if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
- set_error(_("Cannot get process priority.\n"));
+ log_err(ctx, _("Cannot get process priority.\n"));
else
if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY))
- set_error(_("setpriority %u failed: %s"),
+ log_err(ctx, _("setpriority %u failed: %s"),
DEFAULT_PROCESS_PRIORITY, strerror(errno));
}
return _memlock_count ? 1 : 0;
int memlock_dec(struct crypt_device *ctx)
{
if (_memlock_count && (!--_memlock_count)) {
+ log_dbg("Unlocking memory.");
if (munlockall())
- set_error(_("Cannot unlock memory."));
+ log_err(ctx, _("Cannot unlock memory."));
if (setpriority(PRIO_PROCESS, 0, _priority))
- set_error(_("setpriority %u failed: %s"), _priority, strerror(errno));
+ log_err(ctx, _("setpriority %u failed: %s"), _priority, strerror(errno));
}
return _memlock_count ? 1 : 0;
}
const char *device, unsigned int payloadOffset,
const char *key, size_t keyLength,
unsigned int sector, size_t srcLength,
- int mode)
+ int mode, struct crypt_device *ctx)
{
int device_sector_size = sector_size_for_device(device);
uint64_t size;
* device's sector size, otherwise the mapping will be refused.
*/
if(device_sector_size < 0) {
- set_error(_("Unable to obtain sector size for %s"),device);
+ log_err(ctx, _("Unable to obtain sector size for %s"), device);
return -EINVAL;
}
- set_error(NULL);
size = round_up_modulo(srcLength,device_sector_size)/SECTOR_SIZE;
cleaner_size = size;
const char *device,
unsigned int sector,
ssize_t (*func)(int, void *, size_t),
- int mode)
+ int mode,
+ struct crypt_device *ctx)
{
char *name = NULL;
char *fullpath = NULL;
int r = -1;
if(dmDir == NULL) {
- fputs(_("Failed to obtain device mapper directory."), stderr);
+ log_err(ctx, _("Failed to obtain device mapper directory."));
return -1;
}
if(asprintf(&name,"temporary-cryptsetup-%d",getpid()) == -1 ||
r = -ENOMEM;
goto out1;
}
-
+
signal(SIGINT, sigint_handler);
cleaner_name = name;
r = setup_mapping(dmCipherSpec, name, device, hdr->payloadOffset,
- key, keyLength, sector, srcLength, mode);
+ key, keyLength, sector, srcLength, mode, ctx);
if(r < 0) {
- set_error("Failed to setup dm-crypt key mapping for device %s.\n"
- "Check that kernel supports %s cipher (check syslog for more info).\n%s",
- device, dmCipherSpec,
- _error_hint(hdr->cipherName, hdr->cipherMode, keyLength * 8));
+ log_err(ctx, _("Failed to setup dm-crypt key mapping for device %s.\n"
+ "Check that kernel supports %s cipher (check syslog for more info).\n%s"),
+ device, dmCipherSpec,
+ _error_hint(hdr->cipherName, hdr->cipherMode, keyLength * 8));
r = -EIO;
goto out1;
}
devfd = open(fullpath, mode | O_DIRECT | O_SYNC); /* devfd is a global var */
if(devfd == -1) {
+ log_err(ctx, _("Failed to open temporary keystore device.\n"));
r = -EIO;
goto out2;
}
r = func(devfd,src,srcLength);
if(r < 0) {
+ log_err(ctx, _("Failed to access temporary keystore device.\n"));
r = -EIO;
goto out3;
}
struct luks_phdr *hdr,
char *key, size_t keyLength,
const char *device,
- unsigned int sector)
+ unsigned int sector,
+ struct crypt_device *ctx)
{
return LUKS_endec_template(src,srcLength,hdr,key,keyLength, device, sector,
(ssize_t (*)(int, void *, size_t)) write_blockwise,
- O_RDWR);
+ O_RDWR, ctx);
}
int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
struct luks_phdr *hdr,
char *key, size_t keyLength,
const char *device,
- unsigned int sector)
+ unsigned int sector,
+ struct crypt_device *ctx)
{
return LUKS_endec_template(dst,dstLength,hdr,key,keyLength, device,
- sector, read_blockwise, O_RDONLY);
+ sector, read_blockwise, O_RDONLY, ctx);
}
return mk;
}
-int LUKS_read_phdr(const char *device, struct luks_phdr *hdr)
+int LUKS_read_phdr(
+ const char *device,
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ struct crypt_device *ctx)
{
int devfd = 0, r = 0;
unsigned int i;
uint64_t size;
char luksMagic[] = LUKS_MAGIC;
+ log_dbg("Reading LUKS header of size %d from device %s",
+ sizeof(struct luks_phdr), device);
+
devfd = open(device,O_RDONLY | O_DIRECT | O_SYNC);
if(-1 == devfd) {
- set_error(_("Can't open device: %s\n"), device);
+ log_err(ctx, _("Cannot open device %s.\n"), device);
return -EINVAL;
}
if(read_blockwise(devfd, hdr, sizeof(struct luks_phdr)) < sizeof(struct luks_phdr)) {
r = -EIO;
} else if(memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */
- set_error(_("%s is not a LUKS partition\n"), device);
+ log_dbg("LUKS header not detected.");
+ if (require_luks_device)
+ log_err(ctx, _("%s is not a LUKS device.\n"), device);
+ else
+ set_error(_("%s is not a LUKS device."), device);
r = -EINVAL;
} else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */
- set_error(_("unknown LUKS version %d\n"), hdr->version);
+ log_err(ctx, _("Unsupported LUKS version %d.\n"), hdr->version);
r = -EINVAL;
} else if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) {
- set_error(_("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
+ log_err(ctx, _("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec);
r = -EINVAL;
} else {
hdr->payloadOffset = ntohl(hdr->payloadOffset);
}
#ifdef BLKGETSIZE64
- if (ioctl(devfd, BLKGETSIZE64, &size) < 0 ||
- size < (uint64_t)hdr->payloadOffset) {
- set_error(_("LUKS header detected but device %s is too small.\n"), device);
+ if (r == 0 && (ioctl(devfd, BLKGETSIZE64, &size) < 0 ||
+ size < (uint64_t)hdr->payloadOffset)) {
+ log_err(ctx, _("LUKS header detected but device %s is too small.\n"), device);
r = -EINVAL;
}
#endif
return r;
}
-int LUKS_write_phdr(const char *device, struct luks_phdr *hdr)
+int LUKS_write_phdr(
+ const char *device,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx)
{
int devfd = 0;
unsigned int i;
struct luks_phdr convHdr;
int r;
+ log_dbg("Updating LUKS header of size %d on device %s",
+ sizeof(struct luks_phdr), device);
+
devfd = open(device,O_RDWR | O_DIRECT | O_SYNC);
if(-1 == devfd) {
- set_error(_("Can't open device %s"), device);
+ log_err(ctx, _("Cannot open device %s.\n"), device);
return -EINVAL;
}
}
r = write_blockwise(devfd, &convHdr, sizeof(struct luks_phdr)) < sizeof(struct luks_phdr) ? -EIO : 0;
-
+ if (r)
+ log_err(ctx, _("Error during update of LUKS header on device %s.\n"), device);
close(devfd);
+
return r;
}
-int LUKS_generate_phdr(struct luks_phdr *header,
- const struct luks_masterkey *mk,
- const char *cipherName, const char *cipherMode, const char *hashSpec,
- unsigned int stripes,
- unsigned int alignPayload)
+int LUKS_generate_phdr(
+ struct luks_phdr *header,
+ const struct luks_masterkey *mk,
+ const char *cipherName, const char *cipherMode, const char *hashSpec,
+ unsigned int stripes,
+ unsigned int alignPayload,
+ struct crypt_device *ctx)
{
unsigned int i=0;
unsigned int blocksPerStripeSet = div_round_up(mk->keyLength*stripes,SECTOR_SIZE);
header->keyBytes=mk->keyLength;
+ log_dbg("Generating LUKS header version %d using hash %s, %s, %s, MK %d bytes",
+ header->version, header->hashSpec ,header->cipherName, header->cipherMode,
+ header->keyBytes);
+
r = getRandom(header->mkDigestSalt,LUKS_SALTSIZE);
if(r < 0) {
- set_error( _("Cannot create LUKS header: reading random salt failed."));
+ log_err(ctx, _("Cannot create LUKS header: reading random salt failed.\n"));
return r;
}
header->mkDigestIterations,
header->mkDigest,LUKS_DIGESTSIZE);
if(r < 0) {
- set_error( _("Cannot create LUKS header: header digest failed (using hash %s)."), header->hashSpec);
+ log_err(ctx, _("Cannot create LUKS header: header digest failed (using hash %s).\n"),
+ header->hashSpec);
return r;
}
uuid_generate(partitionUuid);
uuid_unparse(partitionUuid, header->uuid);
+ log_dbg("Data offset %d, UUID %s", header->payloadOffset, header->uuid);
+
return 0;
}
-int LUKS_set_key(const char *device, unsigned int keyIndex,
- const char *password, size_t passwordLen,
- struct luks_phdr *hdr, struct luks_masterkey *mk)
+int LUKS_set_key(
+ const char *device,
+ unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey *mk,
+ struct crypt_device *ctx)
{
char derivedKey[hdr->keyBytes];
char *AfKey;
int r;
if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) {
- set_error( _("key %d active, purge first"), keyIndex);
+ log_err(ctx, _("Key slot %d active, purge first.\n"), keyIndex);
return -EINVAL;
}
if(hdr->keyblock[keyIndex].stripes < LUKS_STRIPES) {
- set_error(_("key material section %d includes too few stripes. Header manipulation?"),keyIndex);
+ log_err(ctx, _("Key slot %d material includes too few stripes. Header manipulation?\n"),
+ keyIndex);
return -EINVAL;
}
+
r = getRandom(hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE);
if(r < 0) return r;
AfKey = (char *)malloc(AFEKSize);
if(AfKey == NULL) return -ENOMEM;
+ log_dbg("Using hash %s for AF in key slot %d, %d stripes",
+ hdr->hashSpec, keyIndex, hdr->keyblock[keyIndex].stripes);
r = AF_split(mk->key,AfKey,mk->keyLength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
if(r < 0) goto out;
+ log_dbg("Updating key slot %d [0x%04x] area on device %s.", keyIndex,
+ hdr->keyblock[keyIndex].keyMaterialOffset << 9, device);
/* Encryption via dm */
r = LUKS_encrypt_to_storage(AfKey,
AFEKSize,
derivedKey,
hdr->keyBytes,
device,
- hdr->keyblock[keyIndex].keyMaterialOffset);
+ hdr->keyblock[keyIndex].keyMaterialOffset,
+ ctx);
if(r < 0) {
if(!get_error())
- set_error("Failed to write to key storage");
+ log_err(ctx, _("Failed to write to key storage.\n"));
goto out;
}
/* Mark the key as active in phdr */
hdr->keyblock[keyIndex].active = LUKS_KEY_ENABLED;
- r = LUKS_write_phdr(device,hdr);
+ r = LUKS_write_phdr(device, hdr, ctx);
if(r < 0) goto out;
r = 0;
}
/* Try to open a particular key slot */
-int LUKS_open_key(const char *device,
- unsigned int keyIndex,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey *mk)
+int LUKS_open_key(
+ const char *device,
+ unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey *mk,
+ struct crypt_device *ctx)
{
char derivedKey[hdr->keyBytes];
char *AfKey;
derivedKey, hdr->keyBytes);
if(r < 0) goto out;
+ log_dbg("Reading key slot %d area.", keyIndex);
r = LUKS_decrypt_from_storage(AfKey,
AFEKSize,
hdr,
derivedKey,
hdr->keyBytes,
device,
- hdr->keyblock[keyIndex].keyMaterialOffset);
- if(r < 0) goto out;
+ hdr->keyblock[keyIndex].keyMaterialOffset,
+ ctx);
+ if(r < 0) {
+ log_err(ctx, _("Failed to read from key storage.\n"));
+ goto out;
+ }
r = AF_merge(AfKey,mk->key,mk->keyLength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
if(r < 0) goto out;
if(r < 0) goto out;
r = (memcmp(checkHashBuf,hdr->mkDigest, LUKS_DIGESTSIZE) == 0)?0:-EPERM;
+ if (r >= 0)
+ log_std(ctx, _("Key slot %d unlocked.\n"), keyIndex);
out:
free(AfKey);
-
- if( r < 0 && !get_error())
- set_error("Failed to read from key storage.");
-
return r;
}
-
/* Tries to open any key from a given LUKS device reading the header on its own */
-int LUKS_open_any_key(const char *device,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey **mk)
+int LUKS_open_any_key(
+ const char *device,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey **mk,
+ struct crypt_device *ctx)
{
int r;
- r = LUKS_read_phdr(device, hdr);
+ r = LUKS_read_phdr(device, hdr, 1, ctx);
if(r < 0)
return r;
- return LUKS_open_any_key_with_hdr(device,password,passwordLen,hdr,mk);
+ return LUKS_open_any_key_with_hdr(device,password,passwordLen,hdr,mk, ctx);
}
-int LUKS_open_any_key_with_hdr(const char *device,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey **mk)
+int LUKS_open_any_key_with_hdr(
+ const char *device,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey **mk,
+ struct crypt_device *ctx)
{
unsigned int i;
int r;
*mk=LUKS_alloc_masterkey(hdr->keyBytes);
for(i=0; i<LUKS_NUMKEYS; i++) {
- r = LUKS_open_key(device, i, password, passwordLen, hdr, *mk);
+ r = LUKS_open_key(device, i, password, passwordLen, hdr, *mk, ctx);
if(r == 0)
return i;
- /* Do not retry for errors that are no -EPERM or -ENOENT, former meaning password wrong, latter key slot inactive */
+ /* Do not retry for errors that are no -EPERM or -ENOENT,
+ former meaning password wrong, latter key slot inactive */
if ((r != -EPERM) && (r != -ENOENT))
return r;
}
/* Warning, early returns above */
+ log_err(ctx, _("No key available with this passphrase.\n"));
return -EPERM;
}
int r = 0;
devfd = open(device, O_RDWR | O_DIRECT | O_SYNC);
- if(devfd == -1) {
- set_error(_("Can't open device %s"), device);
+ if(devfd == -1)
return -EINVAL;
- }
buffer = (char *) malloc(bufLen);
if(!buffer) return -ENOMEM;
return r;
}
-int LUKS_del_key(const char *device, unsigned int keyIndex)
+int LUKS_del_key(
+ const char *device,
+ unsigned int keyIndex,
+ struct crypt_device *ctx)
{
struct luks_phdr hdr;
unsigned int startOffset, endOffset, stripesLen;
int r;
- r = LUKS_read_phdr(device, &hdr);
+ r = LUKS_read_phdr(device, &hdr, 1, ctx);
if(r != 0) {
/* placeholder */
} else if(keyIndex >= LUKS_NUMKEYS || hdr.keyblock[keyIndex].active != LUKS_KEY_ENABLED) {
- set_error(_("Key %d not active. Can't wipe.\n"), keyIndex);
+ log_err(ctx, _("Key slot %d is invalid, please select keyslot between 0 and %d.\n"),
+ keyIndex, LUKS_NUMKEYS - 1);
r = -ENOENT;
} else {
/* secure deletion of key material */
if(r == 0) {
/* mark the key as inactive in header */
hdr.keyblock[keyIndex].active = LUKS_KEY_DISABLED;
- r = LUKS_write_phdr(device, &hdr);
+ r = LUKS_write_phdr(device, &hdr, ctx);
}
}
unsigned int i;
int r;
- r = LUKS_read_phdr(device, &hdr);
+ r = LUKS_read_phdr(device, &hdr, 1, NULL);
if(r < 0) return r;
for(i = 0; i < LUKS_NUMKEYS; i++) {
struct luks_masterkey *LUKS_generate_masterkey(int keylength);
-int LUKS_generate_phdr(struct luks_phdr *header,
- const struct luks_masterkey *mk,
- const char *cipherName, const char *cipherMode, const char *hashSpec,
- unsigned int stripes,
- unsigned int alignPayload);
-
-int LUKS_read_phdr(const char *device, struct luks_phdr *hdr);
-
-int LUKS_write_phdr(const char *device, struct luks_phdr *hdr);
-
-int LUKS_set_key(const char *device,
- unsigned int keyIndex,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey *mk);
-
-int LUKS_open_key(const char *device,
- unsigned int keyIndex,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey *mk);
-
-int LUKS_open_any_key(const char *device,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey **mk);
-
-int LUKS_open_any_key_with_hdr(const char *device,
- const char *password,
- size_t passwordLen,
- struct luks_phdr *hdr,
- struct luks_masterkey **mk);
-
-
-int LUKS_del_key(const char *device, unsigned int keyIndex);
+int LUKS_generate_phdr(
+ struct luks_phdr *header,
+ const struct luks_masterkey *mk,
+ const char *cipherName, const char *cipherMode, const char *hashSpec,
+ unsigned int stripes,
+ unsigned int alignPayload,
+ struct crypt_device *ctx);
+
+int LUKS_read_phdr(
+ const char *device,
+ struct luks_phdr *hdr,
+ int require_luks_device,
+ struct crypt_device *ctx);
+
+int LUKS_write_phdr(
+ const char *device,
+ struct luks_phdr *hdr,
+ struct crypt_device *ctx);
+
+int LUKS_set_key(
+ const char *device,
+ unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey *mk,
+ struct crypt_device *ctx);
+
+int LUKS_open_key(
+ const char *device,
+ unsigned int keyIndex,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey *mk,
+ struct crypt_device *ctx);
+
+int LUKS_open_any_key(
+ const char *device,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey **mk,
+ struct crypt_device *ctx);
+
+int LUKS_open_any_key_with_hdr(
+ const char *device,
+ const char *password,
+ size_t passwordLen,
+ struct luks_phdr *hdr,
+ struct luks_masterkey **mk,
+ struct crypt_device *ctx);
+
+int LUKS_del_key(
+ const char *device,
+ unsigned int keyIndex,
+ struct crypt_device *ctx);
+
int LUKS_is_last_keyslot(const char *device, unsigned int keyIndex);
int LUKS_benchmarkt_iterations(const char *hash, unsigned int *count);
-int LUKS_encrypt_to_storage(char *src, size_t srcLength,
- struct luks_phdr *hdr,
- char *key, size_t keyLength,
- const char *device,
- unsigned int sector);
-
-int LUKS_decrypt_from_storage(char *dst, size_t dstLength,
- struct luks_phdr *hdr,
- char *key, size_t keyLength,
- const char *device,
- unsigned int sector);
+int LUKS_encrypt_to_storage(
+ char *src, size_t srcLength,
+ struct luks_phdr *hdr,
+ char *key, size_t keyLength,
+ const char *device,
+ unsigned int sector,
+ struct crypt_device *ctx);
+
+int LUKS_decrypt_from_storage(
+ char *dst, size_t dstLength,
+ struct luks_phdr *hdr,
+ char *key, size_t keyLength,
+ const char *device,
+ unsigned int sector,
+ struct crypt_device *ctx);
+
int LUKS_device_ready(const char *device, int mode);
#endif
#include "cryptsetup.h"
-static int opt_verbose = 1;
+static int opt_verbose = 0;
+static int opt_debug = 0;
static char *opt_cipher = NULL;
static char *opt_hash = NULL;
static int opt_verify_passphrase = 0;
int r = 1;
if(isatty(0) && !opt_batch_mode) {
- fprintf(stderr, "\nWARNING!\n========\n");
- fprintf(stderr, "%s\n\nAre you sure? (Type uppercase yes): ", msg);
+ log_std("\nWARNING!\n========\n");
+ log_std("%s\n\nAre you sure? (Type uppercase yes): ", msg);
if(getline(&answer, &size, stdin) == -1) {
perror("getline");
free(answer);
{
char error[256];
- if(!errcode) {
- fprintf(stderr, _("Command successful.\n"));
- return;
+ if(!errcode && opt_verbose) {
+ log_std(_("Command successful.\n"));
+ return;
}
crypt_get_error(error, sizeof(error));
+
if (!opt_verbose) {
char *error_ = strerror_r(errcode, error, sizeof(error));
if (error_ != error) {
}
}
- fprintf(stderr, _("Command failed"));
+ log_err(_("Command failed"));
if (*error)
- fprintf(stderr, ": %s\n", error);
+ log_err(": %s\n", error);
else
- fputs(".\n", stderr);
+ log_err(".\n");
return;
}
int r;
if(reload)
- fprintf(stderr, _("The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\nWARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"));
+ log_err(_("The reload action is deprecated. Please use \"dmsetup reload\" in case you really need this functionality.\nWARNING: do not use reload to touch LUKS devices. If that is the case, hit Ctrl-C now.\n"));
if (options.hash && strcmp(options.hash, "plain") == 0)
options.hash = NULL;
if (r == 0) {
/* inactive */
- printf("%s/%s is inactive.\n", crypt_get_dir(), options.name);
+ log_std("%s/%s is inactive.\n", crypt_get_dir(), options.name);
r = 1;
} else {
/* active */
- printf("%s/%s is active:\n", crypt_get_dir(), options.name);
- printf(" cipher: %s\n", options.cipher);
- printf(" keysize: %d bits\n", options.key_size * 8);
- printf(" device: %s\n", options.device);
- printf(" offset: %" PRIu64 " sectors\n", options.offset);
- printf(" size: %" PRIu64 " sectors\n", options.size);
+ 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)
- printf(" skipped: %" PRIu64 " sectors\n", options.skip);
- printf(" mode: %s\n", (options.flags & CRYPT_FLAG_READONLY)
+ 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;
{
poptPrintUsage(popt_context, stderr, 0);
if (error)
- fprintf(stderr, "%s: %s\n", more, error);
+ log_err("%s: %s\n", more, error);
exit(exitcode);
}
if (key->shortName == '?') {
struct action_type *action;
- fprintf(stdout, "%s\n",PACKAGE_STRING);
+ log_std("%s\n",PACKAGE_STRING);
poptPrintHelp(popt_context, stdout, 0);
- printf(_("\n"
+ log_std(_("\n"
"<action> is one of:\n"));
for(action = action_types; action->type; action++)
- printf("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
-
- printf(_("\n"
+ log_std("\t%s %s - %s\n", action->type, _(action->arg_desc), _(action->desc));
+
+ log_std(_("\n"
"<name> is the device to create under %s\n"
"<device> is the encrypted device\n"
"<key slot> is the LUKS key slot number to modify\n"
usage(popt_context, 0, NULL, NULL);
}
+void set_debug_level(int level);
+
+static void _dbg_version_and_cmd(int argc, char **argv)
+{
+ int i;
+
+ log_std("# %s %s processing \"", PACKAGE_NAME, PACKAGE_VERSION);
+ for (i = 0; i < argc; i++) {
+ if (i)
+ log_std(" ");
+ log_std(argv[i]);
+ }
+ log_std("\"\n");
+}
+
static int run_action(struct action_type *action)
{
int r;
if (dm_init(NULL, action->required_dm_backend) < 1) {
- fprintf(stderr,_("Cannot communicate with device-mapper. Is dm_mod kernel module loaded?\n"));
+ log_err("Cannot communicate with device-mapper. Is dm_mod kernel module loaded?\n");
return -ENOSYS;
}
static struct poptOption popt_options[] = {
{ NULL, '\0', POPT_ARG_INCLUDE_TABLE, popt_help_options, 0, N_("Help options:"), NULL },
{ "verbose", 'v', POPT_ARG_NONE, &opt_verbose, 0, N_("Shows more detailed error messages"), NULL },
+ { "debug", '\0', POPT_ARG_NONE, &opt_debug, 0, N_("Show debug messsgages"), NULL },
{ "cipher", 'c', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &opt_cipher, 0, N_("The cipher used to encrypt the disk (see /proc/crypto)"), NULL },
{ "hash", 'h', POPT_ARG_STRING | POPT_ARGFLAG_SHOW_DEFAULT, &opt_hash, 0, N_("The hash used to create the encryption key from the passphrase"), NULL },
{ "verify-passphrase", 'y', POPT_ARG_NONE, &opt_verify_passphrase, 0, N_("Verifies the passphrase by asking for it twice"), NULL },
N_("msecs") },
{ "batch-mode", 'q', POPT_ARG_NONE, &opt_batch_mode, 0, N_("Do not ask for confirmation"), NULL },
{ "version", '\0', POPT_ARG_NONE, &opt_version_mode, 0, N_("Print package version"), NULL },
- { "timeout", 't', POPT_ARG_INT, &opt_timeout, 0, N_("Timeout for interactive passphrase prompt (in seconds)"), N_("secs") },
- { "tries", 'T', POPT_ARG_INT, &opt_tries, 0, N_("How often the input of the passphrase can be retried"), NULL },
- { "align-payload", '\0', POPT_ARG_INT, &opt_align_payload, 0, N_("Align payload at <n> sector boundaries - for luksFormat"), N_("SECTORS") },
- { "non-exclusive", '\0', POPT_ARG_NONE, &opt_non_exclusive, 0, N_("Allows non-exclusive access for luksOpen, WARNING see manpage."), NULL },
+ { "timeout", 't', POPT_ARG_INT, &opt_timeout, 0, N_("Timeout for interactive passphrase prompt (in seconds)"), N_("secs") },
+ { "tries", 'T', POPT_ARG_INT, &opt_tries, 0, N_("How often the input of the passphrase canbe retried"), NULL },
+ { "align-payload", '\0', POPT_ARG_INT, &opt_align_payload, 0, N_("Align payload at <n> sector boundaries - for luksFormat"), N_("SECTORS") },
+ { "non-exclusive", '\0', POPT_ARG_NONE, &opt_non_exclusive, 0, N_("Allows non-exclusive access for luksOpen, WARNING see manpage."), NULL },
POPT_TABLEEND
};
poptContext popt_context;
int r;
const char *null_action_argv[] = {NULL};
+ set_default_log(cmdLineLog);
+
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
usage(popt_context, 1, poptStrerror(r),
poptBadOption(popt_context, POPT_BADOPTION_NOALIAS));
if (opt_version_mode) {
- printf("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
+ log_std("%s %s\n", PACKAGE_NAME, PACKAGE_VERSION);
exit(0);
}
-
+
if (opt_key_size % 8)
usage(popt_context, 1,
_("Key size must be a multiple of 8 bits"),
poptGetInvocationName(popt_context));
-
+
if (!(aname = (char *)poptGetArg(popt_context)))
usage(popt_context, 1, _("Argument <action> missing."),
poptGetInvocationName(popt_context));
/* Make return values of poptGetArgs more consistent in case of remaining argc = 0 */
if(!action_argv)
action_argv = null_action_argv;
-
+
/* Count args, somewhat unnice, change? */
while(action_argv[action_argc] != NULL)
action_argc++;
poptGetInvocationName(popt_context));
}
+ if (opt_debug) {
+ opt_verbose = 1;
+ crypt_set_debug_level(-1);
+ _dbg_version_and_cmd(argc, argv);
+ }
+
return run_action(action);
}
#define DEFAULT_KEY_SIZE 256
#define DEFAULT_LUKS_KEY_SIZE 128
+#define MAX_CIPHER_LEN 32
+
/* Helper funcions provided by internal libcryptsetup objects */
struct crypt_device;
+void crypt_set_debug_level(int level);
+void set_default_log(void (*log)(int class, char *msg));
+void logger(struct crypt_device *cd, int class, const char *file, int line, const char *format, ...);
+#define log_dbg(x...) logger(NULL, CRYPT_LOG_DEBUG, __FILE__, __LINE__, x)
+#define log_std(x...) logger(NULL, CRYPT_LOG_NORMAL, __FILE__, __LINE__, x)
+#define log_err(x...) logger(NULL, CRYPT_LOG_ERROR, __FILE__, __LINE__, x)
+
extern int memlock_inc(struct crypt_device *ctx);
extern int memlock_dec(struct crypt_device *ctx);
extern int dm_init(struct crypt_device *context, int check_kernel);
extern void dm_exit(void);
+extern int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode);
#endif /* CRYPTSETUP_H */