* Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results.
authorMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:34 +0000 (18:09 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:34 +0000 (18:09 +0000)
* Add ability to provide pre-generated master key and UUID in LUKS header format.
* Add LUKS function to verify master key digest.
* Move key slot manuipulation function into LUKS specific code.

Signed-off-by: Milan Broz <mbroz@redhat.com>
git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@94 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
lib/libcryptsetup.h
lib/setup.c
luks/keymanage.c
luks/luks.h
luks/pbkdf.c
luks/pbkdf.h

index 65ed80a..835c27b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,10 @@
        * Move device utils code and provide context parameter (for log).
        * Keyfile now must be provided by path, only stdin file descriptor is used (api only).
        * Do not call isatty() on closed keyfile descriptor.
+       * Run performance check for PBKDF2 from LUKS code, do not mix hash algoritms results.
+       * Add ability to provide pre-generated master key and UUID in LUKS header format.
+       * Add LUKS function to verify master key digest.
+       * Move key slot manuipulation function into LUKS specific code.
 
 2009-08-17  Milan Broz  <mbroz@redhat.com>
        * Fix PBKDF2 speed calculation for large passhrases.
index afee144..7602136 100644 (file)
@@ -6,6 +6,11 @@ extern "C" {
 
 #include <stdint.h>
 
+struct crypt_device; /* crypt device handle */
+
+#define CRYPT_ANY_SLOT -1
+
+typedef enum { SLOT_INVALID, SLOT_INACTIVE, SLOT_ACTIVE, SLOT_ACTIVE_LAST } crypt_keyslot_info;
 
 #define CRYPT_LOG_NORMAL 0
 #define CRYPT_LOG_ERROR  1
@@ -16,7 +21,6 @@ struct interface_callbacks {
     void (*log)(int class, char *msg);
 };
 
-
 #define        CRYPT_FLAG_VERIFY               (1 << 0)
 #define CRYPT_FLAG_READONLY            (1 << 1)
 #define        CRYPT_FLAG_VERIFY_IF_POSSIBLE   (1 << 2)
@@ -33,9 +37,9 @@ struct crypt_options {
        const char      *passphrase;
        int             passphrase_fd;
        const char      *key_file;
-       const char      *new_key_file;  
+       const char      *new_key_file;
        int             key_size;
-       
+
        unsigned int    flags;
        int             key_slot;
 
@@ -43,9 +47,9 @@ struct crypt_options {
        uint64_t        offset;
        uint64_t        skip;
        uint64_t        iteration_time;
-       uint64_t        timeout;
+       uint64_t        timeout;
 
-       uint64_t        align_payload;
+       uint64_t        align_payload;
        int             tries;
 
        struct interface_callbacks *icb;
@@ -63,7 +67,6 @@ int crypt_luksRemoveKey(struct crypt_options *options);
 int crypt_luksAddKey(struct crypt_options *options);
 int crypt_luksUUID(struct crypt_options *options);
 int crypt_isLuks(struct crypt_options *options);
-int crypt_luksFormat(struct crypt_options *options);
 int crypt_luksDump(struct crypt_options *options);
 
 void crypt_get_error(char *buf, size_t size);
index 0cf2f0d..fb6aff7 100644 (file)
@@ -250,8 +250,9 @@ static int luks_remove_helper(struct crypt_device *cd,
        int openedIndex;
        int r, last_slot;
 
-       if (!LUKS_device_ready(options->device, O_RDWR))
-           return -ENOTBLK;
+       r = LUKS_read_phdr(options->device, &hdr, 1, cd);
+       if(r < 0)
+               return r;
 
        if(supply_it) {
                get_key("Enter LUKS passphrase to be deleted: ",&password,&passwordLen, 0, options->new_key_file,
@@ -260,7 +261,7 @@ static int luks_remove_helper(struct crypt_device *cd,
                        r = -EINVAL; goto out;
                }
 
-               keyIndex = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk, cd);
+               keyIndex = LUKS_open_key_with_hdr(device, CRYPT_ANY_SLOT, password, passwordLen, &hdr, &mk, cd);
                if(keyIndex < 0) {
                        log_err(cd, "No remaining key available with this passphrase.\n");
                        r = -EPERM; goto out;
@@ -276,7 +277,13 @@ static int luks_remove_helper(struct crypt_device *cd,
                }
        }
 
-       last_slot = LUKS_is_last_keyslot(options->device, keyIndex);
+       if (LUKS_keyslot_info(&hdr, keyIndex) == SLOT_INACTIVE) {
+               log_err(cd, _("Key %d not active. Can't wipe.\n"), keyIndex);
+               r = -EINVAL;
+               goto out;
+       }
+
+       last_slot = (LUKS_keyslot_info(&hdr, keyIndex) == SLOT_ACTIVE_LAST);
        if(last_slot && !(options->icb->yesDialog(_("This is the last keyslot. Device will become unusable after purging this key.")))) {
                r = -EINVAL; goto out;
        }
@@ -298,7 +305,7 @@ static int luks_remove_helper(struct crypt_device *cd,
                if(!last_slot)
                        hdr.keyblock[keyIndex].active = LUKS_KEY_DISABLED;
 
-               openedIndex = LUKS_open_any_key_with_hdr(device, password, passwordLen, &hdr, &mk, cd);
+               openedIndex = LUKS_open_key_with_hdr(device, CRYPT_ANY_SLOT, password, passwordLen, &hdr, &mk, cd);
                 /* Clean up */
                 if (openedIndex >= 0) {
                         LUKS_dealloc_masterkey(mk);
@@ -429,10 +436,10 @@ int crypt_luksFormat(struct crypt_options *options)
        char cipherName[LUKS_CIPHERNAME_L];
        char cipherMode[LUKS_CIPHERMODE_L];
        unsigned int passwordLen;
-       unsigned int PBKDF2perSecond = 0;
+       uint64_t PBKDF2perSecond = 0;
         int r, keyIndex;
 
-       if (!LUKS_device_ready(options->device, O_RDWR | O_EXCL))
+       if (!device_ready(cd, options->device, O_RDWR | O_EXCL))
                return -ENOTBLK;
 
        mk = LUKS_generate_masterkey(options->key_size);
@@ -466,7 +473,7 @@ int crypt_luksFormat(struct crypt_options *options)
                return r;
        }
 
-       r = LUKS_generate_phdr(&header, mk, cipherName, cipherMode, options->hash, LUKS_STRIPES, options->align_payload, NULL);
+       r = LUKS_generate_phdr(&header, mk, cipherName, cipherMode, options->hash, NULL, LUKS_STRIPES, options->align_payload, NULL);
        if(r < 0) return r;
 
        keyIndex = keyslot_from_option(NULL, options->key_slot, &header);
@@ -474,13 +481,6 @@ int crypt_luksFormat(struct crypt_options *options)
                r = -EINVAL; goto out;
        }
 
-       r = LUKS_benchmarkt_iterations(options->hash, &PBKDF2perSecond);
-       if (r < 0) goto out;
-
-       header.keyblock[keyIndex].passwordIterations = at_least_one(PBKDF2perSecond * ((float)options->iteration_time / 1000.0));
-#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->timeout, options->flags, NULL);
        if(!password) {
@@ -492,7 +492,8 @@ int crypt_luksFormat(struct crypt_options *options)
        if(r < 0) goto out;
 
        /* Set key, also writes phdr */
-       r = LUKS_set_key(options->device, keyIndex, password, passwordLen, &header, mk, NULL);
+       r = LUKS_set_key(options->device, keyIndex, password, passwordLen, &header, mk,
+                        options->iteration_time, &PBKDF2perSecond, NULL);
        if(r < 0) goto out; 
 
        r = 0;
@@ -522,7 +523,7 @@ int crypt_luksOpen(struct crypt_options *options)
                return -EEXIST;
        }
 
-       if (!LUKS_device_ready(options->device, O_RDONLY | excl))
+       if (!device_ready(cd, options->device, O_RDONLY | excl))
                return -ENOTBLK;
 
        if (get_device_infos(options->device, &infos, cd) < 0) {
@@ -557,7 +558,11 @@ start:
                r = -EINVAL; goto out;
        }
 
-        r = LUKS_open_any_key(options->device, password, passwordLen, &hdr, &mk, cd);
+       r = LUKS_read_phdr(options->device, &hdr, 1, cd);
+       if(r < 0)
+               return r;
+
+       r = LUKS_open_key_with_hdr(options->device, CRYPT_ANY_SLOT, password, passwordLen, &hdr, &mk, cd);
        if (r == -EPERM)
                log_err(cd, "No key available with this passphrase.\n");
        if (r < 0)
@@ -628,11 +633,11 @@ int crypt_luksAddKey(struct crypt_options *options)
        struct luks_phdr hdr;
        char *password=NULL; unsigned int passwordLen;
        unsigned int keyIndex;
-       unsigned int PBKDF2perSecond = 0;
+       uint64_t PBKDF2perSecond = 0;
        const char *device = options->device;
        int r;
 
-       if (!LUKS_device_ready(options->device, O_RDWR))
+       if (!device_ready(cd, options->device, O_RDWR))
                return -ENOTBLK;
 
        r = LUKS_read_phdr(device, &hdr, 1, cd);
@@ -655,7 +660,7 @@ int crypt_luksAddKey(struct crypt_options *options)
        if(!password) {
                r = -EINVAL; goto out;
        }
-       r = LUKS_open_any_key(device, password, passwordLen, &hdr, &mk, cd);
+       r = LUKS_open_key_with_hdr(device, CRYPT_ANY_SLOT, 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;
@@ -673,11 +678,7 @@ int crypt_luksAddKey(struct crypt_options *options)
                r = -EINVAL; goto out;
        }
 
-       r = LUKS_benchmarkt_iterations(hdr.hashSpec, &PBKDF2perSecond);
-       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, cd);
+       r = LUKS_set_key(device, keyIndex, password, passwordLen, &hdr, mk, options->iteration_time, &PBKDF2perSecond, cd);
        if(r < 0) goto out;
 
        r = 0;
index f095afa..298e09f 100644 (file)
@@ -2,7 +2,7 @@
  * LUKS - Linux Unified Key Setup 
  *
  * Copyright (C) 2004-2006, Clemens Fruhwirth <clemens@endorphin.org>
- * 
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * version 2 as published by the Free Software Foundation.
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <sys/ioctl.h>
 #include <linux/fs.h>
+#include <netinet/in.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <unistd.h>
-#include <assert.h>
-#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -47,11 +43,13 @@ static inline int round_up_modulo(int x, int m) {
        return div_round_up(x, m) * m;
 }
 
-struct luks_masterkey *LUKS_alloc_masterkey(int keylength)
+struct luks_masterkey *LUKS_alloc_masterkey(int keylength, const char *key)
 { 
        struct luks_masterkey *mk=malloc(sizeof(*mk) + keylength);
        if(NULL == mk) return NULL;
        mk->keyLength=keylength;
+       if (key)
+               memcpy(&mk->key, key, keylength);
        return mk;
 }
 
@@ -66,7 +64,7 @@ void LUKS_dealloc_masterkey(struct luks_masterkey *mk)
 
 struct luks_masterkey *LUKS_generate_masterkey(int keylength)
 {
-       struct luks_masterkey *mk=LUKS_alloc_masterkey(keylength);
+       struct luks_masterkey *mk=LUKS_alloc_masterkey(keylength, NULL);
        if(NULL == mk) return NULL;
 
        int r = getRandom(mk->key,keylength);
@@ -77,11 +75,10 @@ struct luks_masterkey *LUKS_generate_masterkey(int keylength)
        return mk;
 }
 
-int LUKS_read_phdr(
-       const char *device,
-       struct luks_phdr *hdr,
-       int require_luks_device,
-       struct crypt_device *ctx)
+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;
@@ -137,10 +134,9 @@ int LUKS_read_phdr(
        return r;
 }
 
-int LUKS_write_phdr(
-       const char *device,
-       struct luks_phdr *hdr,
-       struct crypt_device *ctx)
+int LUKS_write_phdr(const char *device,
+                   struct luks_phdr *hdr,
+                   struct crypt_device *ctx)
 {
        int devfd = 0; 
        unsigned int i; 
@@ -176,16 +172,22 @@ int LUKS_write_phdr(
                log_err(ctx, _("Error during update of LUKS header on device %s.\n"), device);
        close(devfd);
 
+       /* Re-read header from disk to be sure that in-memory and on-disk data are the same. */
+       if (!r) {
+               r = LUKS_read_phdr(device, hdr, 1, ctx);
+               if (r)
+                       log_err(ctx, _("Error re-reading LUKS header after update on device %s.\n"), device);
+       }
+
        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,
-       struct crypt_device *ctx)
+int LUKS_generate_phdr(struct luks_phdr *header,
+                      const struct luks_masterkey *mk,
+                      const char *cipherName, const char *cipherMode, const char *hashSpec,
+                      const char *uuid, 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);
@@ -241,7 +243,12 @@ int LUKS_generate_phdr(
 
        header->payloadOffset=currentSector;
 
-       uuid_generate(partitionUuid);
+       if (uuid && !uuid_parse(uuid, partitionUuid)) {
+               log_err(ctx, _("Wrong UUID format provided, generating new one.\n"));
+               uuid = NULL;
+       }
+       if (!uuid)
+               uuid_generate(partitionUuid);
         uuid_unparse(partitionUuid, header->uuid);
 
        log_dbg("Data offset %d, UUID %s", header->payloadOffset, header->uuid);
@@ -249,14 +256,12 @@ int LUKS_generate_phdr(
        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,
-       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,
+                uint32_t iteration_time_ms,
+                uint64_t *PBKDF2_per_sec,
+                struct crypt_device *ctx)
 {
        char derivedKey[hdr->keyBytes];
        char *AfKey;
@@ -274,6 +279,21 @@ int LUKS_set_key(
                 return -EINVAL;
        }
 
+       log_dbg("Calculating data for key slot %d", keyIndex);
+
+       if (!*PBKDF2_per_sec) {
+               if (PBKDF2_performance_check(hdr->hashSpec, PBKDF2_per_sec) < 0) {
+                       log_err(ctx, _("Not compatible PBKDF2 options (using hash algorithm %s)."), hdr->hashSpec);
+                       return -EINVAL;
+               }
+               log_dbg("PBKDF2: %" PRIu64 " iterations per second using hash %s.", *PBKDF2_per_sec, hdr->hashSpec);
+       }
+
+       /* Avoid floating point operation - don't tell anyone that second have no 1024 miliseconds :-) */
+       iteration_time_ms = at_least_one(iteration_time_ms / 1024);
+       hdr->keyblock[keyIndex].passwordIterations = at_least_one((uint32_t)(*PBKDF2_per_sec/2) * iteration_time_ms);
+       log_dbg("Key slot %d use %d password iterations.", keyIndex, hdr->keyblock[keyIndex].passwordIterations);
+
        r = getRandom(hdr->keyblock[keyIndex].passwordSalt, LUKS_SALTSIZE);
        if(r < 0) return r;
 
@@ -315,7 +335,9 @@ int LUKS_set_key(
        }
 
        /* Mark the key as active in phdr */
-       hdr->keyblock[keyIndex].active = LUKS_KEY_ENABLED;
+       r = LUKS_keyslot_set(hdr, (int)keyIndex, 1);
+       if(r < 0) goto out;
+
        r = LUKS_write_phdr(device, hdr, ctx);
        if(r < 0) goto out;
 
@@ -325,25 +347,43 @@ out:
        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];
+
+       if (PBKDF2_HMAC(hdr->hashSpec, mk->key, mk->keyLength,
+                       hdr->mkDigestSalt, LUKS_SALTSIZE,
+                       hdr->mkDigestIterations, checkHashBuf,
+                       LUKS_DIGESTSIZE) < 0)
+               return -EINVAL;
+
+       if (memcmp(checkHashBuf, hdr->mkDigest, LUKS_DIGESTSIZE))
+               return -EPERM;
+
+       return 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,
-       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)
 {
+       crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyIndex);
        char derivedKey[hdr->keyBytes];
        char *AfKey;
        size_t AFEKSize;
-       char checkHashBuf[LUKS_DIGESTSIZE];
        int r;
 
-       if(hdr->keyblock[keyIndex].active != LUKS_KEY_ENABLED) {
+       log_dbg("Trying to open key slot %d [%d].", keyIndex, (int)ki);
+
+       if (ki < SLOT_ACTIVE)
                return -ENOENT;
-       }
 
        // assert((mk->keyLength % TWOFISH_BLOCKSIZE) == 0); FIXME
 
@@ -374,13 +414,7 @@ int LUKS_open_key(
        r = AF_merge(AfKey,mk->key,mk->keyLength,hdr->keyblock[keyIndex].stripes,hdr->hashSpec);
        if(r < 0) goto out;
 
-       r = PBKDF2_HMAC(hdr->hashSpec,mk->key,mk->keyLength,
-                       hdr->mkDigestSalt,LUKS_SALTSIZE,
-                       hdr->mkDigestIterations,
-                       checkHashBuf,LUKS_DIGESTSIZE);
-       if(r < 0) goto out;
-
-       r = (memcmp(checkHashBuf,hdr->mkDigest, LUKS_DIGESTSIZE) == 0)?0:-EPERM;
+       r = LUKS_verify_master_key(hdr, mk);
        if (r >= 0)
                log_std(ctx, _("Key slot %d unlocked.\n"), keyIndex);
 out:
@@ -388,36 +422,23 @@ out:
        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,
-       struct crypt_device *ctx)
+int LUKS_open_key_with_hdr(const char *device,
+                          int keyIndex,
+                          const char *password,
+                          size_t passwordLen,
+                          struct luks_phdr *hdr,
+                          struct luks_masterkey **mk,
+                          struct crypt_device *ctx)
 {
+       unsigned int i;
        int r;
 
-       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, ctx);
-}
+       *mk = LUKS_alloc_masterkey(hdr->keyBytes, NULL);
 
-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;
+       if (keyIndex >= 0)
+               return LUKS_open_key(device, keyIndex, password, passwordLen, hdr, *mk, ctx);
 
-       *mk=LUKS_alloc_masterkey(hdr->keyBytes);
-       for(i=0; i<LUKS_NUMKEYS; i++) {
+       for(i = 0; i < LUKS_NUMKEYS; i++) {
                r = LUKS_open_key(device, i, password, passwordLen, hdr, *mk, ctx);
                if(r == 0)
                        return i;
@@ -491,84 +512,92 @@ static int wipe(const char *device, unsigned int from, unsigned int to)
        return r;
 }
 
-int LUKS_del_key(
-       const char *device,
-       unsigned int keyIndex,
-       struct crypt_device *ctx)
+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, 1, ctx);
-       if(r != 0) {
-               /* placeholder */
-       } else if(keyIndex >= LUKS_NUMKEYS || hdr.keyblock[keyIndex].active != LUKS_KEY_ENABLED) {
+       if (r)
+               return r;
+
+       r = LUKS_keyslot_set(&hdr, keyIndex, 0);
+       if (r) {
                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 */
-               startOffset = hdr.keyblock[keyIndex].keyMaterialOffset;
-               stripesLen = hdr.keyBytes * hdr.keyblock[keyIndex].stripes;
-               endOffset = startOffset + div_round_up(stripesLen, SECTOR_SIZE);
-
-               r = wipe(device, startOffset, endOffset);
-               if(r == 0) {
-                       /* mark the key as inactive in header */
-                       hdr.keyblock[keyIndex].active = LUKS_KEY_DISABLED;
-                       r = LUKS_write_phdr(device, &hdr, ctx);
-               }
+               return r;
        }
 
+       /* secure deletion of key material */
+       startOffset = hdr.keyblock[keyIndex].keyMaterialOffset;
+       stripesLen = hdr.keyBytes * hdr.keyblock[keyIndex].stripes;
+       endOffset = startOffset + div_round_up(stripesLen, SECTOR_SIZE);
+
+       r = wipe(device, startOffset, endOffset);
+       if (r) {
+               log_err(ctx, _("Cannot wipe device %s.\n"), device);
+               return r;
+       }
+
+       r = LUKS_write_phdr(device, &hdr, ctx);
+
        return r;
 }
 
-int LUKS_is_last_keyslot(const char *device, unsigned int keyIndex)
+crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot)
 {
-       struct luks_phdr hdr;
-       unsigned int i;
-       int r;
+       int i;
 
-       r = LUKS_read_phdr(device, &hdr, 1, NULL);
-       if(r < 0) return r;
+       if(keyslot >= LUKS_NUMKEYS || keyslot < 0)
+               return SLOT_INVALID;
 
-       for(i = 0; i < LUKS_NUMKEYS; i++) {
-               if(i != keyIndex && hdr.keyblock[i].active == LUKS_KEY_ENABLED)
-                       return 0;
-       }
-       return 1;
+       if (hdr->keyblock[keyslot].active == LUKS_KEY_DISABLED)
+               return SLOT_INACTIVE;
+
+       if (hdr->keyblock[keyslot].active != LUKS_KEY_ENABLED)
+               return SLOT_INVALID;
+
+       for(i = 0; i < LUKS_NUMKEYS; i++)
+               if(i != keyslot && hdr->keyblock[i].active == LUKS_KEY_ENABLED)
+                       return SLOT_ACTIVE;
+
+       return SLOT_ACTIVE_LAST;
 }
 
-int LUKS_benchmarkt_iterations(const char *hash, unsigned int *count)
+int LUKS_keyslot_find_empty(struct luks_phdr *hdr)
 {
-       if (PBKDF2_performance_check(hash, count) < 0) {
-               set_error(_("Not compatible options (using hash algorithm %s)."), hash);
+       int i;
+
+       for (i = 0; i < LUKS_NUMKEYS; i++)
+               if(hdr->keyblock[i].active == LUKS_KEY_DISABLED)
+                       break;
+
+       if (i == LUKS_NUMKEYS)
                return -EINVAL;
-       }
 
-       *count /= 2;
-       return 0;
+       return i;
 }
 
-int LUKS_device_ready(const char *device, int mode)
+int LUKS_keyslot_active_count(struct luks_phdr *hdr)
 {
-       int devfd;
-       struct stat st;
+       int i, num = 0;
 
-       if(stat(device, &st) < 0) {
-               set_error(_("Device %s doesn't exist or access denied."), device);
-               return 0;
-       }
+       for (i = 0; i < LUKS_NUMKEYS; i++)
+               if(hdr->keyblock[i].active == LUKS_KEY_ENABLED)
+                       num++;
 
-       devfd = open(device, mode | O_DIRECT | O_SYNC);
-       if(devfd < 0) {
-               set_error(_("Can't open device %s for %s%saccess."), device,
-                         (mode & O_EXCL)?_("exclusive "):"",
-                         (mode & O_RDWR)?_("writable "):"read-only ");
-               return 0;
-       }
-       close(devfd);
+       return num;
+}
+
+int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable)
+{
+       crypt_keyslot_info ki = LUKS_keyslot_info(hdr, keyslot);
+
+       if (ki == SLOT_INVALID)
+               return -EINVAL;
 
-       return 1;
+       hdr->keyblock[keyslot].active = enable ? LUKS_KEY_ENABLED : LUKS_KEY_DISABLED;
+       log_dbg("Key slot %d was %s in LUKS header.", keyslot, enable ? "enabled" : "disabled");
+       return 0;
 }
index ab5b575..c433bc5 100644 (file)
@@ -5,10 +5,7 @@
  * LUKS partition header
  */
 
-#include <stddef.h>
-#include <netinet/in.h>
 #include "libcryptsetup.h"
-#include "internal.h"
 
 #define LUKS_CIPHERNAME_L 32
 #define LUKS_CIPHERMODE_L 32
@@ -78,16 +75,19 @@ struct luks_masterkey {
        char key[];
 };
 
-struct luks_masterkey *LUKS_alloc_masterkey(int keylength);
-
+struct luks_masterkey *LUKS_alloc_masterkey(int keylength, const char *key);
 void LUKS_dealloc_masterkey(struct luks_masterkey *mk);
-
 struct luks_masterkey *LUKS_generate_masterkey(int keylength);
+int LUKS_verify_master_key(const struct luks_phdr *hdr,
+                          const struct luks_masterkey *mk);
 
 int LUKS_generate_phdr(
        struct luks_phdr *header,
        const struct luks_masterkey *mk,
-       const char *cipherName, const char *cipherMode, const char *hashSpec,
+       const char *cipherName,
+       const char *cipherMode,
+       const char *hashSpec,
+       const char *uuid,
        unsigned int stripes,
        unsigned int alignPayload,
        struct crypt_device *ctx);
@@ -110,6 +110,8 @@ int LUKS_set_key(
        size_t passwordLen,
        struct luks_phdr *hdr,
        struct luks_masterkey *mk,
+       uint32_t iteration_time_ms,
+       uint64_t *PBKDF2_per_sec,
        struct crypt_device *ctx);
 
 int LUKS_open_key(
@@ -121,16 +123,9 @@ int LUKS_open_key(
        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(
+int LUKS_open_key_with_hdr(
        const char *device,
+       int keyIndex,
        const char *password,
        size_t passwordLen,
        struct luks_phdr *hdr,
@@ -142,8 +137,10 @@ int LUKS_del_key(
        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);
+crypt_keyslot_info LUKS_keyslot_info(struct luks_phdr *hdr, int keyslot);
+int LUKS_keyslot_find_empty(struct luks_phdr *hdr);
+int LUKS_keyslot_active_count(struct luks_phdr *hdr);
+int LUKS_keyslot_set(struct luks_phdr *hdr, int keyslot, int enable);
 
 int LUKS_encrypt_to_storage(
        char *src, size_t srcLength,
@@ -161,5 +158,4 @@ int LUKS_decrypt_from_storage(
        unsigned int sector,
        struct crypt_device *ctx);
 
-int LUKS_device_ready(const char *device, int mode);
 #endif
index 9581095..15c2de1 100644 (file)
 #include <sys/time.h>
 #include <gcrypt.h>
 
-static volatile unsigned int __PBKDF2_global_j = 0;
-static volatile unsigned int __PBKDF2_performance = 0;
+static volatile uint64_t __PBKDF2_global_j = 0;
+static volatile uint64_t __PBKDF2_performance = 0;
 
 static int init_crypto(void)
 {
        if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
-               if (!gcry_check_version (GCRYPT_VERSION))
-                       return -ENOSYS;
+               //if (!gcry_check_version (GCRYPT_VERSION))
+               //      return -ENOSYS;
                gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
                gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
                gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
@@ -219,7 +219,7 @@ static int pkcs5_pbkdf2(const char *hash,
                        }
 
                        if (perfcheck)
-                               __PBKDF2_global_j--;
+                               __PBKDF2_global_j++;
                }
 
                memcpy(DK + (i - 1) * hLen, T, (uint) i == l ? r : hLen);
@@ -255,21 +255,18 @@ int PBKDF2_HMAC_ready(const char *hash)
 
 static void sigvtalarm(int foo)
 {
-       __PBKDF2_performance = ~(0U) - __PBKDF2_global_j;
-       __PBKDF2_global_j = 0;
+       __PBKDF2_performance = __PBKDF2_global_j;
 }
 
 /* This code benchmarks PBKDF2 and returns iterations/second using wth specified hash */
-int PBKDF2_performance_check(const char *hash, unsigned int *iter)
+int PBKDF2_performance_check(const char *hash, uint64_t *iter)
 {
        int r;
        char buf;
        struct itimerval it;
 
-       if(__PBKDF2_performance != 0) {
-               *iter = __PBKDF2_performance;
-               return 0;
-       }
+       if (__PBKDF2_global_j)
+               return -EBUSY;
 
        if (!PBKDF2_HMAC_ready(hash))
                return -EINVAL;
@@ -284,8 +281,8 @@ int PBKDF2_performance_check(const char *hash, unsigned int *iter)
 
        r = pkcs5_pbkdf2(hash, "foo", 3, "bar", 3, ~(0U), 1, &buf, 1);
 
-       __PBKDF2_global_j = 0;
-
        *iter = __PBKDF2_performance;
+       __PBKDF2_global_j = 0;
+       __PBKDF2_performance = 0;
        return r;
 }
index 1488dec..ae602fe 100644 (file)
@@ -11,7 +11,7 @@ int PBKDF2_HMAC(const char *hash,
                char *dKey, size_t dKeyLen);
 
 
-int PBKDF2_performance_check(const char *hash, unsigned int *iter);
+int PBKDF2_performance_check(const char *hash, uint64_t *iter);
 int PBKDF2_HMAC_ready(const char *hash);
 
 #endif