grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Cryptography


From: Vladimir 'phcoder' Serbinenko
Subject: [PATCH] Cryptography
Date: Mon, 16 Nov 2009 14:48:02 +0100
User-agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109)

Hello, all. This patch imports strong cryptography and fixes some issues
in authentication system.
1) grub_auth_strcmp and grub_auth_strword are removed. They ended up to
be too complex which is security-issue prone. For password I now
hardcode maximum length as was suggested and use grub_crypto_memcmp.
Logins are now considered non-confidential
2) Ciphers and hashes are imported from libgcrypt. Actual import is
automated and imported files are not included in the patch. To import do:
python import_gcry.py <libgcrypt dir> .
Crypto interface is designed for simplicity and small size
3) PBKDF2-SHA512 password support to increase security. To generate the
encrypted password do:
grub-pbkdf2 [-c iteration_count]
It may not work on non-unix platforms due to terminal control functions
(disabling echo) and /dev/random (retrieving salt). Patches are welcome
PBKDF2 is imported from gnulib
4) xnu_uuid is cleanup to use MD5 from libgcrypt through crypto interface
5) Imported devmapper.mod by Simon Peter. Completely UNTESTED.
Known issues:
No cipher and hash autoloading if it's looked up by the name.
Password and hash modules aren't locked if a cipher/digest is used to
prevent accidental unload.
I send the patch and the same is available in my crypto branch

-- 
Regards
Vladimir 'phcoder' Serbinenko

=== modified file '.bzrignore'
--- .bzrignore  2009-11-13 17:32:22 +0000
+++ .bzrignore  2009-11-16 12:57:00 +0000
@@ -31,6 +31,7 @@
 grub_fstest_init.h
 grub-install
 grub-mk*
+grub-pbkdf2
 grub-pe2elf
 grub-probe
 grub_probe_init.c

=== modified file 'commands/password.c'
--- commands/password.c 2009-08-24 23:55:06 +0000
+++ commands/password.c 2009-11-15 22:39:40 +0000
@@ -17,6 +17,7 @@
  */
 
 #include <grub/auth.h>
+#include <grub/crypto.h>
 #include <grub/list.h>
 #include <grub/mm.h>
 #include <grub/misc.h>
@@ -26,18 +27,20 @@
 
 static grub_dl_t my_mod;
 
+#define MAX_PASSLEN 1024
+
 static grub_err_t
 check_password (const char *user,
                void *password)
 {
-  char entered[1024];
+  char entered[MAX_PASSLEN];
 
   grub_memset (entered, 0, sizeof (entered));
 
   if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1))
     return GRUB_ACCESS_DENIED;
 
-  if (grub_auth_strcmp (entered, password) != 0)
+  if (grub_crypto_memcmp (entered, password, MAX_PASSLEN) != 0)
     return GRUB_ACCESS_DENIED;
 
   grub_auth_authenticate (user);
@@ -51,13 +54,18 @@
 {
   grub_err_t err;
   char *pass;
+  int copylen;
 
   if (argc != 2)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
 
-  pass = grub_strdup (args[1]);
+  pass = grub_zalloc (MAX_PASSLEN);
   if (!pass)
     return grub_errno;
+  copylen = grub_strlen (args[1]);
+  if (copylen >= MAX_PASSLEN)
+    copylen = MAX_PASSLEN - 1;
+  grub_memcpy (pass, args[1], copylen);
 
   err = grub_auth_register_authentication (args[0], check_password, pass);
   if (err)

=== added file 'commands/password_pbkdf2.c'
--- commands/password_pbkdf2.c  1970-01-01 00:00:00 +0000
+++ commands/password_pbkdf2.c  2009-11-16 12:53:34 +0000
@@ -0,0 +1,202 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *  Copyright (C) 2009  Vladimir 'phcoder' Serbineko <address@hidden>
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/crypto.h>
+#include <grub/list.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/env.h>
+#include <grub/normal.h>
+#include <grub/dl.h>
+
+static grub_dl_t my_mod;
+
+struct pbkdf2_password
+{
+  grub_uint8_t *salt;
+  grub_size_t saltlen;
+  unsigned int c;
+  grub_uint8_t *expected;
+  grub_size_t buflen;
+};
+
+static grub_err_t
+check_password (const char *user, void *pin)
+{
+  char entered[1024];
+  grub_uint8_t *buf;
+  struct pbkdf2_password *pass = pin;
+  gcry_err_code_t err;
+
+  grub_memset (entered, 0, sizeof (entered));
+
+  if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1))
+    return GRUB_ACCESS_DENIED;
+
+  buf = grub_malloc (pass->buflen);
+  if (!buf)
+    return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY);
+
+  err = grub_crypto_pbkdf2 (GRUB_MD_SHA512, (grub_uint8_t *) &entered,
+                           grub_strlen (entered),
+                           pass->salt, pass->saltlen, pass->c,
+                           buf, pass->buflen);
+  if (err)
+    {
+      grub_free (buf);
+      return grub_crypto_gcry_error (err);
+    }
+
+  if (grub_crypto_memcmp (buf, pass->expected, pass->buflen) != 0)
+    return GRUB_ACCESS_DENIED;
+
+  grub_auth_authenticate (user);
+
+  return GRUB_ERR_NONE;
+}
+
+static inline int
+hex2val (char hex)
+{
+  if ('0' <= hex && hex <= '9')
+    return hex - '0';
+  if ('a' <= hex && hex <= 'f')
+    return hex - 'a' + 10;
+  if ('A' <= hex && hex <= 'F')
+    return hex - 'A' + 10;
+  return -1;
+}
+
+static grub_err_t
+grub_cmd_password (grub_command_t cmd __attribute__ ((unused)),
+                  int argc, char **args)
+{
+  grub_err_t err;
+  char *ptr, *ptr2;
+  grub_uint8_t *ptro;
+  struct pbkdf2_password *pass;
+
+  if (argc != 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.");
+
+  if (grub_memcmp (args[1], "grub.pbkdf2.sha512.",
+                  sizeof ("grub.pbkdf2.sha512.") - 1) != 0)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
+
+  ptr = args[1] + sizeof ("grub.pbkdf2.sha512.") - 1;
+
+  pass = grub_malloc (sizeof (*pass));
+  if (!pass)
+    return grub_errno;
+
+  pass->c = grub_strtoul (ptr, &ptr, 0);
+  if (*ptr != '.')
+    {
+      grub_free (pass);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
+    }
+  ptr++;
+
+  ptr2 = grub_strchr (ptr, '.');
+  if (!ptr2 || ((ptr2 - ptr) & 1) || grub_strlen (ptr2 + 1) & 1)
+    {
+      grub_free (pass);
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password.");
+    }
+
+  pass->saltlen = (ptr2 - ptr) >> 1;
+  pass->buflen = grub_strlen (ptr2 + 1) >> 1;
+  ptro = pass->salt = grub_malloc (pass->saltlen);
+  if (!ptro)
+    {
+      grub_free (pass);
+      return grub_errno;
+    }
+  while (ptr < ptr2)
+    {
+      int hex1, hex2;
+      hex1 = hex2val (*ptr);
+      ptr++;
+      hex2 = hex2val (*ptr);
+      ptr++;
+      if (hex1 < 0 || hex2 < 0)
+       {
+         grub_free (pass->salt);
+         grub_free (pass);
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            "Incorrect PBKDF2 password.");
+       }
+
+      *ptro = (hex1 << 4) | hex2;
+      ptro++;
+    }
+
+  ptro = pass->expected = grub_malloc (pass->buflen);
+  if (!ptro)
+    {
+      grub_free (pass->salt);
+      grub_free (pass);
+      return grub_errno;
+    }
+  ptr = ptr2 + 1;
+  ptr2 += grub_strlen (ptr2); 
+  while (ptr < ptr2)
+    {
+      int hex1, hex2;
+      hex1 = hex2val (*ptr);
+      ptr++;
+      hex2 = hex2val (*ptr);
+      ptr++;
+      if (hex1 < 0 || hex2 < 0)
+       {
+         grub_free (pass->expected);
+         grub_free (pass->salt);
+         grub_free (pass);
+         return grub_error (GRUB_ERR_BAD_ARGUMENT,
+                            "Incorrect PBKDF2 password.");
+       }
+
+      *ptro = (hex1 << 4) | hex2;
+      ptro++;
+    }
+
+  err = grub_auth_register_authentication (args[0], check_password, pass);
+  if (err)
+    {
+      grub_free (pass);
+      return err;
+    }
+  grub_dl_ref (my_mod);
+  return GRUB_ERR_NONE;
+}
+
+static grub_command_t cmd;
+
+GRUB_MOD_INIT(password_pbkdf2)
+{
+  my_mod = mod;
+  cmd = grub_register_command ("password_pbkdf2", grub_cmd_password,
+                              "password_pbkdf2 USER PBKDF2_PASSWORD",
+                              "Set user password (PBKDF2). ");
+}
+
+GRUB_MOD_FINI(password_pbkdf2)
+{
+  grub_unregister_command (cmd);
+}

=== modified file 'commands/xnu_uuid.c'
--- commands/xnu_uuid.c 2009-10-15 12:26:30 +0000
+++ commands/xnu_uuid.c 2009-11-11 00:10:28 +0000
@@ -31,12 +31,7 @@
 #include <grub/misc.h>
 #include <grub/env.h>
 #include <grub/command.h>
-
-struct tohash
-{
-  grub_uint8_t prefix[16];
-  grub_uint64_t serial;
-} __attribute__ ((packed));
+#include <grub/crypto.h>
 
 /* This prefix is used by xnu and boot-132 to hash 
    together with volume serial. */
@@ -44,311 +39,27 @@
   = {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 
      0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC};
 
-#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
-#define ror(x,n) ( ((x) >> (n)) | ((x) << (32-(n))) )
-
-typedef struct {
-  grub_uint32_t A,B,C,D;         /* chaining variables */
-  grub_uint32_t  nblocks;
-  grub_uint8_t buf[64];
-  int  count;
-} MD5_CONTEXT;
-
-static void
-md5_init( void *context )
-{
-  MD5_CONTEXT *ctx = context;
-
-  ctx->A = 0x67452301;
-  ctx->B = 0xefcdab89;
-  ctx->C = 0x98badcfe;
-  ctx->D = 0x10325476;
-
-  ctx->nblocks = 0;
-  ctx->count = 0;
-}
-
-/* These are the four functions used in the four steps of the MD5 algorithm
-   and defined in the RFC 1321.  The first function is a little bit optimized
-   (as found in Colin Plumbs public domain implementation).  */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-
-
-/****************
- * transform n*64 grub_uint8_ts
- */
-static void
-transform ( MD5_CONTEXT *ctx, const unsigned char *data )
-{
-  grub_uint32_t correct_words[16];
-  register grub_uint32_t A = ctx->A;
-  register grub_uint32_t B = ctx->B;
-  register grub_uint32_t C = ctx->C;
-  register grub_uint32_t D = ctx->D;
-  grub_uint32_t *cwp = correct_words;
-
-#ifdef GRUB_CPU_WORDS_BIGENDIAN
-  {
-    int i;
-    const grub_uint32_t *p = (const grub_uint32_t *) data;
-
-    for (i = 0; i < 16; i++)
-      correct_words[i] = grub_le_to_cpu32 (p[i]);
-  }
-#else
-  grub_memcpy (correct_words, data, 64);
-#endif
-
-#define OP(a, b, c, d, s, T) \
-  do                                      \
-  {                                       \
-    a += FF (b, c, d) + (*cwp++) + T;    \
-    a = rol(a, s);                        \
-    a += b;                               \
-  }                                       \
-  while (0)
-
-  /* Before we start, one word about the strange constants.
-     They are defined in RFC 1321 as
-
-     T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
-     */
-
-  /* Round 1.  */
-  OP (A, B, C, D,  7, 0xd76aa478);
-  OP (D, A, B, C, 12, 0xe8c7b756);
-  OP (C, D, A, B, 17, 0x242070db);
-  OP (B, C, D, A, 22, 0xc1bdceee);
-  OP (A, B, C, D,  7, 0xf57c0faf);
-  OP (D, A, B, C, 12, 0x4787c62a);
-  OP (C, D, A, B, 17, 0xa8304613);
-  OP (B, C, D, A, 22, 0xfd469501);
-  OP (A, B, C, D,  7, 0x698098d8);
-  OP (D, A, B, C, 12, 0x8b44f7af);
-  OP (C, D, A, B, 17, 0xffff5bb1);
-  OP (B, C, D, A, 22, 0x895cd7be);
-  OP (A, B, C, D,  7, 0x6b901122);
-  OP (D, A, B, C, 12, 0xfd987193);
-  OP (C, D, A, B, 17, 0xa679438e);
-  OP (B, C, D, A, 22, 0x49b40821);
-
-#undef OP
-#define OP(f, a, b, c, d, k, s, T)  \
-  do                                                                 \
-  {                                                          \
-    a += f (b, c, d) + correct_words[k] + T;                 \
-    a = rol(a, s);                                                   \
-    a += b;                                                  \
-  }                                                          \
-  while (0)
-
-  /* Round 2.  */
-  OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
-  OP (FG, D, A, B, C,  6,  9, 0xc040b340);
-  OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
-  OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
-  OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
-  OP (FG, D, A, B, C, 10,  9, 0x02441453);
-  OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
-  OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
-  OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
-  OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
-  OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
-  OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
-  OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
-  OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
-  OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
-  OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
-  /* Round 3.  */
-  OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
-  OP (FH, D, A, B, C,  8, 11, 0x8771f681);
-  OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
-  OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
-  OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
-  OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
-  OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
-  OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
-  OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
-  OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
-  OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
-  OP (FH, B, C, D, A,  6, 23, 0x04881d05);
-  OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
-  OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
-  OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
-  OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
-
-  /* Round 4.  */
-  OP (FI, A, B, C, D,  0,  6, 0xf4292244);
-  OP (FI, D, A, B, C,  7, 10, 0x432aff97);
-  OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
-  OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
-  OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
-  OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
-  OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
-  OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
-  OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
-  OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
-  OP (FI, C, D, A, B,  6, 15, 0xa3014314);
-  OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
-  OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
-  OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
-  OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
-  OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
-
-  /* Put checksum in context given as argument.  */
-  ctx->A += A;
-  ctx->B += B;
-  ctx->C += C;
-  ctx->D += D;
-}
-
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-static void
-md5_write( void *context, const void *inbuf_arg , grub_size_t inlen)
-{
-  const unsigned char *inbuf = inbuf_arg;
-  MD5_CONTEXT *hd = context;
-
-  if( hd->count == 64 )  /* flush the buffer */
-  {
-    transform( hd, hd->buf );
-    //      _gcry_burn_stack (80+6*sizeof(void*));
-    hd->count = 0;
-    hd->nblocks++;
-  }
-  if( !inbuf )
-    return;
-
-  if( hd->count )
-  {
-    for( ; inlen && hd->count < 64; inlen-- )
-      hd->buf[hd->count++] = *inbuf++;
-    md5_write( hd, NULL, 0 );
-    if( !inlen )
-      return;
-  }
-  //  _gcry_burn_stack (80+6*sizeof(void*));
-
-  while( inlen >= 64 ) 
-  {
-    transform( hd, inbuf );
-    hd->count = 0;
-    hd->nblocks++;
-    inlen -= 64;
-    inbuf += 64;
-  }
-  for( ; inlen && hd->count < 64; inlen-- )
-    hd->buf[hd->count++] = *inbuf++;
-
-}
-
-
-
-/* The routine final terminates the message-digest computation and
- * ends with the desired message digest in mdContext->digest[0...15].
- * The handle is prepared for a new MD5 cycle.
- * Returns 16 grub_uint8_ts representing the digest.
- */
-static void
-md5_final( void *context)
-{
-  MD5_CONTEXT *hd = context;
-  grub_uint32_t t, msb, lsb;
-  grub_uint32_t *p;
-
-  md5_write(hd, NULL, 0); /* flush */;
-
-  t = hd->nblocks;
-  /* multiply by 64 to make a grub_uint8_t count */
-  lsb = t << 6;
-  msb = t >> 26;
-  /* add the count */
-  t = lsb;
-  if( (lsb += hd->count) < t )
-    msb++;
-  /* multiply by 8 to make a bit count */
-  t = lsb;
-  lsb <<= 3;
-  msb <<= 3;
-  msb |= t >> 29;
-
-  if( hd->count < 56 )  /* enough room */
-  {
-    hd->buf[hd->count++] = 0x80; /* pad */
-    while( hd->count < 56 )
-      hd->buf[hd->count++] = 0;  /* pad */
-  }
-  else  /* need one extra block */
-  {
-    hd->buf[hd->count++] = 0x80; /* pad character */
-    while( hd->count < 64 )
-      hd->buf[hd->count++] = 0;
-    md5_write(hd, NULL, 0);  /* flush */;
-    grub_memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
-  }
-  /* append the 64 bit count */
-  hd->buf[56] = lsb       ;
-  hd->buf[57] = lsb >>  8;
-  hd->buf[58] = lsb >> 16;
-  hd->buf[59] = lsb >> 24;
-  hd->buf[60] = msb       ;
-  hd->buf[61] = msb >>  8;
-  hd->buf[62] = msb >> 16;
-  hd->buf[63] = msb >> 24;
-  transform( hd, hd->buf );
-  //  _gcry_burn_stack (80+6*sizeof(void*));
-
-  p = (grub_uint32_t *) hd->buf;
-#define X(a) do { *p = grub_le_to_cpu32 (hd->a); p++; } while (0)
-  X(A);
-  X(B);
-  X(C);
-  X(D);
-#undef X
-
-}
-
-/**
- * GRUB2 Crypto Interface
- * Written by Michael Gorven
- */
-static grub_err_t
-md5 (const char *in, grub_size_t insize, char *out)
-{
-  MD5_CONTEXT hd;
-
-  md5_init (&hd);
-  md5_write (&hd, in, insize);
-  md5_final (&hd);
-  grub_memcpy (out, hd.buf, 16);
-
-  return GRUB_ERR_NONE;
-}
-
 static grub_err_t
 grub_cmd_xnu_uuid (grub_command_t cmd __attribute__ ((unused)),
                   int argc, char **args)
 {
-  struct tohash hashme;
-  grub_uint8_t xnu_uuid[16];
+  grub_uint64_t serial;
+  grub_uint8_t *xnu_uuid;
   char uuid_string[sizeof ("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
   char *ptr;
+  grub_uint8_t ctx[GRUB_MD_MD5->contextsize];
 
   if (argc < 1)
     return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required");
 
-  hashme.serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
-  grub_memcpy (hashme.prefix, hash_prefix, sizeof (hashme.prefix));
-
-  md5 ((char *) &hashme, sizeof (hashme), (char *) xnu_uuid);
+  serial = grub_cpu_to_be64 (grub_strtoull (args[0], 0, 16));
+
+  GRUB_MD_MD5->init (&ctx);
+  GRUB_MD_MD5->write (&ctx, hash_prefix, sizeof (hash_prefix));
+  GRUB_MD_MD5->write (&ctx, &serial, sizeof (serial));
+  GRUB_MD_MD5->final (&ctx);
+  xnu_uuid = GRUB_MD_MD5->read (&ctx);
+
   grub_sprintf (uuid_string,
                
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
                (unsigned int) xnu_uuid[0], (unsigned int) xnu_uuid[1],

=== modified file 'conf/common.rmk'
--- conf/common.rmk     2009-11-11 00:23:29 +0000
+++ conf/common.rmk     2009-11-16 10:18:04 +0000
@@ -621,3 +621,29 @@
 setjmp_mod_SOURCES = lib/$(target_cpu)/setjmp.S
 setjmp_mod_ASFLAGS = $(COMMON_ASFLAGS)
 setjmp_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += crypto.mod
+crypto_mod_SOURCES = lib/crypto.c
+crypto_mod_CFLAGS = $(COMMON_CFLAGS)
+crypto_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += devmapper.mod
+devmapper_mod_SOURCES = disk/devmapper.c
+devmapper_mod_CFLAGS = $(COMMON_CFLAGS)
+devmapper_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+pkglib_MODULES += pbkdf2.mod
+pbkdf2_mod_SOURCES = lib/pbkdf2.c
+pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS)
+pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For password_pbkdf2.mod.
+pkglib_MODULES += password_pbkdf2.mod
+password_pbkdf2_mod_SOURCES = commands/password_pbkdf2.c
+password_pbkdf2_mod_CFLAGS = $(COMMON_CFLAGS)
+password_pbkdf2_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+bin_UTILITIES += grub-pbkdf2
+grub_pbkdf2_SOURCES = util/grub-pbkdf2.c lib/crypto.c gcry/cipher/sha512.c 
lib/pbkdf2.c util/misc.c kern/err.c
+
+include $(srcdir)/conf/gcry.mk

=== modified file 'conf/i386-coreboot.rmk'
--- conf/i386-coreboot.rmk      2009-11-12 12:23:11 +0000
+++ conf/i386-coreboot.rmk      2009-11-16 09:59:06 +0000
@@ -130,7 +130,7 @@
        kern/partition.c kern/reader.c kern/term.c                      \
        kern/rescue_reader.c kern/rescue_parser.c                       \
        lib/arg.c normal/cmdline.c normal/misc.c                        \
-       normal/handler.c normal/auth.c normal/autofs.c                  \
+       normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c             
        \
        normal/completion.c normal/datetime.c normal/main.c             \
        normal/menu_text.c                                              \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \

=== modified file 'conf/i386-efi.rmk'
--- conf/i386-efi.rmk   2009-10-29 10:03:13 +0000
+++ conf/i386-efi.rmk   2009-11-16 09:59:06 +0000
@@ -57,7 +57,7 @@
        kern/partition.c kern/reader.c kern/term.c                      \
        kern/rescue_reader.c kern/rescue_parser.c                       \
        lib/arg.c normal/cmdline.c normal/command.c normal/datetime.c   \
-       normal/auth.c normal/autofs.c                                   \
+       normal/auth.c lib/crypto.c normal/autofs.c                              
        \
        normal/completion.c normal/context.c normal/main.c              \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/menu_text.c                                              \

=== modified file 'conf/i386-ieee1275.rmk'
--- conf/i386-ieee1275.rmk      2009-11-13 13:03:47 +0000
+++ conf/i386-ieee1275.rmk      2009-11-16 09:59:06 +0000
@@ -85,7 +85,7 @@
        kern/partition.c kern/reader.c kern/term.c                      \
        kern/rescue_reader.c kern/rescue_parser.c                       \
        lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c      \
-       normal/handler.c normal/auth.c normal/autofs.c                  \
+       normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c             
        \
        normal/completion.c normal/main.c normal/menu_text.c            \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/color.c                                                  \

=== modified file 'conf/i386-pc.rmk'
--- conf/i386-pc.rmk    2009-11-12 12:23:11 +0000
+++ conf/i386-pc.rmk    2009-11-16 09:59:06 +0000
@@ -123,7 +123,7 @@
        commands/search.c commands/blocklist.c commands/hexdump.c       \
        lib/hexdump.c commands/i386/pc/halt.c commands/reboot.c         \
        lib/envblk.c commands/loadenv.c                                 \
-       commands/gptsync.c commands/probe.c commands/xnu_uuid.c         \
+       commands/gptsync.c commands/probe.c             \
        commands/i386/cpuid.c   \
        commands/password.c commands/keystatus.c                        \
        disk/host.c disk/loopback.c disk/scsi.c                         \
@@ -137,7 +137,7 @@
        kern/partition.c kern/reader.c kern/term.c                      \
        kern/rescue_reader.c kern/rescue_parser.c                       \
        lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c      \
-       normal/handler.c normal/auth.c normal/autofs.c                          
\
+       normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c             
                \
        normal/completion.c normal/main.c normal/color.c                \
        normal/menu.c normal/menu_entry.c normal/menu_viewer.c          \
        normal/menu_text.c                                              \

=== modified file 'conf/powerpc-ieee1275.rmk'
--- conf/powerpc-ieee1275.rmk   2009-10-29 10:03:13 +0000
+++ conf/powerpc-ieee1275.rmk   2009-11-16 09:59:06 +0000
@@ -65,7 +65,7 @@
        kern/command.c kern/corecmd.c commands/extcmd.c                 \
        lib/arg.c normal/cmdline.c normal/datetime.c                    \
        normal/completion.c normal/misc.c                               \
-       normal/handler.c normal/auth.c normal/autofs.c normal/main.c    \
+       normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c 
normal/main.c       \
        normal/menu.c                                                   \
        normal/menu_text.c                                              \
        normal/menu_entry.c normal/menu_viewer.c                        \

=== modified file 'conf/sparc64-ieee1275.rmk'
--- conf/sparc64-ieee1275.rmk   2009-10-29 10:03:13 +0000
+++ conf/sparc64-ieee1275.rmk   2009-11-16 09:59:06 +0000
@@ -123,7 +123,7 @@
        kern/command.c kern/corecmd.c commands/extcmd.c                 \
        lib/arg.c normal/cmdline.c normal/datetime.c                    \
        normal/completion.c normal/misc.c                               \
-       normal/handler.c normal/auth.c normal/autofs.c normal/main.c    \
+       normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c 
normal/main.c       \
        normal/menu.c                                                   \
        normal/menu_text.c                                              \
        normal/menu_entry.c normal/menu_viewer.c                        \

=== modified file 'conf/x86_64-efi.rmk'
--- conf/x86_64-efi.rmk 2009-10-29 10:03:13 +0000
+++ conf/x86_64-efi.rmk 2009-11-16 09:59:06 +0000
@@ -53,7 +53,7 @@
        kern/command.c kern/corecmd.c commands/extcmd.c kern/file.c     \
        kern/fs.c commands/boot.c kern/main.c kern/misc.c kern/parser.c \
        kern/partition.c kern/readerescue.c kern/term.c                 \
-       lib/arg.c normal/cmdline.c normal/misc.c normal/auth.c          \
+       lib/arg.c normal/cmdline.c normal/misc.c normal/auth.c lib/crypto.c     
        \
        normal/autofs.c \
        normal/completion.c normal/datetime.c normal/context.c          \
        normal/main.c           \

=== added file 'disk/devmapper.c'
--- disk/devmapper.c    1970-01-01 00:00:00 +0000
+++ disk/devmapper.c    2009-11-13 00:26:40 +0000
@@ -0,0 +1,414 @@
+/*
+ * devmapper.c - Device mapper (w/ crypto support)
+ *
+ * Copyright (C) 2007 Simon Peter <address@hidden>
+ * Thanks to Raoul Boenisch <address@hidden> for the initial idea.
+ */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2003,2007  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/err.h>
+#include <grub/dl.h>
+#include <grub/normal.h>
+#include <grub/extcmd.h>
+#include <grub/disk.h>
+#include <grub/crypto.h>
+
+#define DEFAULT_HASH   "ripemd160"
+#define DEFAULT_CIPHER "aes-cbc"
+#define MAX_KEYSIZE    64
+#define MAX_PASSPHRASE 256
+
+#define MIN(a, b)      (a < b ? a : b)
+
+struct grub_crypto
+{
+  char *devname, *source_devname;
+  int has_partitions;
+  grub_crypto_cipher_handle_t cipher;
+  grub_disk_t srcdisk;
+  int keysize;
+
+  struct grub_crypto *next;
+};
+
+typedef struct grub_crypto *grub_crypto_t;
+
+struct crypto_private
+{
+  grub_crypto_t crypto;
+  grub_disk_t srcdisk;
+};
+
+typedef struct crypto_private *crypto_private_t;
+
+static grub_crypto_t crypto_list = NULL;
+
+/* Delete a registered crypto device. */
+static grub_err_t
+delete_crypto (const char *name)
+{
+  grub_crypto_t dev, *prev;
+
+  /* Search for the device */
+  for (dev = crypto_list, prev = &crypto_list; dev;
+       prev = &dev->next, dev = dev->next)
+    if (grub_strcmp (dev->devname, name) == 0)
+      break;
+
+  if (!dev)
+    return grub_error (GRUB_ERR_BAD_DEVICE, "Device not found");
+
+  /* Remove the device from the list */
+  *prev = dev->next;
+  grub_free (dev->devname);
+  grub_free (dev->source_devname);
+  grub_crypto_cipher_close (dev->cipher);
+  grub_free (dev);
+
+  return GRUB_ERR_NONE;
+}
+
+/* Hashes a passphrase into a key and stores it with cipher. */
+static gcry_err_code_t
+set_passphrase (grub_crypto_t dev, const gcry_md_spec_t *hashparams,
+               const char *passphrase)
+{
+  grub_uint8_t hash[MAX_KEYSIZE * 2], *key = hash;
+  char *p;
+  unsigned int round, i, size = dev->keysize;
+  unsigned int len;
+
+  /* Need no passphrase if there's no key */
+  if (size == 0)
+    return GPG_ERR_INV_KEYLEN;
+
+  /* Hack to support the "none" hash */
+  if (hashparams)
+    len = hashparams->mdlen;
+  else
+    len = grub_strlen (passphrase);
+
+  if (size > MAX_KEYSIZE || len > MAX_KEYSIZE)
+    return GPG_ERR_INV_KEYLEN;
+
+  p = grub_malloc (grub_strlen (passphrase) + 2 + size / len);
+  if (!p)
+    return grub_errno;
+
+  for (round = 0; size; round++, key += len, size -= len)
+    {
+      /* hack from hashalot to avoid null bytes in key */
+      for (i = 0; i < round; i++)
+       p[i] = 'A';
+
+      grub_strcpy (p + i, passphrase);
+
+      if (len > size)
+       len = size;
+
+      grub_crypto_hash (hashparams, key, p, grub_strlen (p));
+    }
+
+  return grub_crypto_cipher_set_key (dev->cipher, hash, size);
+}
+
+/***** GRUB command line interface *****************************************/
+
+
+static const struct grub_arg_option options[] = {
+  {"delete", 'd', 0, "delete the crypto device entry", 0, ARG_TYPE_NONE},
+  {"partitions", 'p', 0, "set that the device has partitions", 0,
+   ARG_TYPE_NONE},
+  {"cipher", 'c', 0, "set cipher (default=" DEFAULT_CIPHER ")", 0,
+   ARG_TYPE_STRING},
+  {"hash", 'h', 0, "set hash function (default=" DEFAULT_HASH ")", 0,
+   ARG_TYPE_STRING},
+  {"passphrase", 'P', 0, "set decryption passphrase", 0, ARG_TYPE_STRING},
+  {"keysize", 'k', 0, "set key size (default is cipher specific)", 0,
+   ARG_TYPE_INT},
+  {0, 0, 0, 0, 0, 0}
+};
+
+static grub_err_t
+grub_cmd_devmap (grub_extcmd_t cmd, int argc, char **args)
+{
+  grub_disk_t disk;
+  grub_crypto_t newdev;
+  const char *cipher, *hash;
+  const gcry_md_spec_t *hashparams;
+  grub_err_t err = GRUB_ERR_NONE;
+  char *passphrase = "";
+  /* char cmdphrase[MAX_PASSPHRASE]; */
+  const gcry_cipher_spec_t *ciph;
+  struct grub_arg_list *state = cmd->state;
+
+  if (argc < 1)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Device name required");
+
+  /* Check whether delete is requested */
+  if (state[0].set)
+    return delete_crypto (args[0]);
+
+  if (argc < 2)
+    return grub_error (GRUB_ERR_BAD_ARGUMENT, "Source device name required");
+
+  /*** Create device is requested ***/
+
+  /* Choke on already existing devices */
+  for (newdev = crypto_list; newdev != NULL; newdev = newdev->next)
+    if (grub_strcmp (newdev->devname, args[0]) == 0)
+      return grub_error (GRUB_ERR_BAD_ARGUMENT, "Device already exists");
+
+  /* Check whether source device can be opened */
+  disk = grub_disk_open (args[1]);
+  if (!disk)
+    return grub_errno;
+  grub_disk_close (disk);
+
+  /* Parse remaining options */
+  if (state[2].set)
+    cipher = state[2].arg;
+  else
+    cipher = DEFAULT_CIPHER;
+  if (state[3].set)
+    hash = state[3].arg;
+  else
+    hash = DEFAULT_HASH;
+
+  /* Create new device entry */
+  newdev = grub_malloc (sizeof (struct grub_crypto));
+  if (!newdev)
+    return grub_errno;
+  newdev->devname = grub_strdup (args[0]);
+  if (!newdev->devname)
+    {
+      grub_free (newdev);
+      return grub_errno;
+    }
+  newdev->source_devname = grub_strdup (args[1]);
+  if (!newdev->source_devname)
+    {
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      return grub_errno;
+    }
+  newdev->has_partitions = state[1].set;
+  ciph = grub_crypto_lookup_cipher_by_name (cipher);
+  if (!ciph)
+    {
+      grub_free (newdev->source_devname);
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      return grub_error (GRUB_ERR_CIPHER_NOT_FOUND, "Unknown cipher %s", hash);
+    }
+  newdev->cipher = grub_crypto_cipher_open (ciph);
+  if (!newdev->cipher)
+    {
+      grub_free (newdev->source_devname);
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      return grub_errno;
+    }
+  hashparams = grub_crypto_lookup_md_by_name (hash);
+  if (!hashparams)
+    {
+      grub_free (newdev->source_devname);
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      grub_crypto_cipher_close (newdev->cipher);
+      return grub_error (GRUB_ERR_CIPHER_NOT_FOUND, "Unknown digest %s", hash);
+    }
+  newdev->srcdisk = NULL;
+  if (state[5].set)
+    newdev->keysize = grub_strtoul (state[5].arg, NULL, 10);
+  else
+    newdev->keysize = 16;
+
+  /* Get passphrase */
+  if (state[4].set)            /* Passphrase supplied on commandline */
+    passphrase = state[4].arg;
+  else
+    {
+#if 1
+      return 0;
+#else
+      if (grub_strcmp (cipher, "none"))
+       {
+         grub_cmdline_get ("Passphrase: ", cmdphrase, MAX_PASSPHRASE, '*',
+                           0);
+         passphrase = cmdphrase;
+       }
+#endif
+    }
+  err = set_passphrase (newdev, hashparams, passphrase);
+  if (err)
+    {
+      grub_crypto_cipher_close (newdev->cipher);
+      grub_free (newdev->source_devname);
+      grub_free (newdev->devname);
+      grub_free (newdev);
+      return err;
+    }
+
+  /* Add new entry to list and return */
+  newdev->next = crypto_list;
+  crypto_list = newdev;
+
+  /* Error conditions */
+  return GRUB_ERR_NONE;
+}
+
+/***** GRUB disk device interface ******************************************/
+
+static int
+grub_crypto_iterate (int (*hook) (const char *name))
+{
+  grub_crypto_t i;
+
+  for (i = crypto_list; i != NULL; i = i->next)
+    if (hook (i->devname))
+      return 1;
+
+  return 0;
+}
+
+static grub_err_t
+grub_crypto_open (const char *name, grub_disk_t disk)
+{
+  grub_crypto_t dev;
+  crypto_private_t private;
+
+  for (dev = crypto_list; dev != NULL; dev = dev->next)
+    if (grub_strcmp (dev->devname, name) == 0)
+      break;
+
+  if (!dev)
+    return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device");
+
+  /* Setup crypto private structure */
+  if (!(private = grub_malloc (sizeof (struct crypto_private))))
+    return grub_errno;
+  private->crypto = dev;
+
+  /* Open underlying device */
+  private->srcdisk = grub_disk_open (dev->source_devname);
+  if (!private->srcdisk)
+    {
+      return grub_errno;
+    }
+
+  /* Populate requested disk */
+  disk->total_sectors = grub_disk_get_size (private->srcdisk);
+  disk->id = (int) dev;
+  disk->has_partitions = dev->has_partitions;
+  disk->data = private;
+
+  return 0;
+}
+
+static void
+grub_crypto_close (grub_disk_t disk)
+{
+  crypto_private_t private = (crypto_private_t) disk->data;
+
+  grub_disk_close (private->srcdisk);
+  grub_free (private);
+}
+
+static grub_err_t
+grub_crypto_read (grub_disk_t disk, grub_disk_addr_t sector,
+                 grub_size_t size, char *buf)
+{
+  crypto_private_t private = (crypto_private_t) disk->data;
+  grub_err_t err;
+  grub_crypto_cipher_handle_t cipher = private->crypto->cipher;
+  grub_size_t i;
+
+  /* Read sectors from underlying disk */
+  err =
+    grub_disk_read (private->srcdisk, sector, 0,
+                   size << GRUB_DISK_SECTOR_BITS, buf);
+  if (err)
+    return err;
+
+  /* Decrypt sectors */
+  for (i = 0; i < size; i++)
+    {
+      grub_disk_addr_t s = grub_cpu_to_le64 (sector + i);
+      grub_uint8_t iv[cipher->cipher->blocksize];
+      gcry_err_code_t gcry_err;
+
+      /* Set IV from raw sector number (plain mode) */
+      grub_memset (iv, 0, cipher->cipher->blocksize);
+      grub_memcpy (iv, &s,
+                  MIN (sizeof (grub_disk_addr_t),
+                       cipher->cipher->blocksize));
+
+      gcry_err = grub_crypto_cbc_decrypt (cipher,
+                                         buf + (i << GRUB_DISK_SECTOR_BITS),
+                                         buf + (i << GRUB_DISK_SECTOR_BITS),
+                                         GRUB_DISK_SECTOR_SIZE, iv);
+      if (gcry_err)
+       return grub_crypto_gcry_error (gcry_err);
+    }
+
+  return 0;
+}
+
+static grub_err_t
+grub_crypto_write (grub_disk_t disk __attribute ((unused)),
+                  grub_disk_addr_t sector __attribute ((unused)),
+                  grub_size_t size __attribute ((unused)),
+                  const char *buf __attribute ((unused)))
+{
+  return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+static struct grub_disk_dev grub_crypto_dev = {
+  .name = "crypto",
+  .id = GRUB_DISK_DEVICE_DEVMAP_ID,
+  .iterate = grub_crypto_iterate,
+  .open = grub_crypto_open,
+  .close = grub_crypto_close,
+  .read = grub_crypto_read,
+  .write = grub_crypto_write,
+  .next = 0
+};
+
+/***** GRUB module (de-)initialization *************************************/
+
+static grub_extcmd_t cmd;
+
+GRUB_MOD_INIT (devmapper)
+{
+  cmd = grub_register_extcmd ("devmap", grub_cmd_devmap, 
GRUB_COMMAND_FLAG_BOTH,
+                             "devmap [OPTIONS...] [DEVICE] [SRC-DEV]",
+                             "Map one device onto another (w/ cryptography 
support).",
+                             options);
+  grub_disk_dev_register (&grub_crypto_dev);
+}
+
+GRUB_MOD_FINI (devmapper)
+{
+  grub_unregister_extcmd (cmd);
+  grub_disk_dev_unregister (&grub_crypto_dev);
+}

=== added file 'import_gcry.py'
--- import_gcry.py      1970-01-01 00:00:00 +0000
+++ import_gcry.py      2009-11-15 11:05:38 +0000
@@ -0,0 +1,286 @@
+#*
+#*  GRUB  --  GRand Unified Bootloader
+#*  Copyright (C) 2009  Free Software Foundation, Inc.
+#*
+#*  GRUB is free software: you can redistribute it and/or modify
+#*  it under the terms of the GNU General Public License as published by
+#*  the Free Software Foundation, either version 3 of the License, or
+#*  (at your option) any later version.
+#*
+#*  GRUB is distributed in the hope that it will be useful,
+#*  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#*  GNU General Public License for more details.
+#*
+#*  You should have received a copy of the GNU General Public License
+#*  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+#*
+
+import re
+import sys
+import os
+import datetime
+
+if len (sys.argv) < 3:
+    print ("Usage: %s SOURCE DESTINATION" % sys.argv[0])
+    exit (0)
+indir = sys.argv[1]
+outdir = sys.argv[2]
+
+basedir = os.path.join (outdir, "gcry")
+try:
+    os.makedirs (basedir)
+except:
+    print ("WARNING: %s already exists" % basedir)
+cipher_dir_in = os.path.join (indir, "cipher")
+cipher_dir_out = os.path.join (basedir, "cipher")
+try:
+    os.makedirs (cipher_dir_out)
+except:
+    print ("WARNING: %s already exists" % cipher_dir_out)
+
+cipher_files = os.listdir (cipher_dir_in)
+conf = open (os.path.join (outdir, "conf", "gcry.rmk"), "w")
+conf.write ("# -*- makefile -*-\n\n")
+chlog = ""
+
+# Strictly speaking CRC32/CRC24 work on bytes so this value should be 1
+# But libgcrypt uses 64. Let's keep the value for compatibility. Since
+# noone uses CRC24/CRC32 for HMAC this is no problem
+mdblocksizes = {"_gcry_digest_spec_crc32" : 64,
+                "_gcry_digest_spec_crc32_rfc1510" : 64,
+                "_gcry_digest_spec_crc24_rfc2440" : 64,
+                "_gcry_digest_spec_md4" : 64,
+                "_gcry_digest_spec_md5" : 64,
+                "_gcry_digest_spec_rmd160" : 64,
+                "_gcry_digest_spec_sha1" : 64,
+                "_gcry_digest_spec_sha224" : 64,
+                "_gcry_digest_spec_sha256" : 64,
+                "_gcry_digest_spec_sha384" : 128,
+                "_gcry_digest_spec_sha512" : 128,
+                "_gcry_digest_spec_tiger" : 64,
+                "_gcry_digest_spec_whirlpool" : 64}
+
+for cipher_file in cipher_files:
+    infile = os.path.join (cipher_dir_in, cipher_file)
+    outfile = os.path.join (cipher_dir_out, cipher_file)
+    if cipher_file == "ChangeLog":
+        continue
+    chlognew = "       * %s" % cipher_file
+    nch = False
+    if re.match (".*\.[ch]$", cipher_file):
+        isc = re.match (".*\.c$", cipher_file)
+        f = open (infile, "r")
+        fw = open (outfile, "w")
+        fw.write ("/* This file was automatically imported with \n")
+        fw.write ("   import_gcry.py. Please don't modify it */\n");
+        ciphernames = []
+        mdnames = []
+        hold = False
+        skip = False
+        skip2 = False
+        ismd = False
+        iscomma = False
+        for line in f:
+            if skip:
+                if line[0] == "}":
+                    skip = False
+                continue
+            if skip2:
+                if not re.search (" *};", line) is None:
+                    skip2 = False
+                continue
+            if ismd:
+                if not re.search (" *};", line) is None:
+                    if not mdblocksizes.has_key (mdname):
+                        print ("ERROR: Unknown digest blocksize: %s\n" % 
mdname)
+                        exit (1)
+                    if not iscomma:
+                        fw.write ("    ,\n")
+                    fw.write ("    .blocksize = %s\n" % mdblocksizes [mdname])
+                    ismd = False
+                iscomma = not re.search (",$", line) is None
+            if hold:
+                hold = False
+                # We're optimising for size.
+                if not re.match 
("(run_selftests|selftest|_gcry_aes_c.._..c|_gcry_[a-z0-9]*_hash_buffer)", 
line) is None:
+                    skip = True
+                    fname = re.match ("[a-zA-Z0-9_]*", line).group ()
+                    chmsg = "(%s): Removed." % fname
+                    if nch:
+                        chlognew = "%s\n       %s" % (chlognew, chmsg)
+                    else:
+                        chlognew = "%s %s" % (chlognew, chmsg)
+                        nch = True
+                    continue
+                else:
+                    fw.write (holdline)
+            m = re.match ("#include <.*>", line)
+            if not m is None:
+                chmsg = "Removed including of %s" % \
+                m.group () [len ("#include <"):len (m.group ()) - 1]
+                if nch:
+                    chlognew = "%s\n   %s" % (chlognew, chmsg)
+                else:
+                    chlognew = "%s: %s" % (chlognew, chmsg)
+                    nch = True
+                continue
+            m = re.match ("gcry_cipher_spec_t", line)
+            if isc and not m is None:
+                ciphername = line [len ("gcry_cipher_spec_t"):].strip ()
+                ciphername = re.match("[a-zA-Z0-9_]*",ciphername).group ()
+                ciphernames.append (ciphername)
+            m = re.match ("gcry_md_spec_t", line)
+            if isc and not m is None:
+                assert (not ismd)
+                mdname = line [len ("gcry_md_spec_t"):].strip ()
+                mdname = re.match("[a-zA-Z0-9_]*",mdname).group ()
+                mdnames.append (mdname)
+                ismd = True
+            m = re.match ("static const char \*selftest.*;$", line)
+            if not m is None:
+                fname = line[len ("static const char \*"):]
+                fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+                chmsg = "(%s): Removed declaration." % fname
+                if nch:
+                    chlognew = "%s\n   %s" % (chlognew, chmsg)
+                else:
+                    chlognew = "%s %s" % (chlognew, chmsg)
+                    nch = True
+                continue
+            m = re.match ("(static const char( |)\*|static 
gpg_err_code_t|void)$", line)
+            if not m is None:
+                hold = True
+                holdline = line
+                continue
+            m = re.match ("cipher_extra_spec_t", line)
+            if isc and not m is None:
+                skip2 = True
+                fname = line[len ("cipher_extra_spec_t "):]
+                fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+                chmsg = "(%s): Removed." % fname
+                if nch:
+                    chlognew = "%s\n   %s" % (chlognew, chmsg)
+                else:
+                    chlognew = "%s %s" % (chlognew, chmsg)
+                    nch = True
+                continue
+            m = re.match ("md_extra_spec_t", line)
+            if isc and not m is None:
+                skip2 = True
+                fname = line[len ("md_extra_spec_t "):]
+                fname = re.match ("[a-zA-Z0-9_]*", fname).group ()
+                chmsg = "(%s): Removed." % fname
+                if nch:
+                    chlognew = "%s\n   %s" % (chlognew, chmsg)
+                else:
+                    chlognew = "%s %s" % (chlognew, chmsg)
+                    nch = True
+                continue
+            fw.write (line)
+        if len (ciphernames) > 0 or len (mdnames) > 0:
+            modname = cipher_file [0:len(cipher_file) - 2]
+            if re.match (".*-glue$", modname):
+                modfiles = "gcry/cipher/%s gcry/cipher/%s" \
+                    % (cipher_file, cipher_file.replace ("-glue.c", ".c"))
+                modname = modname.replace ("-glue", "")
+            else:
+                modfiles = "gcry/cipher/%s" % cipher_file
+            modname = "gcry_%s" % modname
+            chmsg = "(GRUB_MOD_INIT(%s)): New function\n" % modname
+            if nch:
+                chlognew = "%s\n       %s" % (chlognew, chmsg)
+            else:
+                chlognew = "%s%s" % (chlognew, chmsg)
+                nch = True
+            fw.write ("\n\nGRUB_MOD_INIT(%s)\n" % modname)
+            fw.write ("{\n")
+            for ciphername in ciphernames:
+                chmsg = "Register cipher %s" % ciphername
+                chlognew = "%s\n       %s" % (chlognew, chmsg)
+                fw.write ("  grub_cipher_register (&%s);\n" % ciphername)
+            for mdname in mdnames:
+                chmsg = "Register digest %s" % mdname
+                chlognew = "%s\n       %s" % (chlognew, chmsg)
+                fw.write ("  grub_md_register (&%s);\n" % mdname)
+            fw.write ("}")
+            chmsg = "(GRUB_MOD_FINI(%s)): New function\n" % modname
+            chlognew = "%s\n   %s" % (chlognew, chmsg)
+            fw.write ("\n\nGRUB_MOD_FINI(%s)\n" % modname)
+            fw.write ("{\n")
+            for ciphername in ciphernames:
+                chmsg = "Unregister cipher %s" % ciphername
+                chlognew = "%s\n       %s" % (chlognew, chmsg)
+                fw.write ("  grub_cipher_unregister (&%s);\n" % ciphername)
+            for mdname in mdnames:
+                chmsg = "Unregister MD %s" % mdname
+                chlognew = "%s\n       %s" % (chlognew, chmsg)
+                fw.write ("  grub_md_unregister (&%s);\n" % mdname)
+            fw.write ("}\n")
+            conf.write ("pkglib_MODULES += %s.mod\n" % modname)
+            conf.write ("%s_mod_SOURCES = %s\n" %\
+                            (modname, modfiles))
+            conf.write ("%s_mod_CFLAGS = $(COMMON_CFLAGS) 
-Wno-missing-field-initializers -Wno-error\n" % modname)
+            conf.write ("%s_mod_LDFLAGS = $(COMMON_LDFLAGS)\n\n" % modname)
+        elif isc and cipher_file != "camellia.c":
+            print ("WARNING: C file isn't a module: %s" % cipher_file)
+        f.close ()
+        fw.close ()
+        if nch:
+            chlog = "%s%s\n" % (chlog, chlognew)
+        continue
+    if re.match ("(Manifest|Makefile\.am)$", cipher_file):
+        chlog = "%s%sRemoved\n" % (chlog, chlognew)
+        continue
+    # Autogenerated files. Not even worth mentionning in ChangeLog
+    if re.match ("Makefile\.in$", cipher_file):
+        chlog = "%s%sRemoved\n" % (chlog, chlognew)
+        continue
+    chlog = "%s%sSkipped unknown file\n" % (chlog, chlognew)
+    print ("WARNING: unknown file %s" % cipher_file)
+
+outfile = os.path.join (cipher_dir_out, "types.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/types.h>\n")
+fw.write ("#include <grub/cipher_wrap.h>\n")
+chlog = "%s    * types.h: New file.\n" % chlog
+fw.close ()
+
+outfile = os.path.join (cipher_dir_out, "memory.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/cipher_wrap.h>\n")
+chlog = "%s    * memory.h: New file.\n" % chlog
+fw.close ()
+
+
+outfile = os.path.join (cipher_dir_out, "cipher.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/crypto.h>\n")
+fw.write ("#include <grub/cipher_wrap.h>\n")
+chlog = "%s    * cipher.h: Likewise.\n" % chlog
+fw.close ()
+
+outfile = os.path.join (cipher_dir_out, "g10lib.h")
+fw=open (outfile, "w")
+fw.write ("#include <grub/cipher_wrap.h>\n")
+chlog = "%s    * g10lib.h: Likewise.\n" % chlog
+fw.close ()
+
+infile = os.path.join (cipher_dir_in, "ChangeLog")
+outfile = os.path.join (cipher_dir_out, "ChangeLog")
+
+
+f=open (infile, "r")
+fw=open (outfile, "w")
+dt = datetime.date.today ()
+fw.write ("%04d-%02d-%02d  Automatic import tool\n" % \
+          (dt.year,dt.month, dt.day))
+fw.write ("\n")
+fw.write ("    Imported ciphers to GRUB\n")
+fw.write ("\n")
+fw.write (chlog)
+fw.write ("\n")
+for line in f:
+    fw.write (line)
+f.close ()
+fw.close ()

=== modified file 'include/grub/auth.h'
--- include/grub/auth.h 2009-08-24 23:55:06 +0000
+++ include/grub/auth.h 2009-11-15 22:33:12 +0000
@@ -15,7 +15,7 @@
  *  You should have received a copy of the GNU General Public License
  *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
  */
-#ifndef GRUB_AURH_HEADER
+#ifndef GRUB_AUTH_HEADER
 #define GRUB_AUTH_HEADER       1
 
 #include <grub/err.h>
@@ -26,11 +26,6 @@
                                                         string, len,   \
                                                         '*', 0, 0)
 
-/* Like strcmp but untimeable. Accepts NULL as second argument.  */
-int grub_auth_strcmp (const char *user_input, const char *template);
-/* Like strcmp but untimeable and ignores commas in needle.  */
-int grub_auth_strword (const char *haystack, const char *needle);
-
 typedef grub_err_t (*grub_auth_callback_t) (const char*, void *);
 
 grub_err_t grub_auth_register_authentication (const char *user,

=== added file 'include/grub/cipher_wrap.h'
--- include/grub/cipher_wrap.h  1970-01-01 00:00:00 +0000
+++ include/grub/cipher_wrap.h  2009-11-13 16:51:09 +0000
@@ -0,0 +1,84 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GRUB_GCRY_WRAP_HEADER
+#define GRUB_GCRY_WRAP_HEADER 1
+
+#include <grub/types.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+
+#define __GNU_LIBRARY__
+
+#define DIM ARRAY_SIZE
+
+typedef grub_uint64_t u64;
+typedef grub_uint32_t u32;
+typedef grub_uint16_t u16;
+typedef grub_uint8_t byte;
+typedef grub_size_t size_t;
+
+#define U64_C(c) (c ## ULL)
+
+#define _gcry_burn_stack grub_burn_stack
+#define log_error(fmt, args...) grub_dprintf ("crypto", fmt, ## args)
+
+
+#define PUBKEY_FLAG_NO_BLINDING    (1 << 0)
+
+#define CIPHER_INFO_NO_WEAK_KEY    1
+
+#define HAVE_U64_TYPEDEF 1
+
+typedef union {
+    int a;
+    short b;
+    char c[1];
+    long d;
+#ifdef HAVE_U64_TYPEDEF
+    u64 e;
+#endif
+    float f;
+    double g;
+} PROPERLY_ALIGNED_TYPE;
+
+#define gcry_assert(x) grub_assert_real(__FILE__, __LINE__, x)
+
+static inline void
+grub_assert_real (const char *file, int line, int cond)
+{
+  if (!cond)
+    grub_fatal ("Assertion failed at %s:%d\n", file, line);
+}
+
+/* Selftests are in separate modules.  */
+static inline char *
+selftest (void)
+{
+  return NULL;
+}
+
+static inline int
+fips_mode (void)
+{
+  return 0;
+}
+
+#endif

=== added file 'include/grub/crypto.h'
--- include/grub/crypto.h       1970-01-01 00:00:00 +0000
+++ include/grub/crypto.h       2009-11-16 08:31:32 +0000
@@ -0,0 +1,269 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ *                2007, 2008, 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* Contains elements based on gcrypt-module.h and gcrypt.h.in.
+   If it's changed please update this file.  */
+
+#ifndef GRUB_CRYPTO_HEADER
+#define GRUB_CRYPTO_HEADER 1
+
+#include <grub/symbol.h>
+#include <grub/types.h>
+#include <grub/err.h>
+/* For GRUB_ACCESS_DENIED.  */
+#include <grub/auth.h>
+
+typedef enum 
+  {
+    GPG_ERR_NO_ERROR,
+    GPG_ERR_BAD_MPI,
+    GPG_ERR_BAD_SECKEY,
+    GPG_ERR_BAD_SIGNATURE,
+    GPG_ERR_CIPHER_ALGO,
+    GPG_ERR_CONFLICT,
+    GPG_ERR_DECRYPT_FAILED,
+    GPG_ERR_DIGEST_ALGO,
+    GPG_ERR_GENERAL,
+    GPG_ERR_INTERNAL,
+    GPG_ERR_INV_ARG,
+    GPG_ERR_INV_CIPHER_MODE,
+    GPG_ERR_INV_FLAG,
+    GPG_ERR_INV_KEYLEN,
+    GPG_ERR_INV_OBJ,
+    GPG_ERR_INV_OP,
+    GPG_ERR_INV_SEXP,
+    GPG_ERR_INV_VALUE,
+    GPG_ERR_MISSING_VALUE,
+    GPG_ERR_NO_ENCRYPTION_SCHEME,
+    GPG_ERR_NO_OBJ,
+    GPG_ERR_NO_PRIME,
+    GPG_ERR_NO_SIGNATURE_SCHEME,
+    GPG_ERR_NOT_FOUND,
+    GPG_ERR_NOT_IMPLEMENTED,
+    GPG_ERR_NOT_SUPPORTED,
+    GPG_ERROR_CFLAGS,
+    GPG_ERR_PUBKEY_ALGO,
+    GPG_ERR_SELFTEST_FAILED,
+    GPG_ERR_TOO_SHORT,
+    GPG_ERR_UNSUPPORTED,
+    GPG_ERR_WEAK_KEY,
+    GPG_ERR_WRONG_KEY_USAGE,
+    GPG_ERR_WRONG_PUBKEY_ALGO,
+    GPG_ERR_OUT_OF_MEMORY
+  } gcry_err_code_t;
+#define gpg_err_code_t gcry_err_code_t
+#define gpg_error_t gcry_err_code_t
+
+enum gcry_cipher_modes 
+  {
+    GCRY_CIPHER_MODE_NONE   = 0,  /* Not yet specified. */
+    GCRY_CIPHER_MODE_ECB    = 1,  /* Electronic codebook. */
+    GCRY_CIPHER_MODE_CFB    = 2,  /* Cipher feedback. */
+    GCRY_CIPHER_MODE_CBC    = 3,  /* Cipher block chaining. */
+    GCRY_CIPHER_MODE_STREAM = 4,  /* Used with stream ciphers. */
+    GCRY_CIPHER_MODE_OFB    = 5,  /* Outer feedback. */
+    GCRY_CIPHER_MODE_CTR    = 6   /* Counter. */
+  };
+
+/* Type for the cipher_setkey function.  */
+typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c,
+                                                const unsigned char *key,
+                                                unsigned keylen);
+
+/* Type for the cipher_encrypt function.  */
+typedef void (*gcry_cipher_encrypt_t) (void *c,
+                                      unsigned char *outbuf,
+                                      const unsigned char *inbuf);
+
+/* Type for the cipher_decrypt function.  */
+typedef void (*gcry_cipher_decrypt_t) (void *c,
+                                      unsigned char *outbuf,
+                                      const unsigned char *inbuf);
+
+/* Type for the cipher_stencrypt function.  */
+typedef void (*gcry_cipher_stencrypt_t) (void *c,
+                                        unsigned char *outbuf,
+                                        const unsigned char *inbuf,
+                                        unsigned int n);
+
+/* Type for the cipher_stdecrypt function.  */
+typedef void (*gcry_cipher_stdecrypt_t) (void *c,
+                                        unsigned char *outbuf,
+                                        const unsigned char *inbuf,
+                                        unsigned int n);
+
+typedef struct gcry_cipher_oid_spec
+{
+  const char *oid;
+  int mode;
+} gcry_cipher_oid_spec_t;
+
+/* Module specification structure for ciphers.  */
+typedef struct gcry_cipher_spec
+{
+  const char *name;
+  const char **aliases;
+  gcry_cipher_oid_spec_t *oids;
+  grub_size_t blocksize;
+  grub_size_t keylen;
+  grub_size_t contextsize;
+  gcry_cipher_setkey_t setkey;
+  gcry_cipher_encrypt_t encrypt;
+  gcry_cipher_decrypt_t decrypt;
+  gcry_cipher_stencrypt_t stencrypt;
+  gcry_cipher_stdecrypt_t stdecrypt;
+  struct gcry_cipher_spec *next;
+} gcry_cipher_spec_t;
+
+/* Type for the md_init function.  */
+typedef void (*gcry_md_init_t) (void *c);
+
+/* Type for the md_write function.  */
+typedef void (*gcry_md_write_t) (void *c, const void *buf, grub_size_t nbytes);
+
+/* Type for the md_final function.  */
+typedef void (*gcry_md_final_t) (void *c);
+
+/* Type for the md_read function.  */
+typedef unsigned char *(*gcry_md_read_t) (void *c);
+
+typedef struct gcry_md_oid_spec
+{
+  const char *oidstring;
+} gcry_md_oid_spec_t;
+
+/* Module specification structure for message digests.  */
+typedef struct gcry_md_spec
+{
+  const char *name;
+  unsigned char *asnoid;
+  int asnlen;
+  gcry_md_oid_spec_t *oids;
+  grub_size_t mdlen;
+  gcry_md_init_t init;
+  gcry_md_write_t write;
+  gcry_md_final_t final;
+  gcry_md_read_t read;
+  grub_size_t contextsize; /* allocate this amount of context */
+  /* Block size, needed for HMAC.  */
+  grub_size_t blocksize;
+  struct gcry_md_spec *next;
+} gcry_md_spec_t;
+
+struct grub_crypto_cipher_handle
+{
+  const struct gcry_cipher_spec *cipher;
+  char ctx[0];
+};
+
+typedef struct grub_crypto_cipher_handle *grub_crypto_cipher_handle_t;
+
+struct grub_crypto_hmac_handle;
+
+const gcry_cipher_spec_t *
+grub_crypto_lookup_cipher_by_name (const char *name);
+
+grub_crypto_cipher_handle_t
+grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher);
+
+gcry_err_code_t
+grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
+                           const unsigned char *key,
+                           unsigned keylen);
+
+void
+grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher);
+
+void
+grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t 
size);
+
+gcry_err_code_t
+grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size);
+
+gcry_err_code_t
+grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size);
+gcry_err_code_t
+grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size,
+                        void *iv_in);
+gcry_err_code_t
+grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size,
+                        void *iv);
+void 
+grub_cipher_register (gcry_cipher_spec_t *cipher);
+void
+grub_cipher_unregister (gcry_cipher_spec_t *cipher);
+void 
+grub_md_register (gcry_md_spec_t *digest);
+void 
+grub_md_unregister (gcry_md_spec_t *cipher);
+void
+grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
+                 grub_size_t inlen);
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_name (const char *name);
+
+grub_err_t
+grub_crypto_gcry_error (gcry_err_code_t in);
+
+void grub_burn_stack (grub_size_t size);
+
+struct grub_crypto_hmac_handle *
+grub_crypto_hmac_init (const struct gcry_md_spec *md,
+                      const void *key, grub_size_t keylen);
+void
+grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
+                       grub_size_t datalen);
+gcry_err_code_t
+grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out);
+
+gcry_err_code_t
+grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
+                        const void *key, grub_size_t keylen,
+                        void *data, grub_size_t datalen, void *out);
+
+extern gcry_md_spec_t _gcry_digest_spec_md5;
+extern gcry_md_spec_t _gcry_digest_spec_sha1;
+extern gcry_md_spec_t _gcry_digest_spec_sha256;
+extern gcry_md_spec_t _gcry_digest_spec_sha512;
+#define GRUB_MD_MD5 ((const gcry_md_spec_t *) &_gcry_digest_spec_md5)
+#define GRUB_MD_SHA1 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha1)
+#define GRUB_MD_SHA256 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha256)
+#define GRUB_MD_SHA512 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha512)
+
+/* Implement PKCS#5 PBKDF2 as per RFC 2898.  The PRF to use is HMAC variant
+   of digest supplied by MD.  Inputs are the password P of length PLEN,
+   the salt S of length SLEN, the iteration counter C (> 0), and the
+   desired derived output length DKLEN.  Output buffer is DK which
+   must have room for at least DKLEN octets.  The output buffer will
+   be filled with the derived data.  */
+gcry_err_code_t
+grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
+                   const grub_uint8_t *P, grub_size_t Plen,
+                   const grub_uint8_t *S, grub_size_t Slen,
+                   unsigned int c,
+                   grub_uint8_t *DK, grub_size_t dkLen);
+
+int
+grub_crypto_memcmp (void *a, void *b, grub_size_t n);
+
+#endif

=== modified file 'include/grub/disk.h'
--- include/grub/disk.h 2009-07-16 15:36:43 +0000
+++ include/grub/disk.h 2009-11-13 00:24:44 +0000
@@ -42,6 +42,8 @@
     GRUB_DISK_DEVICE_PXE_ID,
     GRUB_DISK_DEVICE_SCSI_ID,
     GRUB_DISK_DEVICE_FILE_ID,
+    GRUB_DISK_DEVICE_LUKS_ID,
+    GRUB_DISK_DEVICE_DEVMAP_ID
   };
 
 struct grub_disk;

=== modified file 'include/grub/err.h'
--- include/grub/err.h  2009-08-24 23:55:06 +0000
+++ include/grub/err.h  2009-11-13 00:08:56 +0000
@@ -54,7 +54,8 @@
     GRUB_ERR_MENU,
     GRUB_ERR_TIMEOUT,
     GRUB_ERR_IO,
-    GRUB_ERR_ACCESS_DENIED
+    GRUB_ERR_ACCESS_DENIED,
+    GRUB_ERR_CIPHER_NOT_FOUND
   }
 grub_err_t;
 

=== added file 'lib/crypto.c'
--- lib/crypto.c        1970-01-01 00:00:00 +0000
+++ lib/crypto.c        2009-11-15 16:23:49 +0000
@@ -0,0 +1,387 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006
+ *                2007, 2008, 2009  Free Software Foundation, Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/crypto.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
+struct grub_crypto_hmac_handle
+{
+  const struct gcry_md_spec *md;
+  void *ctx;
+  void *opad;
+};
+
+static gcry_cipher_spec_t *grub_ciphers = NULL;
+static gcry_md_spec_t *grub_digests = NULL;
+
+/* Based on libgcrypt-1.4.4/src/misc.c.  */
+void
+grub_burn_stack (grub_size_t size)
+{
+  char buf[64];
+
+  grub_memset (buf, 0, sizeof (buf));
+  if (size > sizeof (buf))
+    grub_burn_stack (size - sizeof (buf));
+}
+
+
+void 
+grub_cipher_register (gcry_cipher_spec_t *cipher)
+{
+  cipher->next = grub_ciphers;
+  grub_ciphers = cipher;
+}
+
+void
+grub_cipher_unregister (gcry_cipher_spec_t *cipher)
+{
+  gcry_cipher_spec_t **ciph;
+  for (ciph = &grub_ciphers; *ciph; ciph = &((*ciph)->next))
+    if (*ciph == cipher)
+      *ciph = (*ciph)->next;
+}
+
+void 
+grub_md_register (gcry_md_spec_t *digest)
+{
+  digest->next = grub_digests;
+  grub_digests = digest;
+}
+
+void 
+grub_md_unregister (gcry_md_spec_t *cipher)
+{
+  gcry_md_spec_t **ciph;
+  for (ciph = &grub_digests; *ciph; ciph = &((*ciph)->next))
+    if (*ciph == cipher)
+      *ciph = (*ciph)->next;
+}
+
+void
+grub_crypto_hash (const gcry_md_spec_t *hash, void *out, const void *in,
+                 grub_size_t inlen)
+{
+  grub_uint8_t ctx[hash->contextsize];
+  hash->init (&ctx);
+  hash->write (&ctx, in, inlen);
+  hash->final (&ctx);
+  grub_memcpy (out, hash->read (&ctx), hash->mdlen);
+}
+
+const gcry_md_spec_t *
+grub_crypto_lookup_md_by_name (const char *name)
+{
+  const gcry_md_spec_t *md;
+  for (md = grub_digests; md; md = md->next)
+    if (grub_strcasecmp (name, md->name) == 0)
+      return md;
+  return NULL;
+}
+
+const gcry_cipher_spec_t *
+grub_crypto_lookup_cipher_by_name (const char *name)
+{
+  const gcry_cipher_spec_t *ciph;
+  for (ciph = grub_ciphers; ciph; ciph = ciph->next)
+    {
+      const char **alias;
+      if (grub_strcasecmp (name, ciph->name) == 0)
+       return ciph;
+      if (!ciph->aliases)
+       continue;
+      for (alias = ciph->aliases; *alias; alias++)
+       if (grub_strcasecmp (name, *alias) == 0)
+         return ciph;
+    }
+  return NULL;
+}
+
+
+grub_crypto_cipher_handle_t
+grub_crypto_cipher_open (const struct gcry_cipher_spec *cipher)
+{
+  grub_crypto_cipher_handle_t ret;
+  ret = grub_malloc (sizeof (*ret) + cipher->contextsize);
+  if (!ret)
+    return NULL;
+  ret->cipher = cipher;
+  return ret;
+}
+
+gcry_err_code_t
+grub_crypto_cipher_set_key (grub_crypto_cipher_handle_t cipher,
+                           const unsigned char *key,
+                           unsigned keylen)
+{
+  return cipher->cipher->setkey (cipher->ctx, key, keylen);
+}
+
+
+void
+grub_crypto_cipher_close (grub_crypto_cipher_handle_t cipher)
+{
+  grub_free (cipher);
+}
+
+
+void
+grub_crypto_xor (void *out, const void *in1, const void *in2, grub_size_t size)
+{
+  const grub_uint8_t *in1ptr = in1, *in2ptr = in2;
+  grub_uint8_t *outptr = out;
+  while (size--)
+    {
+      *outptr = *in1ptr ^ *in2ptr;
+      in1ptr++;
+      in2ptr++;
+      outptr++;
+    }
+}
+
+gcry_err_code_t
+grub_crypto_ecb_decrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size)
+{
+  grub_uint8_t *inptr, *outptr, *end;
+  if (!cipher->cipher->decrypt)
+    return GPG_ERR_NOT_SUPPORTED;
+  if (size % cipher->cipher->blocksize != 0)
+    return GPG_ERR_INV_ARG;
+  end = (grub_uint8_t *) in + size;
+  for (inptr = in, outptr = out; inptr < end;
+       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+    cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
+  return GPG_ERR_NO_ERROR;
+}
+
+gcry_err_code_t
+grub_crypto_ecb_encrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size)
+{
+  grub_uint8_t *inptr, *outptr, *end;
+  if (!cipher->cipher->encrypt)
+    return GPG_ERR_NOT_SUPPORTED;
+  if (size % cipher->cipher->blocksize != 0)
+    return GPG_ERR_INV_ARG;
+  end = (grub_uint8_t *) in + size;
+  for (inptr = in, outptr = out; inptr < end;
+       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+    cipher->cipher->encrypt (cipher->ctx, outptr, inptr);
+  return GPG_ERR_NO_ERROR;
+}
+
+gcry_err_code_t
+grub_crypto_cbc_encrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size,
+                        void *iv_in)
+{
+  grub_uint8_t *inptr, *outptr, *end;
+  void *iv;
+  if (!cipher->cipher->decrypt)
+    return GPG_ERR_NOT_SUPPORTED;
+  if (size % cipher->cipher->blocksize != 0)
+    return GPG_ERR_INV_ARG;
+  end = (grub_uint8_t *) in + size;
+  iv = iv_in;
+  for (inptr = in, outptr = out; inptr < end;
+       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+    {
+      grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize);
+      cipher->cipher->encrypt (cipher->ctx, outptr, outptr);
+      iv = outptr;
+    }
+  grub_memcpy (iv_in, iv, cipher->cipher->blocksize);
+  return GPG_ERR_NO_ERROR;
+}
+
+gcry_err_code_t
+grub_crypto_cbc_decrypt (grub_crypto_cipher_handle_t cipher,
+                        void *out, void *in, grub_size_t size,
+                        void *iv)
+{
+  grub_uint8_t *inptr, *outptr, *end;
+  grub_uint8_t ivt[cipher->cipher->blocksize];
+  if (!cipher->cipher->decrypt)
+    return GPG_ERR_NOT_SUPPORTED;
+  if (size % cipher->cipher->blocksize != 0)
+    return GPG_ERR_INV_ARG;
+  end = (grub_uint8_t *) in + size;
+  for (inptr = in, outptr = out; inptr < end;
+       inptr += cipher->cipher->blocksize, outptr += cipher->cipher->blocksize)
+    {
+      grub_memcpy (ivt, inptr, cipher->cipher->blocksize);
+      cipher->cipher->decrypt (cipher->ctx, outptr, inptr);
+      grub_crypto_xor (outptr, outptr, iv, cipher->cipher->blocksize);
+      grub_memcpy (iv, ivt, cipher->cipher->blocksize);
+    }
+  return GPG_ERR_NO_ERROR;
+}
+
+/* Based on gcry/cipher/md.c.  */
+struct grub_crypto_hmac_handle *
+grub_crypto_hmac_init (const struct gcry_md_spec *md,
+                      const void *key, grub_size_t keylen)
+{
+  grub_uint8_t *helpkey = NULL;
+  grub_uint8_t *ipad = NULL, *opad = NULL;
+  void *ctx = NULL;
+  struct grub_crypto_hmac_handle *ret = NULL;
+  unsigned i;
+
+  if (md->mdlen > md->blocksize)
+    return NULL;
+
+  ctx = grub_malloc (md->contextsize);
+  if (!ctx)
+    goto err;
+
+  if ( keylen > md->blocksize ) 
+    {
+      helpkey = grub_malloc (md->mdlen);
+      if (!helpkey)
+       goto err;
+      grub_crypto_hash (md, helpkey, key, keylen);
+
+      key = helpkey;
+      keylen = md->mdlen;
+    }
+
+  ipad = grub_zalloc (md->blocksize);
+  if (!ipad)
+    goto err;
+
+  opad = grub_zalloc (md->blocksize);
+  if (!opad)
+    goto err;
+
+  grub_memcpy ( ipad, key, keylen );
+  grub_memcpy ( opad, key, keylen );
+  for (i=0; i < md->blocksize; i++ ) 
+    {
+      ipad[i] ^= 0x36;
+      opad[i] ^= 0x5c;
+    }
+  grub_free (helpkey);
+  helpkey = NULL;
+
+  md->init (ctx);
+
+  md->write (ctx, ipad, md->blocksize); /* inner pad */
+  grub_memset (ipad, 0, md->blocksize);
+  grub_free (ipad);
+  ipad = NULL;
+
+  ret = grub_malloc (sizeof (*ret));
+  if (!ret)
+    goto err;
+
+  ret->md = md;
+  ret->ctx = ctx;
+  ret->opad = opad;
+
+  return ret;
+
+ err:
+  grub_free (helpkey);
+  grub_free (ctx);
+  grub_free (ipad);
+  grub_free (opad);
+  return NULL;
+}
+
+void
+grub_crypto_hmac_write (struct grub_crypto_hmac_handle *hnd, void *data,
+                       grub_size_t datalen)
+{
+  hnd->md->write (hnd->ctx, data, datalen);
+}
+
+gcry_err_code_t
+grub_crypto_hmac_fini (struct grub_crypto_hmac_handle *hnd, void *out)
+{
+  grub_uint8_t *p;
+  grub_uint8_t *ctx2;
+
+  ctx2 = grub_malloc (hnd->md->contextsize);
+  if (!ctx2)
+    return GPG_ERR_OUT_OF_MEMORY;
+
+  hnd->md->final (hnd->ctx);
+  hnd->md->read (hnd->ctx);
+  p = hnd->md->read (hnd->ctx);
+
+  hnd->md->init (ctx2);
+  hnd->md->write (ctx2, hnd->opad, hnd->md->blocksize);
+  hnd->md->write (ctx2, p, hnd->md->mdlen);
+  hnd->md->final (ctx2);
+  grub_memset (hnd->opad, 0, hnd->md->blocksize);
+  grub_free (hnd->opad);
+  grub_memset (hnd->ctx, 0, hnd->md->contextsize);
+  grub_free (hnd->ctx);
+
+  grub_memcpy (out, hnd->md->read (ctx2), hnd->md->mdlen);
+  grub_memset (ctx2, 0, hnd->md->contextsize);
+  grub_free (ctx2);
+
+  grub_memset (hnd, 0, sizeof (*hnd));
+  grub_free (hnd);
+
+  return GPG_ERR_NO_ERROR;
+}
+
+gcry_err_code_t
+grub_crypto_hmac_buffer (const struct gcry_md_spec *md,
+                        const void *key, grub_size_t keylen,
+                        void *data, grub_size_t datalen, void *out)
+{
+  struct grub_crypto_hmac_handle *hnd;
+
+  hnd = grub_crypto_hmac_init (md, key, keylen);
+  if (!hnd)
+    return GPG_ERR_OUT_OF_MEMORY;
+
+  grub_crypto_hmac_write (hnd, data, datalen);
+  return grub_crypto_hmac_fini (hnd, out);
+}
+
+
+grub_err_t
+grub_crypto_gcry_error (gcry_err_code_t in)
+{
+  if (in == GPG_ERR_NO_ERROR)
+    return GRUB_ERR_NONE;
+  return GRUB_ACCESS_DENIED;
+}
+
+int
+grub_crypto_memcmp (void *a, void *b, grub_size_t n)
+{
+  register grub_size_t counter = 0;
+  grub_uint8_t *pa, *pb;
+
+  for (pa = a, pb = b; n; pa++, pb++, n--)
+    {
+      if (*pa != *pb)
+       counter++;
+    }
+
+  return !!counter;
+}

=== added file 'lib/pbkdf2.c'
--- lib/pbkdf2.c        1970-01-01 00:00:00 +0000
+++ lib/pbkdf2.c        2009-11-15 13:13:10 +0000
@@ -0,0 +1,101 @@
+/* gc-pbkdf2-sha1.c --- Password-Based Key Derivation Function a'la PKCS#5
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2009 Free Software Foundation, 
Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Simon Josefsson.  */
+
+#include <grub/crypto.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
+
+/* Implement PKCS#5 PBKDF2 as per RFC 2898.  The PRF to use is HMAC variant
+   of digest supplied by MD.  Inputs are the password P of length PLEN,
+   the salt S of length SLEN, the iteration counter C (> 0), and the
+   desired derived output length DKLEN.  Output buffer is DK which
+   must have room for at least DKLEN octets.  The output buffer will
+   be filled with the derived data.  */
+gcry_err_code_t
+grub_crypto_pbkdf2 (const struct gcry_md_spec *md,
+                   const grub_uint8_t *P, grub_size_t Plen,
+                   const grub_uint8_t *S, grub_size_t Slen,
+                   unsigned int c,
+                   grub_uint8_t *DK, grub_size_t dkLen)
+{
+  unsigned int hLen = md->mdlen;
+  grub_uint8_t U[md->mdlen];
+  grub_uint8_t T[md->mdlen];
+  unsigned int u;
+  unsigned int l;
+  unsigned int r;
+  unsigned int i;
+  unsigned int k;
+  gcry_err_code_t rc;
+  grub_uint8_t *tmp;
+  grub_size_t tmplen = Slen + 4;
+
+  if (c == 0)
+    return GPG_ERR_INV_ARG;
+
+  if (dkLen == 0)
+    return GPG_ERR_INV_ARG;
+
+  if (dkLen > 4294967295U)
+    return GPG_ERR_INV_ARG;
+
+  l = ((dkLen - 1) / hLen) + 1;
+  r = dkLen - (l - 1) * hLen;
+
+  tmp = grub_malloc (tmplen);
+  if (tmp == NULL)
+    return GPG_ERR_OUT_OF_MEMORY;
+
+  grub_memcpy (tmp, S, Slen);
+
+  for (i = 1; i <= l; i++)
+    {
+      grub_memset (T, 0, hLen);
+
+      for (u = 1; u <= c; u++)
+       {
+         if (u == 1)
+           {
+             tmp[Slen + 0] = (i & 0xff000000) >> 24;
+             tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
+             tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
+             tmp[Slen + 3] = (i & 0x000000ff) >> 0;
+
+             rc = grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U);
+           }
+         else
+           rc = grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U);
+
+         if (rc != GPG_ERR_NO_ERROR)
+           {
+             grub_free (tmp);
+             return rc;
+           }
+
+         for (k = 0; k < hLen; k++)
+           T[k] ^= U[k];
+       }
+
+      grub_memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
+    }
+
+  grub_free (tmp);
+
+  return GPG_ERR_NO_ERROR;
+}

