Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / commands / password_pbkdf2.c
blob0dd1aef3d9957fd6906f72dca13000faec50daac
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 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/auth.h>
20 #include <grub/crypto.h>
21 #include <grub/list.h>
22 #include <grub/mm.h>
23 #include <grub/misc.h>
24 #include <grub/env.h>
25 #include <grub/normal.h>
26 #include <grub/dl.h>
27 #include <grub/i18n.h>
29 GRUB_MOD_LICENSE ("GPLv3+");
31 static grub_dl_t my_mod;
33 struct pbkdf2_password
35 grub_uint8_t *salt;
36 grub_size_t saltlen;
37 unsigned int c;
38 grub_uint8_t *expected;
39 grub_size_t buflen;
42 static grub_err_t
43 check_password (const char *user, const char *entered, void *pin)
45 grub_uint8_t *buf;
46 struct pbkdf2_password *pass = pin;
47 gcry_err_code_t err;
49 buf = grub_malloc (pass->buflen);
50 if (!buf)
51 return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
53 err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) entered,
54 grub_strlen (entered),
55 pass->salt, pass->saltlen, pass->c,
56 buf, pass->buflen);
57 if (err)
59 grub_free (buf);
60 return grub_crypto_gcry_error (err);
63 if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
64 return GRUB_ACCESS_DENIED;
66 grub_auth_authenticate (user);
68 return GRUB_ERR_NONE;
71 static inline int
72 hex2val (char hex)
74 if ('0' <= hex && hex <= '9')
75 return hex - '0';
76 if ('a' <= hex && hex <= 'f')
77 return hex - 'a' + 10;
78 if ('A' <= hex && hex <= 'F')
79 return hex - 'A' + 10;
80 return -1;
83 static grub_err_t
84 grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
85 int argc, char **args)
87 grub_err_t err;
88 char *ptr, *ptr2;
89 grub_uint8_t *ptro;
90 struct pbkdf2_password *pass;
92 if (argc != 2)
93 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("two arguments expected"));
95 if (grub_memcmp (args[1], "grub.pbkdf2.sha512.",
96 sizeof ("grub.pbkdf2.sha512.") - 1) != 0)
97 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
99 ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1;
101 pass = grub_malloc (sizeof (*pass));
102 if (!pass)
103 return grub_errno;
105 pass->c = grub_strtoul (ptr, &ptr, 0);
106 if (grub_errno)
107 return grub_errno;
108 if (*ptr != '.')
110 grub_free (pass);
111 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
113 ptr++;
115 ptr2 = grub_strchr (ptr, '.');
116 if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1)
118 grub_free (pass);
119 return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("invalid PBKDF2 password"));
122 pass->saltlen = (ptr2 - ptr) >> 1;
123 pass->buflen = grub_strlen (ptr2 + 1) >> 1;
124 ptro = pass->salt = grub_malloc (pass->saltlen);
125 if (!ptro)
127 grub_free (pass);
128 return grub_errno;
130 while (ptr < ptr2)
132 int hex1, hex2;
133 hex1 = hex2val (*ptr);
134 ptr++;
135 hex2 = hex2val (*ptr);
136 ptr++;
137 if (hex1 < 0 || hex2 < 0)
139 grub_free (pass->salt);
140 grub_free (pass);
141 return grub_error (GRUB_ERR_BAD_ARGUMENT,
142 /* TRANSLATORS: it means that the string which
143 was supposed to be a password hash doesn't
144 have a correct format, not to password
145 mismatch. */
146 N_("invalid PBKDF2 password"));
149 *ptro = (hex1 << 4) | hex2;
150 ptro++;
153 ptro = pass->expected = grub_malloc (pass->buflen);
154 if (!ptro)
156 grub_free (pass->salt);
157 grub_free (pass);
158 return grub_errno;
160 ptr = ptr2 + 1;
161 ptr2 += grub_strlen (ptr2);
162 while (ptr < ptr2)
164 int hex1, hex2;
165 hex1 = hex2val (*ptr);
166 ptr++;
167 hex2 = hex2val (*ptr);
168 ptr++;
169 if (hex1 < 0 || hex2 < 0)
171 grub_free (pass->expected);
172 grub_free (pass->salt);
173 grub_free (pass);
174 return grub_error (GRUB_ERR_BAD_ARGUMENT,
175 N_("invalid PBKDF2 password"));
178 *ptro = (hex1 << 4) | hex2;
179 ptro++;
182 err = grub_auth_register_authentication (args[0], check_password, pass);
183 if (err)
185 grub_free (pass);
186 return err;
188 grub_dl_ref (my_mod);
189 return GRUB_ERR_NONE;
192 static grub_command_t cmd;
194 GRUB_MOD_INIT(password_pbkdf2)
196 my_mod = mod;
197 cmd = grub_register_command ("password_pbkdf2", grub_cmd_password,
198 N_("USER PBKDF2_PASSWORD"),
199 N_("Set user password (PBKDF2). "));
202 GRUB_MOD_FINI(password_pbkdf2)
204 grub_unregister_command (cmd);