- Initial build.
This commit is contained in:
parent
78be3b104a
commit
1cf439a8a0
@ -0,0 +1,2 @@
|
|||||||
|
volume_key-0.2.tar.bz2
|
||||||
|
cryptsetup-1.0.7-rc1.tar.bz2
|
674
cryptsetup-svn-r62.patch
Normal file
674
cryptsetup-svn-r62.patch
Normal file
@ -0,0 +1,674 @@
|
|||||||
|
Index: lib/libcryptsetup.h
|
||||||
|
===================================================================
|
||||||
|
--- lib/libcryptsetup.h (revision 62)
|
||||||
|
+++ lib/libcryptsetup.h (working copy)
|
||||||
|
@@ -65,6 +65,78 @@
|
||||||
|
int crypt_luksFormat(struct crypt_options *options);
|
||||||
|
int crypt_luksDump(struct crypt_options *options);
|
||||||
|
|
||||||
|
+struct crypt_luks_volume_info;
|
||||||
|
+
|
||||||
|
+/* Get information about DEVICE,
|
||||||
|
+ Return 0 on sucess, setting INFO to the volume information.
|
||||||
|
+ return a negative errno value otherwise, the caller can try to use
|
||||||
|
+ crypt_get_error() to get an error message.
|
||||||
|
+ INFO can be NULL, in which case the function only verifies DEVICE is a valid
|
||||||
|
+ LUKS device.
|
||||||
|
+ If INFO is not not NULL, it should be freed using crypt_luks_vi_free().
|
||||||
|
+*/
|
||||||
|
+int crypt_luks_get_volume_info(struct crypt_luks_volume_info **info,
|
||||||
|
+ const char *device);
|
||||||
|
+
|
||||||
|
+/* Get cipher name from INFO.
|
||||||
|
+ Return a string for free(), or NULL if out of memory. */
|
||||||
|
+char *crypt_luks_vi_get_cipher_name(struct crypt_luks_volume_info *info);
|
||||||
|
+
|
||||||
|
+/* Get cipher mode from INFO.
|
||||||
|
+ Return a string for free(), or NULL if out of memory. */
|
||||||
|
+char *crypt_luks_vi_get_cipher_mode(struct crypt_luks_volume_info *info);
|
||||||
|
+
|
||||||
|
+/* Get number of master key bytes from INFO. */
|
||||||
|
+unsigned crypt_luks_vi_get_key_bytes(struct crypt_luks_volume_info *info);
|
||||||
|
+
|
||||||
|
+/* Get UUID from INFO.
|
||||||
|
+ Return a string for free(), or NULL if out of memory. */
|
||||||
|
+char *crypt_luks_vi_get_uuid(struct crypt_luks_volume_info *info);
|
||||||
|
+
|
||||||
|
+/* Free INFO. */
|
||||||
|
+void crypt_luks_vi_free(struct crypt_luks_volume_info *info);
|
||||||
|
+
|
||||||
|
+/* Get the master key of DEVICE, using PASSPHRASE with PASSPHRASE_LENGTH.
|
||||||
|
+ Return the used slot on success, setting KEY and KEY_LENGTH to the master
|
||||||
|
+ key;
|
||||||
|
+ return a negative errno value otherwise, the caller can try to use
|
||||||
|
+ crypt_get_error() to get an error message.
|
||||||
|
+ The caller is responsible for calling free(KEY) if this function returns
|
||||||
|
+ 0. */
|
||||||
|
+int crypt_luks_get_master_key(unsigned char **key, size_t *key_length,
|
||||||
|
+ const char *device,
|
||||||
|
+ const unsigned char *passphrase,
|
||||||
|
+ size_t passphrase_length,
|
||||||
|
+ void (*log)(int class, char *msg));
|
||||||
|
+
|
||||||
|
+/* Verify that KEY with KEY_LENGTH is valid for DEVICE.
|
||||||
|
+ Return 0 on success.
|
||||||
|
+ Return a negative errno value otherwise, the caller can try to use
|
||||||
|
+ crypt_get_error() to get an error message. */
|
||||||
|
+int crypt_luks_verify_master_key(const char *device, const unsigned char *key,
|
||||||
|
+ size_t key_length);
|
||||||
|
+
|
||||||
|
+/* Open DEVICE using KEY with KEY_LENGTH as NAME.
|
||||||
|
+ Return 0 on success.
|
||||||
|
+ Return a negative errno value otherwise, the caller can try to use
|
||||||
|
+ crypt_get_error() to get an error message. */
|
||||||
|
+int crypt_luks_open_by_master_key(const char *name, const char *device,
|
||||||
|
+ const unsigned char *key, size_t key_length,
|
||||||
|
+ int flags, void (*log)(int class, char *msg));
|
||||||
|
+
|
||||||
|
+/* Add a PASSPHRASE with PASSPHRASE_LENGTH to SLOT of DEVICE, using KEY with
|
||||||
|
+ KEY_LENGTH.
|
||||||
|
+ Return the used slot on success;
|
||||||
|
+ Return a negative errno value otherwise, the caller can try to use
|
||||||
|
+ crypt_get_error() to get an error message.
|
||||||
|
+ SLOT may be -1 to use the first empty slot. */
|
||||||
|
+int crypt_luks_add_passphrase_by_master_key(const char *device,
|
||||||
|
+ const unsigned char *key,
|
||||||
|
+ size_t key_length, int slot,
|
||||||
|
+ const unsigned char *passphrase,
|
||||||
|
+ size_t passphrase_length,
|
||||||
|
+ void (*log)(int class, char *msg));
|
||||||
|
+
|
||||||
|
void crypt_get_error(char *buf, size_t size);
|
||||||
|
void crypt_put_options(struct crypt_options *options);
|
||||||
|
const char *crypt_get_dir(void);
|
||||||
|
Index: lib/setup.c
|
||||||
|
===================================================================
|
||||||
|
--- lib/setup.c (revision 62)
|
||||||
|
+++ lib/setup.c (working copy)
|
||||||
|
@@ -282,7 +282,7 @@
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_create_device(int reload, struct setup_backend *backend,
|
||||||
|
+static int __crypt_create_device(intptr_t reload, struct setup_backend *backend,
|
||||||
|
struct crypt_options *options)
|
||||||
|
{
|
||||||
|
struct crypt_options tmp = {
|
||||||
|
@@ -359,7 +359,7 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_query_device(int details, struct setup_backend *backend,
|
||||||
|
+static int __crypt_query_device(intptr_t details, struct setup_backend *backend,
|
||||||
|
struct crypt_options *options)
|
||||||
|
{
|
||||||
|
int r = backend->status(details, options, NULL);
|
||||||
|
@@ -371,7 +371,7 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_resize_device(int details, struct setup_backend *backend,
|
||||||
|
+static int __crypt_resize_device(intptr_t details, struct setup_backend *backend,
|
||||||
|
struct crypt_options *options)
|
||||||
|
{
|
||||||
|
struct crypt_options tmp = {
|
||||||
|
@@ -412,7 +412,7 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_remove_device(int arg, struct setup_backend *backend,
|
||||||
|
+static int __crypt_remove_device(intptr_t arg, struct setup_backend *backend,
|
||||||
|
struct crypt_options *options)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
@@ -428,7 +428,7 @@
|
||||||
|
return backend->remove(0, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_luks_format(int arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
+static int __crypt_luks_format(intptr_t arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
@@ -504,8 +504,94 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_luks_open(int arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
+static int open_from_hdr_and_mk(struct luks_phdr *hdr,
|
||||||
|
+ struct luks_masterkey *mk,
|
||||||
|
+ const struct device_infos *infos,
|
||||||
|
+ struct setup_backend *backend,
|
||||||
|
+ struct crypt_options *options)
|
||||||
|
{
|
||||||
|
+ char *dmCipherSpec;
|
||||||
|
+ int excl = (options->flags & CRYPT_FLAG_NON_EXCLUSIVE_ACCESS)
|
||||||
|
+ ? 0 : O_EXCL;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ if (infos->readonly)
|
||||||
|
+ options->flags |= CRYPT_FLAG_READONLY;
|
||||||
|
+ options->offset = hdr->payloadOffset;
|
||||||
|
+ if (asprintf(&dmCipherSpec, "%s-%s", hdr->cipherName, hdr->cipherMode)
|
||||||
|
+ < 0) {
|
||||||
|
+ r = -ENOMEM;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ options->cipher = dmCipherSpec;
|
||||||
|
+ options->key_size = mk->keyLength;
|
||||||
|
+ options->skip = 0;
|
||||||
|
+
|
||||||
|
+ options->size = infos->size;
|
||||||
|
+ if (!options->size) {
|
||||||
|
+ set_error("Not a block device.\n");
|
||||||
|
+ r = -ENOTBLK;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ if (options->size <= options->offset) {
|
||||||
|
+ set_error("Invalid offset");
|
||||||
|
+ r = -EINVAL;
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ options->size -= options->offset;
|
||||||
|
+ /* FIXME: code allows multiple crypt mapping, cannot use uuid then.
|
||||||
|
+ * anyway, it is dangerous and can corrupt data. Remove it in next version! */
|
||||||
|
+ r = backend->create(0, options, mk->key, excl ? hdr->uuid : NULL);
|
||||||
|
+ out:
|
||||||
|
+ free(dmCipherSpec);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __crypt_luks_open_by_master_key(intptr_t arg,
|
||||||
|
+ struct setup_backend *backend,
|
||||||
|
+ struct crypt_options *options)
|
||||||
|
+{
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ struct luks_phdr hdr;
|
||||||
|
+ struct device_infos infos;
|
||||||
|
+ struct crypt_options tmp = {
|
||||||
|
+ .name = options->name,
|
||||||
|
+ };
|
||||||
|
+ int r;
|
||||||
|
+ int excl = (options->flags & CRYPT_FLAG_NON_EXCLUSIVE_ACCESS) != 0
|
||||||
|
+ ? 0 : O_EXCL ;
|
||||||
|
+
|
||||||
|
+ mk = (struct luks_masterkey *)arg;
|
||||||
|
+
|
||||||
|
+ r = backend->status(0, &tmp, NULL);
|
||||||
|
+ if (r >= 0) {
|
||||||
|
+ set_error("Device %s already exists.", options->name);
|
||||||
|
+ return -EEXIST;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (!LUKS_device_ready(options->device, O_RDONLY | excl))
|
||||||
|
+ return -ENOTBLK;
|
||||||
|
+
|
||||||
|
+ if (get_device_infos(options->device, &infos) < 0) {
|
||||||
|
+ set_error("Can't get device information.\n");
|
||||||
|
+ return -ENOTBLK;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ r = LUKS_read_phdr(options->device, &hdr);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ r = LUKS_verify_master_key(&hdr, mk);
|
||||||
|
+ if (r == -EPERM)
|
||||||
|
+ set_error("Master key does not match the volume.\n");
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ return open_from_hdr_and_mk(&hdr, mk, &infos, backend, options);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __crypt_luks_open(intptr_t arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
+{
|
||||||
|
struct luks_masterkey *mk=NULL;
|
||||||
|
struct luks_phdr hdr;
|
||||||
|
char *prompt = NULL;
|
||||||
|
@@ -515,7 +601,6 @@
|
||||||
|
struct crypt_options tmp = {
|
||||||
|
.name = options->name,
|
||||||
|
};
|
||||||
|
- char *dmCipherSpec = NULL;
|
||||||
|
int r, tries = options->tries;
|
||||||
|
int excl = (options->flags & CRYPT_FLAG_NON_EXCLUSIVE_ACCESS) ? 0 : O_EXCL ;
|
||||||
|
|
||||||
|
@@ -533,9 +618,6 @@
|
||||||
|
return -ENOTBLK;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (infos.readonly)
|
||||||
|
- options->flags |= CRYPT_FLAG_READONLY;
|
||||||
|
-
|
||||||
|
if(asprintf(&prompt, "Enter LUKS passphrase for %s: ", options->device) < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
@@ -559,33 +641,8 @@
|
||||||
|
|
||||||
|
logger(options, CRYPT_LOG_NORMAL,"key slot %d unlocked.\n", r);
|
||||||
|
|
||||||
|
+ r = open_from_hdr_and_mk(&hdr, mk, &infos, backend, options);
|
||||||
|
|
||||||
|
- options->offset = hdr.payloadOffset;
|
||||||
|
- if (asprintf(&dmCipherSpec, "%s-%s", hdr.cipherName, hdr.cipherMode) < 0) {
|
||||||
|
- r = -ENOMEM;
|
||||||
|
- goto out2;
|
||||||
|
- }
|
||||||
|
- options->cipher = dmCipherSpec;
|
||||||
|
- options->key_size = mk->keyLength;
|
||||||
|
- options->skip = 0;
|
||||||
|
-
|
||||||
|
- options->size = infos.size;
|
||||||
|
- if (!options->size) {
|
||||||
|
- set_error("Not a block device.\n");
|
||||||
|
- r = -ENOTBLK; goto out2;
|
||||||
|
- }
|
||||||
|
- if (options->size <= options->offset) {
|
||||||
|
- set_error("Invalid offset");
|
||||||
|
- r = -EINVAL; goto out2;
|
||||||
|
- }
|
||||||
|
- options->size -= options->offset;
|
||||||
|
- /* FIXME: code allows multiple crypt mapping, cannot use uuid then.
|
||||||
|
- * anyway, it is dangerous and can corrupt data. Remove it in next version! */
|
||||||
|
- r = backend->create(0, options, mk->key, excl ? hdr.uuid : NULL);
|
||||||
|
-
|
||||||
|
- out2:
|
||||||
|
- free(dmCipherSpec);
|
||||||
|
- dmCipherSpec = NULL;
|
||||||
|
out1:
|
||||||
|
safe_free(password);
|
||||||
|
out:
|
||||||
|
@@ -598,8 +655,76 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_luks_add_key(int arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
+/* arg is a struct luks_masterkey **. Caller must LUKS_dealloc_masterkey(*arg)
|
||||||
|
+ if this function returns 0.
|
||||||
|
+ options->key_size is abused as passphrase length. */
|
||||||
|
+static int __crypt_luks_get_master_key(intptr_t arg,
|
||||||
|
+ struct setup_backend *backend,
|
||||||
|
+ struct crypt_options *options)
|
||||||
|
{
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ struct luks_phdr hdr;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ if (!LUKS_device_ready(options->device, O_RDONLY))
|
||||||
|
+ return -ENOTBLK;
|
||||||
|
+
|
||||||
|
+ r = LUKS_open_any_key(options->device, options->passphrase,
|
||||||
|
+ options->key_size, &hdr, &mk, backend);
|
||||||
|
+ if (r == -EPERM)
|
||||||
|
+ set_error("No key available with this passphrase.");
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ *(struct luks_masterkey **)arg = mk;
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* options->key_size is abused as passphrase length. */
|
||||||
|
+static int __crypt_luks_add_passphrase_by_master_key
|
||||||
|
+ (intptr_t arg, struct setup_backend *backend,
|
||||||
|
+ struct crypt_options *options)
|
||||||
|
+{
|
||||||
|
+ struct luks_phdr hdr;
|
||||||
|
+ unsigned int keyIndex;
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ const char *device = options->device;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ mk = (struct luks_masterkey *)arg;
|
||||||
|
+
|
||||||
|
+ if (!LUKS_device_ready(options->device, O_RDWR))
|
||||||
|
+ return -ENOTBLK;
|
||||||
|
+
|
||||||
|
+ r = LUKS_read_phdr(device, &hdr);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ r = LUKS_verify_master_key(&hdr, mk);
|
||||||
|
+ if (r < 0) {
|
||||||
|
+ set_error("Master key does not match the volume");
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ keyIndex = keyslot_from_option(options->key_slot, &hdr, options);
|
||||||
|
+ if (keyIndex == -EINVAL)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ hdr.keyblock[keyIndex].passwordIterations
|
||||||
|
+ = at_least_one(LUKS_benchmarkt_iterations()
|
||||||
|
+ * ((float)options->iteration_time / 1000));
|
||||||
|
+
|
||||||
|
+ r = LUKS_set_key(device, keyIndex, options->passphrase,
|
||||||
|
+ options->key_size, &hdr, mk, backend);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+ return keyIndex;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int __crypt_luks_add_key(intptr_t arg, struct setup_backend *backend, struct crypt_options *options)
|
||||||
|
+{
|
||||||
|
struct luks_masterkey *mk=NULL;
|
||||||
|
struct luks_phdr hdr;
|
||||||
|
char *password=NULL; unsigned int passwordLen;
|
||||||
|
@@ -664,7 +789,7 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int luks_remove_helper(int arg, struct setup_backend *backend, struct crypt_options *options, int supply_it)
|
||||||
|
+static int luks_remove_helper(intptr_t arg, struct setup_backend *backend, struct crypt_options *options, int supply_it)
|
||||||
|
{
|
||||||
|
struct luks_masterkey *mk;
|
||||||
|
struct luks_phdr hdr;
|
||||||
|
@@ -735,18 +860,18 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_luks_kill_slot(int arg, struct setup_backend *backend, struct crypt_options *options) {
|
||||||
|
+static int __crypt_luks_kill_slot(intptr_t arg, struct setup_backend *backend, struct crypt_options *options) {
|
||||||
|
return luks_remove_helper(arg, backend, options, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int __crypt_luks_remove_key(int arg, struct setup_backend *backend, struct crypt_options *options) {
|
||||||
|
+static int __crypt_luks_remove_key(intptr_t arg, struct setup_backend *backend, struct crypt_options *options) {
|
||||||
|
return luks_remove_helper(arg, backend, options, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-static int crypt_job(int (*job)(int arg, struct setup_backend *backend,
|
||||||
|
+static int crypt_job(int (*job)(intptr_t arg, struct setup_backend *backend,
|
||||||
|
struct crypt_options *options),
|
||||||
|
- int arg, struct crypt_options *options)
|
||||||
|
+ intptr_t arg, struct crypt_options *options)
|
||||||
|
{
|
||||||
|
struct setup_backend *backend;
|
||||||
|
int r;
|
||||||
|
@@ -807,6 +932,96 @@
|
||||||
|
return crypt_job(__crypt_luks_format, 0, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int crypt_luks_get_master_key(unsigned char **key, size_t *key_length,
|
||||||
|
+ const char *device,
|
||||||
|
+ const unsigned char *passphrase,
|
||||||
|
+ size_t passphrase_length,
|
||||||
|
+ void (*log)(int class, char *msg))
|
||||||
|
+{
|
||||||
|
+ struct crypt_options options;
|
||||||
|
+ struct interface_callbacks icb;
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ memset(&icb, 0, sizeof(icb));
|
||||||
|
+ icb.log = log;
|
||||||
|
+ memset(&options, 0, sizeof(options));
|
||||||
|
+ options.device = device;
|
||||||
|
+ options.icb = &icb;
|
||||||
|
+ options.passphrase = (const char *)passphrase;
|
||||||
|
+ options.key_size = passphrase_length; /* Abusing the field */
|
||||||
|
+ if (options.key_size != passphrase_length) {
|
||||||
|
+ set_error("passphrase_length too large");
|
||||||
|
+ return -EOVERFLOW;
|
||||||
|
+ }
|
||||||
|
+ r = crypt_job(__crypt_luks_get_master_key, (intptr_t)&mk, &options);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+ /* Note: this memory is not mlock()ed */
|
||||||
|
+ *key = malloc(mk->keyLength);
|
||||||
|
+ if (*key == NULL) {
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ }
|
||||||
|
+ memcpy(*key, mk->key, mk->keyLength);
|
||||||
|
+ *key_length = mk->keyLength;
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int crypt_luks_verify_master_key(const char *device, const unsigned char *key,
|
||||||
|
+ size_t key_length)
|
||||||
|
+{
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ struct luks_phdr hdr;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ r = LUKS_read_phdr(device, &hdr);
|
||||||
|
+ if (r < 0)
|
||||||
|
+ return r;
|
||||||
|
+
|
||||||
|
+ mk = LUKS_alloc_masterkey(key_length);
|
||||||
|
+ if (mk == NULL)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ memcpy(mk->key, key, key_length);
|
||||||
|
+
|
||||||
|
+ r = LUKS_verify_master_key(&hdr, mk);
|
||||||
|
+ if (r == -EPERM)
|
||||||
|
+ set_error("Master key does not match the volume.\n");
|
||||||
|
+
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int crypt_luks_open_by_master_key(const char *name, const char *device,
|
||||||
|
+ const unsigned char *key, size_t key_length,
|
||||||
|
+ int flags, void (*log)(int class, char *msg))
|
||||||
|
+{
|
||||||
|
+ struct crypt_options options;
|
||||||
|
+ struct interface_callbacks icb;
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ memset(&icb, 0, sizeof(icb));
|
||||||
|
+ icb.log = log;
|
||||||
|
+ memset(&options, 0, sizeof(options));
|
||||||
|
+ options.name = name;
|
||||||
|
+ options.device = device;
|
||||||
|
+ options.flags = flags;
|
||||||
|
+ options.offset = 0;
|
||||||
|
+ options.icb = &icb;
|
||||||
|
+
|
||||||
|
+ mk = LUKS_alloc_masterkey(key_length);
|
||||||
|
+ if (mk == NULL)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ memcpy(mk->key, key, key_length);
|
||||||
|
+ r = crypt_job(__crypt_luks_open_by_master_key, (intptr_t)mk, &options);
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int crypt_luksOpen(struct crypt_options *options)
|
||||||
|
{
|
||||||
|
return crypt_job(__crypt_luks_open, 0, options);
|
||||||
|
@@ -822,6 +1037,39 @@
|
||||||
|
return crypt_job(__crypt_luks_remove_key, 0, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
+int crypt_luks_add_passphrase_by_master_key(const char *device,
|
||||||
|
+ const unsigned char *key,
|
||||||
|
+ size_t key_length, int slot,
|
||||||
|
+ const unsigned char *passphrase,
|
||||||
|
+ size_t passphrase_length,
|
||||||
|
+ void (*log)(int class, char *msg))
|
||||||
|
+{
|
||||||
|
+ struct crypt_options options;
|
||||||
|
+ struct interface_callbacks icb;
|
||||||
|
+ struct luks_masterkey *mk;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ memset(&icb, 0, sizeof(icb));
|
||||||
|
+ icb.log = log;
|
||||||
|
+ memset(&options, 0, sizeof(options));
|
||||||
|
+ options.device = device;
|
||||||
|
+ options.passphrase = (const char *)passphrase;
|
||||||
|
+ options.key_size = passphrase_length; /* Abusing the field */
|
||||||
|
+ options.key_slot = slot;
|
||||||
|
+ options.iteration_time = 1000;
|
||||||
|
+ options.icb = &icb;
|
||||||
|
+
|
||||||
|
+ mk = LUKS_alloc_masterkey(key_length);
|
||||||
|
+ if (mk == NULL)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ memcpy(mk->key, key, key_length);
|
||||||
|
+ r = crypt_job(__crypt_luks_add_passphrase_by_master_key, (intptr_t)mk,
|
||||||
|
+ &options);
|
||||||
|
+ LUKS_dealloc_masterkey(mk);
|
||||||
|
+
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int crypt_luksAddKey(struct crypt_options *options)
|
||||||
|
{
|
||||||
|
return crypt_job(__crypt_luks_add_key, 0, options);
|
||||||
|
@@ -840,6 +1088,84 @@
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct crypt_luks_volume_info
|
||||||
|
+{
|
||||||
|
+ struct luks_phdr h;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+int crypt_luks_get_volume_info(struct crypt_luks_volume_info **info,
|
||||||
|
+ const char *device)
|
||||||
|
+{
|
||||||
|
+ struct crypt_luks_volume_info *vi;
|
||||||
|
+ int r;
|
||||||
|
+
|
||||||
|
+ vi = malloc(sizeof(*vi));
|
||||||
|
+ if (vi == NULL)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ r = LUKS_read_phdr(device, &vi->h);
|
||||||
|
+ if (r != 0) {
|
||||||
|
+ free(vi);
|
||||||
|
+ return r;
|
||||||
|
+ }
|
||||||
|
+ if (info != NULL)
|
||||||
|
+ *info = vi;
|
||||||
|
+ else
|
||||||
|
+ free(vi);
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char *crypt_luks_vi_get_cipher_name(struct crypt_luks_volume_info *info)
|
||||||
|
+{
|
||||||
|
+ size_t field_size;
|
||||||
|
+ char *r;
|
||||||
|
+
|
||||||
|
+ field_size = sizeof(info->h.cipherName);
|
||||||
|
+ r = malloc(field_size + 1);
|
||||||
|
+ if (r != NULL) {
|
||||||
|
+ memcpy(r, info->h.cipherName, field_size);
|
||||||
|
+ r[field_size] = '\0';
|
||||||
|
+ }
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char *crypt_luks_vi_get_cipher_mode(struct crypt_luks_volume_info *info)
|
||||||
|
+{
|
||||||
|
+ size_t field_size;
|
||||||
|
+ char *r;
|
||||||
|
+
|
||||||
|
+ field_size = sizeof(info->h.cipherMode);
|
||||||
|
+ r = malloc(field_size + 1);
|
||||||
|
+ if (r != NULL) {
|
||||||
|
+ memcpy(r, info->h.cipherMode, field_size);
|
||||||
|
+ r[field_size] = '\0';
|
||||||
|
+ }
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+unsigned crypt_luks_vi_get_key_bytes(struct crypt_luks_volume_info *info)
|
||||||
|
+{
|
||||||
|
+ return info->h.keyBytes;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+char *crypt_luks_vi_get_uuid(struct crypt_luks_volume_info *info)
|
||||||
|
+{
|
||||||
|
+ size_t field_size;
|
||||||
|
+ char *r;
|
||||||
|
+
|
||||||
|
+ field_size = sizeof(info->h.uuid);
|
||||||
|
+ r = malloc(field_size + 1);
|
||||||
|
+ if (r != NULL) {
|
||||||
|
+ memcpy(r, info->h.uuid, field_size);
|
||||||
|
+ r[field_size] = '\0';
|
||||||
|
+ }
|
||||||
|
+ return r;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void crypt_luks_vi_free(struct crypt_luks_volume_info *info)
|
||||||
|
+{
|
||||||
|
+ free(info);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
int crypt_isLuks(struct crypt_options *options)
|
||||||
|
{
|
||||||
|
struct luks_phdr hdr;
|
||||||
|
Index: luks/keymanage.c
|
||||||
|
===================================================================
|
||||||
|
--- luks/keymanage.c (revision 62)
|
||||||
|
+++ luks/keymanage.c (working copy)
|
||||||
|
@@ -280,6 +280,20 @@
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
+/* Check whether a master key is invalid. */
|
||||||
|
+int LUKS_verify_master_key(const struct luks_phdr *hdr,
|
||||||
|
+ const struct luks_masterkey *mk)
|
||||||
|
+{
|
||||||
|
+ char checkHashBuf[LUKS_DIGESTSIZE];
|
||||||
|
+
|
||||||
|
+ PBKDF2_HMAC_SHA1(mk->key, mk->keyLength, hdr->mkDigestSalt,
|
||||||
|
+ LUKS_SALTSIZE, hdr->mkDigestIterations, checkHashBuf,
|
||||||
|
+ LUKS_DIGESTSIZE);
|
||||||
|
+
|
||||||
|
+ return memcmp(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE) == 0
|
||||||
|
+ ? 0 : -EPERM;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/* Try to open a particular key slot,
|
||||||
|
|
||||||
|
*/
|
||||||
|
@@ -295,7 +309,6 @@
|
||||||
|
char derivedKey[hdr->keyBytes];
|
||||||
|
char *AfKey;
|
||||||
|
size_t AFEKSize;
|
||||||
|
- char checkHashBuf[LUKS_DIGESTSIZE];
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if(hdr->keyblock[keyIndex].active != LUKS_KEY_ENABLED) {
|
||||||
|
@@ -329,13 +342,8 @@
|
||||||
|
|
||||||
|
r = AF_merge(AfKey,mk->key,mk->keyLength,hdr->keyblock[keyIndex].stripes);
|
||||||
|
if(r < 0) goto out;
|
||||||
|
-
|
||||||
|
- PBKDF2_HMAC_SHA1(mk->key,mk->keyLength,
|
||||||
|
- hdr->mkDigestSalt,LUKS_SALTSIZE,
|
||||||
|
- hdr->mkDigestIterations,
|
||||||
|
- checkHashBuf,LUKS_DIGESTSIZE);
|
||||||
|
|
||||||
|
- r = (memcmp(checkHashBuf,hdr->mkDigest, LUKS_DIGESTSIZE) == 0)?0:-EPERM;
|
||||||
|
+ r = LUKS_verify_master_key(hdr, mk);
|
||||||
|
out:
|
||||||
|
free(AfKey);
|
||||||
|
return r;
|
||||||
|
Index: luks/luks.h
|
||||||
|
===================================================================
|
||||||
|
--- luks/luks.h (revision 62)
|
||||||
|
+++ luks/luks.h (working copy)
|
||||||
|
@@ -124,6 +124,8 @@
|
||||||
|
struct luks_masterkey **mk,
|
||||||
|
struct setup_backend *backend);
|
||||||
|
|
||||||
|
+int LUKS_verify_master_key(const struct luks_phdr *hdr,
|
||||||
|
+ const struct luks_masterkey *mk);
|
||||||
|
|
||||||
|
int LUKS_del_key(const char *device, unsigned int keyIndex);
|
||||||
|
int LUKS_is_last_keyslot(const char *device, unsigned int keyIndex);
|
2
sources
2
sources
@ -0,0 +1,2 @@
|
|||||||
|
882ec96bef41962a33a24d6ee5821a29 volume_key-0.2.tar.bz2
|
||||||
|
0910632173fb960252412bf7342b42fc cryptsetup-1.0.7-rc1.tar.bz2
|
139
volume_key.spec
Normal file
139
volume_key.spec
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
|
||||||
|
|
||||||
|
Summary: An utility for manipulating storage encryption keys and passphrases
|
||||||
|
Name: volume_key
|
||||||
|
Version: 0.2
|
||||||
|
Release: 1
|
||||||
|
License: GPLv2
|
||||||
|
Group: Applications/System
|
||||||
|
URL: https://fedorahosted.org/volume_key/
|
||||||
|
Requires: volume_key-libs = %{version}-%{release}
|
||||||
|
|
||||||
|
Source0: https://fedorahosted.org/releases/v/o/volume_key/volume_key-%{version}.tar.bz2
|
||||||
|
Source1: http://cryptsetup.googlecode.com/files/cryptsetup-1.0.7-rc1.tar.bz2
|
||||||
|
# http://code.google.com/p/cryptsetup/issues/detail?id=15
|
||||||
|
Patch0: https://fedorahosted.org/releases/v/o/volume_key/cryptsetup-svn-r62.patch
|
||||||
|
BuildRoot: %(mktemp -ud %{_tmppath}/%{name}-%{version}-%{release}-XXXXXX)
|
||||||
|
BuildRequires: gettext-devel, glib2-devel, gnupg, gpgme-devel, libblkid-devel
|
||||||
|
BuildRequires: nss-devel, python-devel
|
||||||
|
|
||||||
|
# For cryptsetup
|
||||||
|
BuildRequires: device-mapper-devel, e2fsprogs-devel, libgcrypt-devel
|
||||||
|
BuildRequires: libgpg-error-devel, libselinux-devel, libsepol-devel, popt-devel
|
||||||
|
|
||||||
|
%description
|
||||||
|
This package provides a command-line tool for manipulating storage volume
|
||||||
|
encryption keys and storing them separately from volumes.
|
||||||
|
|
||||||
|
The main goal of the software is to allow restoring access to an encrypted
|
||||||
|
hard drive if the primary user forgets the passphrase. The encryption key
|
||||||
|
back up can also be useful for extracting data after a hardware or software
|
||||||
|
failure that corrupts the header of the encrypted volume, or to access the
|
||||||
|
company data after an employee leaves abruptly.
|
||||||
|
|
||||||
|
%package devel
|
||||||
|
Summary: A library for manipulating storage encryption keys and passphrases
|
||||||
|
Group: Development/Libraries
|
||||||
|
Requires: volume_key-libs = %{version}-%{release}
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
This package provides libvolume_key, a library for manipulating storage volume
|
||||||
|
encryption keys and storing them separately from volumes.
|
||||||
|
|
||||||
|
The main goal of the software is to allow restoring access to an encrypted
|
||||||
|
hard drive if the primary user forgets the passphrase. The encryption key
|
||||||
|
back up can also be useful for extracting data after a hardware or software
|
||||||
|
failure that corrupts the header of the encrypted volume, or to access the
|
||||||
|
company data after an employee leaves abruptly.
|
||||||
|
|
||||||
|
%package libs
|
||||||
|
Summary: A library for manipulating storage encryption keys and passphrases
|
||||||
|
Group: System Environment/Libraries
|
||||||
|
|
||||||
|
%description libs
|
||||||
|
This package provides libvolume_key, a library for manipulating storage volume
|
||||||
|
encryption keys and storing them separately from volumes.
|
||||||
|
|
||||||
|
The main goal of the software is to allow restoring access to an encrypted
|
||||||
|
hard drive if the primary user forgets the passphrase. The encryption key
|
||||||
|
back up can also be useful for extracting data after a hardware or software
|
||||||
|
failure that corrupts the header of the encrypted volume, or to access the
|
||||||
|
company data after an employee leaves abruptly.
|
||||||
|
|
||||||
|
%package -n python-volume_key
|
||||||
|
Summary: Python bindings for libvolume_key
|
||||||
|
Group: System Environment/Libraries
|
||||||
|
Requires: volume_key-libs = %{version}-%{release}
|
||||||
|
|
||||||
|
%description -n python-volume_key
|
||||||
|
This package provides Python bindings for libvolume_key, a library for
|
||||||
|
manipulating storage volume encryption keys and storing them separately from
|
||||||
|
volumes.
|
||||||
|
|
||||||
|
The main goal of the software is to allow restoring access to an encrypted
|
||||||
|
hard drive if the primary user forgets the passphrase. The encryption key
|
||||||
|
back up can also be useful for extracting data after a hardware or software
|
||||||
|
failure that corrupts the header of the encrypted volume, or to access the
|
||||||
|
company data after an employee leaves abruptly.
|
||||||
|
|
||||||
|
volume_key currently supports only the LUKS volume encryption format. Support
|
||||||
|
for other formats is possible, some formats are planned for future releases.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%setup -q -a 1
|
||||||
|
pushd cryptsetup-1.0.7-rc1
|
||||||
|
%patch0 -p0 -b .cs-vk
|
||||||
|
popd
|
||||||
|
|
||||||
|
%build
|
||||||
|
cryptsetup_root=$(pwd)/cryptsetup-root
|
||||||
|
|
||||||
|
pushd cryptsetup-1.0.7-rc1
|
||||||
|
%configure --enable-static --disable-shared --with-pic
|
||||||
|
make %{?_smp_mflags}
|
||||||
|
make install "DESTDIR=$cryptsetup_root" INSTALL='install -p'
|
||||||
|
popd
|
||||||
|
|
||||||
|
%configure "CPPFLAGS=-I$cryptsetup_root"%{_includedir} \
|
||||||
|
"LDFLAGS=-L$cryptsetup_root"%{_libdir} --disable-static
|
||||||
|
make %{?_smp_mflags}
|
||||||
|
|
||||||
|
%install
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
make install DESTDIR=$RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%find_lang volume_key
|
||||||
|
|
||||||
|
%clean
|
||||||
|
rm -rf $RPM_BUILD_ROOT
|
||||||
|
|
||||||
|
%post libs -p /sbin/ldconfig
|
||||||
|
%postun libs -p /sbin/ldconfig
|
||||||
|
|
||||||
|
%files
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%doc README
|
||||||
|
%{_bindir}/volume_key
|
||||||
|
%{_mandir}/man8/volume_key.8*
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_includedir}/volume_key
|
||||||
|
%exclude %{_libdir}/libvolume_key.la
|
||||||
|
%{_libdir}/libvolume_key.so
|
||||||
|
|
||||||
|
%files libs -f volume_key.lang
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%doc AUTHORS COPYING ChangeLog NEWS
|
||||||
|
%{_libdir}/libvolume_key.so.*
|
||||||
|
|
||||||
|
%files -n python-volume_key
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%exclude %{python_sitearch}/_volume_key.la
|
||||||
|
%{python_sitearch}/_volume_key.so
|
||||||
|
%{python_sitearch}/volume_key.py*
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Tue Jun 30 2009 Miloslav Trmač <mitr@redhat.com> - 0.2-1
|
||||||
|
- Initial build.
|
Loading…
Reference in New Issue
Block a user