From 25512d89aed42734b89defb7cb478d0a2dc8290d Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Sun, 13 Mar 2011 23:50:49 +0000 Subject: [PATCH] Clean up plain password hashing, do not ignore error in crypto backend. (New backend can fail there). git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@451 36d66b0a-2a48-0410-832c-cd162a569da5 --- lib/crypt_plain.c | 88 ++++++++++++++++++++++------------------ lib/internal.h | 7 ++-- lib/setup.c | 12 ++++-- tests/password-hash-test | 4 ++ 4 files changed, 66 insertions(+), 45 deletions(-) diff --git a/lib/crypt_plain.c b/lib/crypt_plain.c index 96327225..8c131924 100644 --- a/lib/crypt_plain.c +++ b/lib/crypt_plain.c @@ -2,7 +2,7 @@ * cryptsetup plain device helper functions * * Copyright (C) 2004 Christophe Saout - * Copyright (C) 2010 Red Hat, Inc. All rights reserved. + * Copyright (C) 2010-2011 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -25,70 +25,80 @@ #include "internal.h" #include "crypto_backend.h" -static int hash(const char *hash_name, int size, char *key, - int sizep, const char *passphrase) +static int hash(const char *hash_name, size_t key_size, char *key, + size_t passphrase_size, const char *passphrase) { struct crypt_hash *md = NULL; - size_t slen; - int len = crypt_hash_size(hash_name); - int round, i; + size_t len; + int round, i, r = 0; if (crypt_hash_init(&md, hash_name)) return -ENOENT; - for(round = 0; size; round++) { + len = crypt_hash_size(hash_name); + + for(round = 0; key_size && !r; round++) { /* hack from hashalot to avoid null bytes in key */ for(i = 0; i < round; i++) - crypt_hash_write(md, "A", 1); + if (crypt_hash_write(md, "A", 1)) + r = 1; - crypt_hash_write(md, passphrase, sizep); + if (crypt_hash_write(md, passphrase, passphrase_size)) + r = 1; - if (len > size) - len = size; - slen = len; - crypt_hash_final(md, key, slen); - // FIXME: if slen != len + if (len > key_size) + len = key_size; + + if (crypt_hash_final(md, key, len)) + r = 1; key += len; - size -= len; - if (size) - crypt_hash_restart(md); + key_size -= len; + if (key_size && crypt_hash_restart(md)) + r = 1; } crypt_hash_destroy(md); - return 0; + return r; } -int crypt_plain_hash(struct crypt_device *ctx, const char *hash_name, - char *result, size_t size, - const char *passphrase, size_t sizep) +#define PLAIN_HASH_LEN_MAX 256 + +int crypt_plain_hash(struct crypt_device *ctx, + const char *hash_name, + char *key, size_t key_size, + const char *passphrase, size_t passphrase_size) { - char hash_name_buf[256], *s; - size_t hlen, pad = 0; + char hash_name_buf[PLAIN_HASH_LEN_MAX], *s; + size_t hash_size, pad_size; int r; - if (strlen(hash_name) >= sizeof(hash_name_buf)) - return -EINVAL; + log_dbg("Plain: hashing passphrase using %s.", hash_name); - if ((s = strchr(hash_name, ':'))) { - strcpy(hash_name_buf, hash_name); - hash_name_buf[s-hash_name] = '\0'; - hash_name = hash_name_buf; - hlen = atoi(++s); - if (hlen > size) { - log_err(ctx, "Requested hash length (%zd) > key length (%zd)\n", hlen, size); + if (strlen(hash_name) >= PLAIN_HASH_LEN_MAX) + return -EINVAL; + strncpy(hash_name_buf, hash_name, PLAIN_HASH_LEN_MAX); + hash_name_buf[PLAIN_HASH_LEN_MAX - 1] = '\0'; + + /* hash[:hash_length] */ + if ((s = strchr(hash_name_buf, ':'))) { + *s = '\0'; + hash_size = atoi(++s); + if (hash_size > key_size) { + log_dbg("Hash length %zd > key length %zd", + hash_size, key_size); return -EINVAL; } - pad = size-hlen; - size = hlen; + pad_size = key_size - hash_size; + } else { + hash_size = key_size; + pad_size = 0; } - r = hash(hash_name, size, result, sizep, passphrase); - if (r < 0) - log_err(ctx, "Hash algorithm %s not supported.\n", hash_name); + r = hash(hash_name_buf, hash_size, key, passphrase_size, passphrase); - if (r == 0 && pad) - memset(result+size, 0, pad); + if (r == 0 && pad_size) + memset(key + hash_size, 0, pad_size); return r; } diff --git a/lib/internal.h b/lib/internal.h index 0afdd0f3..8e32749c 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -132,8 +132,9 @@ int crypt_random_get(struct crypt_device *ctx, char *buf, size_t len, int qualit void crypt_random_exit(void); int crypt_random_default_key_rng(void); -int crypt_plain_hash(struct crypt_device *ctx, const char *hash_name, - char *result, size_t size, - const char *passphrase, size_t sizep); +int crypt_plain_hash(struct crypt_device *ctx, + const char *hash_name, + char *key, size_t key_size, + const char *passphrase, size_t passphrase_size); #endif /* INTERNAL_H */ diff --git a/lib/setup.c b/lib/setup.c index 8862fea7..50331c4c 100644 --- a/lib/setup.c +++ b/lib/setup.c @@ -124,6 +124,7 @@ static char *process_key(struct crypt_device *cd, const char *hash_name, const char *pass, size_t passLen) { char *key; + int r; if (!key_size) return NULL; @@ -145,9 +146,14 @@ static char *process_key(struct crypt_device *cd, const char *hash_name, /* key is coming from tty, fd or binary stdin */ if (hash_name) { - if (crypt_plain_hash(cd, hash_name, key, key_size, pass, passLen) < 0) { - log_err(cd, _("Key processing error (using hash algorithm %s).\n"), - hash_name); + r = crypt_plain_hash(cd, hash_name, key, key_size, pass, passLen); + if (r < 0) { + if (r == -ENOENT) + log_err(cd, _("Hash algorithm %s not supported.\n"), + hash_name); + else + log_err(cd, _("Key processing error (using hash %s).\n"), + hash_name); crypt_safe_free(key); return NULL; } diff --git a/tests/password-hash-test b/tests/password-hash-test index b4a83d92..87ea92eb 100755 --- a/tests/password-hash-test +++ b/tests/password-hash-test @@ -85,6 +85,10 @@ crypt_key ripemd160 256 stdin "xxx\n" 625ce2a8dbdf08f1de400dba7ab9fab246f2a55ad6 crypt_key ripemd160 256 file /dev/zero 0000000000000000000000000000000000000000000000000000000000000000 crypt_key sha256 256 file /dev/zero 0000000000000000000000000000000000000000000000000000000000000000 +# limiting key +crypt_key sha256:20 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b4580588000000000000000000000000 +crypt_key sha256:32 256 pwd "xxx" cd2eb0837c9b4c962c22d2ff8b5441b7b45805887f051d39bf133b583baf6860 + # key file, 80 chars echo -n -e "0123456789abcdef\n\x01\x00\x03\xff\xff\r\xff\xff\n\r" \ "2352j3rkjhadcfasc823rqaw7e1 3dq sdq3d 2dkjqw3h2=====" >$KEY_FILE