=== modified file 'normal/auth.c'
--- normal/auth.c       2009-11-09 14:30:47 +0000
+++ normal/auth.c       2009-11-15 22:40:08 +0000
@@ -35,58 +35,6 @@
 
 struct grub_auth_user *users = NULL;
 
-int
-grub_auth_strcmp (const char *s1, const char *s2)
-{
-  int ret;
-  grub_uint64_t end;
-
-  end = grub_get_time_ms () + 100;
-  ret = grub_strcmp (s1, s2);
-
-  /* This prevents an attacker from deriving information about the
-     password from the time it took to execute this function.  */
-  while (grub_get_time_ms () < end);
-
-  return ret;
-}
-
-static int
-grub_iswordseparator (int c)
-{
-  return (grub_isspace (c) || c == ',' || c == ';' || c == '|' || c == '&');
-}
-
-int
-grub_auth_strword (const char *haystack, const char *needle)
-{
-  const char *n_pos = needle;
-  int found = 0;
-
-  while (grub_iswordseparator (*haystack))
-    haystack++;
-
-  while (*haystack)
-    {
-      int ok = 1;
-      /* Crawl both the needle and the haystack word we're on.  */
-      while(*haystack && !grub_iswordseparator (*haystack))
-        {
-         if (*haystack == *n_pos && ok)
-           n_pos++;
-         else
-           ok = 0;
-
-          haystack++;
-        }
-
-      if (ok)
-       found = 1;
-    }
-
-  return found;
-}
-
 grub_err_t
 grub_auth_register_authentication (const char *user,
                                   grub_auth_callback_t callback,
@@ -193,8 +141,8 @@
       return 0;
     name = ((struct grub_auth_user *) item)->name;
 
-    return (userlist && grub_auth_strword (userlist, name))
-      || grub_auth_strword (superusers, name);
+    return (userlist && grub_strword (userlist, name))
+      || grub_strword (superusers, name);
   }
 
   superusers = grub_env_get ("superusers");
