1912 lines
51 KiB
Diff
1912 lines
51 KiB
Diff
|
From c5d08b63d47db48bd239599f8fb53b13f879e1ff Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Wed, 23 Jan 2013 18:31:19 +0800
|
||
|
Subject: [PATCH 1/9] Use crypt_r() to generate the password hash
|
||
|
|
||
|
1. We now use crypt_r() from glibc to generate the password hash.
|
||
|
|
||
|
2. The password length is changed to be compatible with the password
|
||
|
hash from /etc/shadow.
|
||
|
|
||
|
3. The password hash structure was modified to be compatible with
|
||
|
the change in MokManager.
|
||
|
---
|
||
|
configure.ac | 2 +-
|
||
|
src/Makefile.am | 3 +
|
||
|
src/PasswordHash.h | 33 --------
|
||
|
src/mokutil.c | 219 ++++++++++++++++++++++----------------------------
|
||
|
src/password-crypt.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
src/password-crypt.h | 42 ++++++++++
|
||
|
6 files changed, 359 insertions(+), 158 deletions(-)
|
||
|
delete mode 100644 src/PasswordHash.h
|
||
|
create mode 100644 src/password-crypt.c
|
||
|
create mode 100644 src/password-crypt.h
|
||
|
|
||
|
diff --git a/configure.ac b/configure.ac
|
||
|
index 468b108..894790e 100644
|
||
|
--- a/configure.ac
|
||
|
+++ b/configure.ac
|
||
|
@@ -15,7 +15,7 @@ AM_PROG_CC_C_O
|
||
|
AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug], [turn on debug]), CFLAGS="$CFLAGS -g")
|
||
|
|
||
|
# Checks for header files.
|
||
|
-AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h])
|
||
|
+AC_CHECK_HEADERS([fcntl.h stdint.h stdlib.h string.h unistd.h crypt.h])
|
||
|
|
||
|
# Checks for typedefs, structures, and compiler characteristics.
|
||
|
AC_C_INLINE
|
||
|
diff --git a/src/Makefile.am b/src/Makefile.am
|
||
|
index 036a62a..afe1752 100644
|
||
|
--- a/src/Makefile.am
|
||
|
+++ b/src/Makefile.am
|
||
|
@@ -1,6 +1,7 @@
|
||
|
bin_PROGRAMS = mokutil
|
||
|
|
||
|
mokutil_CFLAGS = $(OPENSSL_CFLAGS) \
|
||
|
+ -lcrypt \
|
||
|
$(WARNINGFLAGS_C)
|
||
|
|
||
|
mokutil_LDADD = $(OPENSSL_LIBS)
|
||
|
@@ -8,4 +9,6 @@ mokutil_LDADD = $(OPENSSL_LIBS)
|
||
|
mokutil_SOURCES = efi.h \
|
||
|
efilib.c \
|
||
|
signature.h \
|
||
|
+ password-crypt.h \
|
||
|
+ password-crypt.c \
|
||
|
mokutil.c
|
||
|
diff --git a/src/PasswordHash.h b/src/PasswordHash.h
|
||
|
deleted file mode 100644
|
||
|
index 2aeded6..0000000
|
||
|
--- a/src/PasswordHash.h
|
||
|
+++ /dev/null
|
||
|
@@ -1,33 +0,0 @@
|
||
|
-#ifndef __PASSWORD_HASH_H__
|
||
|
-#define __PASSWORD_HASH_H__
|
||
|
-
|
||
|
-#include <sys/types.h>
|
||
|
-
|
||
|
-#define PASSWORD_HASH_SIZE 88
|
||
|
-
|
||
|
-/* The max salt size (in bits) */
|
||
|
-#define T_DES_SALT_MAX 12
|
||
|
-#define E_BSI_DES_SALT_MAX 24
|
||
|
-#define MD5_SALT_MAX 48
|
||
|
-#define SHA256_SALT_MAX 96
|
||
|
-#define SHA512_SALT_MAX 96
|
||
|
-#define BLOWFISH_SALT_MAX 128
|
||
|
-
|
||
|
-enum HashMethod {
|
||
|
- Tranditional_DES = 0,
|
||
|
- Extend_BSDI_DES,
|
||
|
- MD5_BASED,
|
||
|
- SHA256_BASED,
|
||
|
- SHA512_BASED,
|
||
|
- BLOWFISH_BASED
|
||
|
-};
|
||
|
-
|
||
|
-typedef struct {
|
||
|
- uint16_t method;
|
||
|
- uint32_t iter_count;
|
||
|
- uint16_t salt_size;
|
||
|
- uint8_t salt[16];
|
||
|
- uint8_t hash[64];
|
||
|
-} __attribute__ ((packed)) pw_hash_t;
|
||
|
-
|
||
|
-#endif /* __PASSWORD_HASH_H__ */
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index 38039b9..f71cb6a 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -11,15 +11,20 @@
|
||
|
#include <openssl/sha.h>
|
||
|
#include <openssl/x509.h>
|
||
|
|
||
|
+#define __USE_GNU
|
||
|
+#include <crypt.h>
|
||
|
+
|
||
|
#include "efi.h"
|
||
|
#include "signature.h"
|
||
|
-#include "PasswordHash.h"
|
||
|
+#include "password-crypt.h"
|
||
|
|
||
|
#define SHIM_LOCK_GUID \
|
||
|
EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
|
||
|
|
||
|
-#define PASSWORD_MAX 16
|
||
|
-#define PASSWORD_MIN 8
|
||
|
+#define PASSWORD_MAX 256
|
||
|
+#define PASSWORD_MIN 1
|
||
|
+#define SB_PASSWORD_MAX 16
|
||
|
+#define SB_PASSWORD_MIN 8
|
||
|
|
||
|
#define HELP 0x1
|
||
|
#define LIST_ENROLLED 0x2
|
||
|
@@ -38,6 +43,9 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b,
|
||
|
#define HASH_FILE 0x4000
|
||
|
#define GENERATE_PW_HASH 0x8000
|
||
|
|
||
|
+#define DEFAULT_CRYPT_METHOD SHA256_BASED
|
||
|
+#define DEFAULT_SALT_SIZE SHA256_SALT_MAX
|
||
|
+
|
||
|
typedef struct {
|
||
|
uint32_t mok_size;
|
||
|
void *mok;
|
||
|
@@ -46,7 +54,7 @@ typedef struct {
|
||
|
typedef struct {
|
||
|
uint32_t mok_sb_state;
|
||
|
uint32_t password_length;
|
||
|
- uint16_t password[PASSWORD_MAX];
|
||
|
+ uint16_t password[SB_PASSWORD_MAX];
|
||
|
} MokSBVar;
|
||
|
|
||
|
static void
|
||
|
@@ -71,8 +79,6 @@ print_help ()
|
||
|
printf (" --test-key <der file>\t\t\tTest if the key is enrolled or not\n");
|
||
|
printf (" --reset\t\t\t\tReset MOK list\n");
|
||
|
printf (" --generate-hash[=password]\t\tGenerate the password hash\n");
|
||
|
- printf ("\n");
|
||
|
- printf ("Suboptions:\n");
|
||
|
printf (" --hash-file <hash file>\t\tUse the specific password hash\n");
|
||
|
printf (" \t\t(Only valid with --import, --delete,\n");
|
||
|
printf (" \t\t --password, and --reset)\n");
|
||
|
@@ -310,7 +316,7 @@ get_password (char **password, int *len, int min, int max)
|
||
|
fail = 0;
|
||
|
|
||
|
while (fail < 3) {
|
||
|
- printf ("input password (%d~%d characters): ", min, max);
|
||
|
+ printf ("input password: ");
|
||
|
len_1 = read_hidden_line (&password_1, &n);
|
||
|
printf ("\n");
|
||
|
|
||
|
@@ -361,103 +367,79 @@ error:
|
||
|
static unsigned int
|
||
|
generate_salt (uint8_t salt[], unsigned int max_size, unsigned int min_size)
|
||
|
{
|
||
|
- unsigned int salt_len = max_size / 8;
|
||
|
+ unsigned int salt_size = max_size;
|
||
|
int i;
|
||
|
|
||
|
+ /* TODO use a better random number generator */
|
||
|
srand (time (NULL));
|
||
|
|
||
|
- for (i = 0; i < salt_len; i++)
|
||
|
- salt[i] = rand() % 256;
|
||
|
+ for (i = 0; i < salt_size; i++)
|
||
|
+ salt[i] = int_to_b64 (rand() % 0x3f);
|
||
|
|
||
|
- return max_size;
|
||
|
+ return salt_size;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-generate_hash (void *salt, unsigned int salt_len, char *password,
|
||
|
- int pw_len, uint8_t *auth)
|
||
|
+generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
{
|
||
|
- SHA256_CTX ctx;
|
||
|
-
|
||
|
- if (!password || !auth)
|
||
|
+ pw_crypt_t new_crypt;
|
||
|
+ struct crypt_data data;
|
||
|
+ char settings[64];
|
||
|
+ char *crypt_string;
|
||
|
+ const char *prefix;
|
||
|
+ int hash_len, prefix_len;
|
||
|
+
|
||
|
+ if (!password || !pw_crypt)
|
||
|
return -1;
|
||
|
|
||
|
- SHA256_Init (&ctx);
|
||
|
-
|
||
|
- if (salt)
|
||
|
- SHA256_Update (&ctx, salt, salt_len);
|
||
|
-
|
||
|
- SHA256_Update (&ctx, password, pw_len);
|
||
|
-
|
||
|
- SHA256_Final (auth, &ctx);
|
||
|
-
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-static int
|
||
|
-char_to_int (const char c)
|
||
|
-{
|
||
|
- if (c >= '0' && c <= '9')
|
||
|
- return (c - '0');
|
||
|
-
|
||
|
- if (c >= 'A' && c <= 'F')
|
||
|
- return (c - 'A' + 10);
|
||
|
-
|
||
|
- if (c >= 'a' && c <= 'f')
|
||
|
- return (c - 'a' + 10);
|
||
|
+ prefix = get_crypt_prefix (pw_crypt->method);
|
||
|
+ if (!prefix)
|
||
|
+ return -1;
|
||
|
+ prefix_len = strlen(prefix);
|
||
|
|
||
|
- return -1;
|
||
|
-}
|
||
|
+ strncpy (settings, prefix, prefix_len);
|
||
|
+ strncpy (settings + prefix_len, (const char *)pw_crypt->salt,
|
||
|
+ pw_crypt->salt_size);
|
||
|
+ settings[pw_crypt->salt_size + prefix_len] = '\0';
|
||
|
|
||
|
-static int
|
||
|
-read_hex_array (const char *string, uint8_t *out, unsigned int len)
|
||
|
-{
|
||
|
- int i, digit_1, digit_2;
|
||
|
+ crypt_string = crypt_r (password, settings, &data);
|
||
|
+ if (!crypt_string)
|
||
|
+ return -1;
|
||
|
|
||
|
- for (i = 0; i < len; i++) {
|
||
|
- digit_1 = char_to_int (string[2*i]);
|
||
|
- digit_2 = char_to_int (string[2*i + 1]);
|
||
|
- if (digit_1 < 0 || digit_2 < 0)
|
||
|
- return -1;
|
||
|
+ if (decode_pass (crypt_string, &new_crypt) < 0)
|
||
|
+ return -1;
|
||
|
|
||
|
- out[i] = (uint8_t)digit_1 * 16 + (uint8_t)digit_2;
|
||
|
- }
|
||
|
+ hash_len = get_hash_size (new_crypt.method);
|
||
|
+ if (hash_len < 0)
|
||
|
+ return -1;
|
||
|
+ memcpy (pw_crypt->hash, new_crypt.hash, hash_len);
|
||
|
+ pw_crypt->iter_count = new_crypt.iter_count;
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-get_hash_from_file (const char *file, pw_hash_t *pw_hash)
|
||
|
+get_hash_from_file (const char *file, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
- FILE *fptr;
|
||
|
- unsigned int method, iter_count, salt_size;
|
||
|
- char salt_string[2*(SHA256_SALT_MAX/8)];
|
||
|
- char hash_string[2*SHA256_DIGEST_LENGTH];
|
||
|
+ char string[300];
|
||
|
+ ssize_t read_len;
|
||
|
+ int fd;
|
||
|
|
||
|
- fptr = fopen (file, "r");
|
||
|
- if (fptr == NULL) {
|
||
|
+ fd = open (file, O_RDONLY);
|
||
|
+ if (fd < 0) {
|
||
|
fprintf (stderr, "Failed to open %s\n", file);
|
||
|
return -1;
|
||
|
}
|
||
|
+ read_len = read (fd, string, 300);
|
||
|
+ close (fd);
|
||
|
|
||
|
- memset (salt_string, 0, 2*(SHA256_SALT_MAX/8));
|
||
|
- memset (hash_string, 0, 2*SHA256_DIGEST_LENGTH);
|
||
|
-
|
||
|
- fscanf (fptr, "%x.%x.%x.%24c.%64c", &method, &iter_count, &salt_size,
|
||
|
- salt_string, hash_string);
|
||
|
-
|
||
|
- fclose (fptr);
|
||
|
-
|
||
|
- pw_hash->method = (uint16_t)method;
|
||
|
- pw_hash->iter_count = (uint32_t)iter_count;
|
||
|
- pw_hash->salt_size = (uint16_t)salt_size;
|
||
|
-
|
||
|
- if (read_hex_array (salt_string, pw_hash->salt, salt_size/8) < 0) {
|
||
|
- fprintf (stderr, "Corrupted salt\n");
|
||
|
+ if (string[read_len] != '\0') {
|
||
|
+ fprintf (stderr, "corrupted string\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
- if (read_hex_array (hash_string, pw_hash->hash, SHA256_DIGEST_LENGTH) < 0) {
|
||
|
- fprintf (stderr, "Corrupted hash\n");
|
||
|
+ if (decode_pass (string, pw_crypt) < 0) {
|
||
|
+ fprintf (stderr, "Failed to parse the string\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
@@ -470,15 +452,13 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
{
|
||
|
efi_variable_t var;
|
||
|
const char *req_name, *auth_name;
|
||
|
- pw_hash_t pw_hash;
|
||
|
+ pw_crypt_t pw_crypt;
|
||
|
char *password = NULL;
|
||
|
int pw_len;
|
||
|
int ret = -1;
|
||
|
|
||
|
- bzero (&pw_hash, sizeof(pw_hash_t));
|
||
|
- pw_hash.method = SHA256_BASED;
|
||
|
- pw_hash.iter_count = 1;
|
||
|
- pw_hash.salt_size = SHA256_SALT_MAX;
|
||
|
+ bzero (&pw_crypt, sizeof(pw_crypt_t));
|
||
|
+ pw_crypt.method = DEFAULT_CRYPT_METHOD;
|
||
|
|
||
|
if (import) {
|
||
|
req_name = "MokNew";
|
||
|
@@ -489,7 +469,7 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
}
|
||
|
|
||
|
if (hash_file) {
|
||
|
- if (get_hash_from_file (hash_file, &pw_hash) < 0) {
|
||
|
+ if (get_hash_from_file (hash_file, &pw_crypt) < 0) {
|
||
|
fprintf (stderr, "Failed to read hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
@@ -499,9 +479,10 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
||
|
- if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
||
|
- pw_len, pw_hash.hash) < 0) {
|
||
|
+ pw_crypt.salt_size = generate_salt (pw_crypt.salt,
|
||
|
+ DEFAULT_SALT_SIZE,
|
||
|
+ DEFAULT_SALT_SIZE);
|
||
|
+ if (generate_hash (&pw_crypt, password, pw_len) < 0) {
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
@@ -528,8 +509,8 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
}
|
||
|
|
||
|
/* Write MokAuth or MokDelAuth */
|
||
|
- var.Data = (void *)&pw_hash;
|
||
|
- var.DataSize = PASSWORD_HASH_SIZE;
|
||
|
+ var.Data = (void *)&pw_crypt;
|
||
|
+ var.DataSize = PASSWORD_CRYPT_SIZE;
|
||
|
var.VariableName = auth_name;
|
||
|
|
||
|
var.VendorGuid = SHIM_LOCK_GUID;
|
||
|
@@ -853,18 +834,16 @@ static int
|
||
|
set_password (const char *hash_file)
|
||
|
{
|
||
|
efi_variable_t var;
|
||
|
- pw_hash_t pw_hash;
|
||
|
+ pw_crypt_t pw_crypt;
|
||
|
char *password = NULL;
|
||
|
int pw_len;
|
||
|
int ret = -1;
|
||
|
|
||
|
- bzero (&pw_hash, sizeof(pw_hash_t));
|
||
|
- pw_hash.method = SHA256_BASED;
|
||
|
- pw_hash.iter_count = 1;
|
||
|
- pw_hash.salt_size = SHA256_SALT_MAX;
|
||
|
+ bzero (&pw_crypt, sizeof(pw_crypt_t));
|
||
|
+ pw_crypt.method = DEFAULT_CRYPT_METHOD;
|
||
|
|
||
|
if (hash_file) {
|
||
|
- if (get_hash_from_file (hash_file, &pw_hash) < 0) {
|
||
|
+ if (get_hash_from_file (hash_file, &pw_crypt) < 0) {
|
||
|
fprintf (stderr, "Failed to read hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
@@ -874,16 +853,17 @@ set_password (const char *hash_file)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
||
|
- if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
||
|
- pw_len, pw_hash.hash) < 0) {
|
||
|
+ pw_crypt.salt_size = generate_salt (pw_crypt.salt,
|
||
|
+ DEFAULT_SALT_SIZE,
|
||
|
+ DEFAULT_SALT_SIZE);
|
||
|
+ if (generate_hash (&pw_crypt, password, pw_len) < 0) {
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- var.Data = (void *)&pw_hash;
|
||
|
- var.DataSize = PASSWORD_HASH_SIZE;
|
||
|
+ var.Data = (void *)&pw_crypt;
|
||
|
+ var.DataSize = PASSWORD_CRYPT_SIZE;
|
||
|
var.VariableName = "MokPW";
|
||
|
|
||
|
var.VendorGuid = SHIM_LOCK_GUID;
|
||
|
@@ -910,10 +890,11 @@ set_validation (uint32_t state)
|
||
|
MokSBVar sbvar;
|
||
|
char *password = NULL;
|
||
|
int pw_len;
|
||
|
- efi_char16_t efichar_pass[PASSWORD_MAX];
|
||
|
+ efi_char16_t efichar_pass[SB_PASSWORD_MAX];
|
||
|
int ret = -1;
|
||
|
|
||
|
- if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) {
|
||
|
+ printf ("password length: %d~%d\n", SB_PASSWORD_MIN, SB_PASSWORD_MAX);
|
||
|
+ if (get_password (&password, &pw_len, SB_PASSWORD_MIN, SB_PASSWORD_MAX) < 0) {
|
||
|
fprintf (stderr, "Abort\n");
|
||
|
goto error;
|
||
|
}
|
||
|
@@ -921,10 +902,10 @@ set_validation (uint32_t state)
|
||
|
sbvar.password_length = pw_len;
|
||
|
|
||
|
efichar_from_char (efichar_pass, password,
|
||
|
- PASSWORD_MAX * sizeof(efi_char16_t));
|
||
|
+ SB_PASSWORD_MAX * sizeof(efi_char16_t));
|
||
|
|
||
|
memcpy(sbvar.password, efichar_pass,
|
||
|
- PASSWORD_MAX * sizeof(efi_char16_t));
|
||
|
+ SB_PASSWORD_MAX * sizeof(efi_char16_t));
|
||
|
|
||
|
sbvar.mok_sb_state = state;
|
||
|
|
||
|
@@ -1051,20 +1032,16 @@ reset_moks (const char *hash_file)
|
||
|
static int
|
||
|
generate_pw_hash (const char *input_pw)
|
||
|
{
|
||
|
- pw_hash_t pw_hash;
|
||
|
+ struct crypt_data data;
|
||
|
+ char settings[SHA256_SALT_MAX + 3 + 1];
|
||
|
char *password = NULL;
|
||
|
- int pw_len, i, ret = -1;
|
||
|
-
|
||
|
- bzero (&pw_hash, sizeof(pw_hash_t));
|
||
|
- pw_hash.method = SHA256_BASED;
|
||
|
- pw_hash.iter_count = 1;
|
||
|
- pw_hash.salt_size = SHA256_SALT_MAX;
|
||
|
+ char *crypt_string;
|
||
|
+ int pw_len, ret = -1;
|
||
|
|
||
|
if (input_pw) {
|
||
|
pw_len = strlen (input_pw);
|
||
|
if (pw_len > PASSWORD_MAX || pw_len < PASSWORD_MIN) {
|
||
|
- fprintf (stderr, "password should be %d~%d characters\n",
|
||
|
- PASSWORD_MIN, PASSWORD_MAX);
|
||
|
+ fprintf (stderr, "invalid password length\n");
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
@@ -1081,23 +1058,17 @@ generate_pw_hash (const char *input_pw)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- generate_salt (pw_hash.salt, SHA256_SALT_MAX, 0);
|
||
|
- if (generate_hash (pw_hash.salt, SHA256_SALT_MAX/8, password,
|
||
|
- pw_len, pw_hash.hash) < 0) {
|
||
|
- fprintf (stderr, "Couldn't generate hash\n");
|
||
|
+ strncpy (settings, "$5$", 3);
|
||
|
+ generate_salt ((uint8_t *)(settings + 3), SHA256_SALT_MAX, 0);
|
||
|
+ settings[SHA256_SALT_MAX + 3] = '\0';
|
||
|
+
|
||
|
+ crypt_string = crypt_r (password, settings, &data);
|
||
|
+ if (!crypt_string) {
|
||
|
+ fprintf (stderr, "Failed to generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- /* Print the salt and hash */
|
||
|
- printf ("%x.%x.%x.", pw_hash.method, pw_hash.iter_count,
|
||
|
- pw_hash.salt_size);
|
||
|
- for (i = 0; i < (SHA256_SALT_MAX/8); i++) {
|
||
|
- printf ("%x%x", pw_hash.salt[i]/16, pw_hash.salt[i]%16);
|
||
|
- }
|
||
|
- putchar ('.');
|
||
|
- for (i = 0; i < SHA256_DIGEST_LENGTH; i++)
|
||
|
- printf ("%x%x", pw_hash.hash[i]/16, pw_hash.hash[i]%16);
|
||
|
- putchar ('\n');
|
||
|
+ printf ("%s\n", crypt_string);
|
||
|
|
||
|
ret = 0;
|
||
|
error:
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
new file mode 100644
|
||
|
index 0000000..f004049
|
||
|
--- /dev/null
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -0,0 +1,218 @@
|
||
|
+#include <string.h>
|
||
|
+#include <stdlib.h>
|
||
|
+#include <openssl/md5.h>
|
||
|
+#include <openssl/sha.h>
|
||
|
+#include "password-crypt.h"
|
||
|
+
|
||
|
+#define MIN(a,b) ((a)<(b)?(a):(b))
|
||
|
+
|
||
|
+#define SHA256_DEFAULT_ROUNDS 5000
|
||
|
+
|
||
|
+static const char b64t[64] =
|
||
|
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||
|
+
|
||
|
+static const char sha256_prefix[] = "$5$";
|
||
|
+static const char sha512_prefix[] = "$6$";
|
||
|
+
|
||
|
+static const char sha256_rounds_prefix[] = "rounds=";
|
||
|
+
|
||
|
+static int restore_sha256_array (const char *string, uint8_t *hash);
|
||
|
+
|
||
|
+int
|
||
|
+get_hash_size (int method)
|
||
|
+{
|
||
|
+ switch (method) {
|
||
|
+ case TRANDITIONAL_DES:
|
||
|
+ return 64 / 8; /* per "man crypt" */
|
||
|
+ case EXTEND_BSDI_DES:
|
||
|
+ return 64 / 8; /* per "man crypt" */
|
||
|
+ case MD5_BASED:
|
||
|
+ return MD5_DIGEST_LENGTH;
|
||
|
+ case SHA256_BASED:
|
||
|
+ return SHA256_DIGEST_LENGTH;
|
||
|
+ case SHA512_BASED:
|
||
|
+ return SHA512_DIGEST_LENGTH;
|
||
|
+ case BLOWFISH_BASED:
|
||
|
+ return 184 / 8; /* per "man crypt" */
|
||
|
+ }
|
||
|
+
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+const char *
|
||
|
+get_crypt_prefix (int method)
|
||
|
+{
|
||
|
+ switch (method) {
|
||
|
+ case TRANDITIONAL_DES:
|
||
|
+ return ""; /* per "man crypt" */
|
||
|
+ case EXTEND_BSDI_DES:
|
||
|
+ return "_"; /* per "man crypt" */
|
||
|
+ case MD5_BASED:
|
||
|
+ return "$1$";
|
||
|
+ case SHA256_BASED:
|
||
|
+ return "$5$";
|
||
|
+ case SHA512_BASED:
|
||
|
+ return "$6$";
|
||
|
+ case BLOWFISH_BASED:
|
||
|
+ return "$2y$"; /* per "man crypt" */
|
||
|
+ }
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ /* Expected string: (rounds=[0-9]{1,9}\$)?([./0-9A-Za-z]{1,16})?\$[./0-9A-Za-z]{43} */
|
||
|
+ char *tmp, *ptr = (char *)string;
|
||
|
+ char *b64_hash;
|
||
|
+ int count = 0;
|
||
|
+
|
||
|
+ /* get rounds */
|
||
|
+ pw_crypt->iter_count = SHA256_DEFAULT_ROUNDS;
|
||
|
+ if (strncmp (ptr, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1) == 0) {
|
||
|
+ const char *num = ptr + sizeof(sha256_rounds_prefix) - 1;
|
||
|
+ char *endp;
|
||
|
+ unsigned long int srounds = strtoul (num, &endp, 10);
|
||
|
+ if (*endp == '$') {
|
||
|
+ ptr = endp + 1;
|
||
|
+ pw_crypt->iter_count = (uint32_t)srounds;
|
||
|
+ } else {
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* get salt */
|
||
|
+ for (tmp = ptr; *tmp != '$'; tmp++) {
|
||
|
+ if (tmp == '\0')
|
||
|
+ return -1;
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ count = MIN(count, SHA256_SALT_MAX);
|
||
|
+ memcpy (pw_crypt->salt, ptr, count);
|
||
|
+ pw_crypt->salt_size = count;
|
||
|
+ ptr = tmp + 1;
|
||
|
+
|
||
|
+ /* get hash */
|
||
|
+ if (strlen(ptr) < SHA256_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+ b64_hash = malloc (SHA256_B64_LENGTH + 1);
|
||
|
+ if (!b64_hash)
|
||
|
+ return -1;
|
||
|
+ memcpy (b64_hash, ptr, SHA256_B64_LENGTH);
|
||
|
+ b64_hash[SHA256_B64_LENGTH] = '\0';
|
||
|
+
|
||
|
+ if (restore_sha256_array (b64_hash, pw_crypt->hash) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ free (b64_hash);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int
|
||
|
+decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ if (!pw_crypt)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (strncmp (crypt_pass, sha256_prefix, 3) == 0) {
|
||
|
+ pw_crypt->method = SHA256_BASED;
|
||
|
+ return decode_sha256_pass (crypt_pass + 3, pw_crypt);
|
||
|
+ }
|
||
|
+
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+char
|
||
|
+int_to_b64 (const int i)
|
||
|
+{
|
||
|
+ return b64t[i & 0x3f];
|
||
|
+}
|
||
|
+
|
||
|
+int
|
||
|
+b64_to_int (const char c)
|
||
|
+{
|
||
|
+ if (c == '.')
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ if (c == '/')
|
||
|
+ return 1;
|
||
|
+
|
||
|
+ if (c >= '0' && c <= '9')
|
||
|
+ return (c - '0' + 2);
|
||
|
+
|
||
|
+ if (c >= 'A' && c <= 'Z')
|
||
|
+ return (c - 'A' + 12);
|
||
|
+
|
||
|
+ if (c >= 'a' && c <= 'z')
|
||
|
+ return (c - 'a' + 38);
|
||
|
+
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+split_24bit (const char *string, uint8_t *hash, int start, int n,
|
||
|
+ uint32_t b2, uint32_t b1, uint32_t b0)
|
||
|
+{
|
||
|
+ uint32_t tmp = 0;
|
||
|
+ int i, value;
|
||
|
+
|
||
|
+ for (i = start; i < start + n; i++) {
|
||
|
+ value = b64_to_int (string[i]);
|
||
|
+ if (value < 0)
|
||
|
+ return -1;
|
||
|
+ tmp |= value << (6*(i - start));
|
||
|
+ }
|
||
|
+
|
||
|
+ hash[b0] = (uint8_t)(tmp & 0xff);
|
||
|
+ hash[b1] = (uint8_t)((tmp >> 8) & 0xff);
|
||
|
+ hash[b2] = (uint8_t)((tmp >> 16) & 0xff);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+int
|
||
|
+restore_sha256_array (const char *string, uint8_t *hash)
|
||
|
+{
|
||
|
+ uint32_t tmp = 0;
|
||
|
+ int i, value;
|
||
|
+
|
||
|
+ if (strlen (string) != SHA256_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 0, 4, 0, 10, 20) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 4, 4, 21, 1, 11) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 8, 4, 12, 22, 2) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 12, 4, 3, 13, 23) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 16, 4, 24, 4, 14) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 20, 4, 15, 25, 5) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 24, 4, 6, 16, 26) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 28, 4, 27, 7, 17) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 32, 4, 18, 28, 8) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 36, 4, 9, 19, 29) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ for (i = 40; i < 43 ; i++) {
|
||
|
+ value = b64_to_int (string[i]);
|
||
|
+ if (value < 0)
|
||
|
+ return -1;
|
||
|
+ tmp |= value << (6*(i - 40));
|
||
|
+ }
|
||
|
+
|
||
|
+ hash[30] = (uint8_t)(tmp & 0xff);
|
||
|
+ hash[31] = (uint8_t)((tmp >> 8) & 0xff);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
diff --git a/src/password-crypt.h b/src/password-crypt.h
|
||
|
new file mode 100644
|
||
|
index 0000000..149a05e
|
||
|
--- /dev/null
|
||
|
+++ b/src/password-crypt.h
|
||
|
@@ -0,0 +1,42 @@
|
||
|
+#ifndef __PASSWORD_CRYPT_H__
|
||
|
+#define __PASSWORD_CRYPT_H__
|
||
|
+
|
||
|
+#include <stdint.h>
|
||
|
+
|
||
|
+/* The max salt size (in characters [./0-9A-Za-z]) */
|
||
|
+#define T_DES_SALT_MAX 2
|
||
|
+#define E_BSI_DES_SALT_MAX 4
|
||
|
+#define MD5_SALT_MAX 8
|
||
|
+#define SHA256_SALT_MAX 16
|
||
|
+#define SHA512_SALT_MAX 16
|
||
|
+/* The max salt size of Blowfish in UINT8 */
|
||
|
+#define BLOWFISH_SALT_MAX 16
|
||
|
+
|
||
|
+enum HashMethod {
|
||
|
+ TRANDITIONAL_DES = 0,
|
||
|
+ EXTEND_BSDI_DES,
|
||
|
+ MD5_BASED,
|
||
|
+ SHA256_BASED,
|
||
|
+ SHA512_BASED,
|
||
|
+ BLOWFISH_BASED
|
||
|
+};
|
||
|
+
|
||
|
+typedef struct {
|
||
|
+ uint16_t method;
|
||
|
+ uint64_t iter_count;
|
||
|
+ uint16_t salt_size;
|
||
|
+ uint8_t salt[32];
|
||
|
+ uint8_t hash[128];
|
||
|
+} __attribute__ ((packed)) pw_crypt_t;
|
||
|
+
|
||
|
+#define PASSWORD_CRYPT_SIZE sizeof(pw_crypt_t)
|
||
|
+
|
||
|
+#define SHA256_B64_LENGTH 43
|
||
|
+
|
||
|
+int get_hash_size (int method);
|
||
|
+const char *get_crypt_prefix (int method);
|
||
|
+int decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt);
|
||
|
+char int_to_b64 (const int i);
|
||
|
+int b64_to_int (const char c);
|
||
|
+
|
||
|
+#endif /* __PASSWORD_CRYPT_H__ */
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 80ddd5d426e96d251f53bf5653a3bd20aebb32ab Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Thu, 24 Jan 2013 18:37:33 +0800
|
||
|
Subject: [PATCH 2/9] Support SHA512-based crypt_r() hash
|
||
|
|
||
|
---
|
||
|
src/mokutil.c | 23 ++++++---
|
||
|
src/password-crypt.c | 127 ++++++++++++++++++++++++++++++++++++++++++++++++--
|
||
|
src/password-crypt.h | 1 +
|
||
|
3 files changed, 140 insertions(+), 11 deletions(-)
|
||
|
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index f71cb6a..d1c3763 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -43,8 +43,9 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b,
|
||
|
#define HASH_FILE 0x4000
|
||
|
#define GENERATE_PW_HASH 0x8000
|
||
|
|
||
|
-#define DEFAULT_CRYPT_METHOD SHA256_BASED
|
||
|
-#define DEFAULT_SALT_SIZE SHA256_SALT_MAX
|
||
|
+#define DEFAULT_CRYPT_METHOD SHA512_BASED
|
||
|
+#define DEFAULT_SALT_SIZE SHA512_SALT_MAX
|
||
|
+#define SETTINGS_LEN (DEFAULT_SALT_SIZE*2)
|
||
|
|
||
|
typedef struct {
|
||
|
uint32_t mok_size;
|
||
|
@@ -384,7 +385,7 @@ generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
{
|
||
|
pw_crypt_t new_crypt;
|
||
|
struct crypt_data data;
|
||
|
- char settings[64];
|
||
|
+ char settings[SETTINGS_LEN];
|
||
|
char *crypt_string;
|
||
|
const char *prefix;
|
||
|
int hash_len, prefix_len;
|
||
|
@@ -1033,9 +1034,11 @@ static int
|
||
|
generate_pw_hash (const char *input_pw)
|
||
|
{
|
||
|
struct crypt_data data;
|
||
|
- char settings[SHA256_SALT_MAX + 3 + 1];
|
||
|
+ char settings[SETTINGS_LEN];
|
||
|
char *password = NULL;
|
||
|
char *crypt_string;
|
||
|
+ const char *prefix;
|
||
|
+ int prefix_len;
|
||
|
int pw_len, ret = -1;
|
||
|
|
||
|
if (input_pw) {
|
||
|
@@ -1058,9 +1061,15 @@ generate_pw_hash (const char *input_pw)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
- strncpy (settings, "$5$", 3);
|
||
|
- generate_salt ((uint8_t *)(settings + 3), SHA256_SALT_MAX, 0);
|
||
|
- settings[SHA256_SALT_MAX + 3] = '\0';
|
||
|
+ prefix = get_crypt_prefix (DEFAULT_CRYPT_METHOD);
|
||
|
+ if (!prefix)
|
||
|
+ return -1;
|
||
|
+ prefix_len = strlen(prefix);
|
||
|
+
|
||
|
+ strncpy (settings, prefix, prefix_len);
|
||
|
+ generate_salt ((uint8_t *)(settings + prefix_len),
|
||
|
+ DEFAULT_SALT_SIZE, DEFAULT_SALT_SIZE);
|
||
|
+ settings[DEFAULT_SALT_SIZE + prefix_len] = '\0';
|
||
|
|
||
|
crypt_string = crypt_r (password, settings, &data);
|
||
|
if (!crypt_string) {
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
index f004049..84ee079 100644
|
||
|
--- a/src/password-crypt.c
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -7,6 +7,7 @@
|
||
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||
|
|
||
|
#define SHA256_DEFAULT_ROUNDS 5000
|
||
|
+#define SHA512_DEFAULT_ROUNDS 5000
|
||
|
|
||
|
static const char b64t[64] =
|
||
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||
|
@@ -14,9 +15,10 @@ static const char b64t[64] =
|
||
|
static const char sha256_prefix[] = "$5$";
|
||
|
static const char sha512_prefix[] = "$6$";
|
||
|
|
||
|
-static const char sha256_rounds_prefix[] = "rounds=";
|
||
|
+static const char sha_rounds_prefix[] = "rounds=";
|
||
|
|
||
|
static int restore_sha256_array (const char *string, uint8_t *hash);
|
||
|
+static int restore_sha512_array (const char *string, uint8_t *hash);
|
||
|
|
||
|
int
|
||
|
get_hash_size (int method)
|
||
|
@@ -70,8 +72,8 @@ decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
|
||
|
/* get rounds */
|
||
|
pw_crypt->iter_count = SHA256_DEFAULT_ROUNDS;
|
||
|
- if (strncmp (ptr, sha256_rounds_prefix, sizeof(sha256_rounds_prefix) - 1) == 0) {
|
||
|
- const char *num = ptr + sizeof(sha256_rounds_prefix) - 1;
|
||
|
+ if (strncmp (ptr, sha_rounds_prefix, sizeof(sha_rounds_prefix) - 1) == 0) {
|
||
|
+ const char *num = ptr + sizeof(sha_rounds_prefix) - 1;
|
||
|
char *endp;
|
||
|
unsigned long int srounds = strtoul (num, &endp, 10);
|
||
|
if (*endp == '$') {
|
||
|
@@ -110,6 +112,56 @@ decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+decode_sha512_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ /* Expected string: (rounds=[0-9]{1,9}\$)?([./0-9A-Za-z]{1,16})?\$[./0-9A-Za-z]{86} */
|
||
|
+ char *tmp, *ptr = (char *)string;
|
||
|
+ char *b64_hash;
|
||
|
+ int count = 0;
|
||
|
+
|
||
|
+ /* get rounds */
|
||
|
+ pw_crypt->iter_count = SHA512_DEFAULT_ROUNDS;
|
||
|
+ if (strncmp (ptr, sha_rounds_prefix, sizeof(sha_rounds_prefix) - 1) == 0) {
|
||
|
+ const char *num = ptr + sizeof(sha_rounds_prefix) - 1;
|
||
|
+ char *endp;
|
||
|
+ unsigned long int srounds = strtoul (num, &endp, 10);
|
||
|
+ if (*endp == '$') {
|
||
|
+ ptr = endp + 1;
|
||
|
+ pw_crypt->iter_count = (uint32_t)srounds;
|
||
|
+ } else {
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /* get salt */
|
||
|
+ for (tmp = ptr; *tmp != '$'; tmp++) {
|
||
|
+ if (tmp == '\0')
|
||
|
+ return -1;
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ count = MIN(count, SHA512_SALT_MAX);
|
||
|
+ memcpy (pw_crypt->salt, ptr, count);
|
||
|
+ pw_crypt->salt_size = count;
|
||
|
+ ptr = tmp + 1;
|
||
|
+
|
||
|
+ /* get hash */
|
||
|
+ if (strlen(ptr) < SHA512_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+ b64_hash = malloc (SHA512_B64_LENGTH + 1);
|
||
|
+ if (!b64_hash)
|
||
|
+ return -1;
|
||
|
+ memcpy (b64_hash, ptr, SHA512_B64_LENGTH);
|
||
|
+ b64_hash[SHA512_B64_LENGTH] = '\0';
|
||
|
+
|
||
|
+ if (restore_sha512_array (b64_hash, pw_crypt->hash) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ free (b64_hash);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int
|
||
|
decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
@@ -118,7 +170,12 @@ decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
|
||
|
if (strncmp (crypt_pass, sha256_prefix, 3) == 0) {
|
||
|
pw_crypt->method = SHA256_BASED;
|
||
|
- return decode_sha256_pass (crypt_pass + 3, pw_crypt);
|
||
|
+ return decode_sha256_pass (crypt_pass + strlen (sha256_prefix), pw_crypt);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (strncmp (crypt_pass, sha512_prefix, 3) == 0) {
|
||
|
+ pw_crypt->method = SHA512_BASED;
|
||
|
+ return decode_sha512_pass (crypt_pass + strlen (sha512_prefix), pw_crypt);
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
@@ -215,4 +272,66 @@ restore_sha256_array (const char *string, uint8_t *hash)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+int
|
||
|
+restore_sha512_array (const char *string, uint8_t *hash)
|
||
|
+{
|
||
|
+ uint32_t tmp = 0;
|
||
|
+ int value1, value2;
|
||
|
+
|
||
|
+ if (strlen (string) != SHA512_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 0, 4, 0, 21, 42) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 4, 4, 22, 43, 1) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 8, 4, 44, 2, 23) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 12, 4, 3, 24, 45) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 16, 4, 25, 46, 4) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 20, 4, 47, 5, 26) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 24, 4, 6, 27, 48) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 28, 4, 28, 49, 7) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 32, 4, 50, 8, 29) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 36, 4, 9, 30, 51) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 40, 4, 31, 52, 10) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 44, 4, 53, 11, 32) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 48, 4, 12, 33, 54) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 52, 4, 34, 55, 13) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 56, 4, 56, 14, 35) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 60, 4, 15, 36, 57) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 64, 4, 37, 58, 16) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 68, 4, 59, 17, 38) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 72, 4, 18, 39, 60) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 76, 4, 40, 61, 19) < 0)
|
||
|
+ return -1;
|
||
|
+ if (split_24bit (string, hash, 80, 4, 62, 20, 41) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ value1 = b64_to_int (string[85]);
|
||
|
+ if (value1 < 0)
|
||
|
+ return -1;
|
||
|
+ value2 = b64_to_int (string[84]);
|
||
|
+ if (value2 < 0)
|
||
|
+ return -1;
|
||
|
+ tmp = (value1 << 6) | value2;
|
||
|
+ hash[63] = (uint8_t)tmp;
|
||
|
|
||
|
+ return 0;
|
||
|
+}
|
||
|
diff --git a/src/password-crypt.h b/src/password-crypt.h
|
||
|
index 149a05e..a1f7710 100644
|
||
|
--- a/src/password-crypt.h
|
||
|
+++ b/src/password-crypt.h
|
||
|
@@ -32,6 +32,7 @@ typedef struct {
|
||
|
#define PASSWORD_CRYPT_SIZE sizeof(pw_crypt_t)
|
||
|
|
||
|
#define SHA256_B64_LENGTH 43
|
||
|
+#define SHA512_B64_LENGTH 86
|
||
|
|
||
|
int get_hash_size (int method);
|
||
|
const char *get_crypt_prefix (int method);
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 032018daddfe6bca086c5ef1f79d147e3ac0b02a Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Fri, 25 Jan 2013 14:22:02 +0800
|
||
|
Subject: [PATCH 3/9] Add the new option to import root password hash
|
||
|
|
||
|
---
|
||
|
src/mokutil.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-----------
|
||
|
1 file changed, 63 insertions(+), 15 deletions(-)
|
||
|
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index d1c3763..006eff1 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -7,6 +7,7 @@
|
||
|
#include <unistd.h>
|
||
|
#include <termios.h>
|
||
|
#include <getopt.h>
|
||
|
+#include <shadow.h>
|
||
|
|
||
|
#include <openssl/sha.h>
|
||
|
#include <openssl/x509.h>
|
||
|
@@ -42,6 +43,7 @@ EFI_GUID (0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b,
|
||
|
#define RESET 0x2000
|
||
|
#define HASH_FILE 0x4000
|
||
|
#define GENERATE_PW_HASH 0x8000
|
||
|
+#define ROOT_PW 0x10000
|
||
|
|
||
|
#define DEFAULT_CRYPT_METHOD SHA512_BASED
|
||
|
#define DEFAULT_SALT_SIZE SHA512_SALT_MAX
|
||
|
@@ -83,6 +85,9 @@ print_help ()
|
||
|
printf (" --hash-file <hash file>\t\tUse the specific password hash\n");
|
||
|
printf (" \t\t(Only valid with --import, --delete,\n");
|
||
|
printf (" \t\t --password, and --reset)\n");
|
||
|
+ printf (" --root-pw\t\t\t\tUse the root password\n");
|
||
|
+ printf (" \t\t\t\t(Only valid with --import, --delete,\n");
|
||
|
+ printf (" \t\t\t\t --password, and --reset)\n");
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
@@ -448,8 +453,23 @@ get_hash_from_file (const char *file, pw_crypt_t *pw_crypt)
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
+get_password_from_shadow (pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ struct spwd *pw_ent;
|
||
|
+
|
||
|
+ pw_ent = getspnam ("root");
|
||
|
+ if (!pw_ent)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (decode_pass (pw_ent->sp_pwdp, pw_crypt) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
update_request (void *new_list, int list_len, uint8_t import,
|
||
|
- const char *hash_file)
|
||
|
+ const char *hash_file, const int root_pw)
|
||
|
{
|
||
|
efi_variable_t var;
|
||
|
const char *req_name, *auth_name;
|
||
|
@@ -474,6 +494,11 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
fprintf (stderr, "Failed to read hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
+ } else if (root_pw) {
|
||
|
+ if (get_password_from_shadow (&pw_crypt) < 0) {
|
||
|
+ fprintf (stderr, "Failed to get root password hash\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
} else {
|
||
|
if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) {
|
||
|
fprintf (stderr, "Abort\n");
|
||
|
@@ -618,7 +643,7 @@ is_valid_request (void *mok, uint32_t mok_size, uint8_t import)
|
||
|
|
||
|
static int
|
||
|
issue_mok_request (char **files, uint32_t total, uint8_t import,
|
||
|
- const char *hash_file)
|
||
|
+ const char *hash_file, const int root_pw)
|
||
|
{
|
||
|
efi_variable_t old_req;
|
||
|
const char *req_name;
|
||
|
@@ -731,7 +756,7 @@ issue_mok_request (char **files, uint32_t total, uint8_t import,
|
||
|
real_size += old_req.DataSize;
|
||
|
}
|
||
|
|
||
|
- if (update_request (new_list, real_size, import, hash_file) < 0) {
|
||
|
+ if (update_request (new_list, real_size, import, hash_file, root_pw) < 0) {
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
@@ -748,15 +773,17 @@ error:
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-import_moks (char **files, uint32_t total, const char *hash_file)
|
||
|
+import_moks (char **files, uint32_t total, const char *hash_file,
|
||
|
+ const int root_pw)
|
||
|
{
|
||
|
- return issue_mok_request (files, total, 1, hash_file);
|
||
|
+ return issue_mok_request (files, total, 1, hash_file, root_pw);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-delete_moks (char **files, uint32_t total, const char *hash_file)
|
||
|
+delete_moks (char **files, uint32_t total, const char *hash_file,
|
||
|
+ const int root_pw)
|
||
|
{
|
||
|
- return issue_mok_request (files, total, 0, hash_file);
|
||
|
+ return issue_mok_request (files, total, 0, hash_file, root_pw);
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
@@ -832,7 +859,7 @@ error:
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-set_password (const char *hash_file)
|
||
|
+set_password (const char *hash_file, const int root_pw)
|
||
|
{
|
||
|
efi_variable_t var;
|
||
|
pw_crypt_t pw_crypt;
|
||
|
@@ -848,6 +875,11 @@ set_password (const char *hash_file)
|
||
|
fprintf (stderr, "Failed to read hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
+ } else if (root_pw) {
|
||
|
+ if (get_password_from_shadow (&pw_crypt) < 0) {
|
||
|
+ fprintf (stderr, "Failed to get root password hash\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
} else {
|
||
|
if (get_password (&password, &pw_len, PASSWORD_MIN, PASSWORD_MAX) < 0) {
|
||
|
fprintf (stderr, "Abort\n");
|
||
|
@@ -1020,9 +1052,9 @@ error:
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
-reset_moks (const char *hash_file)
|
||
|
+reset_moks (const char *hash_file, const int root_pw)
|
||
|
{
|
||
|
- if (update_request (NULL, 0, 1, hash_file)) {
|
||
|
+ if (update_request (NULL, 0, 1, hash_file, root_pw)) {
|
||
|
fprintf (stderr, "Failed to issue a reset request\n");
|
||
|
return -1;
|
||
|
}
|
||
|
@@ -1117,11 +1149,12 @@ main (int argc, char *argv[])
|
||
|
{"reset", no_argument, 0, 0 },
|
||
|
{"hash-file", required_argument, 0, 'f'},
|
||
|
{"generate-hash", optional_argument, 0, 'g'},
|
||
|
+ {"root-pw", no_argument, 0, 'P'},
|
||
|
{0, 0, 0, 0}
|
||
|
};
|
||
|
|
||
|
int option_index = 0;
|
||
|
- c = getopt_long (argc, argv, "d:f:g::hi:pt:x",
|
||
|
+ c = getopt_long (argc, argv, "d:f:g::hi:pt:xP",
|
||
|
long_options, &option_index);
|
||
|
|
||
|
if (c == -1)
|
||
|
@@ -1189,6 +1222,9 @@ main (int argc, char *argv[])
|
||
|
case 'p':
|
||
|
command |= PASSWORD;
|
||
|
break;
|
||
|
+ case 'P':
|
||
|
+ command |= ROOT_PW;
|
||
|
+ break;
|
||
|
case 't':
|
||
|
key_file = strdup (optarg);
|
||
|
|
||
|
@@ -1215,11 +1251,17 @@ main (int argc, char *argv[])
|
||
|
break;
|
||
|
case IMPORT:
|
||
|
case IMPORT | HASH_FILE:
|
||
|
- ret = import_moks (files, total, hash_file);
|
||
|
+ ret = import_moks (files, total, hash_file, 0);
|
||
|
+ break;
|
||
|
+ case IMPORT | ROOT_PW:
|
||
|
+ ret = import_moks (files, total, NULL, 1);
|
||
|
break;
|
||
|
case DELETE:
|
||
|
case DELETE | HASH_FILE:
|
||
|
- ret = delete_moks (files, total, hash_file);
|
||
|
+ ret = delete_moks (files, total, hash_file, 0);
|
||
|
+ break;
|
||
|
+ case DELETE | ROOT_PW:
|
||
|
+ ret = delete_moks (files, total, NULL, 1);
|
||
|
break;
|
||
|
case REVOKE_IMPORT:
|
||
|
ret = revoke_request (1);
|
||
|
@@ -1232,7 +1274,10 @@ main (int argc, char *argv[])
|
||
|
break;
|
||
|
case PASSWORD:
|
||
|
case PASSWORD | HASH_FILE:
|
||
|
- ret = set_password (hash_file);
|
||
|
+ ret = set_password (hash_file, 0);
|
||
|
+ break;
|
||
|
+ case PASSWORD | ROOT_PW:
|
||
|
+ ret = set_password (NULL, 1);
|
||
|
break;
|
||
|
case DISABLE_VALIDATION:
|
||
|
ret = disable_validation ();
|
||
|
@@ -1248,7 +1293,10 @@ main (int argc, char *argv[])
|
||
|
break;
|
||
|
case RESET:
|
||
|
case RESET | HASH_FILE:
|
||
|
- ret = reset_moks (hash_file);
|
||
|
+ ret = reset_moks (hash_file, 0);
|
||
|
+ break;
|
||
|
+ case RESET | ROOT_PW:
|
||
|
+ ret = reset_moks (NULL, 1);
|
||
|
break;
|
||
|
case GENERATE_PW_HASH:
|
||
|
ret = generate_pw_hash (input_pw);
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 282c97b30c87687e43a019fcde3db8d809f8d227 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Fri, 25 Jan 2013 18:29:06 +0800
|
||
|
Subject: [PATCH 4/9] Support blowfish-based crypt() hash
|
||
|
|
||
|
---
|
||
|
src/mokutil.c | 15 +++++++++++++++
|
||
|
src/password-crypt.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++--
|
||
|
src/password-crypt.h | 3 +--
|
||
|
3 files changed, 62 insertions(+), 4 deletions(-)
|
||
|
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index 006eff1..b6c665d 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -508,10 +508,18 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
pw_crypt.salt_size = generate_salt (pw_crypt.salt,
|
||
|
DEFAULT_SALT_SIZE,
|
||
|
DEFAULT_SALT_SIZE);
|
||
|
+
|
||
|
if (generate_hash (&pw_crypt, password, pw_len) < 0) {
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
+ if (pw_crypt.method == BLOWFISH_BASED) {
|
||
|
+ const char *prefix = get_crypt_prefix (BLOWFISH_BASED);
|
||
|
+ memmove (pw_crypt.salt + 7, pw_crypt.salt, BLOWFISH_SALT_MAX);
|
||
|
+ memcpy (pw_crypt.salt, prefix, 7);
|
||
|
+ pw_crypt.salt[7 + BLOWFISH_SALT_MAX] = '\0';
|
||
|
+ pw_crypt.salt_size = BLOWFISH_SALT_MAX + 7 + 1;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
if (new_list) {
|
||
|
@@ -893,6 +901,13 @@ set_password (const char *hash_file, const int root_pw)
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
+ if (pw_crypt.method == BLOWFISH_BASED) {
|
||
|
+ const char *prefix = get_crypt_prefix (BLOWFISH_BASED);
|
||
|
+ memmove (pw_crypt.salt + 7, pw_crypt.salt, BLOWFISH_SALT_MAX);
|
||
|
+ memcpy (pw_crypt.salt, prefix, 7);
|
||
|
+ pw_crypt.salt[7 + BLOWFISH_SALT_MAX] = '\0';
|
||
|
+ pw_crypt.salt_size = BLOWFISH_SALT_MAX + 7 + 1;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
var.Data = (void *)&pw_crypt;
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
index 84ee079..3ecb6ff 100644
|
||
|
--- a/src/password-crypt.c
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -6,6 +6,8 @@
|
||
|
|
||
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||
|
|
||
|
+#define BLOWFISH_HASH_SIZE 31 /* 184 / 6 + 1 */
|
||
|
+
|
||
|
#define SHA256_DEFAULT_ROUNDS 5000
|
||
|
#define SHA512_DEFAULT_ROUNDS 5000
|
||
|
|
||
|
@@ -15,6 +17,10 @@ static const char b64t[64] =
|
||
|
static const char sha256_prefix[] = "$5$";
|
||
|
static const char sha512_prefix[] = "$6$";
|
||
|
|
||
|
+static const char bf_a_prefix[] = "$2a$";
|
||
|
+static const char bf_x_prefix[] = "$2x$";
|
||
|
+static const char bf_y_prefix[] = "$2y$";
|
||
|
+
|
||
|
static const char sha_rounds_prefix[] = "rounds=";
|
||
|
|
||
|
static int restore_sha256_array (const char *string, uint8_t *hash);
|
||
|
@@ -35,7 +41,7 @@ get_hash_size (int method)
|
||
|
case SHA512_BASED:
|
||
|
return SHA512_DIGEST_LENGTH;
|
||
|
case BLOWFISH_BASED:
|
||
|
- return 184 / 8; /* per "man crypt" */
|
||
|
+ return BLOWFISH_HASH_SIZE;
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
@@ -56,7 +62,7 @@ get_crypt_prefix (int method)
|
||
|
case SHA512_BASED:
|
||
|
return "$6$";
|
||
|
case BLOWFISH_BASED:
|
||
|
- return "$2y$"; /* per "man crypt" */
|
||
|
+ return "$2y$10$"; /* FIXME change the count */
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
@@ -162,6 +168,37 @@ decode_sha512_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+static int
|
||
|
+decode_blowfish_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ /* Expected string: \$2[axy]\$[0-9]{2}\$[./A-Za-z0-9]{53} */
|
||
|
+ /* Store the first (22+7) bytes in salt[] and the rest in hash */
|
||
|
+
|
||
|
+ if (strlen(string) != (53 + 7))
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (string[0] != '$' ||
|
||
|
+ string[1] != '2' ||
|
||
|
+ (string[2] != 'a' && string[2] != 'x' && string[2] != 'y') ||
|
||
|
+ string[3] != '$' ||
|
||
|
+ string[4] < '0' || string[4] > '3' ||
|
||
|
+ string[5] < '0' || string[5] > '9' ||
|
||
|
+ (string[4] == '3' && string[5] > '1') ||
|
||
|
+ string[6] != '$') {
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+
|
||
|
+ pw_crypt->iter_count = 0;
|
||
|
+
|
||
|
+ memcpy (pw_crypt->salt, string, (22 + 7));
|
||
|
+ pw_crypt->salt[22 + 7] = '\0';
|
||
|
+ pw_crypt->salt_size = 22 + 7 + 1;
|
||
|
+
|
||
|
+ memcpy (pw_crypt->hash, string + 22 + 7, BLOWFISH_HASH_SIZE);
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int
|
||
|
decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
@@ -178,6 +215,13 @@ decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
return decode_sha512_pass (crypt_pass + strlen (sha512_prefix), pw_crypt);
|
||
|
}
|
||
|
|
||
|
+ if (strncmp (crypt_pass, bf_a_prefix, 4) == 0 ||
|
||
|
+ strncmp (crypt_pass, bf_x_prefix, 4) == 0 ||
|
||
|
+ strncmp (crypt_pass, bf_y_prefix, 4) == 0) {
|
||
|
+ pw_crypt->method = BLOWFISH_BASED;
|
||
|
+ return decode_blowfish_pass (crypt_pass, pw_crypt);
|
||
|
+ }
|
||
|
+
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/password-crypt.h b/src/password-crypt.h
|
||
|
index a1f7710..701dfd9 100644
|
||
|
--- a/src/password-crypt.h
|
||
|
+++ b/src/password-crypt.h
|
||
|
@@ -9,8 +9,7 @@
|
||
|
#define MD5_SALT_MAX 8
|
||
|
#define SHA256_SALT_MAX 16
|
||
|
#define SHA512_SALT_MAX 16
|
||
|
-/* The max salt size of Blowfish in UINT8 */
|
||
|
-#define BLOWFISH_SALT_MAX 16
|
||
|
+#define BLOWFISH_SALT_MAX 22
|
||
|
|
||
|
enum HashMethod {
|
||
|
TRANDITIONAL_DES = 0,
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 97f0dec8aa8f63a7ef81e060a512b13bcdf4e3a7 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Mon, 28 Jan 2013 16:12:44 +0800
|
||
|
Subject: [PATCH 5/9] Simplify the hash generation
|
||
|
|
||
|
---
|
||
|
src/mokutil.c | 30 +++++++++---------------------
|
||
|
1 file changed, 9 insertions(+), 21 deletions(-)
|
||
|
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index b6c665d..ecf9e00 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -403,6 +403,10 @@ generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
return -1;
|
||
|
prefix_len = strlen(prefix);
|
||
|
|
||
|
+ pw_crypt->salt_size = generate_salt (pw_crypt->salt,
|
||
|
+ DEFAULT_SALT_SIZE,
|
||
|
+ DEFAULT_SALT_SIZE);
|
||
|
+
|
||
|
strncpy (settings, prefix, prefix_len);
|
||
|
strncpy (settings + prefix_len, (const char *)pw_crypt->salt,
|
||
|
pw_crypt->salt_size);
|
||
|
@@ -421,6 +425,11 @@ generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
memcpy (pw_crypt->hash, new_crypt.hash, hash_len);
|
||
|
pw_crypt->iter_count = new_crypt.iter_count;
|
||
|
|
||
|
+ if (pw_crypt->method == BLOWFISH_BASED) {
|
||
|
+ pw_crypt->salt_size = new_crypt.salt_size;
|
||
|
+ memcpy (pw_crypt->salt, new_crypt.salt, new_crypt.salt_size);
|
||
|
+ }
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -505,21 +514,10 @@ update_request (void *new_list, int list_len, uint8_t import,
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- pw_crypt.salt_size = generate_salt (pw_crypt.salt,
|
||
|
- DEFAULT_SALT_SIZE,
|
||
|
- DEFAULT_SALT_SIZE);
|
||
|
-
|
||
|
if (generate_hash (&pw_crypt, password, pw_len) < 0) {
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
- if (pw_crypt.method == BLOWFISH_BASED) {
|
||
|
- const char *prefix = get_crypt_prefix (BLOWFISH_BASED);
|
||
|
- memmove (pw_crypt.salt + 7, pw_crypt.salt, BLOWFISH_SALT_MAX);
|
||
|
- memcpy (pw_crypt.salt, prefix, 7);
|
||
|
- pw_crypt.salt[7 + BLOWFISH_SALT_MAX] = '\0';
|
||
|
- pw_crypt.salt_size = BLOWFISH_SALT_MAX + 7 + 1;
|
||
|
- }
|
||
|
}
|
||
|
|
||
|
if (new_list) {
|
||
|
@@ -894,20 +892,10 @@ set_password (const char *hash_file, const int root_pw)
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
- pw_crypt.salt_size = generate_salt (pw_crypt.salt,
|
||
|
- DEFAULT_SALT_SIZE,
|
||
|
- DEFAULT_SALT_SIZE);
|
||
|
if (generate_hash (&pw_crypt, password, pw_len) < 0) {
|
||
|
fprintf (stderr, "Couldn't generate hash\n");
|
||
|
goto error;
|
||
|
}
|
||
|
- if (pw_crypt.method == BLOWFISH_BASED) {
|
||
|
- const char *prefix = get_crypt_prefix (BLOWFISH_BASED);
|
||
|
- memmove (pw_crypt.salt + 7, pw_crypt.salt, BLOWFISH_SALT_MAX);
|
||
|
- memcpy (pw_crypt.salt, prefix, 7);
|
||
|
- pw_crypt.salt[7 + BLOWFISH_SALT_MAX] = '\0';
|
||
|
- pw_crypt.salt_size = BLOWFISH_SALT_MAX + 7 + 1;
|
||
|
- }
|
||
|
}
|
||
|
|
||
|
var.Data = (void *)&pw_crypt;
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 9205203a929aac32fc1e4a53cd8e1c1bb74cfde3 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Tue, 29 Jan 2013 12:16:17 +0800
|
||
|
Subject: [PATCH 6/9] Support MD5-based crypt() hash
|
||
|
|
||
|
---
|
||
|
src/password-crypt.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
||
|
src/password-crypt.h | 1 +
|
||
|
2 files changed, 77 insertions(+)
|
||
|
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
index 3ecb6ff..e435ad3 100644
|
||
|
--- a/src/password-crypt.c
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -14,6 +14,8 @@
|
||
|
static const char b64t[64] =
|
||
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||
|
|
||
|
+static const char md5_prefix[] = "$1$";
|
||
|
+
|
||
|
static const char sha256_prefix[] = "$5$";
|
||
|
static const char sha512_prefix[] = "$6$";
|
||
|
|
||
|
@@ -23,6 +25,7 @@ static const char bf_y_prefix[] = "$2y$";
|
||
|
|
||
|
static const char sha_rounds_prefix[] = "rounds=";
|
||
|
|
||
|
+static int restore_md5_array (const char *string, uint8_t *hash);
|
||
|
static int restore_sha256_array (const char *string, uint8_t *hash);
|
||
|
static int restore_sha512_array (const char *string, uint8_t *hash);
|
||
|
|
||
|
@@ -69,6 +72,39 @@ get_crypt_prefix (int method)
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
+decode_md5_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ /* Expected string: [./0-9A-Za-z]{1,8}\$[./0-9A-Za-z]{22} */
|
||
|
+ char *tmp, *ptr = (char *)string;
|
||
|
+ char b64_hash[MD5_B64_LENGTH + 1];
|
||
|
+ int count = 0;
|
||
|
+
|
||
|
+ pw_crypt->iter_count = 1000;
|
||
|
+
|
||
|
+ /* get salt */
|
||
|
+ for (tmp = ptr; *tmp != '$'; tmp++) {
|
||
|
+ if (*tmp == '\0')
|
||
|
+ return -1;
|
||
|
+ count++;
|
||
|
+ }
|
||
|
+ count = MIN(count, MD5_SALT_MAX);
|
||
|
+ memcpy (pw_crypt->salt, ptr, count);
|
||
|
+ pw_crypt->salt_size = count;
|
||
|
+ ptr = tmp + 1;
|
||
|
+
|
||
|
+ /* get hash */
|
||
|
+ if (strlen(ptr) != MD5_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+ memcpy (b64_hash, ptr, MD5_B64_LENGTH);
|
||
|
+ b64_hash[MD5_B64_LENGTH] = '\0';
|
||
|
+
|
||
|
+ if (restore_md5_array (b64_hash, pw_crypt->hash) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
/* Expected string: (rounds=[0-9]{1,9}\$)?([./0-9A-Za-z]{1,16})?\$[./0-9A-Za-z]{43} */
|
||
|
@@ -205,6 +241,11 @@ decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
if (!pw_crypt)
|
||
|
return -1;
|
||
|
|
||
|
+ if (strncmp (crypt_pass, md5_prefix, 3) == 0) {
|
||
|
+ pw_crypt->method = MD5_BASED;
|
||
|
+ return decode_md5_pass (crypt_pass + strlen (md5_prefix), pw_crypt);
|
||
|
+ }
|
||
|
+
|
||
|
if (strncmp (crypt_pass, sha256_prefix, 3) == 0) {
|
||
|
pw_crypt->method = SHA256_BASED;
|
||
|
return decode_sha256_pass (crypt_pass + strlen (sha256_prefix), pw_crypt);
|
||
|
@@ -273,6 +314,41 @@ split_24bit (const char *string, uint8_t *hash, int start, int n,
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+int restore_md5_array (const char *string, uint8_t *hash)
|
||
|
+{
|
||
|
+ uint32_t tmp = 0;
|
||
|
+ int value1, value2;
|
||
|
+
|
||
|
+ if (strlen (string) != MD5_B64_LENGTH)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 0, 4, 0, 6, 12) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 4, 4, 1, 7, 13) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 8, 4, 2, 8, 14) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 12, 4, 3, 9, 15) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ if (split_24bit (string, hash, 16, 4, 4, 10, 5) < 0)
|
||
|
+ return -1;
|
||
|
+
|
||
|
+ value1 = b64_to_int (string[21]);
|
||
|
+ if (value1 < 0)
|
||
|
+ return -1;
|
||
|
+ value2 = b64_to_int (string[20]);
|
||
|
+ if (value2 < 0)
|
||
|
+ return -1;
|
||
|
+ tmp = (value1 << 6) | value2;
|
||
|
+ hash[11] = (uint8_t)tmp;
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
int
|
||
|
restore_sha256_array (const char *string, uint8_t *hash)
|
||
|
{
|
||
|
diff --git a/src/password-crypt.h b/src/password-crypt.h
|
||
|
index 701dfd9..aba6975 100644
|
||
|
--- a/src/password-crypt.h
|
||
|
+++ b/src/password-crypt.h
|
||
|
@@ -30,6 +30,7 @@ typedef struct {
|
||
|
|
||
|
#define PASSWORD_CRYPT_SIZE sizeof(pw_crypt_t)
|
||
|
|
||
|
+#define MD5_B64_LENGTH 22
|
||
|
#define SHA256_B64_LENGTH 43
|
||
|
#define SHA512_B64_LENGTH 86
|
||
|
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From 472dbeefd87085e4164369110e0ba3d8bf05a964 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Tue, 29 Jan 2013 13:59:36 +0800
|
||
|
Subject: [PATCH 7/9] Fix SHA256/SHA512 parsing on hashes with no salt
|
||
|
|
||
|
---
|
||
|
src/password-crypt.c | 60 +++++++++++++++++++++++++++-----------------------
|
||
|
1 file changed, 32 insertions(+), 28 deletions(-)
|
||
|
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
index e435ad3..de15193 100644
|
||
|
--- a/src/password-crypt.c
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -109,7 +109,7 @@ decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
/* Expected string: (rounds=[0-9]{1,9}\$)?([./0-9A-Za-z]{1,16})?\$[./0-9A-Za-z]{43} */
|
||
|
char *tmp, *ptr = (char *)string;
|
||
|
- char *b64_hash;
|
||
|
+ char b64_hash[SHA256_B64_LENGTH + 1];
|
||
|
int count = 0;
|
||
|
|
||
|
/* get rounds */
|
||
|
@@ -127,30 +127,32 @@ decode_sha256_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
}
|
||
|
|
||
|
/* get salt */
|
||
|
- for (tmp = ptr; *tmp != '$'; tmp++) {
|
||
|
- if (tmp == '\0')
|
||
|
- return -1;
|
||
|
- count++;
|
||
|
+ tmp = ptr;
|
||
|
+ if (strlen (ptr) > SHA256_B64_LENGTH) {
|
||
|
+ while (*tmp != '$') {
|
||
|
+ if (tmp == '\0')
|
||
|
+ return -1;
|
||
|
+ count++;
|
||
|
+ tmp++;
|
||
|
+ }
|
||
|
+
|
||
|
+ count = MIN(count, SHA256_SALT_MAX);
|
||
|
+ memcpy (pw_crypt->salt, ptr, count);
|
||
|
+ pw_crypt->salt_size = count;
|
||
|
+ ptr = tmp + 1;
|
||
|
+ } else {
|
||
|
+ pw_crypt->salt_size = 0;
|
||
|
}
|
||
|
- count = MIN(count, SHA256_SALT_MAX);
|
||
|
- memcpy (pw_crypt->salt, ptr, count);
|
||
|
- pw_crypt->salt_size = count;
|
||
|
- ptr = tmp + 1;
|
||
|
|
||
|
/* get hash */
|
||
|
if (strlen(ptr) < SHA256_B64_LENGTH)
|
||
|
return -1;
|
||
|
- b64_hash = malloc (SHA256_B64_LENGTH + 1);
|
||
|
- if (!b64_hash)
|
||
|
- return -1;
|
||
|
memcpy (b64_hash, ptr, SHA256_B64_LENGTH);
|
||
|
b64_hash[SHA256_B64_LENGTH] = '\0';
|
||
|
|
||
|
if (restore_sha256_array (b64_hash, pw_crypt->hash) < 0)
|
||
|
return -1;
|
||
|
|
||
|
- free (b64_hash);
|
||
|
-
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -159,7 +161,7 @@ decode_sha512_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
/* Expected string: (rounds=[0-9]{1,9}\$)?([./0-9A-Za-z]{1,16})?\$[./0-9A-Za-z]{86} */
|
||
|
char *tmp, *ptr = (char *)string;
|
||
|
- char *b64_hash;
|
||
|
+ char b64_hash[SHA512_B64_LENGTH + 1];
|
||
|
int count = 0;
|
||
|
|
||
|
/* get rounds */
|
||
|
@@ -177,30 +179,32 @@ decode_sha512_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
}
|
||
|
|
||
|
/* get salt */
|
||
|
- for (tmp = ptr; *tmp != '$'; tmp++) {
|
||
|
- if (tmp == '\0')
|
||
|
- return -1;
|
||
|
- count++;
|
||
|
+ tmp = ptr;
|
||
|
+ if (strlen (ptr) > SHA512_B64_LENGTH) {
|
||
|
+ while (*tmp != '$') {
|
||
|
+ if (tmp == '\0')
|
||
|
+ return -1;
|
||
|
+ count++;
|
||
|
+ tmp++;
|
||
|
+ }
|
||
|
+
|
||
|
+ count = MIN(count, SHA512_SALT_MAX);
|
||
|
+ memcpy (pw_crypt->salt, ptr, count);
|
||
|
+ pw_crypt->salt_size = count;
|
||
|
+ ptr = tmp + 1;
|
||
|
+ } else {
|
||
|
+ pw_crypt->salt_size = 0;
|
||
|
}
|
||
|
- count = MIN(count, SHA512_SALT_MAX);
|
||
|
- memcpy (pw_crypt->salt, ptr, count);
|
||
|
- pw_crypt->salt_size = count;
|
||
|
- ptr = tmp + 1;
|
||
|
|
||
|
/* get hash */
|
||
|
if (strlen(ptr) < SHA512_B64_LENGTH)
|
||
|
return -1;
|
||
|
- b64_hash = malloc (SHA512_B64_LENGTH + 1);
|
||
|
- if (!b64_hash)
|
||
|
- return -1;
|
||
|
memcpy (b64_hash, ptr, SHA512_B64_LENGTH);
|
||
|
b64_hash[SHA512_B64_LENGTH] = '\0';
|
||
|
|
||
|
if (restore_sha512_array (b64_hash, pw_crypt->hash) < 0)
|
||
|
return -1;
|
||
|
|
||
|
- free (b64_hash);
|
||
|
-
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From ddd501071734325a213fe994471dac269c69153a Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Tue, 29 Jan 2013 16:34:59 +0800
|
||
|
Subject: [PATCH 8/9] Just use crypt() to generate hashes
|
||
|
|
||
|
---
|
||
|
src/mokutil.c | 7 ++-----
|
||
|
1 file changed, 2 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/src/mokutil.c b/src/mokutil.c
|
||
|
index ecf9e00..27ebf09 100644
|
||
|
--- a/src/mokutil.c
|
||
|
+++ b/src/mokutil.c
|
||
|
@@ -12,7 +12,6 @@
|
||
|
#include <openssl/sha.h>
|
||
|
#include <openssl/x509.h>
|
||
|
|
||
|
-#define __USE_GNU
|
||
|
#include <crypt.h>
|
||
|
|
||
|
#include "efi.h"
|
||
|
@@ -389,7 +388,6 @@ static int
|
||
|
generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
{
|
||
|
pw_crypt_t new_crypt;
|
||
|
- struct crypt_data data;
|
||
|
char settings[SETTINGS_LEN];
|
||
|
char *crypt_string;
|
||
|
const char *prefix;
|
||
|
@@ -412,7 +410,7 @@ generate_hash (pw_crypt_t *pw_crypt, char *password, int pw_len)
|
||
|
pw_crypt->salt_size);
|
||
|
settings[pw_crypt->salt_size + prefix_len] = '\0';
|
||
|
|
||
|
- crypt_string = crypt_r (password, settings, &data);
|
||
|
+ crypt_string = crypt (password, settings);
|
||
|
if (!crypt_string)
|
||
|
return -1;
|
||
|
|
||
|
@@ -1068,7 +1066,6 @@ reset_moks (const char *hash_file, const int root_pw)
|
||
|
static int
|
||
|
generate_pw_hash (const char *input_pw)
|
||
|
{
|
||
|
- struct crypt_data data;
|
||
|
char settings[SETTINGS_LEN];
|
||
|
char *password = NULL;
|
||
|
char *crypt_string;
|
||
|
@@ -1106,7 +1103,7 @@ generate_pw_hash (const char *input_pw)
|
||
|
DEFAULT_SALT_SIZE, DEFAULT_SALT_SIZE);
|
||
|
settings[DEFAULT_SALT_SIZE + prefix_len] = '\0';
|
||
|
|
||
|
- crypt_string = crypt_r (password, settings, &data);
|
||
|
+ crypt_string = crypt (password, settings);
|
||
|
if (!crypt_string) {
|
||
|
fprintf (stderr, "Failed to generate hash\n");
|
||
|
goto error;
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|
||
|
|
||
|
From f944da88acfffe80279de37c4181c9c19ff9a864 Mon Sep 17 00:00:00 2001
|
||
|
From: Gary Ching-Pang Lin <glin@suse.com>
|
||
|
Date: Tue, 29 Jan 2013 16:35:30 +0800
|
||
|
Subject: [PATCH 9/9] Support Traditional DES hash
|
||
|
|
||
|
---
|
||
|
src/password-crypt.c | 29 +++++++++++++++++++++++++----
|
||
|
src/password-crypt.h | 2 +-
|
||
|
2 files changed, 26 insertions(+), 5 deletions(-)
|
||
|
|
||
|
diff --git a/src/password-crypt.c b/src/password-crypt.c
|
||
|
index de15193..95bb687 100644
|
||
|
--- a/src/password-crypt.c
|
||
|
+++ b/src/password-crypt.c
|
||
|
@@ -6,6 +6,8 @@
|
||
|
|
||
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||
|
|
||
|
+#define TRAD_DES_HASH_SIZE 13 /* (64/6+1) + (12/6) */
|
||
|
+#define BSDI_DES_HASH_SIZE 20 /* (64/6+1) + (24/6) + 4 + 1 */
|
||
|
#define BLOWFISH_HASH_SIZE 31 /* 184 / 6 + 1 */
|
||
|
|
||
|
#define SHA256_DEFAULT_ROUNDS 5000
|
||
|
@@ -33,10 +35,10 @@ int
|
||
|
get_hash_size (int method)
|
||
|
{
|
||
|
switch (method) {
|
||
|
- case TRANDITIONAL_DES:
|
||
|
- return 64 / 8; /* per "man crypt" */
|
||
|
+ case TRADITIONAL_DES:
|
||
|
+ return TRAD_DES_HASH_SIZE;
|
||
|
case EXTEND_BSDI_DES:
|
||
|
- return 64 / 8; /* per "man crypt" */
|
||
|
+ return BSDI_DES_HASH_SIZE;
|
||
|
case MD5_BASED:
|
||
|
return MD5_DIGEST_LENGTH;
|
||
|
case SHA256_BASED:
|
||
|
@@ -54,7 +56,7 @@ const char *
|
||
|
get_crypt_prefix (int method)
|
||
|
{
|
||
|
switch (method) {
|
||
|
- case TRANDITIONAL_DES:
|
||
|
+ case TRADITIONAL_DES:
|
||
|
return ""; /* per "man crypt" */
|
||
|
case EXTEND_BSDI_DES:
|
||
|
return "_"; /* per "man crypt" */
|
||
|
@@ -72,6 +74,20 @@ get_crypt_prefix (int method)
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
+decode_trad_des_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
+{
|
||
|
+ /* Expected string: [./0-9A-Za-z]{13} */
|
||
|
+ pw_crypt->iter_count = 25;
|
||
|
+ pw_crypt->salt_size = 2;
|
||
|
+ memcpy (pw_crypt->salt, string, 2);
|
||
|
+ pw_crypt->salt[2] = '\0';
|
||
|
+ memcpy (pw_crypt->hash, string, TRAD_DES_HASH_SIZE);
|
||
|
+ pw_crypt->hash[TRAD_DES_HASH_SIZE] = '\0';
|
||
|
+
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
decode_md5_pass (const char *string, pw_crypt_t *pw_crypt)
|
||
|
{
|
||
|
/* Expected string: [./0-9A-Za-z]{1,8}\$[./0-9A-Za-z]{22} */
|
||
|
@@ -267,6 +283,11 @@ decode_pass (const char *crypt_pass, pw_crypt_t *pw_crypt)
|
||
|
return decode_blowfish_pass (crypt_pass, pw_crypt);
|
||
|
}
|
||
|
|
||
|
+ if (strlen (crypt_pass) == TRAD_DES_HASH_SIZE) {
|
||
|
+ pw_crypt->method = TRADITIONAL_DES;
|
||
|
+ return decode_trad_des_pass (crypt_pass, pw_crypt);
|
||
|
+ }
|
||
|
+
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
diff --git a/src/password-crypt.h b/src/password-crypt.h
|
||
|
index aba6975..92338ad 100644
|
||
|
--- a/src/password-crypt.h
|
||
|
+++ b/src/password-crypt.h
|
||
|
@@ -12,7 +12,7 @@
|
||
|
#define BLOWFISH_SALT_MAX 22
|
||
|
|
||
|
enum HashMethod {
|
||
|
- TRANDITIONAL_DES = 0,
|
||
|
+ TRADITIONAL_DES = 0,
|
||
|
EXTEND_BSDI_DES,
|
||
|
MD5_BASED,
|
||
|
SHA256_BASED,
|
||
|
--
|
||
|
1.7.10.4
|
||
|
|