~hamo/ubuntu/precise/grub2/grub2.hi_res

« back to all changes in this revision

Viewing changes to grub-core/lib/crypto.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson, Colin Watson, Evan Broder, Mario Limonciello
  • Date: 2010-11-24 13:59:55 UTC
  • mfrom: (1.17.6 upstream) (17.6.15 experimental)
  • Revision ID: james.westby@ubuntu.com-20101124135955-r6ii5sepayr7jt53
Tags: 1.99~20101124-1ubuntu1
[ Colin Watson ]
* Resynchronise with Debian experimental.  Remaining changes:
  - Adjust for default Ubuntu boot options ("quiet splash").
  - Default to hiding the menu; holding down Shift at boot will show it.
  - Set a monochromatic theme for Ubuntu.
  - Apply Ubuntu GRUB Legacy changes to legacy update-grub script: title,
    recovery mode, quiet option, tweak how memtest86+ is displayed, and
    use UUIDs where appropriate.
  - Fix backslash-escaping in merge_debconf_into_conf.
  - Remove "GNU/Linux" from default distributor string.
  - Add crashkernel= options if kdump and makedumpfile are available.
  - If other operating systems are installed, then automatically unhide
    the menu.  Otherwise, if GRUB_HIDDEN_TIMEOUT is 0, then use keystatus
    if available to check whether Shift is pressed.  If it is, show the
    menu, otherwise boot immediately.  If keystatus is not available, then
    fall back to a short delay interruptible with Escape.
  - Allow Shift to interrupt 'sleep --interruptible'.
  - Don't display introductory message about line editing unless we're
    actually offering a shell prompt.  Don't clear the screen just before
    booting if we never drew the menu in the first place.
  - Remove some verbose messages printed before reading the configuration
    file.
  - Suppress progress messages as the kernel and initrd load for
    non-recovery kernel menu entries.
  - Change prepare_grub_to_access_device to handle filesystems
    loop-mounted on file images.
  - Ignore devices loop-mounted from files in 10_linux.
  - Show the boot menu if the previous boot failed, that is if it failed
    to get to the end of one of the normal runlevels.
  - Don't generate /boot/grub/device.map during grub-install or
    grub-mkconfig by default.
  - Adjust upgrade version checks for Ubuntu.
  - Don't display "GRUB loading" unless Shift is held down.
  - Adjust versions of grub-doc and grub-legacy-doc conflicts to tolerate
    our backport of the grub-doc split.
  - Fix LVM/RAID probing in the absence of /boot/grub/device.map.
  - Look for .mo files in /usr/share/locale-langpack as well, in
    preference.
  - Make sure GRUB_TIMEOUT isn't quoted unnecessarily.
  - Probe all devices in 'grub-probe --target=drive' if
    /boot/grub/device.map is missing.
  - Build-depend on qemu-kvm rather than qemu-system for grub-pc tests.
  - Use qemu rather than qemu-system-i386.
  - Program vesafb on BIOS systems rather than efifb.
  - Add a grub-rescue-efi-amd64 package containing a rescue CD-ROM image
    for EFI-AMD64.
  - On Wubi, don't ask for an install device, but just update wubildr
    using the diverted grub-install.
  - When embedding the core image in a post-MBR gap, check for and avoid
    sectors matching any of a list of known signatures.
  - Disable video_bochs and video_cirrus on PC BIOS systems, as probing
    PCI space seems to break on some systems.
* Downgrade "ACPI shutdown failed" error to a debug message, since it can
  cause spurious test failures.

[ Evan Broder ]
* Enable lua from grub-extras.
* Incorporate the bitop library into lua.
* Add enum_pci function to grub module in lua.
* Switch back to gfxpayload=keep by default, unless the video hardware
  is known to not support it.

