Commit 74b26c7b authored by Milan Broz's avatar Milan Broz

* 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.
Signed-off-by: Milan Broz's avatarMilan Broz <mbroz@redhat.com>

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@94 36d66b0a-2a48-0410-832c-cd162a569da5
parent cee0f0b4
......@@ -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.
......
......@@ -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);
......
......@@ -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;
......
This diff is collapsed.
......@@ -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
......@@ -29,14 +29,14 @@
#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;
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment