~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, Robert Millan, Updated translations
  • Date: 2010-11-22 12:24:56 UTC
  • mfrom: (1.26.4 upstream) (17.3.36 sid)
  • mto: (17.3.43 sid)
  • mto: This revision was merged to the branch mainline in revision 89.
  • Revision ID: james.westby@ubuntu.com-20101122122456-y82z3sfb7k4zfdcc
Tags: 1.99~20101122-1
[ Colin Watson ]
* New Bazaar snapshot.  Too many changes to list in full, but some of the
  more user-visible ones are as follows:
  - GRUB script:
    + Function parameters, "break", "continue", "shift", "setparams",
      "return", and "!".
    + "export" command supports multiple variable names.
    + Multi-line quoted strings support.
    + Wildcard expansion.
  - sendkey support.
  - USB hotunplugging and USB serial support.
  - Rename CD-ROM to cd on BIOS.
  - Add new --boot-directory option to grub-install, grub-reboot, and
    grub-set-default; the old --root-directory option is still accepted
    but was often confusing.
  - Basic btrfs detection/UUID support (but no file reading yet).
  - bash-completion for utilities.
  - If a device is listed in device.map, always assume that it is
    BIOS-visible rather than using extra layers such as LVM or RAID.
  - Add grub-mknetdir script (closes: #550658).
  - Remove deprecated "root" command.
  - Handle RAID devices containing virtio components.
  - GRUB Legacy configuration file support (via grub-menulst2cfg).
  - Keyboard layout support (via grub-mklayout and grub-kbdcomp).
  - Check generated grub.cfg for syntax errors before saving.
  - Pause execution for at most ten seconds if any errors are displayed,
    so that the user has a chance to see them.
  - Support submenus.
  - Write embedding zone using Reed-Solomon, so that it's robust against
    being partially overwritten (closes: #550702, #591416, #593347).
  - GRUB_DISABLE_LINUX_RECOVERY and GRUB_DISABLE_NETBSD_RECOVERY merged
    into a single GRUB_DISABLE_RECOVERY variable.
  - Fix loader memory allocation failure (closes: #551627).
  - Don't call savedefault on recovery entries (closes: #589325).
  - Support triple-indirect blocks on ext2 (closes: #543924).
  - Recognise DDF1 fake RAID (closes: #603354).

[ Robert Millan ]
* Use dpkg architecture wildcards.

[ Updated translations ]
* Slovenian (Vanja Cvelbar).  Closes: #604003
* Dzongkha (dawa pemo via Tenzin Dendup).  Closes: #604102

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