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
struct grub_crypto_hmac_handle
27
const struct gcry_md_spec *md;
32
static gcry_cipher_spec_t *grub_ciphers = NULL;
33
static gcry_md_spec_t *grub_digests = NULL;
35
void (*grub_crypto_autoload_hook) (const char *name) = NULL;
37
/* Based on libgcrypt-1.4.4/src/misc.c. */
39
grub_burn_stack (grub_size_t size)
43
grub_memset (buf, 0, sizeof (buf));
44
if (size > sizeof (buf))
45
grub_burn_stack (size - sizeof (buf));
50
grub_cipher_register (gcry_cipher_spec_t *cipher)
52
cipher->next = grub_ciphers;
53
grub_ciphers = cipher;
57
grub_cipher_unregister (gcry_cipher_spec_t *cipher)
59
gcry_cipher_spec_t **ciph;
60
for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
63
*ciph = (*ciph)->next;
69
grub_md_register (gcry_md_spec_t *digest)
71
digest->next = grub_digests;
72
grub_digests = digest;
76
grub_md_unregister (gcry_md_spec_t *cipher)
78
gcry_md_spec_t **ciph;
79
for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
82
*ciph = (*ciph)->next;
88
grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
91
grub_uint8_t ctx[hash->contextsize];
93
hash->write (&ctx, in, inlen);
95
grub_memcpy (out, hash->read (&ctx), hash->mdlen);
98
const gcry_md_spec_t *
99
grub_crypto_lookup_md_by_name (const char *name)
101
const gcry_md_spec_t *md;
105
for (md = grub_digests; md; md = md->next)
106
if (grub_strcasecmp (name, md->name) == 0)
108
if (grub_crypto_autoload_hook && first)
109
grub_crypto_autoload_hook (name);
116
const gcry_cipher_spec_t *
117
grub_crypto_lookup_cipher_by_name (const char *name)
119
const gcry_cipher_spec_t *ciph;
123
for (ciph = grub_ciphers; ciph; ciph = ciph->next)
126
if (grub_strcasecmp (name, ciph->name) == 0)
130
for (alias = ciph->aliases; *alias; alias++)
131
if (grub_strcasecmp (name, *alias) == 0)
134
if (grub_crypto_autoload_hook && first)
135
grub_crypto_autoload_hook (name);
143
grub_crypto_cipher_handle_t
144
grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
146
grub_crypto_cipher_handle_t ret;
147
ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
150
ret->cipher = cipher;
155
grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
156
const unsigned char *key,
159
return cipher->cipher->setkey (cipher->ctx, key, keylen);
164
grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
171
grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
173
const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
174
grub_uint8_t *outptr = out;
177
*outptr = *in1ptr ^ *in2ptr;
185
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
186
void *out, void *in, grub_size_t size)
188
grub_uint8_t *inptr, *outptr, *end;
189
if (!cipher->cipher->decrypt)
190
return GPG_ERR_NOT_SUPPORTED;
191
if (size % cipher->cipher->blocksize != 0)
192
return GPG_ERR_INV_ARG;
193
end = (grub_uint8_t *) in + size;
194
for (inptr = in, outptr = out; inptr < end;
195
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
196
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
197
return GPG_ERR_NO_ERROR;
201
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
202
void *out, void *in, grub_size_t size)
204
grub_uint8_t *inptr, *outptr, *end;
205
if (!cipher->cipher->encrypt)
206
return GPG_ERR_NOT_SUPPORTED;
207
if (size % cipher->cipher->blocksize != 0)
208
return GPG_ERR_INV_ARG;
209
end = (grub_uint8_t *) in + size;
210
for (inptr = in, outptr = out; inptr < end;
211
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
212
cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
213
return GPG_ERR_NO_ERROR;
217
grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
218
void *out, void *in, grub_size_t size,
221
grub_uint8_t *inptr, *outptr, *end;
223
if (!cipher->cipher->decrypt)
224
return GPG_ERR_NOT_SUPPORTED;
225
if (size % cipher->cipher->blocksize != 0)
226
return GPG_ERR_INV_ARG;
227
end = (grub_uint8_t *) in + size;
229
for (inptr = in, outptr = out; inptr < end;
230
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
232
grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
233
cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
236
grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
237
return GPG_ERR_NO_ERROR;
241
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
242
void *out, void *in, grub_size_t size,
245
grub_uint8_t *inptr, *outptr, *end;
246
grub_uint8_t ivt[cipher->cipher->blocksize];
247
if (!cipher->cipher->decrypt)
248
return GPG_ERR_NOT_SUPPORTED;
249
if (size % cipher->cipher->blocksize != 0)
250
return GPG_ERR_INV_ARG;
251
end = (grub_uint8_t *) in + size;
252
for (inptr = in, outptr = out; inptr < end;
253
inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
255
grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
256
cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
257
grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
258
grub_memcpy (iv, ivt, cipher->cipher->blocksize);
260
return GPG_ERR_NO_ERROR;
263
/* Based on gcry/cipher/md.c. */
264
struct grub_crypto_hmac_handle *
265
grub_crypto_hmac_init (const struct gcry_md_spec *md,
266
const void *key, grub_size_t keylen)
268
grub_uint8_t *helpkey = NULL;
269
grub_uint8_t *ipad = NULL, *opad = NULL;
271
struct grub_crypto_hmac_handle *ret = NULL;
274
if (md->mdlen > md->blocksize)
277
ctx = grub_malloc (md->contextsize);
281
if ( keylen > md->blocksize )
283
helpkey = grub_malloc (md->mdlen);
286
grub_crypto_hash (md, helpkey, key, keylen);
292
ipad = grub_zalloc (md->blocksize);
296
opad = grub_zalloc (md->blocksize);
300
grub_memcpy ( ipad, key, keylen );
301
grub_memcpy ( opad, key, keylen );
302
for (i=0; i < md->blocksize; i++ )
312
md->write (ctx, ipad, md->blocksize); /* inner pad */
313
grub_memset (ipad, 0, md->blocksize);
317
ret = grub_malloc (sizeof (*ret));
336
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
339
hnd->md->write (hnd->ctx, data, datalen);
343
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
348
ctx2 = grub_malloc (hnd->md->contextsize);
350
return GPG_ERR_OUT_OF_MEMORY;
352
hnd->md->final (hnd->ctx);
353
hnd->md->read (hnd->ctx);
354
p = hnd->md->read (hnd->ctx);
356
hnd->md->init (ctx2);
357
hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
358
hnd->md->write (ctx2, p, hnd->md->mdlen);
359
hnd->md->final (ctx2);
360
grub_memset (hnd->opad, 0, hnd->md->blocksize);
361
grub_free (hnd->opad);
362
grub_memset (hnd->ctx, 0, hnd->md->contextsize);
363
grub_free (hnd->ctx);
365
grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
366
grub_memset (ctx2, 0, hnd->md->contextsize);
369
grub_memset (hnd, 0, sizeof (*hnd));
372
return GPG_ERR_NO_ERROR;
376
grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
377
const void *key, grub_size_t keylen,
378
void *data, grub_size_t datalen, void *out)
380
struct grub_crypto_hmac_handle *hnd;
382
hnd = grub_crypto_hmac_init (md, key, keylen);
384
return GPG_ERR_OUT_OF_MEMORY;
386
grub_crypto_hmac_write (hnd, data, datalen);
387
return grub_crypto_hmac_fini (hnd, out);
392
grub_crypto_gcry_error (gcry_err_code_t in)
394
if (in == GPG_ERR_NO_ERROR)
395
return GRUB_ERR_NONE;
396
return GRUB_ACCESS_DENIED;
400
grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
402
register grub_size_t counter = 0;
403
const grub_uint8_t *pa, *pb;
405
for (pa = a, pb = b; n; pa++, pb++, n--)
414
#ifndef GRUB_MKPASSWD
416
grub_password_get (char buf[], unsigned buf_size)
418
unsigned cur_len = 0;
423
key = grub_getkey ();
424
if (key == '\n' || key == '\r')
439
if (!grub_isprint (key))
442
if (cur_len + 2 < buf_size)
443
buf[cur_len++] = key;
446
grub_memset (buf + cur_len, 0, buf_size - cur_len);
451
return (key != '\e');