* Add new libcryptsetup API (documented in libcryptsetup.h).
authorMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:53 +0000 (18:09 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sun, 30 Aug 2009 18:09:53 +0000 (18:09 +0000)
Signed-off-by: Milan Broz <mbroz@redhat.com>
git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@96 36d66b0a-2a48-0410-832c-cd162a569da5

ChangeLog
lib/libcryptsetup.h
lib/setup.c

index 9839d3b..961a612 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -13,6 +13,7 @@
        * Add LUKS function to verify master key digest.
        * Move key slot manuipulation function into LUKS specific code.
        * Replace global options struct with separate parameters in helper functions.
+       * Add new libcryptsetup API (documented in libcryptsetup.h).
 
 2009-08-17  Milan Broz  <mbroz@redhat.com>
        * Fix PBKDF2 speed calculation for large passhrases.
index 7602136..daf425c 100644 (file)
@@ -8,13 +8,411 @@ extern "C" {
 
 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;
+/**
+ * Initialise crypt device handle and check if provided device exists.
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - returns pointer to crypt device handle
+ *
+ * Note that logging is not initialized here, possible messages uses
+ * default log function.
+ */
+int crypt_init(struct crypt_device **cd, const char *device);
 
+/**
+ * Set log function.
+ *
+ * @cd - crypt device handle
+ * @usrptr - provided identification in callback
+ * @class  - log type below (debug messages can uses other levels)
+ * @msg    - log message
+ */
 #define CRYPT_LOG_NORMAL 0
 #define CRYPT_LOG_ERROR  1
-#define CRYPT_LOG_DEBUG  -1 /* always on stdout */
+#define CRYPT_LOG_DEBUG -1 /* always on stdout */
+void crypt_set_log_callback(struct crypt_device *cd,
+       void (*log)(int class, const char *msg, void *usrptr),
+       void *usrptr);
+
+/**
+ * Set confirmation callback (yes/no)
+ *
+ * If code need confirmation (like deleting last key slot) this function
+ * is called. If not defined, everything is confirmed.
+ *
+ * Calback should return 0 if operation is declined, other values mean accepted.
+ *
+ * @cd - crypt device handle
+ * @usrptr - provided identification in callback
+ * @msg - Message for user to confirm
+ */
+void crypt_set_confirm_callback(struct crypt_device *cd,
+       int (*confirm)(const char *msg, void *usrptr),
+       void *usrptr);
+
+/**
+ * Set password query callback.
+ *
+ * If code need _interactive_ query for password, this callback is called.
+ * If not defined, compiled-in default is called (uses terminal input).
+ *
+ * @cd - crypt device handle
+ * @usrptr - provided identification in callback
+ * @msg - Message for user
+ * @buf - buffer for password
+ * @length - size of buffer
+ *
+ * - Note that if this function is defined, verify option is ignored
+ *   (caller whch provided callback is responsible fo password verification)
+ * - Only zero terminated passwords can be enteted this way, for complex
+ *   API functions directly.
+ * - Maximal length of password is limited to @length-1 (minimal 511 chars)
+ */
+void crypt_set_password_callback(struct crypt_device *cd,
+       int (*password)(const char *msg, char *buf, size_t length, void *usrptr),
+       void *usrptr);
+
+/**
+ * Various crypt device parameters
+ *
+ * @cd - crypt device handle
+ * @timeout - timeout in secons for password entry if compiled-in function used
+ * @password_retry - number of tries for password if not verified
+ * @iteration_time - iteration time for LUKS header in miliseconds
+ * @password_verify - for compiled-in password query always verify passwords twice
+ */
+void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec);
+void crypt_set_password_retry(struct crypt_device *cd, int tries);
+void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms);
+void crypt_set_password_verify(struct crypt_device *cd, int password_verify);
+
+/**
+ * Helper to lock/unlock memory to avoid swapping sesitive data_alignment
+ *
+ * @cd - crypt device handle, can be NULL
+ * @lock - 0 to unloct otherwise lock memory
+ *
+ * Return value indicated that memory is locked (function can be called multiple times).
+ * Only root can do this. Note it locks/unlocks all process memory, not only crypt context.
+ */
+int crypt_memory_lock(struct crypt_device *cd, int lock);
+
+#define CRYPT_PLAIN "PLAIN" /* regular crypt device, no on-disk header */
+#define CRYPT_LUKS1 "LUKS1" /* LUKS version 1 header on-disk */
+
+struct crypt_params_plain {
+       const char *hash; /* password hash function */
+       uint64_t offset;  /* offset in sectors */
+       uint64_t skip;    /* IV initilisation sector */
+};
+
+struct crypt_params_luks1 {
+       const char *hash;      /* hash used in LUKS header */
+       size_t data_alignment; /* in sectors, data offset is multiple of this */
+};
+
+/**
+ * Create (format) new crypt device (and possible header on-disk) but not activates it.
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle
+ * @type - type of device (optional params struct must be of this type)
+ * @cipher - (e.g. "aes")
+ * @cipher_mode - including IV specification (e.g. "xts-plain")
+ * @uuid - requested UUID or NULL if it should be generated
+ * @volume_key - pre-generated volume key or NULL if it should be generated (only for LUKS)
+ * @volume_key_size - size og volume key in bytes.
+ * @params - crypt type specific parameters
+ *
+ * Note that crypt_format do not enable any keyslot, but it stores volume key internally
+ * and subsequent crypt_keyslot_add_* calls can be used.
+ * (It is the only situation when crypt_keyslot_add_* do not require active key slots.)
+ */
+int crypt_format(struct crypt_device *cd,
+       const char *type,
+       const char *cipher,
+       const char *cipher_mode,
+       const char *uuid,
+       const char *volume_key,
+       size_t volume_key_size,
+       void *params);
+
+/**
+ * Load crypt device parameters from on-disk header
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle
+ * @requested_type - use NULL for all known
+ * @params - crypt type specific parameters
+ */
+int crypt_load(struct crypt_device *cd,
+              const char *requested_type,
+              void *params);
+
+/**
+ * Releases crypt device context and used memory.
+ *
+ * @cd - crypt device handle
+ */
+void crypt_free(struct crypt_device *cd);
+
+/**
+ * Add key slot using provided passphrase
+ *
+ * Returns allocated key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @keyslot - requested keyslot or CRYPT_ANY_SLOT
+ * @passphrase - passphrase used to unlock volume key, NULL for query
+ * @passphrase_size - size of @passphrase (binary data)
+ * @new_passphrase - passphrase for new keyslot, NULL for query
+ * @new_passphrase_size - size of @new_passphrase (binary data)
+ */
+#define CRYPT_ANY_SLOT -1
+int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
+       int keyslot,
+       const char *passphrase,
+       size_t passphrase_size,
+       const char *new_passphrase,
+       size_t new_passphrase_size);
+
+/**
+* Add key slot using provided key file path
+ *
+ * Returns allocated key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @keyslot - requested keyslot or CRYPT_ANY_SLOT
+ * @keyfile - key file used to unlock volume key, NULL for passphrase query
+ * @keyfile_size - number of bytes to read from @keyfile, 0 is unlimited
+ * @new_keyfile - keyfile for new keyslot, NULL for passphrase query
+ * @new_keyfile_size - number of bytes to read from @new_keyfile, 0 is unlimited
+ *
+ * Note that @keyfile can be "-" for STDIN
+ */
+int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
+       int keyslot,
+       const char *keyfile,
+       size_t keyfile_size,
+       const char *new_keyfile,
+       size_t new_keyfile_size);
+
+/**
+ * Add key slot using provided volume key
+ *
+ * Returns allocated key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @keyslot - requested keyslot or CRYPT_ANY_SLOT
+ * @volume_key - provided volume key or NULL if used after crypt_format
+ * @volume_key_size - size of @volume_key
+ * @passphrase - passphrase for new keyslot, NULL for query
+ * @passphrase_size - size of @passphrase
+ */
+int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
+       int keyslot,
+       const char *volume_key,
+       size_t volume_key_size,
+       const char *passphrase,
+       size_t passphrase_size);
+
+/**
+ * Destroy (and disable) key slot
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle
+ * @keyslot - requested key slot to destroy
+ *
+ * Note that there is no passphrase verification used.
+ */
+int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot);
+
+/**
+ * Activation flags
+ */
+#define CRYPT_ACTIVATE_READONLY (1 << 0)
+#define CRYPT_ACTIVATE_NO_UUID  (1 << 1)
+
+/**
+ * Activate device or check passphrase
+ *
+ * Returns unlocked key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @name - name of device to create, if NULL only check passphrase
+ * @keyslot - requested keyslot to check or CRYPT_ANY_SLOT
+ * @passphrase - passphrase used to unlock volume key, NULL for query
+ * @passphrase_size - size of @passphrase
+ * @flags - activation flags
+ */
+int crypt_activate_by_passphrase(struct crypt_device *cd,
+       const char *name,
+       int keyslot,
+       const char *passphrase,
+       size_t passphrase_size,
+       uint32_t flags);
+
+/**
+ * Activate device or check using key file
+ *
+ * Returns unlocked key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @name - name of device to create, if NULL only check keyfile
+ * @keyslot - requested keyslot to check or CRYPT_ANY_SLOT
+ * @keyfile - key file used to unlock volume key
+ * @keyfile_size - number of bytes to read from @keyfile, 0 is unlimited
+ * @flags - activation flags
+ */
+int crypt_activate_by_keyfile(struct crypt_device *cd,
+       const char *name,
+       int keyslot,
+       const char *keyfile,
+       size_t keyfile_size,
+       uint32_t flags);
+
+/**
+ * Activate device using provided volume key
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle
+ * @name - name of device to create, if NULL only check volume key
+ * @volume_key - provided volume key
+ * @volume_key_size - size of @volume_key
+ * @flags - activation flags
+ */
+int crypt_activate_by_volume_key(struct crypt_device *cd,
+       const char *name,
+       const char *volume_key,
+       size_t volume_key_size,
+       uint32_t flags);
+
+/**
+ * Deactivate crypt device
+ *
+ * @cd - crypt device handle, can be NULL
+ * @name - name of device to deactivate
+  */
+int crypt_deactivate(struct crypt_device *cd, const char *name);
+
+/**
+ * Get volume key from of crypt device
+ *
+ * Returns unlocked key slot number or negative errno otherwise.
+ *
+ * @cd - crypt device handle
+ * @keyslot - use this keyslot or CRYPT_ANY_SLOT
+ * @volume_key - buffer for volume key
+ * @volume_key_size - on input, size of buffer @volume_key,
+ *                    on output size of @volume_key
+ * @passphrase - passphrase used to unlock volume key, NULL for query
+ * @passphrase_size - size of @passphrase
+ */
+int crypt_volume_key_get(struct crypt_device *cd,
+       int keyslot,
+       char *volume_key,
+       size_t *volume_key_size,
+       const char *passphrase,
+       size_t passphrase_size);
+
+/**
+ * Verify that provided volume key is valid for crypt device
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle
+ * @volume_key - provided volume key
+ * @volume_key_size - size of @volume_key
+ */
+int crypt_volume_key_verify(struct crypt_device *cd,
+       const char *volume_key,
+       size_t volume_key_size);
+
+/**
+ * Get status info about device name
+ *
+ * Returns value defined by crypt_status_info.
+ *
+ * @cd - crypt device handle, can be NULL
+ * @name -crypt device name
+ *
+ * INACTIVE - no such mapped device
+ * ACTIVE - device is active
+ * BUSY - device is active and has open count > 0
+ */
+typedef enum { INVALID, INACTIVE, ACTIVE, BUSY } crypt_status_info;
+crypt_status_info crypt_status(struct crypt_device *cd, const char *name);
+
+/**
+ * Dump text-formatted information about crypt device to log output
+ *
+ * Returns 0 on success or negative errno value otherwise.
+ *
+ * @cd - crypt device handle, can be NULL
+ */
+int crypt_dump(struct crypt_device *cd);
+
+/**
+ * Various crypt device info functions
+ *
+ * @cd - crypt device handle
+ *
+ * cipher - used cipher, e.g. "aes" or NULL otherwise
+ * cipher_mode - used cipher mode including IV, e.g. "xts-plain" or NULL otherwise
+ * uuid - device UUID or NULL if not set
+ * data_offset - device offset in sectors where real data starts on underlying device)
+ * volume_key_size - size (in bytes) of volume key for crypt device
+ */
+const char *crypt_get_cipher(struct crypt_device *cd);
+const char *crypt_get_cipher_mode(struct crypt_device *cd);
+const char *crypt_get_uuid(struct crypt_device *cd);
+uint64_t crypt_get_data_offset(struct crypt_device *cd);
+int crypt_get_volume_key_size(struct crypt_device *cd);
+
+/**
+ * Get information about particular key slot
+ *
+ * Returns value defined by crypt_keyslot_info.
+ *
+ * @cd - crypt device handle
+ * @keyslot - requested keyslot to check or CRYPT_ANY_SLOT
+ */
+typedef enum { SLOT_INVALID, SLOT_INACTIVE, SLOT_ACTIVE, SLOT_ACTIVE_LAST } crypt_keyslot_info;
+crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot);
+
+/**
+ * Receives last reported error
+ *
+ * @buf - buffef for message
+ * @size - size of buffer
+ *
+ * Note that this is old API function using global context.
+ * All error messages are reported also through log callback.
+ */
+void crypt_get_error(char *buf, size_t size);
+
+/**
+ * Get directory where mapped crypt devices are created
+ */
+const char *crypt_get_dir(void);
+
+/**
+ * Set library debug level
+ */
+#define CRYPT_DEBUG_ALL  -1
+#define CRYPT_DEBUG_NONE  0
+void crypt_set_debug_level(int level);
+
+/**
+ * OLD DEPRECATED API **********************************
+ *
+ * Provided only for backward compatibility.
+ */
 
 struct interface_callbacks { 
     int (*yesDialog)(char *msg);
@@ -69,9 +467,7 @@ int crypt_luksUUID(struct crypt_options *options);
 int crypt_isLuks(struct crypt_options *options);
 int crypt_luksDump(struct crypt_options *options);
 
-void crypt_get_error(char *buf, size_t size);
 void crypt_put_options(struct crypt_options *options);
-const char *crypt_get_dir(void);
 
 #ifdef __cplusplus
 }
