From ed9e146cb66ea7ec7cd494a4e7b1365a44f93e27 Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 30 Jul 2009 14:57:52 +0000 Subject: [PATCH] Add required parameters for changing hash used in LUKS key setup scheme. git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@80 36d66b0a-2a48-0410-832c-cd162a569da5 --- ChangeLog | 1 + lib/setup.c | 28 +++++++++++++++------------- luks/keymanage.c | 46 +++++++++++++++++++++------------------------- luks/luks.h | 9 +++++---- src/cryptsetup.c | 7 +++++-- src/cryptsetup.h | 1 + 6 files changed, 48 insertions(+), 44 deletions(-) diff --git a/ChangeLog b/ChangeLog index ce82339b..d3532c2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4,6 +4,7 @@ * Remove po/cryptsetup-luks.pot, it's autogenerated. * Return ENOENT for empty keyslots, EINVAL will be used later for other type of error. * Switch PBKDF2 from internal SHA1 to libgcrypt, make hash algorithm not hardcoded to SHA1 here. + * Add required parameters for changing hash used in LUKS key setup scheme. 2009-07-28 Milan Broz * Pad luks header to 512 sector size. diff --git a/lib/setup.c b/lib/setup.c index 7c3641b8..601ddf21 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -447,7 +447,7 @@ static int __crypt_luks_format(int arg, struct setup_backend *backend, struct cr char cipherName[LUKS_CIPHERNAME_L]; char cipherMode[LUKS_CIPHERMODE_L]; unsigned int passwordLen; - int PBKDF2perSecond; + unsigned int PBKDF2perSecond = 0; int keyIndex; if (!LUKS_device_ready(options->device, O_RDWR | O_EXCL)) @@ -482,18 +482,17 @@ static int __crypt_luks_format(int arg, struct setup_backend *backend, struct cr r = parse_into_name_and_mode(options->cipher, cipherName, cipherMode); if(r < 0) return r; - r = LUKS_generate_phdr(&header,mk,cipherName, cipherMode,LUKS_STRIPES, options->align_payload); - if(r < 0) { - set_error("Can't generate phdr"); - return r; + r = LUKS_generate_phdr(&header, mk, cipherName, cipherMode, options->hash, LUKS_STRIPES, options->align_payload); + if(r < 0) return r; + + keyIndex = keyslot_from_option(options->key_slot, &header, options); + if(keyIndex == -EINVAL) { + r = -EINVAL; goto out; } - keyIndex = keyslot_from_option(options->key_slot, &header, options); - if(keyIndex == -EINVAL) { - r = -EINVAL; goto out; - } + r = LUKS_benchmarkt_iterations(options->hash, &PBKDF2perSecond); + if (r < 0) goto out; - PBKDF2perSecond = LUKS_benchmarkt_iterations(); 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); @@ -617,7 +616,8 @@ static int __crypt_luks_add_key(int arg, struct setup_backend *backend, struct c struct luks_masterkey *mk=NULL; struct luks_phdr hdr; char *password=NULL; unsigned int passwordLen; - unsigned int keyIndex; + unsigned int keyIndex; + unsigned int PBKDF2perSecond = 0; const char *device = options->device; int r; @@ -666,9 +666,11 @@ static int __crypt_luks_add_key(int arg, struct setup_backend *backend, struct c r = -EINVAL; goto out; } - hdr.keyblock[keyIndex].passwordIterations = at_least_one(LUKS_benchmarkt_iterations() * ((float)options->iteration_time / 1000)); + 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, backend); + r = LUKS_set_key(device, keyIndex, password, passwordLen, &hdr, mk, backend); if(r < 0) goto out; r = 0; diff --git a/luks/keymanage.c b/luks/keymanage.c index 6011b90b..aba9fe2b 100644 --- a/luks/keymanage.c +++ b/luks/keymanage.c @@ -81,8 +81,8 @@ struct luks_masterkey *LUKS_generate_masterkey(int keylength) int LUKS_read_phdr(const char *device, struct luks_phdr *hdr) { - int devfd = 0, r = 0; - unsigned int i; + int devfd = 0, r = 0; + unsigned int i; uint64_t size; char luksMagic[] = LUKS_MAGIC; @@ -97,12 +97,12 @@ int LUKS_read_phdr(const char *device, struct luks_phdr *hdr) } else if(memcmp(hdr->magic, luksMagic, LUKS_MAGIC_L)) { /* Check magic */ set_error(_("%s is not a LUKS partition\n"), device); r = -EINVAL; - } else if(memcmp(hdr->hashSpec, "sha1", 4)) { /* Check for SHA1 - other hashspecs are not implemented ATM */ - set_error(_("unknown hash spec in phdr\n"), stderr); - r = -EINVAL; } else if((hdr->version = ntohs(hdr->version)) != 1) { /* Convert every uint16/32_t item from network byte order */ set_error(_("unknown LUKS version %d\n"), hdr->version); r = -EINVAL; + } else if (PBKDF2_HMAC_ready(hdr->hashSpec) < 0) { + set_error(_("Requested LUKS hash %s is not supported.\n"), hdr->hashSpec); + r = -EINVAL; } else { hdr->payloadOffset = ntohl(hdr->payloadOffset); hdr->keyBytes = ntohl(hdr->keyBytes); @@ -162,9 +162,10 @@ int LUKS_write_phdr(const char *device, struct luks_phdr *hdr) return r; } -int LUKS_generate_phdr(struct luks_phdr *header, - const struct luks_masterkey *mk, const char *cipherName, - const char *cipherMode, unsigned int stripes, +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) { unsigned int i=0; @@ -184,9 +185,7 @@ int LUKS_generate_phdr(struct luks_phdr *header, header->version=1; strncpy(header->cipherName,cipherName,LUKS_CIPHERNAME_L); strncpy(header->cipherMode,cipherMode,LUKS_CIPHERMODE_L); - - /* This is hard coded ATM */ - strncpy(header->hashSpec,"sha1",LUKS_HASHSPEC_L); + strncpy(header->hashSpec,hashSpec,LUKS_HASHSPEC_L); header->keyBytes=mk->keyLength; @@ -224,8 +223,8 @@ int LUKS_generate_phdr(struct luks_phdr *header, return 0; } -int LUKS_set_key(const char *device, unsigned int keyIndex, - const char *password, size_t passwordLen, +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 setup_backend *backend) { @@ -291,11 +290,11 @@ out: } /* 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, +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 setup_backend *backend) { @@ -497,18 +496,15 @@ int LUKS_is_last_keyslot(const char *device, unsigned int keyIndex) return 1; } - -int LUKS_benchmarkt_iterations() +int LUKS_benchmarkt_iterations(const char *hash, unsigned int *count) { - unsigned int count; - char *hash = "sha1"; - - if (PBKDF2_performance_check(hash, &count) < 0) { + if (PBKDF2_performance_check(hash, count) < 0) { set_error(_("Not compatible options (using hash algorithm %s)."), hash); return -EINVAL; } - return count/2; + *count /= 2; + return 0; } int LUKS_device_ready(const char *device, int mode) diff --git a/luks/luks.h b/luks/luks.h index caa4a997..31057f19 100644 --- a/luks/luks.h +++ b/luks/luks.h @@ -89,8 +89,9 @@ void LUKS_dealloc_masterkey(struct luks_masterkey *mk); struct luks_masterkey *LUKS_generate_masterkey(int keylength); int LUKS_generate_phdr(struct luks_phdr *header, - const struct luks_masterkey *mk, const char *cipherName, - const char *cipherMode, unsigned int stripes, + const struct luks_masterkey *mk, + const char *cipherName, const char *cipherMode, const char *hashSpec, + unsigned int stripes, unsigned int alignPayload); int LUKS_read_phdr(const char *device, struct luks_phdr *hdr); @@ -130,14 +131,14 @@ int LUKS_open_any_key_with_hdr(const char *device, int LUKS_del_key(const char *device, unsigned int keyIndex); int LUKS_is_last_keyslot(const char *device, unsigned int keyIndex); -int LUKS_benchmarkt_iterations(); +int LUKS_benchmarkt_iterations(const char *hash, unsigned int *count); int LUKS_encrypt_to_storage(char *src, size_t srcLength, struct luks_phdr *hdr, char *key, size_t keyLength, const char *device, unsigned int sector, struct setup_backend *backend); - + int LUKS_decrypt_from_storage(char *dst, size_t dstLength, struct luks_phdr *hdr, char *key, size_t keyLength, diff --git a/src/cryptsetup.c b/src/cryptsetup.c index 179d3519..3a1e42f3 100644 --- a/src/cryptsetup.c +++ b/src/cryptsetup.c @@ -16,7 +16,7 @@ static int opt_verbose = 1; static char *opt_cipher = NULL; -static char *opt_hash = DEFAULT_HASH; +static char *opt_hash = NULL; static int opt_verify_passphrase = 0; static char *opt_key_file = NULL; static unsigned int opt_key_size = 0; @@ -153,7 +153,7 @@ static int action_create(int reload) .name = action_argv[0], .device = action_argv[1], .cipher = opt_cipher?opt_cipher:DEFAULT_CIPHER, - .hash = opt_hash, + .hash = opt_hash ?: DEFAULT_HASH, .key_file = opt_key_file, .key_size = ((opt_key_size)?opt_key_size:DEFAULT_KEY_SIZE)/8, .key_slot = opt_key_slot, @@ -258,6 +258,9 @@ static int action_luksFormat(int arg) .key_slot = opt_key_slot, .device = action_argv[0], .cipher = opt_cipher?opt_cipher:DEFAULT_LUKS_CIPHER, + .hash = DEFAULT_LUKS_HASH, + // FIXME: enable other hash use here + //.hash = opt_hash ?: DEFAULT_LUKS_HASH, .new_key_file = action_argc > 1 ? action_argv[1] : NULL, .flags = opt_verify_passphrase ? CRYPT_FLAG_VERIFY : (!opt_batch_mode?CRYPT_FLAG_VERIFY_IF_POSSIBLE : 0), .iteration_time = opt_iteration_time, diff --git a/src/cryptsetup.h b/src/cryptsetup.h index 7e35824d..14f67637 100644 --- a/src/cryptsetup.h +++ b/src/cryptsetup.h @@ -29,6 +29,7 @@ #define DEFAULT_CIPHER "aes" #define DEFAULT_LUKS_CIPHER "aes-cbc-essiv:sha256" #define DEFAULT_HASH "ripemd160" +#define DEFAULT_LUKS_HASH "sha1" #define DEFAULT_KEY_SIZE 256 #define DEFAULT_LUKS_KEY_SIZE 128