[Top][All Lists]
[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;
+}
signature.asc
Description: OpenPGP digital signature
- [PATCH] Cryptography,
Vladimir 'phcoder' Serbinenko <=
- Re: [PATCH] Cryptography, Robert Millan, 2009/11/16
- Re: [PATCH] Cryptography, Vladimir 'phcoder' Serbinenko, 2009/11/16
- Re: [PATCH] Cryptography, Robert Millan, 2009/11/16
- Re: [PATCH] Cryptography, Vladimir 'phcoder' Serbinenko, 2009/11/16
- Re: [PATCH] Cryptography, Robert Millan, 2009/11/16
- Re: [PATCH] Cryptography, Vladimir 'phcoder' Serbinenko, 2009/11/16
- Import of libgcrypt 1.4.4 ciphers (was: Re: [PATCH] Cryptography), Robert Millan, 2009/11/16
Re: [PATCH] Cryptography, Felix Zielcke, 2009/11/16
Re: [PATCH] Cryptography, Robert Millan, 2009/11/17