index 2f97f60..8f3e4a0 100644 (file)
 #include "internal.h"
 
 struct crypt_device {
+       char *type;
+
+       char *device;
+       struct luks_masterkey *volume_key;
+       uint64_t timeout;
+       uint64_t iteration_time;
+       int tries;
+       int password_verify;
+
+       /* used in CRYPT_LUKS1 */
+       struct luks_phdr hdr;
+       uint64_t PBKDF2_per_sec;
+
+       /* used in CRYPT_PLAIN */
+       struct crypt_params_plain plain_hdr;
+       char *plain_cipher;
+       char *plain_cipher_mode;
+       char *plain_uuid;
+
        /* callbacks definitions */
        void (*log)(int class, const char *msg, void *usrptr);
        void *log_usrptr;
+       int (*confirm)(const char *msg, void *usrptr);
+       void *confirm_usrptr;
+       int (*password)(const char *msg, char *buf, size_t length, void *usrptr);
+       void *password_usrptr;
 };
 
 /* Log helper */
@@ -56,13 +79,6 @@ void logger(struct crypt_device *cd, int class, const char *file,
        free(target);
 }
 
-static void hexprintICB(struct crypt_device *cd, char *d, int n)
-{
-       int i;
-       for(i = 0; i < n; i++)
-               log_std(cd, "%02hhx ", (char)d[i]);
-}
-
 /*
  * Password processing behaviour matrix of process_key
  *
@@ -129,7 +145,43 @@ int parse_into_name_and_mode(const char *nameAndMode, char *name, char *mode)
 #undef xstr
 }
 
+static int isPLAIN(const char *type)
+{
+       return (type && !strcmp(CRYPT_PLAIN, type));
+}
+
+static int isLUKS(const char *type)
+{
+       return (type && !strcmp(CRYPT_LUKS1, type));
+}
+
 /* keyslot helpers */
