From e49a47fba8bce3bc4457d7b5133d7366b99513e3 Mon Sep 17 00:00:00 2001 From: Jean-Christophe PLAGNIOL-VILLARD Date: Wed, 18 Mar 2015 10:37:54 +0100 Subject: password: add pbkdf2 support We will use random 32 bytes salt and 10000 round to generate a 32 bytes key. Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD Signed-off-by: Sascha Hauer --- common/password.c | 96 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 30 deletions(-) (limited to 'common/password.c') diff --git a/common/password.c b/common/password.c index 6ecf7177f0..c8454228d0 100644 --- a/common/password.c +++ b/common/password.c @@ -25,7 +25,9 @@ #include #include #include +#include #include +#include #if defined(CONFIG_PASSWD_SUM_MD5) #define PASSWD_SUM "md5" @@ -35,8 +37,14 @@ #define PASSWD_SUM "sha256" #elif defined(CONFIG_PASSWD_SUM_SHA512) #define PASSWD_SUM "sha512" +#else +#define PASSWD_SUM NULL #endif +#define PBKDF2_SALT_LEN 32 +#define PBKDF2_LENGTH 64 +#define PBKDF2_COUNT 10000 + int password(unsigned char *passwd, size_t length, int flags, int timeout) { unsigned char *buf = passwd; @@ -277,45 +285,57 @@ EXPORT_SYMBOL(write_env_passwd); static int __check_passwd(unsigned char* passwd, size_t length, int std) { - struct digest *d; + struct digest *d = NULL; unsigned char *passwd1_sum; unsigned char *passwd2_sum; int ret = 0; + int hash_len; - d = digest_alloc(PASSWD_SUM); + if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) { + hash_len = PBKDF2_LENGTH; + } else { + d = digest_alloc(PASSWD_SUM); - passwd1_sum = calloc(digest_length(d), sizeof(unsigned char)); + hash_len = digest_length(d); + } + passwd1_sum = calloc(hash_len * 2, sizeof(unsigned char)); if (!passwd1_sum) return -ENOMEM; - passwd2_sum = calloc(digest_length(d), sizeof(unsigned char)); + passwd2_sum = passwd1_sum + hash_len; - if (!passwd2_sum) { - ret = -ENOMEM; - goto err1; - } + if (std) + ret = read_env_passwd(passwd2_sum, hash_len); + else + ret = read_default_passwd(passwd2_sum, hash_len); - digest_init(d); + if (ret < 0) + goto err; - digest_update(d, passwd, length); + if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) { + char *key = passwd2_sum + PBKDF2_SALT_LEN; + char *salt = passwd2_sum; + int keylen = PBKDF2_LENGTH - PBKDF2_SALT_LEN; - digest_final(d, passwd1_sum); + ret = pkcs5_pbkdf2_hmac_sha1(passwd, length, salt, + PBKDF2_SALT_LEN, PBKDF2_COUNT, keylen, passwd1_sum); + if (ret) + goto err; - if (std) - ret = read_env_passwd(passwd2_sum, digest_length(d)); - else - ret = read_default_passwd(passwd2_sum, digest_length(d)); + if (strncmp(passwd1_sum, key, keylen) == 0) + ret = 1; + } else { + ret = digest_digest(d, passwd, length, passwd1_sum); - if (ret < 0) - goto err2; + if (ret) + goto err; - if (strncmp(passwd1_sum, passwd2_sum, digest_length(d)) == 0) - ret = 1; + if (strncmp(passwd1_sum, passwd2_sum, hash_len) == 0) + ret = 1; + } -err2: - free(passwd2_sum); -err1: +err: free(passwd1_sum); digest_free(d); @@ -346,25 +366,41 @@ int check_passwd(unsigned char* passwd, size_t length) int set_env_passwd(unsigned char* passwd, size_t length) { - struct digest *d; + struct digest *d = NULL; unsigned char *passwd_sum; - int ret; + int ret, hash_len; - d = digest_alloc(PASSWD_SUM); + if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) { + hash_len = PBKDF2_LENGTH; + } else { + d = digest_alloc(PASSWD_SUM); - passwd_sum = calloc(digest_length(d), sizeof(unsigned char)); + hash_len = digest_length(d); + } + passwd_sum = calloc(hash_len, sizeof(unsigned char)); if (!passwd_sum) return -ENOMEM; - digest_init(d); + if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) { + char *key = passwd_sum + PBKDF2_SALT_LEN; + char *salt = passwd_sum; + int keylen = PBKDF2_LENGTH - PBKDF2_SALT_LEN; - digest_update(d, passwd, length); + get_random_bytes(passwd_sum, PBKDF2_SALT_LEN); - digest_final(d, passwd_sum); + ret = pkcs5_pbkdf2_hmac_sha1(passwd, length, salt, + PBKDF2_SALT_LEN, PBKDF2_COUNT, keylen, key); + } else { + ret = digest_digest(d, passwd, length, passwd_sum); + } + if (ret) + goto err; - ret = write_env_passwd(passwd_sum, digest_length(d)); + ret = write_env_passwd(passwd_sum, hash_len); +err: + digest_free(d); free(passwd_sum); return ret; -- cgit v1.2.3