[ Mario Limonciello ]
* Built part_msdos and vfat into bootx64.efi (LP: #677758)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 */
 
19
 
 
20
#include <grub/crypto.h>
 
21
#include <grub/misc.h>
 
22
#include <grub/mm.h>
 
23
#include <grub/term.h>
 
24
 
 
25
struct grub_crypto_hmac_handle
 
26
{
 
27
  const struct gcry_md_spec *md;
 
28
  void *ctx;
 
29
  void *opad;
 
30
};
 
31
 
 
32
static gcry_cipher_spec_t *grub_ciphers = NULL;
 
33
static gcry_md_spec_t *grub_digests = NULL;
 
34
 
 
35
void (*grub_crypto_autoload_hook) (const char *name) = NULL;
 
36
 
 
37
/* Based on libgcrypt-1.4.4/src/misc.c.  */
 
38
void
 
39
grub_burn_stack (grub_size_t size)
 
40
{
 
41
  char buf[64];
 
42
 
 
43
  grub_memset (buf, 0, sizeof (buf));
 
44
  if (size > sizeof (buf))
 
45
    grub_burn_stack (size - sizeof (buf));
 
46
}
 
47
 
 
48
 
 
49
void 
 
50
grub_cipher_register (gcry_cipher_spec_t *cipher)
 
51
{
 
52
  cipher->next = grub_ciphers;
 
53
  grub_ciphers = cipher;
 
54
}
 
55
 
 
56
void
 
57
grub_cipher_unregister (gcry_cipher_spec_t *cipher)
 
58
{
 
59
  gcry_cipher_spec_t **ciph;
 
60
  for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
 
61
    if (*ciph == cipher)
 
62
      {
 
63
        *ciph = (*ciph)->next;
 
64
        break;
 
65
      }
 
66
}
 
67
 
 
68
void 
 
69
grub_md_register (gcry_md_spec_t *digest)
 
70
{
 
71
  digest->next = grub_digests;
 
72
  grub_digests = digest;
 
73
}
 
74
 
 
75
void 
 
76
grub_md_unregister (gcry_md_spec_t *cipher)
 
77
{
 
78
  gcry_md_spec_t **ciph;
 
79
  for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
 
80
    if (*ciph == cipher)
 
81
      {
 
82
        *ciph = (*ciph)->next;
 
83
        break;
 
84
      }
 
85
}
 
86
 
 
87
void
 
88
grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
 
89
                  grub_size_t inlen)
 
90
{
 
91
  grub_uint8_t ctx[hash->contextsize];
 
92
  hash->init (&ctx);
 
93
  hash->write (&ctx, in, inlen);
 
94
  hash->final (&ctx);
 
95
  grub_memcpy (out, hash->read (&ctx), hash->mdlen);
 
96
}
 
97
 
 
98
const gcry_md_spec_t *
 
99
grub_crypto_lookup_md_by_name (const char *name)
 
100
{
 
101
  const gcry_md_spec_t *md;
 
102
  int first = 1;
 
103
  while (1)
 
104
    {
 
105
      for (md = grub_digests; md; md = md->next)
 
106
        if (grub_strcasecmp (name, md->name) == 0)
 
107
          return md;
 
108
      if (grub_crypto_autoload_hook && first)
 
109
        grub_crypto_autoload_hook (name);
 
110
      else
 
111
        return NULL;
 
112
      first = 0;
 
113
    }
 
114
}
 
115
 
 
116
const gcry_cipher_spec_t *
 
117
grub_crypto_lookup_cipher_by_name (const char *name)
 
118
{
 
119
  const gcry_cipher_spec_t *ciph;
 
120
  int first = 1;
 
121
  while (1)
 
122
    {
 
123
      for (ciph = grub_ciphers; ciph; ciph = ciph->next)
 
124
        {
 
125
          const char **alias;
 
126
          if (grub_strcasecmp (name, ciph->name) == 0)
 
127
            return ciph;
 
128
          if (!ciph->aliases)
 
129
            continue;
 
130
          for (alias = ciph->aliases; *alias; alias++)
 
131
            if (grub_strcasecmp (name, *alias) == 0)
 
132
              return ciph;
 
133
        }
 
134
      if (grub_crypto_autoload_hook && first)
 
135
        grub_crypto_autoload_hook (name);
 
136
      else
 
137
        return NULL;
 
138
      first = 0;
 
139
    }
 
140
}
 
141
 
 
142
 
 
143
grub_crypto_cipher_handle_t
 
144
grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
 
