>From d289bbb5f5dffbbed2c871989f55e48b756e9ae2 Mon Sep 17 00:00:00 2001 From: Klaus Frank Date: Tue, 25 Dec 2018 06:17:38 +0100 Subject: [PATCH] Implement salt-value and quiet parameter for grub-mkpasswd-pbkdf2 --- util/grub-mkpasswd-pbkdf2.c | 103 ++++++++++++++++++++++++++++++------ 1 file changed, 88 insertions(+), 15 deletions(-) diff --git a/util/grub-mkpasswd-pbkdf2.c b/util/grub-mkpasswd-pbkdf2.c index 5805f3c10..018715bf3 100644 --- a/util/grub-mkpasswd-pbkdf2.c +++ b/util/grub-mkpasswd-pbkdf2.c @@ -42,10 +42,15 @@ #include "progname.h" +static int dec_from_hex(const int); // Converts the charcode into an integer representation of the representing hex value. +int unhexify(grub_uint8_t*, const char*); + static struct argp_option options[] = { {"iteration-count", 'c', N_("NUM"), 0, N_("Number of PBKDF2 iterations"), 0}, {"buflen", 'l', N_("NUM"), 0, N_("Length of generated hash"), 0}, {"salt", 's', N_("NUM"), 0, N_("Length of salt"), 0}, + {"salt-value", 'v', N_("STR"), 0, N_("Salt"), 0}, + {"quiet", 'q', 0, 0, N_("Only output hash, suppress other output, indended for pipes"), 0}, { 0, 0, 0, 0, 0, 0 } }; @@ -54,6 +59,8 @@ struct arguments unsigned int count; unsigned int buflen; unsigned int saltlen; + char *value; + unsigned char quiet; }; static error_t @@ -76,6 +83,15 @@ argp_parser (int key, char *arg, struct argp_state *state) case 's': arguments->saltlen = strtoul (arg, NULL, 0); break; + + case 'v': + arguments->value = arg; + break; + + case 'q': + arguments->quiet = 1; + break; + default: return ARGP_ERR_UNKNOWN; } @@ -94,29 +110,70 @@ hexify (char *hex, grub_uint8_t *bin, grub_size_t n) { while (n--) { - if (((*bin & 0xf0) >> 4) < 10) - *hex = ((*bin & 0xf0) >> 4) + '0'; - else - *hex = ((*bin & 0xf0) >> 4) + 'A' - 10; + if (((*bin & 0xf0) >> 4) < 10) { + *hex = ((*bin & 0xf0) >> 4) + '0'; + } else { + *hex = ((*bin & 0xf0) >> 4) + 'A' - 10; + } hex++; if ((*bin & 0xf) < 10) - *hex = (*bin & 0xf) + '0'; + *hex = (*bin & 0xf) + '0'; else - *hex = (*bin & 0xf) + 'A' - 10; + *hex = (*bin & 0xf) + 'A' - 10; hex++; bin++; } *hex = 0; } +static int +dec_from_hex(const int hex) { + if (48 <= hex && hex <= 57) { + return hex - 48; + } else if (65 <= hex && hex <= 90) { + return hex - 65 + 10; + } else if (97 <= hex && hex <= 122) { + return hex - 97 + 10; + } else { + exit(1); + } +} + +int +unhexify(grub_uint8_t* output, const char* hexstring) { + // sizeof(output) == (sizeof(hexstring) - 1) / 2 + 1 + if (sizeof(output) < (sizeof(hexstring) - 1) / 2 + 1) { + return -1; + } + char *output_ptr = NULL; + output_ptr = (char*)output; + int CharCodeInDecimal = 0; + void *HexDigits = xmalloc(sizeof("FF")); + char *HexDigitOne = HexDigits; + char *HexDigitTwo = (char*)HexDigits + 1; + char *HexString_ptr = NULL; + HexString_ptr = (char*)hexstring; + while(*HexString_ptr) { + memcpy (HexDigitOne, HexString_ptr++, sizeof (char)); + memcpy (HexDigitTwo, HexString_ptr++, sizeof (char)); + + CharCodeInDecimal = dec_from_hex((int)*HexDigitOne) * 16 + dec_from_hex((int)*HexDigitTwo); + *output_ptr++ = (char)CharCodeInDecimal; + } + output_ptr = '\0'; + return 0; +} + int main (int argc, char *argv[]) { struct arguments arguments = { .count = 10000, .buflen = 64, - .saltlen = 64 + .saltlen = 64, + .value = NULL, + .quiet = 0 }; char *result, *ptr; gcry_err_code_t gcry_err; @@ -136,22 +193,25 @@ main (int argc, char *argv[]) buf = xmalloc (arguments.buflen); salt = xmalloc (arguments.saltlen); - printf ("%s", _("Enter password: ")); + if (!arguments.quiet) { + printf ("%s", _("Enter password: ")); + } if (!grub_password_get (pass1, GRUB_AUTH_MAX_PASSLEN)) { free (buf); free (salt); grub_util_error ("%s", _("failure to read password")); } - printf ("%s", _("Reenter password: ")); - if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN)) + if (!arguments.quiet) { + printf ("%s", _("Reenter password: ")); + if (!grub_password_get (pass2, GRUB_AUTH_MAX_PASSLEN)) { free (buf); free (salt); grub_util_error ("%s", _("failure to read password")); } - if (strcmp (pass1, pass2) != 0) + if (strcmp (pass1, pass2) != 0) { memset (pass1, 0, sizeof (pass1)); memset (pass2, 0, sizeof (pass2)); @@ -159,15 +219,25 @@ main (int argc, char *argv[]) free (salt); grub_util_error ("%s", _("passwords don't match")); } - memset (pass2, 0, sizeof (pass2)); + memset (pass2, 0, sizeof (pass2)); + } - if (grub_get_random (salt, arguments.saltlen)) + if (arguments.value) { + if (unhexify(salt, arguments.value)) { + memset(pass1, 0, sizeof(pass1)); + free(buf); + free(salt); + grub_util_error("%s", _("couldn't convert hexstring into salt")); + } + } else { + if (grub_get_random (salt, arguments.saltlen)) { memset (pass1, 0, sizeof (pass1)); free (buf); free (salt); grub_util_error ("%s", _("couldn't retrieve random data for salt")); } + } gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) pass1, strlen (pass1), @@ -200,11 +270,14 @@ main (int argc, char *argv[]) ptr += arguments.buflen * 2; *ptr = '\0'; - printf (_("PBKDF2 hash of your password is %s\n"), result); + if (arguments.quiet) { + printf ("%s\n", result); + } else { + printf (_("PBKDF2 hash of your password is %s\n"), result); + } memset (buf, 0, arguments.buflen); free (buf); memset (salt, 0, arguments.saltlen); free (salt); - return 0; } -- 2.20.1