Upgraded GRUB2 to 2.00 release.
[AROS.git] / arch / all-pc / boot / grub2-aros / grub-core / lib / crypto.c
blobf4b13ed3d8418b5ed7c5bb11f3aa39b7296b3b25
1 /*
2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
4 * 2007, 2008, 2009 Free Software Foundation, Inc.
6 * GRUB is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * GRUB is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/crypto.h>
21 #include <grub/misc.h>
22 #include <grub/mm.h>
23 #include <grub/term.h>
24 #include <grub/dl.h>
25 #include <grub/i18n.h>
27 #ifdef GRUB_UTIL
28 #include <termios.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdio.h>
32 #endif
34 GRUB_MOD_LICENSE ("GPLv3+");
36 struct grub_crypto_hmac_handle
38 const struct gcry_md_spec *md;
39 void *ctx;
40 void *opad;
43 static gcry_cipher_spec_t *grub_ciphers = NULL;
44 static gcry_md_spec_t *grub_digests = NULL;
46 void (*grub_crypto_autoload_hook) (const char *name) = NULL;
48 /* Based on libgcrypt-1.4.4/src/misc.c. */
49 void
50 grub_burn_stack (grub_size_t size)
52 char buf[64];
54 grub_memset (buf, 0, sizeof (buf));
55 if (size > sizeof (buf))
56 grub_burn_stack (size - sizeof (buf));
60 void
61 grub_cipher_register (gcry_cipher_spec_t *cipher)
63 cipher->next = grub_ciphers;
64 grub_ciphers = cipher;
67 void
68 grub_cipher_unregister (gcry_cipher_spec_t *cipher)
70 gcry_cipher_spec_t **ciph;
71 for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
72 if (*ciph == cipher)
74 *ciph = (*ciph)->next;
75 break;
79 void
80 grub_md_register (gcry_md_spec_t *digest)
82 digest->next = grub_digests;
83 grub_digests = digest;
86 void
87 grub_md_unregister (gcry_md_spec_t *cipher)
89 gcry_md_spec_t **ciph;
90 for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
91 if (*ciph == cipher)
93 *ciph = (*ciph)->next;
94 break;
98 void
99 grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
100 grub_size_t inlen)
102 grub_uint8_t ctx[hash->contextsize];
103 hash->init (&ctx);
104 hash->write (&ctx, in, inlen);
105 hash->final (&ctx);
106 grub_memcpy (out, hash->read (&ctx), hash->mdlen);
109 const gcry_md_spec_t *
110 grub_crypto_lookup_md_by_name (const char *name)
112 const gcry_md_spec_t *md;
113 int first = 1;
114 while (1)
116 for (md = grub_digests; md; md = md->next)
117 if (grub_strcasecmp (name, md->name) == 0)
118 return md;
119 if (grub_crypto_autoload_hook && first)
120 grub_crypto_autoload_hook (name);
121 else
122 return NULL;
123 first = 0;
127 const gcry_cipher_spec_t *
128 grub_crypto_lookup_cipher_by_name (const char *name)
130 const gcry_cipher_spec_t *ciph;
131 int first = 1;
132 while (1)
134 for (ciph = grub_ciphers; ciph; ciph = ciph->next)
136 const char **alias;
137 if (grub_strcasecmp (name, ciph->name) == 0)
138 return ciph;
139 if (!ciph->aliases)
140 continue;
141 for (alias = ciph->aliases; *alias; alias++)
142 if (grub_strcasecmp (name, *alias) == 0)
143 return ciph;
145 if (grub_crypto_autoload_hook && first)
146 grub_crypto_autoload_hook (name);
147 else
148 return NULL;
149 first = 0;
154 grub_crypto_cipher_handle_t
155 grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
157 grub_crypto_cipher_handle_t ret;
158 ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
159 if (!ret)
160 return NULL;
161 ret->cipher = cipher;
162 return ret;
165 gcry_err_code_t
166 grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
167 const unsigned char *key,
168 unsigned keylen)
170 return cipher->cipher->setkey (cipher->ctx, key, keylen);
173 gcry_err_code_t
174 grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
175 void *out, const void *in, grub_size_t size)
177 const grub_uint8_t *inptr;
178 grub_uint8_t *outptr, *end;
179 if (!cipher->cipher->decrypt)
180 return GPG_ERR_NOT_SUPPORTED;
181 if (size % cipher->cipher->blocksize != 0)
182 return GPG_ERR_INV_ARG;
183 end = (grub_uint8_t *) in + size;
184 for (inptr = in, outptr = out; inptr < end;
185 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
186 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
187 return GPG_ERR_NO_ERROR;
190 gcry_err_code_t
191 grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
192 void *out, const void *in, grub_size_t size)
194 const grub_uint8_t *inptr;
195 grub_uint8_t *outptr, *end;
196 if (!cipher->cipher->encrypt)
197 return GPG_ERR_NOT_SUPPORTED;
198 if (size % cipher->cipher->blocksize != 0)
199 return GPG_ERR_INV_ARG;
200 end = (grub_uint8_t *) in + size;
201 for (inptr = in, outptr = out; inptr < end;
202 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
203 cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
204 return GPG_ERR_NO_ERROR;
207 gcry_err_code_t
208 grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
209 void *out, void *in, grub_size_t size,
210 void *iv_in)
212 grub_uint8_t *inptr, *outptr, *end;
213 void *iv;
214 if (!cipher->cipher->decrypt)
215 return GPG_ERR_NOT_SUPPORTED;
216 if (size % cipher->cipher->blocksize != 0)
217 return GPG_ERR_INV_ARG;
218 end = (grub_uint8_t *) in + size;
219 iv = iv_in;
220 for (inptr = in, outptr = out; inptr < end;
221 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
223 grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
224 cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
225 iv = outptr;
227 grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
228 return GPG_ERR_NO_ERROR;
231 gcry_err_code_t
232 grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
233 void *out, const void *in, grub_size_t size,
234 void *iv)
236 const grub_uint8_t *inptr;
237 grub_uint8_t *outptr, *end;
238 grub_uint8_t ivt[cipher->cipher->blocksize];
239 if (!cipher->cipher->decrypt)
240 return GPG_ERR_NOT_SUPPORTED;
241 if (size % cipher->cipher->blocksize != 0)
242 return GPG_ERR_INV_ARG;
243 end = (grub_uint8_t *) in + size;
244 for (inptr = in, outptr = out; inptr < end;
245 inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
247 grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
248 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
249 grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
250 grub_memcpy (iv, ivt, cipher->cipher->blocksize);
252 return GPG_ERR_NO_ERROR;
255 /* Based on gcry/cipher/md.c. */
256 struct grub_crypto_hmac_handle *
257 grub_crypto_hmac_init (const struct gcry_md_spec *md,
258 const void *key, grub_size_t keylen)
260 grub_uint8_t *helpkey = NULL;
261 grub_uint8_t *ipad = NULL, *opad = NULL;
262 void *ctx = NULL;
263 struct grub_crypto_hmac_handle *ret = NULL;
264 unsigned i;
266 if (md->mdlen > md->blocksize)
267 return NULL;
269 ctx = grub_malloc (md->contextsize);
270 if (!ctx)
271 goto err;
273 if ( keylen > md->blocksize )
275 helpkey = grub_malloc (md->mdlen);
276 if (!helpkey)
277 goto err;
278 grub_crypto_hash (md, helpkey, key, keylen);
280 key = helpkey;
281 keylen = md->mdlen;
284 ipad = grub_zalloc (md->blocksize);
285 if (!ipad)
286 goto err;
288 opad = grub_zalloc (md->blocksize);
289 if (!opad)
290 goto err;
292 grub_memcpy ( ipad, key, keylen );
293 grub_memcpy ( opad, key, keylen );
294 for (i=0; i < md->blocksize; i++ )
296 ipad[i] ^= 0x36;
297 opad[i] ^= 0x5c;
299 grub_free (helpkey);
300 helpkey = NULL;
302 md->init (ctx);
304 md->write (ctx, ipad, md->blocksize); /* inner pad */
305 grub_memset (ipad, 0, md->blocksize);
306 grub_free (ipad);
307 ipad = NULL;
309 ret = grub_malloc (sizeof (*ret));
310 if (!ret)
311 goto err;
313 ret->md = md;
314 ret->ctx = ctx;
315 ret->opad = opad;
317 return ret;
319 err:
320 grub_free (helpkey);
321 grub_free (ctx);
322 grub_free (ipad);
323 grub_free (opad);
324 return NULL;
327 void
328 grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
329 const void *data,
330 grub_size_t datalen)
332 hnd->md->write (hnd->ctx, data, datalen);
335 gcry_err_code_t
336 grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
338 grub_uint8_t *p;
339 grub_uint8_t *ctx2;
341 ctx2 = grub_malloc (hnd->md->contextsize);
342 if (!ctx2)
343 return GPG_ERR_OUT_OF_MEMORY;
345 hnd->md->final (hnd->ctx);
346 hnd->md->read (hnd->ctx);
347 p = hnd->md->read (hnd->ctx);
349 hnd->md->init (ctx2);
350 hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
351 hnd->md->write (ctx2, p, hnd->md->mdlen);
352 hnd->md->final (ctx2);
353 grub_memset (hnd->opad, 0, hnd->md->blocksize);
354 grub_free (hnd->opad);
355 grub_memset (hnd->ctx, 0, hnd->md->contextsize);
356 grub_free (hnd->ctx);
358 grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
359 grub_memset (ctx2, 0, hnd->md->contextsize);
360 grub_free (ctx2);
362 grub_memset (hnd, 0, sizeof (*hnd));
363 grub_free (hnd);
365 return GPG_ERR_NO_ERROR;
368 gcry_err_code_t
369 grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
370 const void *key, grub_size_t keylen,
371 const void *data, grub_size_t datalen, void *out)
373 struct grub_crypto_hmac_handle *hnd;
375 hnd = grub_crypto_hmac_init (md, key, keylen);
376 if (!hnd)
377 return GPG_ERR_OUT_OF_MEMORY;
379 grub_crypto_hmac_write (hnd, data, datalen);
380 return grub_crypto_hmac_fini (hnd, out);
384 grub_err_t
385 grub_crypto_gcry_error (gcry_err_code_t in)
387 if (in == GPG_ERR_NO_ERROR)
388 return GRUB_ERR_NONE;
389 return GRUB_ACCESS_DENIED;
393 grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
395 register grub_size_t counter = 0;
396 const grub_uint8_t *pa, *pb;
398 for (pa = a, pb = b; n; pa++, pb++, n--)
400 if (*pa != *pb)
401 counter++;
404 return !!counter;
408 grub_password_get (char buf[], unsigned buf_size)
410 #ifdef GRUB_UTIL
411 FILE *in;
412 struct termios s, t;
413 int tty_changed = 0;
414 char *ptr;
416 /* Disable echoing. Based on glibc. */
417 in = fopen ("/dev/tty", "w+c");
418 if (in == NULL)
419 in = stdin;
421 if (tcgetattr (fileno (in), &t) == 0)
423 /* Save the old one. */
424 s = t;
425 /* Tricky, tricky. */
426 t.c_lflag &= ~(ECHO|ISIG);
427 tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
429 else
430 tty_changed = 0;
431 fgets (buf, buf_size, stdin);
432 ptr = buf + strlen (buf) - 1;
433 while (buf <= ptr && (*ptr == '\n' || *ptr == '\r'))
434 *ptr-- = 0;
435 /* Restore the original setting. */
436 if (tty_changed)
437 (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
439 grub_xputs ("\n");
440 grub_refresh ();
442 return 1;
443 #else
444 unsigned cur_len = 0;
445 int key;
447 while (1)
449 key = grub_getkey ();
450 if (key == '\n' || key == '\r')
451 break;
453 if (key == '\e')
455 cur_len = 0;
456 break;
459 if (key == '\b')
461 cur_len--;
462 continue;
465 if (!grub_isprint (key))
466 continue;
468 if (cur_len + 2 < buf_size)
469 buf[cur_len++] = key;
472 grub_memset (buf + cur_len, 0, buf_size - cur_len);
474 grub_xputs ("\n");
475 grub_refresh ();
477 return (key != '\e');
478 #endif