145
{
 
146
  grub_crypto_cipher_handle_t ret;
 
147
  ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
 
148
  if (!ret)
 
149
    return NULL;
 
150
  ret->cipher = cipher;
 
151
  return ret;
 
152
}
 
153
 
 
154
gcry_err_code_t
 
155
grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
 
156
                            const unsigned char *key,
 
157
                            unsigned keylen)
 
158
{
 
159
  return cipher->cipher->setkey (cipher->ctx, key, keylen);
 
160
}
 
161
 
 
162
 
 
163
void
 
164
grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
 
165
{
 
166
  grub_free (cipher);
 
167
}
 
168
 
 
169
 
 
170
void
 
171
grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
 
172
{
 
173
  const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
 
174
  grub_uint8_t *outptr = out;
 
175
  while (size--)
 
176
    {
 
177
      *outptr = *in1ptr ^ *in2ptr;
 
178
      in1ptr++;
 
179
      in2ptr++;
 
180
      outptr++;
 
181
    }
 
182
}
 
183
 
 
184
gcry_err_code_t
 
185
grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
 
186
                         void *out, void *in, grub_size_t size)
 
187
{
 
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;
 
198
}
 
199
 
 
200
gcry_err_code_t
 
201
grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
 
202
                         void *out, void *in, grub_size_t size)
 
203
{
 
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;
 
214
}
 
215
 
 
216
gcry_err_code_t
 
217
grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
 
218
                         void *out, void *in, grub_size_t size,
 
219
                         void *iv_in)
 
220
{
 
221
  grub_uint8_t *inptr, *outptr, *end;
 
222
  void *iv;
 
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;
 
228
  iv = iv_in;
 
229
  for (inptr = in, outptr = out; inptr < end;
 
230
       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
 
231
    {
 
232
      grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
 
233
      cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
 
234
      iv = outptr;
 
235
    }
 
236
  grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
 
237
  return GPG_ERR_NO_ERROR;
 
238
}
 
239
 
 
240
gcry_err_code_t
 
241
grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
 
242
                         void *out, void *in, grub_size_t size,
 
243
                         void *iv)
 
244
{
 
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)
 
254
    {
 
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);
 
259
    }
 
260
  return GPG_ERR_NO_ERROR;
 
261
}
 
262
 
 
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)
 
267
{
 
268
  grub_uint8_t *helpkey = NULL;
 
269
  grub_uint8_t *ipad = NULL, *opad = NULL;
 
270
  void *ctx = NULL;
 
271
  struct grub_crypto_hmac_handle *ret = NULL;
 
272
  unsigned i;
 
273
 
 
274
  if (md->mdlen > md->blocksize)
 
275
    return NULL;
 
276
 
 
277
  ctx = grub_malloc (md->contextsize);
 
278
  if (!ctx)
 
279
    goto err;
 
280
 
 
281
  if ( keylen > md->blocksize ) 
 
282
    {
 
283
      helpkey = grub_malloc (md->mdlen);
 
284
      if (!helpkey)
 
285
        goto err;
 
286
      grub_crypto_hash (md, helpkey, key, keylen);
 
287
 
 
288
      key = helpkey;
 
289
      keylen = md->mdlen;
 
290
    }
 
291
 
 
292
  ipad = grub_zalloc (md->blocksize);
 
293
  if (!ipad)
 
294
    goto err;
 
295
 
 
296
  opad = grub_zalloc (md->blocksize);
 
297
  if (!opad)
 
298
    goto err;
 
299
 
 
300
  grub_memcpy ( ipad, key, keylen );
 
301
  grub_memcpy ( opad, key, keylen );
 
302
  for (i=0; i < md->blocksize; i++ ) 
 
303
    {
 
304
      ipad[i] ^= 0x36;
 
305
      opad[i] ^= 0x5c;
 
306
    }
 
307
  grub_free (helpkey);
 
308
  helpkey = NULL;
 
309
 
 
310
  md->init (ctx);
 
311
 
 
312
  md->write (ctx, ipad, md->blocksize); /* inner pad */
 
313
  grub_memset (ipad, 0, md->blocksize);
 
314
  grub_free (ipad);
 
315
  ipad = NULL;
 
316
 
 
317
  ret = grub_malloc (sizeof (*ret));
 
318
  if (!ret)
 
319
    goto err;
 
320
 
 
321
  ret->md = md;
 
322
  ret->ctx = ctx;
 
323
  ret->opad = opad;
 
324
 
 
325
  return ret;
 
326
 
 
327
 err:
 
328
  grub_free (helpkey);
 
329
  grub_free (ctx);
 
330
  grub_free (ipad);
 
331
  grub_free (opad);
 
332
  return NULL;
 
333
}
 
