GRUB-1.98 changes
[grub2/jjazz.git] / util / grub-mkpasswd-pbkdf2.c
bloba00b1e99072f0566bab8b6c353c48a5974b3e7df
1 /*
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/>.
19 #include <grub/types.h>
20 #include <grub/crypto.h>
21 #include <grub/util/misc.h>
22 #include <grub/i18n.h>
24 #include <unistd.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <getopt.h>
29 #include <termios.h>
31 #include "progname.h"
33 /* Few functions to make crypto happy. */
34 void *
35 grub_memmove (void *dest, const void *src, grub_size_t n)
37 return memmove (dest, src, n);
40 void *
41 grub_memset (void *s, int c, grub_size_t n)
43 return memset (s, c, n);
46 int
47 grub_vprintf (const char *fmt, va_list args)
49 return vprintf (fmt, args);
52 int
53 grub_vsnprintf (char *str, grub_size_t n, const char *fmt, va_list args)
55 return vsnprintf (str, n, fmt, args);
58 void
59 grub_abort (void)
61 abort ();
64 static struct option options[] =
66 {"iteration_count", required_argument, 0, 'c'},
67 {"buflen", required_argument, 0, 'l'},
68 {"saltlen", required_argument, 0, 's'},
69 {"help", no_argument, 0, 'h'},
70 {"version", no_argument, 0, 'V'},
73 static void
74 usage (int status)
76 if (status)
77 fprintf (stderr, "Try `%s --help' for more information.\n", program_name);
78 else
79 printf ("\
80 Usage: %s [OPTIONS]\n\
81 \nOptions:\n\
82 -c number, --iteration-count=number Number of PBKDF2 iterations\n\
83 -l number, --buflen=number Length of generated hash\n\
84 -s number, --salt=number Length of salt\n\
85 \n\
86 Report bugs to <%s>.\n", program_name, PACKAGE_BUGREPORT);
88 exit (status);
91 static void
92 hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
94 while (n--)
96 if (((*bin & 0xf0) >> 4) < 10)
97 *hex = ((*bin & 0xf0) >> 4) + '0';
98 else
99 *hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
100 hex++;
102 if ((*bin & 0xf) < 10)
103 *hex = (*bin & 0xf) + '0';
104 else
105 *hex = (*bin & 0xf) + 'A' - 10;
106 hex++;
107 bin++;
109 *hex = 0;
113 main (int argc, char *argv[])
115 unsigned int c = 10000, buflen = 64, saltlen = 64;
116 char *pass1, *pass2;
117 char *bufhex, *salthex;
118 gcry_err_code_t gcry_err;
119 grub_uint8_t *buf, *salt;
120 ssize_t nr;
121 FILE *in, *out;
122 struct termios s, t;
123 int tty_changed;
125 set_program_name (argv[0]);
127 grub_util_init_nls ();
129 /* Check for options. */
130 while (1)
132 int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0);
134 if (c == -1)
135 break;
137 switch (c)
139 case 'c':
140 c = strtoul (optarg, NULL, 0);
141 break;
143 case 'l':
144 buflen = strtoul (optarg, NULL, 0);
145 break;
147 case 's':
148 saltlen = strtoul (optarg, NULL, 0);
149 break;
151 case 'h':
152 usage (0);
153 return 0;
155 case 'V':
156 printf ("%s (%s) %s\n", program_name,
157 PACKAGE_NAME, PACKAGE_VERSION);
158 return 0;
160 default:
161 usage (1);
162 return 1;
166 bufhex = malloc (buflen * 2 + 1);
167 if (!bufhex)
168 grub_util_error ("out of memory");
169 buf = malloc (buflen);
170 if (!buf)
172 free (bufhex);
173 grub_util_error ("out of memory");
176 salt = malloc (saltlen);
177 if (!salt)
179 free (bufhex);
180 free (buf);
181 grub_util_error ("out of memory");
183 salthex = malloc (saltlen * 2 + 1);
184 if (!salthex)
186 free (salt);
187 free (bufhex);
188 free (buf);
189 grub_util_error ("out of memory");
192 /* Disable echoing. Based on glibc. */
193 in = fopen ("/dev/tty", "w+c");
194 if (in == NULL)
196 in = stdin;
197 out = stderr;
199 else
200 out = in;
202 if (tcgetattr (fileno (in), &t) == 0)
204 /* Save the old one. */
205 s = t;
206 /* Tricky, tricky. */
207 t.c_lflag &= ~(ECHO|ISIG);
208 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
210 else
211 tty_changed = 0;
213 printf ("Enter password: ");
214 pass1 = NULL;
216 grub_size_t n;
217 nr = getline (&pass1, &n, stdin);
219 if (nr < 0 || !pass1)
221 free (buf);
222 free (bufhex);
223 free (salthex);
224 free (salt);
225 /* Restore the original setting. */
226 if (tty_changed)
227 (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
228 grub_util_error ("failure to read password");
230 if (nr >= 1 && pass1[nr-1] == '\n')
231 pass1[nr-1] = 0;
233 printf ("\nReenter password: ");
234 pass2 = NULL;
236 grub_size_t n;
237 nr = getline (&pass2, &n, stdin);
239 /* Restore the original setting. */
240 if (tty_changed)
241 (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
242 printf ("\n");
244 if (nr < 0 || !pass2)
246 memset (pass1, 0, strlen (pass1));
247 free (pass1);
248 free (buf);
249 free (bufhex);
250 free (salthex);
251 free (salt);
252 grub_util_error ("failure to read password");
254 if (nr >= 1 && pass2[nr-1] == '\n')
255 pass2[nr-1] = 0;
257 if (strcmp (pass1, pass2) != 0)
259 memset (pass1, 0, strlen (pass1));
260 memset (pass2, 0, strlen (pass2));
261 free (pass1);
262 free (pass2);
263 free (buf);
264 free (bufhex);
265 free (salthex);
266 free (salt);
267 grub_util_error ("passwords don't match");
269 memset (pass2, 0, strlen (pass2));
270 free (pass2);
272 #if ! defined (__linux__) && ! defined (__FreeBSD__)
273 printf ("WARNING: your random generator isn't known to be secure\n");
274 #endif
277 FILE *f;
278 size_t rd;
279 f = fopen ("/dev/random", "rb");
280 if (!f)
282 memset (pass1, 0, strlen (pass1));
283 free (pass1);
284 free (buf);
285 free (bufhex);
286 free (salthex);
287 free (salt);
288 fclose (f);
289 grub_util_error ("couldn't retrieve random data for salt");
291 rd = fread (salt, 1, saltlen, f);
292 if (rd != saltlen)
294 fclose (f);
295 memset (pass1, 0, strlen (pass1));
296 free (pass1);
297 free (buf);
298 free (bufhex);
299 free (salthex);
300 free (salt);
301 fclose (f);
302 grub_util_error ("couldn't retrieve random data for salt");
304 fclose (f);
307 gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
308 (grub_uint8_t *) pass1, strlen (pass1),
309 salt, saltlen,
310 c, buf, buflen);
311 memset (pass1, 0, strlen (pass1));
312 free (pass1);
314 if (gcry_err)
316 memset (buf, 0, buflen);
317 memset (bufhex, 0, 2 * buflen);
318 free (buf);
319 free (bufhex);
320 memset (salt, 0, saltlen);
321 memset (salthex, 0, 2 * saltlen);
322 free (salt);
323 free (salthex);
324 grub_util_error ("cryptographic error number %d", gcry_err);
327 hexify (bufhex, buf, buflen);
328 hexify (salthex, salt, saltlen);
330 printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex);
331 memset (buf, 0, buflen);
332 memset (bufhex, 0, 2 * buflen);
333 free (buf);
334 free (bufhex);
335 memset (salt, 0, saltlen);
336 memset (salthex, 0, 2 * saltlen);
337 free (salt);
338 free (salthex);
340 return 0;