Clean up plain password hashing, do not ignore error in crypto backend.
authorMilan Broz <gmazyland@gmail.com>
Sun, 13 Mar 2011 23:50:49 +0000 (23:50 +0000)
committerMilan Broz <gmazyland@gmail.com>
Sun, 13 Mar 2011 23:50:49 +0000 (23:50 +0000)
(New backend can fail there).

git-svn-id: https://cryptsetup.googlecode.com/svn/trunk@451 36d66b0a-2a48-0410-832c-cd162a569da5

lib/crypt_plain.c
lib/internal.h
lib/setup.c
tests/password-hash-test

index 9632722..8c13192 100644 (file)
@@ -2,7 +2,7 @@
  * cryptsetup plain device helper functions
  *
  * Copyright (C) 2004 Christophe Saout <christophe@saout.de>
- * 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
 #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;
+
+               if (crypt_hash_write(md, passphrase, passphrase_size))
+                       r = 1;
 
-               crypt_hash_write(md, passphrase, sizep);
+               if (len > key_size)
+                       len = key_size;
 
-               if (len > size)
-                       len = size;
-               slen = len;
-               crypt_hash_final(md, key, slen);
-               // FIXME: if slen != len
+               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))
+       log_dbg("Plain: hashing passphrase using %s.", hash_name);
+
+       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';
 
-       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);
+       /* 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;
 }
index 0afdd0f..8e32749 100644 (file)
@@ -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 */
index 8862fea..50331c4 100644 (file)
@@ -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;
                }
index b4a83d9..87ea92e 100755 (executable)
@@ -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