From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Cryptography
Date: Mon, 16 Nov 2009 14:48:02 +0100 [thread overview]
Message-ID: <4B015812.3040808@gmail.com> (raw)
[-- Attachment #1.1: Type: text/plain, Size: 1337 bytes --]
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
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.2: crypto.diff --]
[-- Type: text/x-diff; name="crypto.diff", Size: 83251 bytes --]
=== 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 <phcoder@gmail.com>
+ *
+ * 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;
+\f
+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 <dn.tlp@gmx.net>
+ * Thanks to Raoul Boenisch <jkl345@gmx.net> 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 #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]
next reply other threads:[~2009-11-16 13:48 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-11-16 13:48 Vladimir 'phcoder' Serbinenko [this message]
2009-11-16 14:35 ` [PATCH] Cryptography Robert Millan
2009-11-16 14:56 ` Vladimir 'phcoder' Serbinenko
2009-11-16 18:26 ` Robert Millan
2009-11-16 19:38 ` Vladimir 'phcoder' Serbinenko
2009-11-16 19:59 ` Robert Millan
2009-11-16 20:20 ` Vladimir 'phcoder' Serbinenko
2009-11-16 21:16 ` Import of libgcrypt 1.4.4 ciphers (was: Re: [PATCH] Cryptography) Robert Millan
2009-11-16 14:42 ` [PATCH] Cryptography Felix Zielcke
2009-11-16 14:58 ` Vladimir 'phcoder' Serbinenko
2009-11-17 12:21 ` Robert Millan
2009-11-17 12:56 ` Robert Millan
2009-12-05 15:44 ` Vladimir 'φ-coder/phcoder' Serbinenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4B015812.3040808@gmail.com \
--to=phcoder@gmail.com \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.