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>
23 #include <grub/term.h>
25 #include <grub/i18n.h>
28 GRUB_MOD_LICENSE ("GPLv3+");
30 struct grub_crypto_hmac_handle
32 const struct gcry_md_spec *md;
37 static gcry_cipher_spec_t *grub_ciphers = NULL;
38 static gcry_md_spec_t *grub_digests = NULL;
40 void (*grub_crypto_autoload_hook) (const char *name) = NULL;
42 /* Based on libgcrypt-1.4.4/src/misc.c. */
44 grub_burn_stack (grub_size_t size)
48 grub_memset (buf, 0, sizeof (buf));
49 if (size > sizeof (buf))
50 grub_burn_stack (size - sizeof (buf));
54 _gcry_burn_stack (int size)
56 grub_burn_stack (size);
59 void __attribute__ ((noreturn))
60 _gcry_assert_failed (const char *expr, const char *file, int line,
64 grub_fatal ("assertion %s at %s:%d (%s) failed\n", expr, file, line, func);
68 void _gcry_log_error (const char *fmt, ...)
71 const char *debug = grub_env_get ("debug");
76 if (grub_strword (debug, "all") || grub_strword (debug, "gcrypt"))
78 grub_printf ("gcrypt error: ");
80 grub_vprintf (fmt, args);
87 grub_cipher_register (gcry_cipher_spec_t *cipher)
89 cipher->next = grub_ciphers;
90 grub_ciphers = cipher;
94 grub_cipher_unregister (gcry_cipher_spec_t *cipher)
96 gcry_cipher_spec_t **ciph;
97 for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
100 *ciph = (*ciph)->next;
106 grub_md_register (gcry_md_spec_t *digest)
108 digest->next = grub_digests;
109 grub_digests = digest;
113 grub_md_unregister (gcry_md_spec_t *cipher)
115 gcry_md_spec_t **ciph;
116 for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
119 *ciph = (*ciph)->next;
125 grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
128 GRUB_PROPERLY_ALIGNED_ARRAY (ctx, GRUB_CRYPTO_MAX_MD_CONTEXT_SIZE);
130 if (hash->contextsize > sizeof (ctx))
131 grub_fatal ("Too large md context");
133 hash->write (&ctx, in, inlen);
135 grub_memcpy (out, hash->read (&ctx), hash->mdlen);
138 const gcry_md_spec_t *
139 grub_crypto_lookup_md_by_name (const char *name)
141 const gcry_md_spec_t *md;
145 for (md = grub_digests; md; md = md->next)
146 if (grub_strcasecmp (name, md->name) == 0)
148 if (grub_crypto_autoload_hook && first)
149 grub_crypto_autoload_hook (name);
156 const gcry_cipher_spec_t *
157 grub_crypto_lookup_cipher_by_name (const char *name)
159 const gcry_cipher_spec_t *ciph;
163 for (ciph = grub_ciphers; ciph; ciph = ciph->next)
166 if (grub_strcasecmp (name, ciph->name) == 0)
170 for (alias = ciph->aliases; *alias; alias++)
171 if (grub_strcasecmp (name, *alias) == 0)
174 if (grub_crypto_autoload_hook && first)
175 grub_crypto_autoload_hook (name);
183 grub_crypto_cipher_handle_t
184 grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
186 grub_crypto_cipher_handle_t ret;
187 ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
190 ret->cipher = cipher;
195 grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
196 const unsigned char *key,
199 return cipher->cipher->setkey (cipher->ctx, key, keylen);
203 grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
204 void *out, const void *in, grub_size_t size)
206 const grub_uint8_t *inptr, *end;
207 grub_uint8_t *outptr;
208 grub_size_t blocksize;
209 if (!cipher->cipher->decrypt)
210 return GPG_ERR_NOT_SUPPORTED;
211 blocksize = cipher->cipher->blocksize;
212 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
213 || ((size & (blocksize - 1)) != 0))
214 return GPG_ERR_INV_ARG;
215 end = (const grub_uint8_t *) in + size;
216 for (inptr = in, outptr = out; inptr < end;
217 inptr += blocksize, outptr += blocksize)
218 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
219 return GPG_ERR_NO_ERROR;
223 grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
224 void *out, const void *in, grub_size_t size)
226 const grub_uint8_t *inptr, *end;
227 grub_uint8_t *outptr;
228 grub_size_t blocksize;
229 if (!cipher->cipher->encrypt)
230 return GPG_ERR_NOT_SUPPORTED;
231 blocksize = cipher->cipher->blocksize;
232 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
233 || ((size & (blocksize - 1)) != 0))
234 return GPG_ERR_INV_ARG;
235 end = (const grub_uint8_t *) in + size;
236 for (inptr = in, outptr = out; inptr < end;
237 inptr += blocksize, outptr += blocksize)
238 cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
239 return GPG_ERR_NO_ERROR;
243 grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
244 void *out, const void *in, grub_size_t size,
247 grub_uint8_t *outptr;
248 const grub_uint8_t *inptr, *end;
250 grub_size_t blocksize;
251 if (!cipher->cipher->encrypt)
252 return GPG_ERR_NOT_SUPPORTED;
253 blocksize = cipher->cipher->blocksize;
254 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
255 || ((size & (blocksize - 1)) != 0))
256 return GPG_ERR_INV_ARG;
257 end = (const grub_uint8_t *) in + size;
259 for (inptr = in, outptr = out; inptr < end;
260 inptr += blocksize, outptr += blocksize)
262 grub_crypto_xor (outptr, inptr, iv, blocksize);
263 cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
266 grub_memcpy (iv_in, iv, blocksize);
267 return GPG_ERR_NO_ERROR;
271 grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
272 void *out, const void *in, grub_size_t size,
275 const grub_uint8_t *inptr, *end;
276 grub_uint8_t *outptr;
277 grub_uint8_t ivt[GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE];
278 grub_size_t blocksize;
279 if (!cipher->cipher->decrypt)
280 return GPG_ERR_NOT_SUPPORTED;
281 blocksize = cipher->cipher->blocksize;
282 if (blocksize == 0 || (((blocksize - 1) & blocksize) != 0)
283 || ((size & (blocksize - 1)) != 0))
284 return GPG_ERR_INV_ARG;
285 if (blocksize > GRUB_CRYPTO_MAX_CIPHER_BLOCKSIZE)
286 return GPG_ERR_INV_ARG;
287 end = (const grub_uint8_t *) in + size;
288 for (inptr = in, outptr = out; inptr < end;
289 inptr += blocksize, outptr += blocksize)
291 grub_memcpy (ivt, inptr, blocksize);
292 cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
293 grub_crypto_xor (outptr, outptr, iv, blocksize);
294 grub_memcpy (iv, ivt, blocksize);
296 return GPG_ERR_NO_ERROR;
299 /* Based on gcry/cipher/md.c. */
300 struct grub_crypto_hmac_handle *
301 grub_crypto_hmac_init (const struct gcry_md_spec *md,
302 const void *key, grub_size_t keylen)
304 grub_uint8_t *helpkey = NULL;
305 grub_uint8_t *ipad = NULL, *opad = NULL;
307 struct grub_crypto_hmac_handle *ret = NULL;
310 if (md->mdlen > md->blocksize)
313 ctx = grub_malloc (md->contextsize);
317 if ( keylen > md->blocksize )
319 helpkey = grub_malloc (md->mdlen);
322 grub_crypto_hash (md, helpkey, key, keylen);
328 ipad = grub_zalloc (md->blocksize);
332 opad = grub_zalloc (md->blocksize);
336 grub_memcpy ( ipad, key, keylen );
337 grub_memcpy ( opad, key, keylen );
338 for (i=0; i < md->blocksize; i++ )
348 md->write (ctx, ipad, md->blocksize); /* inner pad */
349 grub_memset (ipad, 0, md->blocksize);
353 ret = grub_malloc (sizeof (*ret));
372 grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd,
376 hnd->md->write (hnd->ctx, data, datalen);
380 grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
385 ctx2 = grub_malloc (hnd->md->contextsize);
387 return GPG_ERR_OUT_OF_MEMORY;
389 hnd->md->final (hnd->ctx);
390 hnd->md->read (hnd->ctx);
391 p = hnd->md->read (hnd->ctx);
393 hnd->md->init (ctx2);
394 hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
395 hnd->md->write (ctx2, p, hnd->md->mdlen);
396 hnd->md->final (ctx2);
397 grub_memset (hnd->opad, 0, hnd->md->blocksize);
398 grub_free (hnd->opad);
399 grub_memset (hnd->ctx, 0, hnd->md->contextsize);
400 grub_free (hnd->ctx);
402 grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
403 grub_memset (ctx2, 0, hnd->md->contextsize);
406 grub_memset (hnd, 0, sizeof (*hnd));
409 return GPG_ERR_NO_ERROR;
413 grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
414 const void *key, grub_size_t keylen,
415 const void *data, grub_size_t datalen, void *out)
417 struct grub_crypto_hmac_handle *hnd;
419 hnd = grub_crypto_hmac_init (md, key, keylen);
421 return GPG_ERR_OUT_OF_MEMORY;
423 grub_crypto_hmac_write (hnd, data, datalen);
424 return grub_crypto_hmac_fini (hnd, out);
429 grub_crypto_gcry_error (gcry_err_code_t in)
431 if (in == GPG_ERR_NO_ERROR)
432 return GRUB_ERR_NONE;
433 return GRUB_ACCESS_DENIED;
437 grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
439 register grub_size_t counter = 0;
440 const grub_uint8_t *pa, *pb;
442 for (pa = a, pb = b; n; pa++, pb++, n--)
454 grub_password_get (char buf[], unsigned buf_size)
456 unsigned cur_len = 0;
461 key = grub_getkey ();
462 if (key == '\n' || key == '\r')
465 if (key == GRUB_TERM_ESC)
478 if (!grub_isprint (key))
481 if (cur_len + 2 < buf_size)
482 buf[cur_len++] = key;
485 grub_memset (buf + cur_len, 0, buf_size - cur_len);
490 return (key != GRUB_TERM_ESC);