2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1992-1999,2001,2003,2004,2005,2009 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
21 #include <grub/types.h>
22 #include <grub/crypto.h>
23 #include <grub/auth.h>
24 #include <grub/emu/misc.h>
25 #include <grub/util/misc.h>
26 #include <grub/i18n.h>
39 static struct argp_option options
[] = {
40 {"iteration-count", 'c', N_("NUM"), 0, N_("Number of PBKDF2 iterations"), 0},
41 {"buflen", 'l', N_("NUM"), 0, N_("Length of generated hash"), 0},
42 {"salt", 's', N_("NUM"), 0, N_("Length of salt"), 0},
54 argp_parser (int key
, char *arg
, struct argp_state
*state
)
56 /* Get the input argument from argp_parse, which we
57 know is a pointer to our arguments structure. */
58 struct arguments
*arguments
= state
->input
;
63 arguments
->count
= strtoul (arg
, NULL
, 0);
67 arguments
->buflen
= strtoul (arg
, NULL
, 0);
71 arguments
->saltlen
= strtoul (arg
, NULL
, 0);
74 return ARGP_ERR_UNKNOWN
;
79 static struct argp argp
= {
80 options
, argp_parser
, N_("[OPTIONS]"),
81 N_("Generate PBKDF2 password hash."),
87 hexify (char *hex
, grub_uint8_t
*bin
, grub_size_t n
)
91 if (((*bin
& 0xf0) >> 4) < 10)
92 *hex
= ((*bin
& 0xf0) >> 4) + '0';
94 *hex
= ((*bin
& 0xf0) >> 4) + 'A' - 10;
97 if ((*bin
& 0xf) < 10)
98 *hex
= (*bin
& 0xf) + '0';
100 *hex
= (*bin
& 0xf) + 'A' - 10;
108 main (int argc
, char *argv
[])
110 struct arguments arguments
= {
115 char *bufhex
, *salthex
, *result
;
116 gcry_err_code_t gcry_err
;
117 grub_uint8_t
*buf
, *salt
;
118 char pass1
[GRUB_AUTH_MAX_PASSLEN
];
119 char pass2
[GRUB_AUTH_MAX_PASSLEN
];
121 set_program_name (argv
[0]);
123 grub_util_init_nls ();
125 /* Check for options. */
126 if (argp_parse (&argp
, argc
, argv
, 0, 0, &arguments
) != 0)
128 fprintf (stderr
, "%s", _("Error in parsing command line arguments\n"));
132 bufhex
= xmalloc (arguments
.buflen
* 2 + 1);
133 buf
= xmalloc (arguments
.buflen
);
134 salt
= xmalloc (arguments
.saltlen
);
135 salthex
= xmalloc (arguments
.saltlen
* 2 + 1);
137 printf ("%s", _("Enter password: "));
138 if (!grub_password_get (pass1
, GRUB_AUTH_MAX_PASSLEN
))
144 grub_util_error ("%s", _("failure to read password"));
146 printf ("\n%s", _("Reenter password: "));
147 if (!grub_password_get (pass2
, GRUB_AUTH_MAX_PASSLEN
))
153 grub_util_error ("%s", _("failure to read password"));
156 if (strcmp (pass1
, pass2
) != 0)
158 memset (pass1
, 0, sizeof (pass1
));
159 memset (pass2
, 0, sizeof (pass2
));
164 grub_util_error ("%s", _("passwords don't match"));
166 memset (pass2
, 0, sizeof (pass2
));
168 #if ! defined (__linux__) && ! defined (__FreeBSD__)
169 /* TRANSLATORS: The generator might still be secure just GRUB isn't sure about it. */
170 printf ("%s", _("WARNING: your random generator isn't known to be secure\n"));
176 f
= fopen ("/dev/urandom", "rb");
179 memset (pass1
, 0, sizeof (pass1
));
185 grub_util_error ("%s", _("couldn't retrieve random data for salt"));
187 rd
= fread (salt
, 1, arguments
.saltlen
, f
);
188 if (rd
!= arguments
.saltlen
)
191 memset (pass1
, 0, sizeof (pass1
));
196 grub_util_error ("%s", _("couldn't retrieve random data for salt"));
201 gcry_err
= grub_crypto_pbkdf2 (GRUB_MD_SHA512
,
202 (grub_uint8_t
*) pass1
, strlen (pass1
),
203 salt
, arguments
.saltlen
,
204 arguments
.count
, buf
, arguments
.buflen
);
205 memset (pass1
, 0, sizeof (pass1
));
209 memset (buf
, 0, arguments
.buflen
);
210 memset (bufhex
, 0, 2 * arguments
.buflen
);
213 memset (salt
, 0, arguments
.saltlen
);
214 memset (salthex
, 0, 2 * arguments
.saltlen
);
217 grub_util_error (_("cryptographic error number %d"), gcry_err
);
220 hexify (bufhex
, buf
, arguments
.buflen
);
221 hexify (salthex
, salt
, arguments
.saltlen
);
223 result
= xmalloc (sizeof ("grub.pbkdf2.sha512.XXXXXXXXXXXXXXXXXXX.S.S")
224 + arguments
.buflen
* 2 + arguments
.saltlen
* 2);
225 snprintf (result
, sizeof ("grub.pbkdf2.sha512.XXXXXXXXXXXXXXXXXXX.S.S")
226 + arguments
.buflen
* 2 + arguments
.saltlen
* 2,
227 "grub.pbkdf2.sha512.%d.%s.%s",
228 arguments
.count
, salthex
, bufhex
);
230 printf (_("PBKDF2 hash of your password is %s\n"), result
);
231 memset (buf
, 0, arguments
.buflen
);
232 memset (bufhex
, 0, 2 * arguments
.buflen
);
235 memset (salt
, 0, arguments
.saltlen
);
236 memset (salthex
, 0, 2 * arguments
.saltlen
);