2010-09-07 19:55:21 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2008-2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
|
|
|
|
*
|
|
|
|
* See file CREDITS for list of people who contributed to this
|
|
|
|
* project.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2
|
|
|
|
* as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <password.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <readkey.h>
|
|
|
|
#include <fs.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <digest.h>
|
|
|
|
#include <malloc.h>
|
|
|
|
#include <xfuncs.h>
|
2011-08-10 10:47:08 +00:00
|
|
|
#include <clock.h>
|
2015-03-18 09:37:54 +00:00
|
|
|
#include <stdlib.h>
|
2013-09-16 17:49:59 +00:00
|
|
|
#include <generated/passwd.h>
|
2015-03-18 09:37:54 +00:00
|
|
|
#include <crypto/pbkdf2.h>
|
2010-09-07 19:55:21 +00:00
|
|
|
|
|
|
|
#if defined(CONFIG_PASSWD_SUM_MD5)
|
|
|
|
#define PASSWD_SUM "md5"
|
|
|
|
#elif defined(CONFIG_PASSWD_SUM_SHA1)
|
|
|
|
#define PASSWD_SUM "sha1"
|
|
|
|
#elif defined(CONFIG_PASSWD_SUM_SHA256)
|
|
|
|
#define PASSWD_SUM "sha256"
|
2015-03-11 16:53:07 +00:00
|
|
|
#elif defined(CONFIG_PASSWD_SUM_SHA512)
|
|
|
|
#define PASSWD_SUM "sha512"
|
2015-03-18 09:37:54 +00:00
|
|
|
#else
|
|
|
|
#define PASSWD_SUM NULL
|
2010-09-07 19:55:21 +00:00
|
|
|
#endif
|
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
#define PBKDF2_SALT_LEN 32
|
|
|
|
#define PBKDF2_LENGTH 64
|
|
|
|
#define PBKDF2_COUNT 10000
|
|
|
|
|
2011-08-10 10:47:08 +00:00
|
|
|
int password(unsigned char *passwd, size_t length, int flags, int timeout)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
|
|
|
unsigned char *buf = passwd;
|
|
|
|
int pos = 0;
|
|
|
|
unsigned char ch;
|
2011-10-23 09:59:12 +00:00
|
|
|
uint64_t start;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
|
|
|
if (!passwd)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2011-08-10 10:47:08 +00:00
|
|
|
start = get_time_ns();
|
|
|
|
|
2010-09-07 19:55:21 +00:00
|
|
|
do {
|
2011-08-10 10:47:08 +00:00
|
|
|
if (tstc()) {
|
|
|
|
ch = getc();
|
|
|
|
|
|
|
|
switch (ch) {
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
|
|
|
*buf = '\0';
|
|
|
|
puts("\r\n");
|
|
|
|
return pos;
|
|
|
|
case '\0':
|
|
|
|
case '\t':
|
|
|
|
continue;
|
|
|
|
case CTL_CH('c'):
|
|
|
|
passwd[0] = '\0';
|
|
|
|
puts("\r\n");
|
|
|
|
return 0;
|
|
|
|
case CTL_CH('h'):
|
2014-02-14 10:23:57 +00:00
|
|
|
case BB_KEY_DEL7:
|
|
|
|
case BB_KEY_DEL:
|
2012-12-04 12:04:25 +00:00
|
|
|
if (pos > 0) {
|
|
|
|
if (flags & STAR)
|
|
|
|
puts("\b \b");
|
|
|
|
|
|
|
|
*buf = '\0';
|
|
|
|
buf--;
|
|
|
|
pos--;
|
|
|
|
}
|
2011-08-10 10:47:08 +00:00
|
|
|
continue;
|
|
|
|
default:
|
|
|
|
if (pos < length - 1) {
|
|
|
|
if (flags & STAR)
|
|
|
|
putchar('*');
|
|
|
|
else if (flags & CLEAR)
|
|
|
|
putchar(ch);
|
|
|
|
|
|
|
|
*buf = ch;
|
|
|
|
buf++;
|
|
|
|
pos++;
|
|
|
|
} else {
|
|
|
|
if (flags & STAR)
|
|
|
|
putchar('\a');
|
|
|
|
}
|
2010-09-07 19:55:21 +00:00
|
|
|
}
|
|
|
|
}
|
2011-08-10 10:47:08 +00:00
|
|
|
} while (!is_timeout(start, timeout * SECOND) || timeout == 0);
|
|
|
|
|
|
|
|
return -1;
|
2010-09-07 19:55:21 +00:00
|
|
|
}
|
2011-07-05 05:55:57 +00:00
|
|
|
EXPORT_SYMBOL(password);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2013-09-16 17:49:59 +00:00
|
|
|
int is_passwd_default_enable(void)
|
|
|
|
{
|
|
|
|
return strlen(default_passwd) > 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(is_passwd_default_enable);
|
|
|
|
|
|
|
|
int is_passwd_env_enable(void)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
fd = open(PASSWD_FILE, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
2013-09-16 17:49:59 +00:00
|
|
|
EXPORT_SYMBOL(is_passwd_env_enable);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2013-09-16 17:49:59 +00:00
|
|
|
int passwd_env_disable(void)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
|
|
|
return unlink(PASSWD_FILE);
|
|
|
|
}
|
2013-09-16 17:49:59 +00:00
|
|
|
EXPORT_SYMBOL(passwd_env_disable);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
|
|
|
static unsigned char to_digit(unsigned char c)
|
|
|
|
{
|
|
|
|
if (c >= '0' && c <= '9')
|
|
|
|
c -= '0';
|
|
|
|
else
|
|
|
|
c -= 'a' - 10;
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned char to_hexa(unsigned char c)
|
|
|
|
{
|
|
|
|
if (c < 10)
|
|
|
|
c += '0';
|
|
|
|
else
|
|
|
|
c += 'a' - 10;
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
int read_passwd(unsigned char *sum, size_t length)
|
2013-09-16 17:49:59 +00:00
|
|
|
{
|
|
|
|
if (is_passwd_env_enable())
|
|
|
|
return read_env_passwd(sum, length);
|
|
|
|
else if (is_passwd_default_enable())
|
|
|
|
return read_default_passwd(sum, length);
|
|
|
|
else
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int read_default_passwd(unsigned char *sum, size_t length)
|
|
|
|
{
|
|
|
|
int i = 0;
|
|
|
|
int len = strlen(default_passwd);
|
|
|
|
unsigned char *buf = (unsigned char *)default_passwd;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
if (!sum || length < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
for (i = 0; i < len && length > 0; i++) {
|
|
|
|
c = buf[i];
|
|
|
|
i++;
|
|
|
|
|
|
|
|
*sum = to_digit(c) << 4;
|
|
|
|
|
|
|
|
c = buf[i];
|
|
|
|
|
|
|
|
*sum |= to_digit(c);
|
|
|
|
sum++;
|
|
|
|
length--;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(read_default_passwd);
|
|
|
|
|
|
|
|
int read_env_passwd(unsigned char *sum, size_t length)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
int ret = 0;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
if (!sum && length < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
fd = open(PASSWD_FILE, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
do {
|
|
|
|
ret = read(fd, &c, sizeof(char));
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
*sum = to_digit(c) << 4;
|
|
|
|
|
|
|
|
ret = read(fd, &c, sizeof(char));
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
*sum |= to_digit(c);
|
|
|
|
sum++;
|
|
|
|
length--;
|
|
|
|
} while(length > 0);
|
|
|
|
|
|
|
|
exit:
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2013-09-16 17:49:59 +00:00
|
|
|
EXPORT_SYMBOL(read_env_passwd);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2013-09-16 17:49:59 +00:00
|
|
|
int write_env_passwd(unsigned char *sum, size_t length)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
unsigned char c;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
if (!sum && length < 1)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
fd = open(PASSWD_DIR, O_RDONLY);
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
mkdir(PASSWD_DIR, 644);
|
|
|
|
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
fd = open(PASSWD_FILE, O_WRONLY | O_CREAT, 600);
|
|
|
|
|
|
|
|
if (fd < 0)
|
|
|
|
return fd;
|
|
|
|
|
|
|
|
do {
|
|
|
|
c = to_hexa(*sum >> 4 & 0xf);
|
|
|
|
|
|
|
|
ret = write(fd, &c, sizeof(unsigned char));
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
c = to_hexa(*sum & 0xf);
|
|
|
|
|
|
|
|
ret = write(fd, &c, sizeof(unsigned char));
|
|
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
sum++;
|
|
|
|
length--;
|
|
|
|
} while(length > 0);
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
|
|
|
|
exit:
|
|
|
|
close(fd);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2013-09-16 17:49:59 +00:00
|
|
|
EXPORT_SYMBOL(write_env_passwd);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2013-09-16 17:49:59 +00:00
|
|
|
static int __check_passwd(unsigned char* passwd, size_t length, int std)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
2015-03-18 09:37:54 +00:00
|
|
|
struct digest *d = NULL;
|
2010-09-07 19:55:21 +00:00
|
|
|
unsigned char *passwd1_sum;
|
|
|
|
unsigned char *passwd2_sum;
|
|
|
|
int ret = 0;
|
2015-03-18 09:37:54 +00:00
|
|
|
int hash_len;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) {
|
|
|
|
hash_len = PBKDF2_LENGTH;
|
|
|
|
} else {
|
|
|
|
d = digest_alloc(PASSWD_SUM);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
hash_len = digest_length(d);
|
|
|
|
}
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
passwd1_sum = calloc(hash_len * 2, sizeof(unsigned char));
|
2010-09-07 19:55:21 +00:00
|
|
|
if (!passwd1_sum)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
passwd2_sum = passwd1_sum + hash_len;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (std)
|
|
|
|
ret = read_env_passwd(passwd2_sum, hash_len);
|
|
|
|
else
|
|
|
|
ret = read_default_passwd(passwd2_sum, hash_len);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (ret < 0)
|
|
|
|
goto err;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
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;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
ret = pkcs5_pbkdf2_hmac_sha1(passwd, length, salt,
|
|
|
|
PBKDF2_SALT_LEN, PBKDF2_COUNT, keylen, passwd1_sum);
|
|
|
|
if (ret)
|
|
|
|
goto err;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (strncmp(passwd1_sum, key, keylen) == 0)
|
|
|
|
ret = 1;
|
|
|
|
} else {
|
|
|
|
ret = digest_digest(d, passwd, length, passwd1_sum);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (ret)
|
|
|
|
goto err;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (strncmp(passwd1_sum, passwd2_sum, hash_len) == 0)
|
|
|
|
ret = 1;
|
|
|
|
}
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
err:
|
2010-09-07 19:55:21 +00:00
|
|
|
free(passwd1_sum);
|
2015-03-11 16:53:04 +00:00
|
|
|
digest_free(d);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2013-09-16 17:49:59 +00:00
|
|
|
int check_default_passwd(unsigned char* passwd, size_t length)
|
|
|
|
{
|
|
|
|
return __check_passwd(passwd, length, 0);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(check_default_passwd);
|
|
|
|
|
|
|
|
int check_env_passwd(unsigned char* passwd, size_t length)
|
|
|
|
{
|
|
|
|
return __check_passwd(passwd, length, 1);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(check_env_passwd);
|
|
|
|
|
|
|
|
int check_passwd(unsigned char* passwd, size_t length)
|
|
|
|
{
|
|
|
|
if (is_passwd_env_enable())
|
|
|
|
return check_env_passwd(passwd, length);
|
|
|
|
else if (is_passwd_default_enable())
|
|
|
|
return check_default_passwd(passwd, length);
|
|
|
|
else
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
int set_env_passwd(unsigned char* passwd, size_t length)
|
2010-09-07 19:55:21 +00:00
|
|
|
{
|
2015-03-18 09:37:54 +00:00
|
|
|
struct digest *d = NULL;
|
2010-09-07 19:55:21 +00:00
|
|
|
unsigned char *passwd_sum;
|
2015-03-18 09:37:54 +00:00
|
|
|
int ret, hash_len;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
if (IS_ENABLED(CONFIG_PASSWD_CRYPTO_PBKDF2)) {
|
|
|
|
hash_len = PBKDF2_LENGTH;
|
|
|
|
} else {
|
|
|
|
d = digest_alloc(PASSWD_SUM);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
hash_len = digest_length(d);
|
|
|
|
}
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
passwd_sum = calloc(hash_len, sizeof(unsigned char));
|
2010-09-07 19:55:21 +00:00
|
|
|
if (!passwd_sum)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
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;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
get_random_bytes(passwd_sum, PBKDF2_SALT_LEN);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
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;
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
ret = write_env_passwd(passwd_sum, hash_len);
|
2010-09-07 19:55:21 +00:00
|
|
|
|
2015-03-18 09:37:54 +00:00
|
|
|
err:
|
|
|
|
digest_free(d);
|
2010-09-07 19:55:21 +00:00
|
|
|
free(passwd_sum);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
2013-09-16 17:49:59 +00:00
|
|
|
EXPORT_SYMBOL(set_env_passwd);
|