diff --git a/common/Kconfig b/common/Kconfig index 200423a..16d1397 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -453,6 +453,10 @@ bool "SHA512" select SHA512 +config PASSWD_CRYPTO_PBKDF2 + bool "PBKDF2" + select CRYPTO_PBKDF2 + endchoice endif diff --git a/common/password.c b/common/password.c index 6ecf717..c845422 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 @@ 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)); - - if (!passwd2_sum) { - ret = -ENOMEM; - goto err1; - } - - digest_init(d); - - digest_update(d, passwd, length); - - digest_final(d, passwd1_sum); + passwd2_sum = passwd1_sum + hash_len; if (std) - ret = read_env_passwd(passwd2_sum, digest_length(d)); + ret = read_env_passwd(passwd2_sum, hash_len); else - ret = read_default_passwd(passwd2_sum, digest_length(d)); + ret = read_default_passwd(passwd2_sum, hash_len); if (ret < 0) - goto err2; + goto err; - if (strncmp(passwd1_sum, passwd2_sum, digest_length(d)) == 0) - ret = 1; + 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; -err2: - free(passwd2_sum); -err1: + ret = pkcs5_pbkdf2_hmac_sha1(passwd, length, salt, + PBKDF2_SALT_LEN, PBKDF2_COUNT, keylen, passwd1_sum); + if (ret) + goto err; + + if (strncmp(passwd1_sum, key, keylen) == 0) + ret = 1; + } else { + ret = digest_digest(d, passwd, length, passwd1_sum); + + if (ret) + goto err; + + if (strncmp(passwd1_sum, passwd2_sum, hash_len) == 0) + ret = 1; + } + +err: free(passwd1_sum); digest_free(d); @@ -346,25 +366,41 @@ 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;