334
 
 
335
void
 
336
grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
 
337
                        grub_size_t datalen)
 
338
{
 
339
  hnd->md->write (hnd->ctx, data, datalen);
 
340
}
 
341
 
 
342
gcry_err_code_t
 
343
grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
 
344
{
 
345
  grub_uint8_t *p;
 
346
  grub_uint8_t *ctx2;
 
347
 
 
348
  ctx2 = grub_malloc (hnd->md->contextsize);
 
349
  if (!ctx2)
 
350
    return GPG_ERR_OUT_OF_MEMORY;
 
351
 
 
352
  hnd->md->final (hnd->ctx);
 
353
  hnd->md->read (hnd->ctx);
 
354
  p = hnd->md->read (hnd->ctx);
 
355
 
 
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);
 
364
 
 
365
  grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
 
366
  grub_memset (ctx2, 0, hnd->md->contextsize);
 
367
  grub_free (ctx2);
 
368
 
 
369
  grub_memset (hnd, 0, sizeof (*hnd));
 
370
  grub_free (hnd);
 
371
 
 
372
  return GPG_ERR_NO_ERROR;
 
373
}
 
374
 
 
375
gcry_err_code_t
 
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)
 
379
{
 
380
  struct grub_crypto_hmac_handle *hnd;
 
381
 
 
382
  hnd = grub_crypto_hmac_init (md, key, keylen);
 
383
  if (!hnd)
 
384
    return GPG_ERR_OUT_OF_MEMORY;
 
385
 
 
386
  grub_crypto_hmac_write (hnd, data, datalen);
 
387
  return grub_crypto_hmac_fini (hnd, out);
 
388
}
 
389
 
 
390
 
 
391
grub_err_t
 
392
grub_crypto_gcry_error (gcry_err_code_t in)
 
393
{
 
394
  if (in == GPG_ERR_NO_ERROR)
 
395
    return GRUB_ERR_NONE;
 
396
  return GRUB_ACCESS_DENIED;
 
397
}
 
398
 
 
399
int
 
400
grub_crypto_memcmp (const void *a, const void *b, grub_size_t n)
 
401
{
 
402
  register grub_size_t counter = 0;
 
403
  const grub_uint8_t *pa, *pb;
 
404
 
 
405
  for (pa = a, pb = b; n; pa++, pb++, n--)
 
406
    {
 
407
      if (*pa != *pb)
 
408
        counter++;
 
409
    }
 
410
 
 
411
  return !!counter;
 
412
}
 
413
 
 
414
#ifndef GRUB_MKPASSWD
 
415
int
 
416
grub_password_get (char buf[], unsigned buf_size)
 
417
{
 
418
  unsigned cur_len = 0;
 
419
  int key;
 
420
 
 
421
  while (1)
 
422
    {
 
423
      key = grub_getkey (); 
 
424
      if (key == '\n' || key == '\r')
 
425
        break;
 
426
 
 
427
      if (key == '\e')
 
428
        {
 
429
          cur_len = 0;
 
430
          break;
 
431
        }
 
432
 
 
433
      if (key == '\b')
 
434
        {
 
435
          cur_len--;
 
436
          continue;
 
437
        }
 
438
 
 
439
      if (!grub_isprint (key))
 
440
        continue;
 
441
 
 
442
      if (cur_len + 2 < buf_size)
 
443
        buf[cur_len++] = key;
 
444
    }
 
445
 
 
446
  grub_memset (buf + cur_len, 0, buf_size - cur_len);
 
447
 
 
448
  grub_xputs ("\n");
 
449
  grub_refresh ();
 
450
 
 
451
  return (key != '\e');
 
452
}
 
453
#endif