@@ -216,7 +164,7 @@
   auto int hook (grub_list_t item);
   int hook (grub_list_t item)
   {
-    if (grub_auth_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
+    if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) == 0)
       cur = (struct grub_auth_user *) item;
     return 0;
   }

=== added file 'util/grub-pbkdf2.c'
--- util/grub-pbkdf2.c  1970-01-01 00:00:00 +0000
+++ util/grub-pbkdf2.c  2009-11-16 12:51:39 +0000
@@ -0,0 +1,337 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 1992-1999,2001,2003,2004,2005,2009 Free Software Foundation, 
Inc.
+ *
+ *  GRUB is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  GRUB is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <grub/types.h>
+#include <grub/crypto.h>
+#include <grub/util/misc.h>
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <termios.h>
+
+
+/* Few functions to make crypto happy.  */
+void *
+grub_memmove (void *dest, const void *src, grub_size_t n)
+{
+  return memmove (dest, src, n);
+}
+
+void *
+grub_memset (void *s, int c, grub_size_t n)
+{
+  return memset (s, c, n);
+}
+
+int 
+grub_vprintf (const char *fmt, va_list args)
+{
+  return vprintf (fmt, args);
+}
+
+int 
+grub_vsprintf (char *str, const char *fmt, va_list args)
+{
+  return vsprintf (str, fmt, args);
+}
+
+void
+grub_abort (void)
+{
+  abort ();
+}
+
+static struct option options[] =
+  {
+    {"iteration_count", required_argument, 0, 'c'},
+    {"buflen", required_argument, 0, 'l'},
+    {"saltlen", required_argument, 0, 's'},
+    {"help", no_argument, 0, 'h'},
+    {"version", no_argument, 0, 'V'},
+  };
+
+static void
+usage (int status)
+{
+  if (status)
+    fprintf (stderr, "Try ``grub-scrypt --help'' for more information.\n");
+  else
+    printf ("\
+Usage: grub-scrypt [OPTIONS]\n\
+\nOptions:\n\
+     -c number, --iteration-count=number  Number of PBKDF2 iterations\n\
+     -l number, --buflen=number           Length of generated hash\n\
+     -s number, --salt=number             Length of salt\n\
+\n\
+Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
+
+  exit (status);
+}
+
+static void
+hexify (char *hex, grub_uint8_t *bin, grub_size_t n)
+{
+  while (n--)
+    {
+      if (((*bin & 0xf0) >> 4) < 10)
+       *hex = ((*bin & 0xf0) >> 4) + '0';
+      else
+       *hex = ((*bin & 0xf0) >> 4) + 'A' - 10;
+      hex++;
+
+      if ((*bin & 0xf) < 10)
+       *hex = (*bin & 0xf) + '0';
+      else
+       *hex = (*bin & 0xf) + 'A' - 10;
+      hex++;
+      bin++;
+    }
+  *hex = 0;
+}
+
+int
+main (int argc, char *argv[])
+{
+  unsigned int c = 10000, buflen = 64, saltlen = 64;
+  char *pass1, *pass2;
+  char *bufhex, *salthex;
+  gcry_err_code_t gcry_err;
+  grub_uint8_t *buf, *salt;
+  ssize_t nr;
+  FILE *in, *out;
+  struct termios s, t;
+  int tty_changed;
+
+  progname = "grub-pbkdf2";
+
+  /* Check for options.  */
+  while (1)
+    {
+      int c = getopt_long (argc, argv, "c:l:s:hvV", options, 0);
+
+      if (c == -1)
+       break;
+
+      switch (c)
+       {
+       case 'c':
+         c = strtoul (optarg, NULL, 0);
+         break;
+
+       case 'l':
+         buflen = strtoul (optarg, NULL, 0);
+         break;
+
+       case 's':
+         saltlen = strtoul (optarg, NULL, 0);
+         break;
+
+       case 'h':
+         usage (0);
+         return 0;
+         
+       case 'V':
+         printf ("%s (%s) %s\n", progname,
+                 PACKAGE_NAME, PACKAGE_VERSION);
+         return 0;
+           
+       default:
+         usage (1);
+         return 1;
+       }
+    }
+
+  bufhex = malloc (buflen * 2 + 1);
+  if (!bufhex)
+    grub_util_error ("Out of memory");
+  buf = malloc (buflen);
+  if (!buf)
+    {
+      free (bufhex);
+      grub_util_error ("Out of memory");
+    }
+
+  salt = malloc (saltlen);
+  if (!salt)
+    {
+      free (bufhex);
+      free (buf);
+      grub_util_error ("Out of memory");
+    }
+  salthex = malloc (saltlen * 2 + 1);
+  if (!salthex)
+    {
+      free (salt);
+      free (bufhex);
+      free (buf);
+      grub_util_error ("Out of memory");
+    }
+
+  /* Disable echoing. Based on glibc.  */
+  in = fopen ("/dev/tty", "w+c");
+  if (in == NULL)
+    {
+      in = stdin;
+      out = stderr;
+    }
+  else
+    out = in;
+
+  if (tcgetattr (fileno (in), &t) == 0)
+    {
+      /* Save the old one. */
+      s = t;
+      /* Tricky, tricky. */
+      t.c_lflag &= ~(ECHO|ISIG);
+      tty_changed = (tcsetattr (fileno (in), TCSAFLUSH, &t) == 0);
+    }
+  else
+    tty_changed = 0;
+  
+  printf ("Enter password: ");
+  pass1 = NULL;
+  {
+    grub_size_t n;
+    nr = getline (&pass1, &n, stdin);
+  }
+  if (nr < 0 || !pass1)
+    {
+      free (buf);
+      free (bufhex);
+      free (salthex);
+      free (salt);
+      /* Restore the original setting.  */
+      if (tty_changed)
+       (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
+      grub_util_error ("Failure to read password");
+    }
+  if (nr >= 1 && pass1[nr-1] == '\n')
+    pass1[nr-1] = 0;
+
+  printf ("\nReenter password: ");
+  pass2 = NULL;
+  {
+    grub_size_t n;
+    nr = getline (&pass2, &n, stdin);
+  }
+  /* Restore the original setting.  */
+  if (tty_changed)
+    (void) tcsetattr (fileno (in), TCSAFLUSH, &s);
+  printf ("\n");
+
+  if (nr < 0 || !pass2)
+    {
+      memset (pass1, 0, strlen (pass1));
+      free (pass1);
+      free (buf);
+      free (bufhex);
+      free (salthex);
+      free (salt);
+      grub_util_error ("Failure to read password");
+    }
+  if (nr >= 1 && pass2[nr-1] == '\n')
+    pass2[nr-1] = 0;
+
+  if (strcmp (pass1, pass2) != 0)
+    {
+      memset (pass1, 0, strlen (pass1));
+      memset (pass2, 0, strlen (pass2));
+      free (pass1);
+      free (pass2);
+      free (buf);
+      free (bufhex);
+      free (salthex);
+      free (salt);
+      grub_util_error ("Passwords don't match");
+    }
+  memset (pass2, 0, strlen (pass2));
+  free (pass2);
+
+#if ! defined (__linux__) && ! defined (__FreeBSD__)
+  printf ("WARNING: your random generator isn't known to be secure\n");
+#endif
+
+  {
+    FILE *f;
+    size_t rd;
+    f = fopen ("/dev/random", "rb");
+    if (!f)
+      {
+       memset (pass1, 0, strlen (pass1));
+       free (pass1);
+       free (buf);
+       free (bufhex);
+       free (salthex);
+       free (salt);
+       fclose (f);
+       grub_util_error ("Couldn't retrieve random data for salt");
+      }
+    rd = fread (salt, 1, saltlen, f);
+    if (rd != saltlen)
+      {
+       fclose (f);
+       memset (pass1, 0, strlen (pass1));
+       free (pass1);
+       free (buf);
+       free (bufhex);
+       free (salthex);
+       free (salt);
+       fclose (f);
+       grub_util_error ("Couldn't retrieve random data for salt");
+      }
+    fclose (f);
+  }
+
+  gcry_err = grub_crypto_pbkdf2 (GRUB_MD_SHA512,
+                                (grub_uint8_t *) pass1, strlen (pass1),
+                                salt, saltlen,
+                                c, buf, buflen);
+  memset (pass1, 0, strlen (pass1));
+  free (pass1);
+
+  if (gcry_err)
+    {
+      memset (buf, 0, buflen);
+      memset (bufhex, 0, 2 * buflen);
+      free (buf);
+      free (bufhex);
+      memset (salt, 0, saltlen);
+      memset (salthex, 0, 2 * saltlen);
+      free (salt);
+      free (salthex);
+      grub_util_error ("Cryptographic error number %d", gcry_err);
+    }
+
+  hexify (bufhex, buf, buflen);
+  hexify (salthex, salt, saltlen);
+
+  printf ("Your PBKDF2 is grub.pbkdf2.sha512.%d.%s.%s\n", c, salthex, bufhex);
+  memset (buf, 0, buflen);
+  memset (bufhex, 0, 2 * buflen);
+  free (buf);
+  free (bufhex);
+  memset (salt, 0, saltlen);
+  memset (salthex, 0, 2 * saltlen);
+  free (salt);
+  free (salthex);
+
+  return 0;
+}

Attachment: signature.asc
Description: OpenPGP digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]