Commit ad224b47 authored by Milan Broz's avatar Milan Broz

Change in iterations counts:

  * Fix key slot iteration count calculation (small -i value was the same as default).
  * The slot and key digest iteration minimun is now 1000.
  * The key digest iteration # is calculated from iteration time (approx 1/8 of that).

If something very strange happens, and the generated key is not completely random
(wrong RNG), attacker can skip the whole kesylot area processing and try to
brute force key according to limited set of keys.

The iteration time (default, inherited from slot iteration time, is cca 120ms)
can make this attack slower, if not impossible.

Note, that this is just theorethic problem, anyway it is better to be prepared
if possible:-)

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@159 36d66b0a-2a48-0410-832c-cd162a569da5
parent 163abe35
2009-12-30 Milan Broz <mbroz@redhat.com>
* Fix key slot iteration count calculation (small -i value was the same as default).
* The slot and key digest iteration minimun is now 1000.
* The key digest iteration # is calculated from iteration time (approx 1/8 of that).
2009-12-11 Milan Broz <mbroz@redhat.com>
* Fix error handling during reading passhrase.
......
......@@ -25,7 +25,7 @@
#define CRYPT_FLAG_PRIVATE_MASK ((unsigned int)-1 << 24)
#define at_least_one(a) ({ __typeof__(a) __at_least_one=(a); (__at_least_one)?__at_least_one:1; })
#define at_least(a, b) ({ __typeof__(a) __at_least = (a); (__at_least >= (b))?__at_least:(b); })
struct hash_type {
char *name;
......
......@@ -1101,7 +1101,8 @@ static int _crypt_format_luks1(struct crypt_device *cd,
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);
params ? params->data_alignment: DEFAULT_ALIGNMENT,
cd->iteration_time, &cd->PBKDF2_per_sec, cd);
if(r < 0)
return r;
......
......@@ -385,11 +385,28 @@ int LUKS_write_phdr(const char *device,
return r;
}
static int LUKS_PBKDF2_performance_check(const char *hashSpec,
uint64_t *PBKDF2_per_sec,
struct crypt_device *ctx)
{
if (!*PBKDF2_per_sec) {
if (PBKDF2_performance_check(hashSpec, PBKDF2_per_sec) < 0) {
log_err(ctx, _("Not compatible PBKDF2 options (using hash algorithm %s)."), hashSpec);
return -EINVAL;
}
log_dbg("PBKDF2: %" PRIu64 " iterations per second using hash %s.", *PBKDF2_per_sec, hashSpec);
}
return 0;
}
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,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
struct crypt_device *ctx)
{
unsigned int i=0;
......@@ -423,8 +440,14 @@ int LUKS_generate_phdr(struct luks_phdr *header,
return r;
}
if ((r = LUKS_PBKDF2_performance_check(header->hashSpec, PBKDF2_per_sec, ctx)))
return r;
/* Compute master key digest */
header->mkDigestIterations = LUKS_MKD_ITER;
iteration_time_ms /= 8;
header->mkDigestIterations = at_least((uint32_t)(*PBKDF2_per_sec/1024) * iteration_time_ms,
LUKS_MKD_ITERATIONS_MIN);
r = PBKDF2_HMAC(header->hashSpec,mk->key,mk->keyLength,
header->mkDigestSalt,LUKS_SALTSIZE,
header->mkDigestIterations,
......@@ -454,7 +477,8 @@ int LUKS_generate_phdr(struct luks_phdr *header,
uuid_generate(partitionUuid);
uuid_unparse(partitionUuid, header->uuid);
log_dbg("Data offset %d, UUID %s", header->payloadOffset, header->uuid);
log_dbg("Data offset %d, UUID %s, digest iterations %" PRIu32,
header->payloadOffset, header->uuid, header->mkDigestIterations);
return 0;
}
......@@ -469,6 +493,7 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
char derivedKey[hdr->keyBytes];
char *AfKey;
unsigned int AFEKSize;
uint64_t PBKDF2_temp;
int r;
if(hdr->keyblock[keyIndex].active != LUKS_KEY_DISABLED) {
......@@ -484,17 +509,20 @@ int LUKS_set_key(const char *device, unsigned int keyIndex,
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);
}
if ((r = LUKS_PBKDF2_performance_check(hdr->hashSpec, PBKDF2_per_sec, ctx)))
return r;
/*
* Avoid floating point operation
* Final iteration count is at least LUKS_SLOT_ITERATIONS_MIN
*/
PBKDF2_temp = (*PBKDF2_per_sec / 2) * (uint64_t)iteration_time_ms;
PBKDF2_temp /= 1024;
if (PBKDF2_temp > UINT32_MAX)
PBKDF2_temp = UINT32_MAX;
hdr->keyblock[keyIndex].passwordIterations = at_least((uint32_t)PBKDF2_temp,
LUKS_SLOT_ITERATIONS_MIN);
/* 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);
......
......@@ -15,10 +15,9 @@
#define LUKS_SALTSIZE 32
#define LUKS_NUMKEYS 8
// Numbers of iterations for the master key digest
#define LUKS_MKD_ITER 10
// LUKS_KT defines Key types
// Minimal number of iterations
#define LUKS_MKD_ITERATIONS_MIN 1000
#define LUKS_SLOT_ITERATIONS_MIN 1000
#define LUKS_KEY_DISABLED_OLD 0
#define LUKS_KEY_ENABLED_OLD 0xCAFE
......@@ -29,7 +28,6 @@
#define LUKS_STRIPES 4000
// partition header starts with magic
#define LUKS_MAGIC {'L','U','K','S', 0xba, 0xbe};
#define LUKS_MAGIC_L 6
......@@ -93,6 +91,8 @@ int LUKS_generate_phdr(
const char *uuid,
unsigned int stripes,
unsigned int alignPayload,
uint32_t iteration_time_ms,
uint64_t *PBKDF2_per_sec,
struct crypt_device *ctx);
int LUKS_read_phdr(
......
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