+static int keyslot_verify_or_find_empty(struct crypt_device *cd, int *keyslot)
+{
+       if (*keyslot == CRYPT_ANY_SLOT) {
+               *keyslot = LUKS_keyslot_find_empty(&cd->hdr);
+               if (*keyslot < 0) {
+                       log_err(cd, _("All key slots full.\n"));
+                       return -EINVAL;
+               }
+       }
+
+       switch (LUKS_keyslot_info(&cd->hdr, *keyslot)) {
+               case SLOT_INVALID:
+                       log_err(cd, _("Key slot %d is invalid, please select between 0 and %d.\n"),
+                               *keyslot, LUKS_NUMKEYS - 1);
+                       return -EINVAL;
+               case SLOT_INACTIVE:
+                       break;
+               default:
+                       log_err(cd, _("Key slot %d is full, please select another one.\n"),
+                               *keyslot);
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int keyslot_is_valid(struct crypt_device *cd, int keySlotIndex)
 {
        if(keySlotIndex >= LUKS_NUMKEYS || keySlotIndex < 0) {
@@ -198,7 +250,7 @@ static int device_check_and_adjust(struct crypt_device *cd,
        return 0;
 }
 
-static int create_device_helper(int reload, struct crypt_options *options)
+static int create_device_helper_old(int reload, struct crypt_options *options)
 {
        struct crypt_device *cd = NULL;
        char *key = NULL;
@@ -253,7 +305,7 @@ static int create_device_helper(int reload, struct crypt_options *options)
        return r;
 }
 
-static int luks_remove_helper(struct crypt_device *cd,
+static int luks_remove_helper_old(struct crypt_device *cd,
                              struct crypt_options *options, int supply_it)
 {
        struct luks_masterkey *mk;
@@ -341,18 +393,158 @@ out:
        return r;
 }
 
+static int create_device_helper(struct crypt_device *cd,
+                               const char *name,
+                               const char *hash,
+                               const char *cipher,
+                               const char *cipher_mode,
+                               const char *key_file,
+                               const char *key,
+                               unsigned int keyLen,
+                               int key_size,
+                               uint64_t size,
+                               uint64_t skip,
+                               uint64_t offset,
+                               const char *uuid,
+                               int read_only,
+                               unsigned int flags,
+                               int reload)
+{
+       crypt_status_info ci;
+       char *dm_cipher = NULL;
+       char *processed_key = NULL;
+       int r;
+
+       ci = crypt_status(cd, name);
+       if (ci == INVALID)
+               return -EINVAL;
+
+       if (reload && ci < ACTIVE)
+               return -EINVAL;
+
+       if (!reload && ci >= ACTIVE) {
+               log_err(cd, _("Device %s already exists.\n"), name);
+               return -EEXIST;
+       }
+
+       if (key_size < 0 || key_size > 1024) {
+               log_err(cd, _("Invalid key size %d.\n"), key_size);
+               return -EINVAL;
+       }
+
+       r = device_check_and_adjust(cd, cd->device, &size, &offset, &read_only);
+       if (r)
+               return r;
+
+       if (cipher_mode && asprintf(&dm_cipher, "%s-%s", cipher, cipher_mode) < 0)
+               return -ENOMEM;
+
+       processed_key = process_key(cd, hash, key_file, key_size, key, keyLen);
+       if (!processed_key)
+               return -ENOENT;
+
+       r = dm_create_device(name, cd->device, dm_cipher ?: cipher, uuid, size, skip, offset,
+                            key_size, processed_key, read_only, reload);
+
+       free(dm_cipher);
+       safe_free(processed_key);
+       return r;
+}
+
+static int open_from_hdr_and_mk(struct crypt_device *cd,
+                               struct luks_masterkey *mk,
+                               const char *name,
+                               uint32_t flags)
+{
+       uint64_t size, offset;
+       char *cipher;
+       int read_only, no_uuid, r;
+
+       size = 0;
+       offset = crypt_get_data_offset(cd);
+       read_only = flags & CRYPT_ACTIVATE_READONLY;
+       no_uuid = flags & CRYPT_ACTIVATE_NO_UUID;
+
+       r = device_check_and_adjust(cd, cd->device, &size, &offset, &read_only);
+       if (r)
+               return r;
+
+       if (asprintf(&cipher, "%s-%s", crypt_get_cipher(cd),
+                    crypt_get_cipher_mode(cd)) < 0)
+               r = -ENOMEM;
+       else
+               r = dm_create_device(name, cd->device, cipher, no_uuid ? NULL : crypt_get_uuid(cd),
+                               size, 0, offset, mk->keyLength, mk->key,
+                               read_only, 0);
+       free(cipher);
+       return r;
+}
+
+static void key_from_terminal(struct crypt_device *cd, char *msg, char **key,
+                             unsigned int *key_len, int force_verify)
+{
+       int r, flags = 0;
+
+       if (cd->password) {
+               *key = safe_alloc(MAX_TTY_PASSWORD_LEN);
+               if (*key)
+                       return;
+               r = cd->password(msg, *key, (size_t)key_len, cd->password_usrptr);
+               if (r < 0) {
+                       safe_free(*key);
+                       *key = NULL;
+               } else
+                       *key_len = r;
+       } else {
+               if (force_verify || cd->password_verify)
+                       flags |= CRYPT_FLAG_VERIFY_IF_POSSIBLE;
+               get_key(msg, key, key_len, 0, NULL, cd->timeout, flags, cd);
+       }
+}
+
+static void key_from_file(struct crypt_device *cd, char *msg,
+                         char **key, unsigned int *key_len,
+                         const char *key_file, size_t key_size)
+{
+       get_key(msg, key, key_len, key_size, key_file, cd->timeout, 0, cd);
+}
+
+void crypt_set_log_callback(struct crypt_device *cd,
+       void (*log)(int class, const char *msg, void *usrptr),
+       void *usrptr)
+{
+       cd->log = log;
+       cd->log_usrptr = usrptr;
+}
+
+void crypt_set_confirm_callback(struct crypt_device *cd,
+       int (*confirm)(const char *msg, void *usrptr),
+       void *usrptr)
+{
+       cd->confirm = confirm;
+       cd->confirm_usrptr = usrptr;
+}
+
+void crypt_set_password_callback(struct crypt_device *cd,
+       int (*password)(const char *msg, char *buf, size_t length, void *usrptr),
+       void *usrptr)
+{
+       cd->password = password;
+       cd->password_usrptr = usrptr;
+}
+
 /* 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);
+       return create_device_helper_old(0, options);
 }
 
 /* OPTIONS: same as create above */
 int crypt_update_device(struct crypt_options *options)
 {
-       return create_device_helper(1, options);
+       return create_device_helper_old(1, options);
 }
 
 /* OPTIONS: name, size, icb */
@@ -602,13 +794,13 @@ start:
 /* OPTIONS: device, keys_slot, key_file, timeout, flags, icb */
 int crypt_luksKillSlot(struct crypt_options *options)
 {
-       return luks_remove_helper(NULL, options, 0);
+       return luks_remove_helper_old(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);
+       return luks_remove_helper_old(NULL, options, 1);
 }
 
 /* OPTIONS: device, new_key_file, key_file, key_slot, flags,
@@ -699,6 +891,7 @@ int crypt_isLuks(struct crypt_options *options)
 }
 
 /* OPTIONS: device, icb */
+static void hexprintICB(struct crypt_device *cd, char *d, int n);
 int crypt_luksDump(struct crypt_options *options)
 {
        struct crypt_device *cd = NULL;
@@ -781,3 +974,864 @@ const char *crypt_get_dir(void)
 {
        return dm_get_dir();
 }
+
+/////////////////////////////////
+//
+// New API
+//
+
+int crypt_init(struct crypt_device **cd, const char *device)
+{
+       struct crypt_device *h = NULL;
+
+       if (!cd)
+               return -EINVAL;
+
+       log_dbg("Allocating crypt device %s context.", device);
+
+       if (!device_ready(NULL, device, 0))
+               return -ENOTBLK;
+
+       if (!(h = malloc(sizeof(struct crypt_device))))
+               return -ENOMEM;
+
+       memset(h, 0, sizeof(*h));
+
+       h->device = strdup(device);
+       if (!h->device) {
+               free(h);
+               return -ENOMEM;
+       }
+
+       if (!dm_init(h, 1) < 0) {
+               free(h);
+               return -ENOSYS;
+       }
+
+       h->iteration_time = 1000;
+       h->password_verify = 0;
+       h->tries = 3;
+       *cd = h;
+       return 0;
+}
+
+static int _crypt_format_plain(struct crypt_device *cd,
+                              const char *cipher,
+                              const char *cipher_mode,
+                              const char *uuid,
+                              struct crypt_params_plain *params)
+{
+       if (!cipher || !cipher_mode || !params || !params->hash) {
+               log_err(cd, _("Invalid plain crypt parameters.\n"));
+               return -EINVAL;
+       }
+
+       if (cd->volume_key->keyLength > 1024) {
+               log_err(cd, _("Invalid key size.\n"));
+               return -EINVAL;
+       }
+
+       cd->plain_cipher = strdup(cipher);
+       cd->plain_cipher_mode = strdup(cipher_mode);
+
+       if (uuid)
+               cd->plain_uuid = strdup(uuid);
+
+       if (params->hash)
+               cd->plain_hdr.hash = strdup(params->hash);
+
+       cd->plain_hdr.offset = params->offset;
+       cd->plain_hdr.skip = params->skip;
+
+       if ((params->hash && !cd->plain_hdr.hash) ||
+           !cd->plain_cipher || !cd->plain_cipher_mode)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static int _crypt_format_luks1(struct crypt_device *cd,
+                              const char *cipher,
+                              const char *cipher_mode,
+                              const char *uuid,
+                              struct crypt_params_luks1 *params)
+{
+       int r;
+
+       r = LUKS_generate_phdr(&cd->hdr, cd->volume_key, cipher, cipher_mode,
+                              (params && params->hash) ? params->hash : "sha1",
+                              uuid, LUKS_STRIPES,
+                              params ? params->data_alignment: DEFAULT_ALIGNMENT, cd);
+       if(r < 0)
+               return r;
+
+       /* Wipe first 8 sectors - fs magic numbers etc. */
+       r = wipe_device_header(cd->device, 8);
+       if(r < 0) {
+               log_err(cd, _("Can't wipe header on device %s.\n"), cd->device);
+               return r;
+       }
+
+       r = LUKS_write_phdr(cd->device, &cd->hdr, cd);
+
+       return r;
+}
+
+int crypt_format(struct crypt_device *cd,
+       const char *type,
+       const char *cipher,
+       const char *cipher_mode,
+       const char *uuid,
+       const char *volume_key,
+       size_t volume_key_size,
+       void *params)
+{
+       int r;
+
+       log_dbg("Formatting device %s as type %s.", cd->device, cd->type ?: "(none)");
+
+       if (!type)
+               return -EINVAL;
+
+       if (volume_key)
+               cd->volume_key = LUKS_alloc_masterkey(volume_key_size, 
+                                                     volume_key);
+       else
+               cd->volume_key = LUKS_generate_masterkey(volume_key_size);
+
+       if(!cd->volume_key)
+               return -ENOMEM;
+
+       if (isPLAIN(type))
+               r = _crypt_format_plain(cd, cipher, cipher_mode,
+                                       uuid, params);
+       else if (isLUKS(type))
+               r = _crypt_format_luks1(cd, cipher, cipher_mode,
+                                       uuid, params);
+       else {
+               /* FIXME: allow plugins here? */
+               log_err(cd, _("Unkown crypt device type %s requesed.\n"), type);
+               r = -EINVAL;
+       }
+
+       if (!r && !(cd->type = strdup(type)))
+               r = -ENOMEM;
+
+       if (r < 0) {
+               LUKS_dealloc_masterkey(cd->volume_key);
+               cd->volume_key = NULL;
+       }
+
+       return r;
+}
+
+int crypt_load(struct crypt_device *cd,
+              const char *requested_type,
+              void *params)
+{
+       struct luks_phdr hdr;
+       int r;
+
+       log_dbg("Trying to load %s crypt type from device %s.",
+               requested_type ?: "any", cd->device);
+
+       if (requested_type && !isPLAIN(requested_type) && !isLUKS(requested_type))
+               return -EINVAL;
+
+       r = LUKS_read_phdr(cd->device, &hdr, 0, cd);
+
+       if (!r) {
+               memcpy(&cd->hdr, &hdr, sizeof(hdr));
+               cd->type = strdup(requested_type);
+               if (!cd->type)
+                       r = -ENOMEM;
+       }
+
+       return r;
+}
+
+void crypt_free(struct crypt_device *cd)
+{
+       if (cd) {
+               log_dbg("Releasing crypt device %s context.", cd->device);
+
+               dm_exit();
+               if (cd->volume_key)
+                       LUKS_dealloc_masterkey(cd->volume_key);
+
+               free(cd->device);
+               free(cd->type);
+
+               /* used in plain device only */
+               free((char*)cd->plain_hdr.hash);
+               free(cd->plain_cipher);
+               free(cd->plain_cipher_mode);
+               free(cd->plain_uuid);
+
+               free(cd);
+       }
+}
+
+// slot manipulation
+int crypt_keyslot_add_by_passphrase(struct crypt_device *cd,
+       int keyslot, // -1 any
+       const char *passphrase, // NULL -> terminal
+       size_t passphrase_size,
+       const char *new_passphrase, // NULL -> terminal
+       size_t new_passphrase_size)
+{
+       struct luks_masterkey *mk = NULL;
+       char *password = NULL, *new_password = NULL;
+       unsigned int passwordLen, new_passwordLen;
+       int r;
+
+       log_dbg("Adding new keyslot, existing passphrase %sprovided,"
+               "new passphrase %sprovided.",
+               passphrase ? "" : "not ", new_passphrase  ? "" : "not ");
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       r = keyslot_verify_or_find_empty(cd, &keyslot);
+       if (r)
+               return r;
+
+       if (!LUKS_keyslot_active_count(&cd->hdr)) {
+               /* No slots used, try to use pre-generated key in header */
+               if (cd->volume_key) {
+                       mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
+                       r = mk ? 0 : -ENOMEM;
+               } else {
+                       log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n"));
+                       return -EINVAL;
+               }
+       } else if (passphrase) {
+               /* Passphrase provided, use it to unlock existing keyslot */
+               r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, passphrase,
+                                          passphrase_size, &cd->hdr, &mk, cd);
+       } else {
+               /* Passphrase not provided, ask first and use it to unlock existing keyslot */
+               key_from_terminal(cd, _("Enter any passphrase: "),
+                                 &password, &passwordLen, 0);
+               if (!password) {
+                       r = -EINVAL;
+                       goto out;
+               }
+
+               r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password,
+                                          passwordLen, &cd->hdr, &mk, cd);
+               safe_free(password);
+       }
+
+       if(r < 0)
+               goto out;
+
+       if (new_passphrase) {
+               new_password = (char *)new_passphrase;
+               new_passwordLen = new_passphrase_size;
+       } else {
+               key_from_terminal(cd, _("Enter new passphrase for key slot: "),
+                                 &new_password, &new_passwordLen, 1);
+               if(!new_password) {
+                       r = -EINVAL;
+                       goto out;
+               }
+       }
+
+       r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
+                        &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
+       if(r < 0) goto out;
+
+       r = 0;
+out:
+       if (!new_passphrase)
+               safe_free(new_password);
+       LUKS_dealloc_masterkey(mk);
+       return r ?: keyslot;
+}
+
+int crypt_keyslot_add_by_keyfile(struct crypt_device *cd,
+       int keyslot,
+       const char *keyfile,
+       size_t keyfile_size,
+       const char *new_keyfile,
+       size_t new_keyfile_size)
+{
+       struct luks_masterkey *mk=NULL;
+       char *password=NULL; unsigned int passwordLen;
+       char *new_password = NULL; unsigned int new_passwordLen;
+       int r;
+
+       log_dbg("Adding new keyslot, existing keyfile %s, new keyfile %s.",
+               keyfile ?: "[none]", new_keyfile ?: "[none]");
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       r = keyslot_verify_or_find_empty(cd, &keyslot);
+       if (r)
+               return r;
+
+       if (!LUKS_keyslot_active_count(&cd->hdr)) {
+               /* No slots used, try to use pre-generated key in header */
+               if (cd->volume_key) {
+                       mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
+                       r = mk ? 0 : -ENOMEM;
+               } else {
+                       log_err(cd, _("Cannot add key slot, all slots disabled and no volume key provided.\n"));
+                       return -EINVAL;
+               }
+       } else {
+               /* Read password from file of (if NULL) from terminal */
+               if (keyfile)
+                       key_from_file(cd, _("Enter any passphrase: "), &password, &passwordLen,
+                                     keyfile, keyfile_size);
+               else
+                       key_from_terminal(cd, _("Enter any passphrase: "),
+                                       &password, &passwordLen, 1);
+
+               if (!password)
+                       return -EINVAL;
+
+               r = LUKS_open_key_with_hdr(cd->device, CRYPT_ANY_SLOT, password, passwordLen,
+                                          &cd->hdr, &mk, cd);
+               safe_free(password);
+       }
+
+       if(r < 0)
+               goto out;
+
+       if (new_keyfile)
+               key_from_file(cd, _("Enter new passphrase for key slot: "),
+                             &new_password, &new_passwordLen, new_keyfile,
+                             new_keyfile_size);
+       else
+               key_from_terminal(cd, _("Enter new passphrase for key slot: "),
+                                 &new_password, &new_passwordLen, 1);
+
+       if(!new_password) {
+               r = -EINVAL;
+               goto out;
+       }
+
+       r = LUKS_set_key(cd->device, keyslot, new_password, new_passwordLen,
+                        &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
+out:
+       safe_free(new_password);
+       LUKS_dealloc_masterkey(mk);
+       return r < 0 ? r : keyslot;
+}
+
+int crypt_keyslot_add_by_volume_key(struct crypt_device *cd,
+       int keyslot,
+       const char *volume_key,
+       size_t volume_key_size,
+       const char *passphrase,
+       size_t passphrase_size
+)
+{
+       struct luks_masterkey *mk;
+       int r = -EINVAL;
+       char *new_password = NULL; unsigned int new_passwordLen;
+
+       log_dbg("Adding new keyslot %d using volume key.", keyslot);
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       if (volume_key)
+               mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
+       else if (cd->volume_key)
+               mk = LUKS_alloc_masterkey(cd->volume_key->keyLength, cd->volume_key->key);
+
+       if (!mk)
+               return -ENOMEM;
+
+       r = LUKS_verify_master_key(&cd->hdr, mk);
+       if (r < 0) {
+               log_err(cd, _("Volume key does not match the volume.\n"));
+               goto out;
+       }
+
+       r = keyslot_verify_or_find_empty(cd, &keyslot);
+       if (r)
+               goto out;
+
+       if (!passphrase) {
+               key_from_terminal(cd, _("Enter new passphrase for key slot: "),
+                                 &new_password, &new_passwordLen, 1);
+               passphrase = new_password;
+               passphrase_size = new_passwordLen;
+       }
+
+       r = LUKS_set_key(cd->device, keyslot, passphrase, passphrase_size,
+                        &cd->hdr, mk, cd->iteration_time, &cd->PBKDF2_per_sec, cd);
+out:
+       if (new_password)
+               safe_free(new_password);
+       LUKS_dealloc_masterkey(mk);
+       return r ?: keyslot;
+}
+
+int crypt_keyslot_destroy(struct crypt_device *cd, int keyslot)
+{
+       crypt_keyslot_info ki;
+
+       log_dbg("Destroying keyslot %d.", keyslot);
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       ki = crypt_keyslot_status(cd, keyslot);
+       if (ki == SLOT_INVALID)
+               return -EINVAL;
+
+       if (ki == SLOT_INACTIVE)
+               return 0;
+
+       return LUKS_del_key(cd->device, keyslot, cd);
+}
+
+// activation/deactivation of device mapping
+int crypt_activate_by_passphrase(struct crypt_device *cd,
+       const char *name,
+       int keyslot,
+       const char *passphrase,
+       size_t passphrase_size,
+       uint32_t flags)
+{
+       crypt_status_info ci;
+       struct luks_masterkey *mk = NULL;
+       char *prompt = NULL, *passphrase_read = NULL;
+       unsigned int passphrase_size_read;
+       int r, tries = cd->tries;
+
+       log_dbg("%s volume %s [keyslot %d] using %spassphrase.",
+               name ? "Activating" : "Checking", name ?: "",
+               keyslot, passphrase ? "" : "[none] ");
+
+       if (!name)
+               return -EINVAL;
+
+       /* plain, use hashed passphrase */
+       if (isPLAIN(cd->type))
+               return create_device_helper(cd, name, cd->plain_hdr.hash,
+                       cd->plain_cipher, cd->plain_cipher_mode, NULL, passphrase, passphrase_size,
+                       cd->volume_key->keyLength, 0, cd->plain_hdr.skip,
+                       cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
+
+       if (name) {
+               ci = crypt_status(NULL, name);
+               if (ci == INVALID)
+                       return -EINVAL;
+               else if (ci >= ACTIVE) {
+                       log_err(cd, _("Device %s already exists.\n"), name);
+                       return -EEXIST;
+               }
+       }
+
+       if(asprintf(&prompt, _("Enter passphrase for %s: "), cd->device) < 0)
+               return -ENOMEM;
+
+       /* provided passphrase, do not retry */
+       if (passphrase) {
+                       r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
+                                                  passphrase_size, &cd->hdr, &mk, cd);
+       } else do {
+               if (mk)
+                       LUKS_dealloc_masterkey(mk);
+               mk = NULL;
+
+               key_from_terminal(cd, prompt, &passphrase_read,
+                                 &passphrase_size_read, 0);
+               if(!passphrase_read) {
+                       r = -EINVAL;
+                       break;
+               }
+
+               r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
+                                          passphrase_size_read, &cd->hdr, &mk, cd);
+               safe_free(passphrase_read);
+               passphrase_read = NULL;
+       } while (r == -EPERM && (--tries > 0));
+
+       if (r >= 0) {
+               keyslot = r;
+               if (name)
+                       r = open_from_hdr_and_mk(cd, mk, name, flags);
+       }
+
+       LUKS_dealloc_masterkey(mk);
+       free(prompt);
+
+       return r < 0  ? r : keyslot;
+}
+
+int crypt_activate_by_keyfile(struct crypt_device *cd,
+       const char *name,
+       int keyslot,
+       const char *keyfile,
+       size_t keyfile_size,
+       uint32_t flags)
+{
+       crypt_status_info ci;
+       struct luks_masterkey *mk = NULL;
+       char *passphrase_read = NULL;
+       unsigned int passphrase_size_read;
+       int r;
+
+       log_dbg("Activating volume %s [keyslot %d] using keyfile %s.",
+               name, keyslot, keyfile ?: "[none]");
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       if (name) {
+               ci = crypt_status(NULL, name);
+               if (ci == INVALID)
+                       return -EINVAL;
+               else if (ci >= ACTIVE) {
+                       log_err(cd, _("Device %s already exists.\n"), name);
+                       return -EEXIST;
+               }
+       }
+
+       if (!keyfile)
+               return -EINVAL;
+
+       key_from_file(cd, _("Enter passphrase: "), &passphrase_read,
+                     &passphrase_size_read, keyfile, keyfile_size);
+       if(!passphrase_read)
+               r = -EINVAL;
+       else {
+               r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase_read,
+                                          passphrase_size_read, &cd->hdr, &mk, cd);
+               safe_free(passphrase_read);
+       }
+
+       if (r >= 0) {
+               keyslot = r;
+               r = open_from_hdr_and_mk(cd, mk, name, flags);
+       }
+
+       LUKS_dealloc_masterkey(mk);
+
+       return r < 0 ? r : keyslot;
+}
+
+int crypt_activate_by_volume_key(struct crypt_device *cd,
+       const char *name,
+       const char *volume_key,
+       size_t volume_key_size,
+       uint32_t flags)
+{
+       crypt_status_info ci;
+       struct luks_masterkey *mk;
+       int r;
+
+       log_dbg("Activating volume %s by volume key.", name);
+
+       /* use key directly, no hash */
+       if (isPLAIN(cd->type))
+               return create_device_helper(cd, name, NULL,
+                       cd->plain_cipher, cd->plain_cipher_mode, NULL, volume_key, volume_key_size,
+                       cd->volume_key->keyLength, 0, cd->plain_hdr.skip,
+                       cd->plain_hdr.offset, cd->plain_uuid, flags & CRYPT_ACTIVATE_READONLY, 0, 0);
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       if (name) {
+               ci = crypt_status(NULL, name);
+               if (ci == INVALID)
+                       return -EINVAL;
+               else if (ci >= ACTIVE) {
+                       log_err(cd, _("Device %s already exists.\n"), name);
+                       return -EEXIST;
+               }
+       }
+
+       mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
+       if (!mk)
+               return -ENOMEM;
+       r = LUKS_verify_master_key(&cd->hdr, mk);
+
+       if (r == -EPERM)
+               log_err(cd, _("Volume key does not match the volume.\n"));
+
+       if (!r && name)
+               r = open_from_hdr_and_mk(cd, mk, name, flags);
+
+       LUKS_dealloc_masterkey(mk);
+
+       return r;
+}
+
+int crypt_deactivate(struct crypt_device *cd, const char *name)
+{
+       if (!name)
+               return -EINVAL;
+
+       log_dbg("Deactivating volume %s.", name);
+
+       switch (crypt_status(cd, name)) {
+               case ACTIVE:    return dm_remove_device(name, 0, 0);
+               case BUSY:      log_err(cd, _("Device %s is busy."), name);
+                               return -EBUSY;
+               case INACTIVE:  return -ENODEV;
+               default:        log_err(cd, _("Invalid device %s."), name);
+                               return -EINVAL;
+       }
+}
+
+// misc helper functions
+int crypt_volume_key_get(struct crypt_device *cd,
+       int keyslot,
+       char *volume_key,
+       size_t *volume_key_size,
+       const char *passphrase,
+       size_t passphrase_size)
+{
+       struct luks_masterkey *mk;
+       char *processed_key = NULL;
+       int r, key_len;
+
+       key_len = crypt_get_volume_key_size(cd);
+       if (key_len > *volume_key_size) {
+               log_err(cd, _("Volume key buffer too small.\n"));
+               return -ENOMEM;
+       }
+
+       if (isPLAIN(cd->type)) {
+               processed_key = process_key(cd, cd->plain_hdr.hash, NULL, key_len,
+                                           passphrase, passphrase_size);
+               if (!processed_key) {
+                       log_err(cd, _("Cannot retrieve volume key for plain device.\n"));
+                       return -EINVAL;
+               }
+               memcpy(volume_key, processed_key, key_len);
+               *volume_key_size = key_len;
+               safe_free(processed_key);
+               return 0;
+       }
+
+       if (isLUKS(cd->type)) {
+               r = LUKS_open_key_with_hdr(cd->device, keyslot, passphrase,
+                                       passphrase_size, &cd->hdr, &mk, cd);
+
+               if (r >= 0) {
+                       memcpy(volume_key, mk->key, mk->keyLength);
+                       *volume_key_size = mk->keyLength;
+               }
+
+               LUKS_dealloc_masterkey(mk);
+               return r;
+       }
+
+       log_err(cd, _("This operation is not supported for %s crypt device.\n"), cd->type ?: "(none)");
+       return -EINVAL;
+}
+
+int crypt_volume_key_verify(struct crypt_device *cd,
+       const char *volume_key,
+       size_t volume_key_size)
+{
+       struct luks_masterkey *mk;
+       int r;
+
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       mk = LUKS_alloc_masterkey(volume_key_size, volume_key);
+       if (!mk)
+               return -ENOMEM;
+
+       r = LUKS_verify_master_key(&cd->hdr, mk);
+
+       if (r == -EPERM)
+               log_err(cd, _("Volume key does not match the volume.\n"));
+
+       LUKS_dealloc_masterkey(mk);
+
+       return r;
+}
+
+void crypt_set_timeout(struct crypt_device *cd, uint64_t timeout_sec)
+{
+       log_dbg("Timeout set to %" PRIu64 " miliseconds.", timeout_sec);
+       cd->timeout = timeout_sec;
+}
+
+void crypt_set_password_retry(struct crypt_device *cd, int tries)
+{
+       log_dbg("Password retry count set to %d.", tries);
+       cd->tries = tries;
+}
+
+void crypt_set_iterarion_time(struct crypt_device *cd, uint64_t iteration_time_ms)
+{
+       log_dbg("Iteration time set to %" PRIu64 " miliseconds.", iteration_time_ms);
+       cd->iteration_time = iteration_time_ms;
+}
+
+void crypt_set_password_verify(struct crypt_device *cd, int password_verify)
+{
+       log_dbg("Password verification %s.", password_verify ? "enabled" : "disabled");
+       cd->password_verify = password_verify ? 1 : 0;
+}
+
+int crypt_memory_lock(struct crypt_device *cd, int lock)
+{
+       return lock ? memlock_inc(cd) : memlock_dec(cd);
+}
+
+// reporting
+crypt_status_info crypt_status(struct crypt_device *cd, const char *name)
+{
+       int r;
+
+       r = dm_status_device(name);
+
+       if (r < 0 && r != -ENODEV)
+               return INVALID;
+
+       if (r == 0)
+               return ACTIVE;
+
+       if (r > 0)
+               return BUSY;
+
+       return INACTIVE;
+}
+
+static void hexprintICB(struct crypt_device *cd, char *d, int n)
+{
+       int i;
+       for(i = 0; i < n; i++)
+               log_std(cd, "%02hhx ", (char)d[i]);
+}
+
+int crypt_dump(struct crypt_device *cd)
+{
+       int i;
+       if (!isLUKS(cd->type)) { //FIXME
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return -EINVAL;
+       }
+
+       log_std(cd, "LUKS header information for %s\n\n", cd->device);
+       log_std(cd, "Version:       \t%d\n", cd->hdr.version);
+       log_std(cd, "Cipher name:   \t%s\n", cd->hdr.cipherName);
+       log_std(cd, "Cipher mode:   \t%s\n", cd->hdr.cipherMode);
+       log_std(cd, "Hash spec:     \t%s\n", cd->hdr.hashSpec);
+       log_std(cd, "Payload offset:\t%d\n", cd->hdr.payloadOffset);
+       log_std(cd, "MK bits:       \t%d\n", cd->hdr.keyBytes * 8);
+       log_std(cd, "MK digest:     \t");
+       hexprintICB(cd, cd->hdr.mkDigest, LUKS_DIGESTSIZE);
+       log_std(cd, "\n");
+       log_std(cd, "MK salt:       \t");
+       hexprintICB(cd, cd->hdr.mkDigestSalt, LUKS_SALTSIZE/2);
+       log_std(cd, "\n               \t");
+       hexprintICB(cd, cd->hdr.mkDigestSalt+LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
+       log_std(cd, "\n");
+       log_std(cd, "MK iterations: \t%d\n", cd->hdr.mkDigestIterations);
+       log_std(cd, "UUID:          \t%s\n\n", cd->hdr.uuid);
+       for(i = 0; i < LUKS_NUMKEYS; i++) {
+               if(cd->hdr.keyblock[i].active == LUKS_KEY_ENABLED) {
+                       log_std(cd, "Key Slot %d: ENABLED\n",i);
+                       log_std(cd, "\tIterations:         \t%d\n",
+                               cd->hdr.keyblock[i].passwordIterations);
+                       log_std(cd, "\tSalt:               \t");
+                       hexprintICB(cd, cd->hdr.keyblock[i].passwordSalt,
+                                   LUKS_SALTSIZE/2);
+                       log_std(cd, "\n\t                      \t");
+                       hexprintICB(cd, cd->hdr.keyblock[i].passwordSalt +
+                                   LUKS_SALTSIZE/2, LUKS_SALTSIZE/2);
+                       log_std(cd, "\n");
+
+                       log_std(cd, "\tKey material offset:\t%d\n",
+                               cd->hdr.keyblock[i].keyMaterialOffset);
+                       log_std(cd, "\tAF stripes:            \t%d\n",
+                               cd->hdr.keyblock[i].stripes);
+               }
+               else 
+                       log_std(cd, "Key Slot %d: DISABLED\n", i);
+       }
+       return 0;
+}
+
+const char *crypt_get_cipher(struct crypt_device *cd)
+{
+       if (isPLAIN(cd->type))
+               return cd->plain_cipher;
+
+       if (isLUKS(cd->type))
+               return cd->hdr.cipherName;
+
+       return NULL;
+}
+
+const char *crypt_get_cipher_mode(struct crypt_device *cd)
+{
+       if (isPLAIN(cd->type))
+               return cd->plain_cipher_mode;
+
+       if (isLUKS(cd->type))
+               return cd->hdr.cipherMode;
+
+       return NULL;
+}
+
+const char *crypt_get_uuid(struct crypt_device *cd)
+{
+       if (isLUKS(cd->type))
+               return cd->hdr.uuid;
+
+       return NULL;
+}
+
+int crypt_get_volume_key_size(struct crypt_device *cd)
+{
+       if (isPLAIN(cd->type))
+               return cd->volume_key->keyLength;
+
+       if (isLUKS(cd->type))
+               return cd->hdr.keyBytes;
+
+       return 0;
+}
+
+uint64_t crypt_get_data_offset(struct crypt_device *cd)
+{
+       if (isPLAIN(cd->type))
+               return cd->plain_hdr.offset;
+
+       if (isLUKS(cd->type))
+               return cd->hdr.payloadOffset;
+
+       return 0;
+}
+
+crypt_keyslot_info crypt_keyslot_status(struct crypt_device *cd, int keyslot)
+{
+       if (!isLUKS(cd->type)) {
+               log_err(cd, _("This operation is supported only for LUKS device.\n"));
+               return SLOT_INVALID;
+       }
+
+       return LUKS_keyslot_info(&cd->hdr, keyslot);
+}