* Fw: Re: Strong Crypto Support for GRUB2
@ 2008-07-20 23:49 Simon Peter
2008-07-21 0:20 ` Pavel Roskin
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Simon Peter @ 2008-07-20 23:49 UTC (permalink / raw)
To: grub-devel
[-- Attachment #1: Type: text/plain, Size: 1310 bytes --]
Did the message below ever arrive on the list?
I'm still interested in getting strong crypto into grub mainline and
while it's still not in, I just saw you guys proposed this as a project
for Google's summer of code. Are you going to point students at the
code I already produced? Would be a shame if you have someone replicate
the work already done.
What's missing to get my code into GRUB2 mainline?
Thanks!
Simon
Begin forwarded message:
Date: Sun, 3 Feb 2008 18:25:47 +0100
From: Simon Peter <simon.peter@gmx.de>
To: The development of GRUB 2 <grub-devel@gnu.org>
Cc: Marco Gerards <mgerards@xs4all.nl>, Robert Millan <rmh@aybabtu.com>
Subject: Re: Strong Crypto Support for GRUB2
> Sorry for the *very* late reply.
Sorry for my late reply. I wasn't subscribed anymore (and I'm still
not) and only now I found out that you replied...
Attached is my patch against current CVS with the changes you proposed
incorporated.
I'd appreciate very much if you could review this complete patch again.
Sorry for any inconvenience with my first weird double-patch.
> > +int
> > +aes_self_test (int verbose)
> > {
[...]
> > + printf ("passed\n");
> Where does printf come from?
It's in a self-test routine that's actually never included in the GRUB
source. Shall I remove the whole thing?
Thanks!
Simon
[-- Attachment #2: crypto.patch --]
[-- Type: text/x-diff, Size: 76357 bytes --]
diff -u -urNp grub2-orig/ChangeLog grub2/ChangeLog
--- grub2-orig/ChangeLog 2008-02-03 14:57:53.000000000 +0100
+++ grub2/ChangeLog 2008-02-03 18:14:51.484325803 +0100
@@ -1,3 +1,15 @@
+2008-02-03 Simon Peter <dn.tlp@gmx.net>
+ * disk/devmapper.c: New file.
+ * include/grub/crypto.h: New file.
+ * conf/common.rmk: Add devmapper.mod and dependency
+ declaratins. Add crypto.mod, aes.mod and rmd160.mod and dependency
+ declarations.
+ * include/grub/disk.h (grub_disk_dev_id): Add
+ `GRUB_DISK_DEVICE_CRYPTO_ID'.
+ * crypto/aes.c: New file.
+ * crypto/crypto.c: New file.
+ * crypto/rmd160.c: New file.
+
2008-02-03 Yoshinori K. Okuji <okuji@enbug.org>
* configure.ac (AC_INIT): Bumped to 1.96.
diff -u -urNp grub2-orig/conf/common.rmk grub2/conf/common.rmk
--- grub2-orig/conf/common.rmk 2008-02-02 21:35:08.000000000 +0100
+++ grub2/conf/common.rmk 2008-02-03 17:57:44.758807156 +0100
@@ -232,7 +232,7 @@ pkglib_MODULES += hello.mod boot.mod ter
cmp.mod cat.mod help.mod font.mod search.mod \
loopback.mod configfile.mod echo.mod \
terminfo.mod test.mod blocklist.mod hexdump.mod \
- read.mod
+ read.mod devmapper.mod
# For hello.mod.
hello_mod_SOURCES = hello/hello.c
@@ -294,6 +294,11 @@ loopback_mod_SOURCES = disk/loopback.c
loopback_mod_CFLAGS = $(COMMON_CFLAGS)
loopback_mod_LDFLAGS = $(COMMON_LDFLAGS)
+# For devmapper.mod
+devmapper_mod_SOURCES = disk/devmapper.c
+devmapper_mod_CFLAGS = $(COMMON_CFLAGS)
+devmapper_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
# For configfile.mod
configfile_mod_SOURCES = commands/configfile.c
configfile_mod_CFLAGS = $(COMMON_CFLAGS)
@@ -331,3 +336,21 @@ gzio_mod_LDFLAGS = $(COMMON_LDFLAGS)
read_mod_SOURCES = commands/read.c
read_mod_CFLAGS = $(COMMON_CFLAGS)
read_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# Cryptography.
+pkgdata_MODULES += crypto.mod aes.mod rmd160.mod
+
+# For crypto.mod
+crypto_mod_SOURCES = crypto/crypto.c
+crypto_mod_CFLAGS = $(COMMON_CFLAGS)
+crypto_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For aes.mod
+aes_mod_SOURCES = crypto/aes.c
+aes_mod_CFLAGS = $(COMMON_CFLAGS)
+aes_mod_LDFLAGS = $(COMMON_LDFLAGS)
+
+# For rmd160.mod
+rmd160_mod_SOURCES = crypto/rmd160.c
+rmd160_mod_CFLAGS = $(COMMON_CFLAGS)
+rmd160_mod_LDFLAGS = $(COMMON_LDFLAGS)
diff -u -urNp grub2-orig/crypto/aes.c grub2/crypto/aes.c
--- grub2-orig/crypto/aes.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2/crypto/aes.c 2008-02-03 18:07:24.746421102 +0100
@@ -0,0 +1,1088 @@
+/*
+ * FIPS-197 compliant AES implementation
+ *
+ * Copyright (C) 2006-2007 Christophe Devine
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License, version 2.1 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+/*
+ * The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
+ *
+ * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
+ * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
+ */
+/*
+ * 2007-08-31: Modified for GNU GRUB by Simon Peter <dn.tlp@gmx.net>.
+ */
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
+#define _CRT_SECURE_NO_DEPRECATE 1
+#endif
+
+#include <grub/err.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+
+/**
+ * \brief AES context structure
+ */
+typedef struct
+{
+ unsigned long erk[64]; /* Encryption round keys. */
+ unsigned long drk[64]; /* Decryption round keys. */
+ int nr; /* Number of rounds. */
+}
+aes_context;
+
+/*
+ * 32-bit integer manipulation macros (big endian)
+ */
+#ifndef GET_UINT32_BE
+#define GET_UINT32_BE(n,b,i) \
+{ \
+ (n) = ( (grub_uint32_t) (b)[(i) ] << 24 ) \
+ | ( (grub_uint32_t) (b)[(i) + 1] << 16 ) \
+ | ( (grub_uint32_t) (b)[(i) + 2] << 8 ) \
+ | ( (grub_uint32_t) (b)[(i) + 3] ); \
+}
+#endif
+#ifndef PUT_UINT32_BE
+#define PUT_UINT32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (grub_uint8_t) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (grub_uint8_t) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (grub_uint8_t) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (grub_uint8_t) ( (n) ); \
+}
+#endif
+
+/*
+ * Uncomment the following line to use pre-computed tables,
+ * otherwise the tables will be generated at the first run.
+ *
+ * #define FIXED_TABLES
+ */
+
+#if !defined(FIXED_TABLES)
+
+/*
+ * Forward S-box & tables
+ */
+static grub_uint8_t FSb[256];
+static grub_uint32_t FT0[256];
+static grub_uint32_t FT1[256];
+static grub_uint32_t FT2[256];
+static grub_uint32_t FT3[256];
+
+/*
+ * Reverse S-box & tables
+ */
+static grub_uint8_t RSb[256];
+static grub_uint32_t RT0[256];
+static grub_uint32_t RT1[256];
+static grub_uint32_t RT2[256];
+static grub_uint32_t RT3[256];
+
+/*
+ * Round constants
+ */
+static grub_uint32_t RCON[10];
+
+/*
+ * Tables generation code
+ */
+#define ROTR8(x) ( ( ( x << 24 ) & 0xFFFFFFFF ) | \
+ ( ( x & 0xFFFFFFFF ) >> 8 ) )
+#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) )
+#define MUL(x,y) ( ( x && y ) ? pow[(log[x] + log[y]) % 255] : 0 )
+
+static void
+aes_gen_tables (void)
+{
+ int i;
+ grub_uint8_t x, y;
+ grub_uint8_t pow[256];
+ grub_uint8_t log[256];
+
+ /*
+ * compute pow and log tables over GF(2^8)
+ */
+ for (i = 0, x = 1; i < 256; i++, x ^= XTIME (x))
+ {
+ pow[i] = x;
+ log[x] = i;
+ }
+
+ /*
+ * calculate the round constants
+ */
+ for (i = 0, x = 1; i < 10; i++, x = XTIME (x))
+ {
+ RCON[i] = (grub_uint32_t) x << 24;
+ }
+
+ /*
+ * generate the forward and reverse S-boxes
+ */
+ FSb[0x00] = 0x63;
+ RSb[0x63] = 0x00;
+
+ for (i = 1; i < 256; i++)
+ {
+ x = pow[255 - log[i]];
+
+ y = x;
+ y = (y << 1) | (y >> 7);
+ x ^= y;
+ y = (y << 1) | (y >> 7);
+ x ^= y;
+ y = (y << 1) | (y >> 7);
+ x ^= y;
+ y = (y << 1) | (y >> 7);
+ x ^= y ^ 0x63;
+
+ FSb[i] = x;
+ RSb[x] = i;
+ }
+
+ /*
+ * generate the forward and reverse tables
+ */
+ for (i = 0; i < 256; i++)
+ {
+ x = FSb[i];
+ y = XTIME (x);
+
+ FT0[i] = (grub_uint32_t) (x ^ y) ^
+ ((grub_uint32_t) x << 8) ^ ((grub_uint32_t) x << 16) ^ ((grub_uint32_t) y << 24);
+
+ FT0[i] &= 0xFFFFFFFF;
+
+ FT1[i] = ROTR8 (FT0[i]);
+ FT2[i] = ROTR8 (FT1[i]);
+ FT3[i] = ROTR8 (FT2[i]);
+
+ y = RSb[i];
+
+ RT0[i] = ((grub_uint32_t) MUL (0x0B, y)) ^
+ ((grub_uint32_t) MUL (0x0D, y) << 8) ^
+ ((grub_uint32_t) MUL (0x09, y) << 16) ^ ((grub_uint32_t) MUL (0x0E, y) << 24);
+
+ RT0[i] &= 0xFFFFFFFF;
+
+ RT1[i] = ROTR8 (RT0[i]);
+ RT2[i] = ROTR8 (RT1[i]);
+ RT3[i] = ROTR8 (RT2[i]);
+ }
+}
+
+#else
+
+/*
+ * Forward S-box
+ *
+ * See Figure 7 of FIPS PUB 197. This array is generated by
+ * the algorithm described in Section 5.1.1 of FIPS PUB 197.
+ */
+static const grub_uint8_t FSb[256] = {
+ 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
+ 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
+ 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
+ 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
+ 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
+ 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
+ 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
+ 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
+ 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
+ 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
+ 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
+ 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
+ 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
+ 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
+ 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
+ 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
+ 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
+ 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
+ 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
+ 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
+ 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
+ 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
+ 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
+ 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
+ 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
+ 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
+ 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
+ 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
+ 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
+ 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
+ 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
+ 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
+};
+
+/*
+ * Forward tables
+ *
+ * These are optimization tables, as described for example in:
+ * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ * Section "Optimization of the Cipher".
+ */
+#define FT \
+\
+ V(C6,63,63,A5), V(F8,7C,7C,84), V(EE,77,77,99), V(F6,7B,7B,8D), \
+ V(FF,F2,F2,0D), V(D6,6B,6B,BD), V(DE,6F,6F,B1), V(91,C5,C5,54), \
+ V(60,30,30,50), V(02,01,01,03), V(CE,67,67,A9), V(56,2B,2B,7D), \
+ V(E7,FE,FE,19), V(B5,D7,D7,62), V(4D,AB,AB,E6), V(EC,76,76,9A), \
+ V(8F,CA,CA,45), V(1F,82,82,9D), V(89,C9,C9,40), V(FA,7D,7D,87), \
+ V(EF,FA,FA,15), V(B2,59,59,EB), V(8E,47,47,C9), V(FB,F0,F0,0B), \
+ V(41,AD,AD,EC), V(B3,D4,D4,67), V(5F,A2,A2,FD), V(45,AF,AF,EA), \
+ V(23,9C,9C,BF), V(53,A4,A4,F7), V(E4,72,72,96), V(9B,C0,C0,5B), \
+ V(75,B7,B7,C2), V(E1,FD,FD,1C), V(3D,93,93,AE), V(4C,26,26,6A), \
+ V(6C,36,36,5A), V(7E,3F,3F,41), V(F5,F7,F7,02), V(83,CC,CC,4F), \
+ V(68,34,34,5C), V(51,A5,A5,F4), V(D1,E5,E5,34), V(F9,F1,F1,08), \
+ V(E2,71,71,93), V(AB,D8,D8,73), V(62,31,31,53), V(2A,15,15,3F), \
+ V(08,04,04,0C), V(95,C7,C7,52), V(46,23,23,65), V(9D,C3,C3,5E), \
+ V(30,18,18,28), V(37,96,96,A1), V(0A,05,05,0F), V(2F,9A,9A,B5), \
+ V(0E,07,07,09), V(24,12,12,36), V(1B,80,80,9B), V(DF,E2,E2,3D), \
+ V(CD,EB,EB,26), V(4E,27,27,69), V(7F,B2,B2,CD), V(EA,75,75,9F), \
+ V(12,09,09,1B), V(1D,83,83,9E), V(58,2C,2C,74), V(34,1A,1A,2E), \
+ V(36,1B,1B,2D), V(DC,6E,6E,B2), V(B4,5A,5A,EE), V(5B,A0,A0,FB), \
+ V(A4,52,52,F6), V(76,3B,3B,4D), V(B7,D6,D6,61), V(7D,B3,B3,CE), \
+ V(52,29,29,7B), V(DD,E3,E3,3E), V(5E,2F,2F,71), V(13,84,84,97), \
+ V(A6,53,53,F5), V(B9,D1,D1,68), V(00,00,00,00), V(C1,ED,ED,2C), \
+ V(40,20,20,60), V(E3,FC,FC,1F), V(79,B1,B1,C8), V(B6,5B,5B,ED), \
+ V(D4,6A,6A,BE), V(8D,CB,CB,46), V(67,BE,BE,D9), V(72,39,39,4B), \
+ V(94,4A,4A,DE), V(98,4C,4C,D4), V(B0,58,58,E8), V(85,CF,CF,4A), \
+ V(BB,D0,D0,6B), V(C5,EF,EF,2A), V(4F,AA,AA,E5), V(ED,FB,FB,16), \
+ V(86,43,43,C5), V(9A,4D,4D,D7), V(66,33,33,55), V(11,85,85,94), \
+ V(8A,45,45,CF), V(E9,F9,F9,10), V(04,02,02,06), V(FE,7F,7F,81), \
+ V(A0,50,50,F0), V(78,3C,3C,44), V(25,9F,9F,BA), V(4B,A8,A8,E3), \
+ V(A2,51,51,F3), V(5D,A3,A3,FE), V(80,40,40,C0), V(05,8F,8F,8A), \
+ V(3F,92,92,AD), V(21,9D,9D,BC), V(70,38,38,48), V(F1,F5,F5,04), \
+ V(63,BC,BC,DF), V(77,B6,B6,C1), V(AF,DA,DA,75), V(42,21,21,63), \
+ V(20,10,10,30), V(E5,FF,FF,1A), V(FD,F3,F3,0E), V(BF,D2,D2,6D), \
+ V(81,CD,CD,4C), V(18,0C,0C,14), V(26,13,13,35), V(C3,EC,EC,2F), \
+ V(BE,5F,5F,E1), V(35,97,97,A2), V(88,44,44,CC), V(2E,17,17,39), \
+ V(93,C4,C4,57), V(55,A7,A7,F2), V(FC,7E,7E,82), V(7A,3D,3D,47), \
+ V(C8,64,64,AC), V(BA,5D,5D,E7), V(32,19,19,2B), V(E6,73,73,95), \
+ V(C0,60,60,A0), V(19,81,81,98), V(9E,4F,4F,D1), V(A3,DC,DC,7F), \
+ V(44,22,22,66), V(54,2A,2A,7E), V(3B,90,90,AB), V(0B,88,88,83), \
+ V(8C,46,46,CA), V(C7,EE,EE,29), V(6B,B8,B8,D3), V(28,14,14,3C), \
+ V(A7,DE,DE,79), V(BC,5E,5E,E2), V(16,0B,0B,1D), V(AD,DB,DB,76), \
+ V(DB,E0,E0,3B), V(64,32,32,56), V(74,3A,3A,4E), V(14,0A,0A,1E), \
+ V(92,49,49,DB), V(0C,06,06,0A), V(48,24,24,6C), V(B8,5C,5C,E4), \
+ V(9F,C2,C2,5D), V(BD,D3,D3,6E), V(43,AC,AC,EF), V(C4,62,62,A6), \
+ V(39,91,91,A8), V(31,95,95,A4), V(D3,E4,E4,37), V(F2,79,79,8B), \
+ V(D5,E7,E7,32), V(8B,C8,C8,43), V(6E,37,37,59), V(DA,6D,6D,B7), \
+ V(01,8D,8D,8C), V(B1,D5,D5,64), V(9C,4E,4E,D2), V(49,A9,A9,E0), \
+ V(D8,6C,6C,B4), V(AC,56,56,FA), V(F3,F4,F4,07), V(CF,EA,EA,25), \
+ V(CA,65,65,AF), V(F4,7A,7A,8E), V(47,AE,AE,E9), V(10,08,08,18), \
+ V(6F,BA,BA,D5), V(F0,78,78,88), V(4A,25,25,6F), V(5C,2E,2E,72), \
+ V(38,1C,1C,24), V(57,A6,A6,F1), V(73,B4,B4,C7), V(97,C6,C6,51), \
+ V(CB,E8,E8,23), V(A1,DD,DD,7C), V(E8,74,74,9C), V(3E,1F,1F,21), \
+ V(96,4B,4B,DD), V(61,BD,BD,DC), V(0D,8B,8B,86), V(0F,8A,8A,85), \
+ V(E0,70,70,90), V(7C,3E,3E,42), V(71,B5,B5,C4), V(CC,66,66,AA), \
+ V(90,48,48,D8), V(06,03,03,05), V(F7,F6,F6,01), V(1C,0E,0E,12), \
+ V(C2,61,61,A3), V(6A,35,35,5F), V(AE,57,57,F9), V(69,B9,B9,D0), \
+ V(17,86,86,91), V(99,C1,C1,58), V(3A,1D,1D,27), V(27,9E,9E,B9), \
+ V(D9,E1,E1,38), V(EB,F8,F8,13), V(2B,98,98,B3), V(22,11,11,33), \
+ V(D2,69,69,BB), V(A9,D9,D9,70), V(07,8E,8E,89), V(33,94,94,A7), \
+ V(2D,9B,9B,B6), V(3C,1E,1E,22), V(15,87,87,92), V(C9,E9,E9,20), \
+ V(87,CE,CE,49), V(AA,55,55,FF), V(50,28,28,78), V(A5,DF,DF,7A), \
+ V(03,8C,8C,8F), V(59,A1,A1,F8), V(09,89,89,80), V(1A,0D,0D,17), \
+ V(65,BF,BF,DA), V(D7,E6,E6,31), V(84,42,42,C6), V(D0,68,68,B8), \
+ V(82,41,41,C3), V(29,99,99,B0), V(5A,2D,2D,77), V(1E,0F,0F,11), \
+ V(7B,B0,B0,CB), V(A8,54,54,FC), V(6D,BB,BB,D6), V(2C,16,16,3A)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const grub_uint32_t FT0[256] = { FT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const grub_uint32_t FT1[256] = { FT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const grub_uint32_t FT2[256] = { FT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const grub_uint32_t FT3[256] = { FT };
+
+#undef V
+
+#undef FT
+
+/*
+ * Reverse S-box
+ *
+ * See Figure 14 of FIPS PUB 197. This array is generated by
+ * the algorithm described in Section 5.3.2 of FIPS PUB 197.
+ */
+static const grub_uint8_t RSb[256] = {
+ 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
+ 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
+ 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
+ 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
+ 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
+ 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
+ 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
+ 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
+ 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
+ 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
+ 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
+ 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
+ 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
+ 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
+ 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
+ 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
+ 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
+ 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
+ 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
+ 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
+ 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
+ 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
+ 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
+ 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
+ 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
+ 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
+ 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
+ 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
+ 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
+ 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
+ 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
+ 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
+};
+
+/*
+ * Reverse tables
+ *
+ * These are optimization tables, as described for example in:
+ * http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
+ * Section "Optimization of the Cipher".
+ */
+#define RT \
+\
+ V(51,F4,A7,50), V(7E,41,65,53), V(1A,17,A4,C3), V(3A,27,5E,96), \
+ V(3B,AB,6B,CB), V(1F,9D,45,F1), V(AC,FA,58,AB), V(4B,E3,03,93), \
+ V(20,30,FA,55), V(AD,76,6D,F6), V(88,CC,76,91), V(F5,02,4C,25), \
+ V(4F,E5,D7,FC), V(C5,2A,CB,D7), V(26,35,44,80), V(B5,62,A3,8F), \
+ V(DE,B1,5A,49), V(25,BA,1B,67), V(45,EA,0E,98), V(5D,FE,C0,E1), \
+ V(C3,2F,75,02), V(81,4C,F0,12), V(8D,46,97,A3), V(6B,D3,F9,C6), \
+ V(03,8F,5F,E7), V(15,92,9C,95), V(BF,6D,7A,EB), V(95,52,59,DA), \
+ V(D4,BE,83,2D), V(58,74,21,D3), V(49,E0,69,29), V(8E,C9,C8,44), \
+ V(75,C2,89,6A), V(F4,8E,79,78), V(99,58,3E,6B), V(27,B9,71,DD), \
+ V(BE,E1,4F,B6), V(F0,88,AD,17), V(C9,20,AC,66), V(7D,CE,3A,B4), \
+ V(63,DF,4A,18), V(E5,1A,31,82), V(97,51,33,60), V(62,53,7F,45), \
+ V(B1,64,77,E0), V(BB,6B,AE,84), V(FE,81,A0,1C), V(F9,08,2B,94), \
+ V(70,48,68,58), V(8F,45,FD,19), V(94,DE,6C,87), V(52,7B,F8,B7), \
+ V(AB,73,D3,23), V(72,4B,02,E2), V(E3,1F,8F,57), V(66,55,AB,2A), \
+ V(B2,EB,28,07), V(2F,B5,C2,03), V(86,C5,7B,9A), V(D3,37,08,A5), \
+ V(30,28,87,F2), V(23,BF,A5,B2), V(02,03,6A,BA), V(ED,16,82,5C), \
+ V(8A,CF,1C,2B), V(A7,79,B4,92), V(F3,07,F2,F0), V(4E,69,E2,A1), \
+ V(65,DA,F4,CD), V(06,05,BE,D5), V(D1,34,62,1F), V(C4,A6,FE,8A), \
+ V(34,2E,53,9D), V(A2,F3,55,A0), V(05,8A,E1,32), V(A4,F6,EB,75), \
+ V(0B,83,EC,39), V(40,60,EF,AA), V(5E,71,9F,06), V(BD,6E,10,51), \
+ V(3E,21,8A,F9), V(96,DD,06,3D), V(DD,3E,05,AE), V(4D,E6,BD,46), \
+ V(91,54,8D,B5), V(71,C4,5D,05), V(04,06,D4,6F), V(60,50,15,FF), \
+ V(19,98,FB,24), V(D6,BD,E9,97), V(89,40,43,CC), V(67,D9,9E,77), \
+ V(B0,E8,42,BD), V(07,89,8B,88), V(E7,19,5B,38), V(79,C8,EE,DB), \
+ V(A1,7C,0A,47), V(7C,42,0F,E9), V(F8,84,1E,C9), V(00,00,00,00), \
+ V(09,80,86,83), V(32,2B,ED,48), V(1E,11,70,AC), V(6C,5A,72,4E), \
+ V(FD,0E,FF,FB), V(0F,85,38,56), V(3D,AE,D5,1E), V(36,2D,39,27), \
+ V(0A,0F,D9,64), V(68,5C,A6,21), V(9B,5B,54,D1), V(24,36,2E,3A), \
+ V(0C,0A,67,B1), V(93,57,E7,0F), V(B4,EE,96,D2), V(1B,9B,91,9E), \
+ V(80,C0,C5,4F), V(61,DC,20,A2), V(5A,77,4B,69), V(1C,12,1A,16), \
+ V(E2,93,BA,0A), V(C0,A0,2A,E5), V(3C,22,E0,43), V(12,1B,17,1D), \
+ V(0E,09,0D,0B), V(F2,8B,C7,AD), V(2D,B6,A8,B9), V(14,1E,A9,C8), \
+ V(57,F1,19,85), V(AF,75,07,4C), V(EE,99,DD,BB), V(A3,7F,60,FD), \
+ V(F7,01,26,9F), V(5C,72,F5,BC), V(44,66,3B,C5), V(5B,FB,7E,34), \
+ V(8B,43,29,76), V(CB,23,C6,DC), V(B6,ED,FC,68), V(B8,E4,F1,63), \
+ V(D7,31,DC,CA), V(42,63,85,10), V(13,97,22,40), V(84,C6,11,20), \
+ V(85,4A,24,7D), V(D2,BB,3D,F8), V(AE,F9,32,11), V(C7,29,A1,6D), \
+ V(1D,9E,2F,4B), V(DC,B2,30,F3), V(0D,86,52,EC), V(77,C1,E3,D0), \
+ V(2B,B3,16,6C), V(A9,70,B9,99), V(11,94,48,FA), V(47,E9,64,22), \
+ V(A8,FC,8C,C4), V(A0,F0,3F,1A), V(56,7D,2C,D8), V(22,33,90,EF), \
+ V(87,49,4E,C7), V(D9,38,D1,C1), V(8C,CA,A2,FE), V(98,D4,0B,36), \
+ V(A6,F5,81,CF), V(A5,7A,DE,28), V(DA,B7,8E,26), V(3F,AD,BF,A4), \
+ V(2C,3A,9D,E4), V(50,78,92,0D), V(6A,5F,CC,9B), V(54,7E,46,62), \
+ V(F6,8D,13,C2), V(90,D8,B8,E8), V(2E,39,F7,5E), V(82,C3,AF,F5), \
+ V(9F,5D,80,BE), V(69,D0,93,7C), V(6F,D5,2D,A9), V(CF,25,12,B3), \
+ V(C8,AC,99,3B), V(10,18,7D,A7), V(E8,9C,63,6E), V(DB,3B,BB,7B), \
+ V(CD,26,78,09), V(6E,59,18,F4), V(EC,9A,B7,01), V(83,4F,9A,A8), \
+ V(E6,95,6E,65), V(AA,FF,E6,7E), V(21,BC,CF,08), V(EF,15,E8,E6), \
+ V(BA,E7,9B,D9), V(4A,6F,36,CE), V(EA,9F,09,D4), V(29,B0,7C,D6), \
+ V(31,A4,B2,AF), V(2A,3F,23,31), V(C6,A5,94,30), V(35,A2,66,C0), \
+ V(74,4E,BC,37), V(FC,82,CA,A6), V(E0,90,D0,B0), V(33,A7,D8,15), \
+ V(F1,04,98,4A), V(41,EC,DA,F7), V(7F,CD,50,0E), V(17,91,F6,2F), \
+ V(76,4D,D6,8D), V(43,EF,B0,4D), V(CC,AA,4D,54), V(E4,96,04,DF), \
+ V(9E,D1,B5,E3), V(4C,6A,88,1B), V(C1,2C,1F,B8), V(46,65,51,7F), \
+ V(9D,5E,EA,04), V(01,8C,35,5D), V(FA,87,74,73), V(FB,0B,41,2E), \
+ V(B3,67,1D,5A), V(92,DB,D2,52), V(E9,10,56,33), V(6D,D6,47,13), \
+ V(9A,D7,61,8C), V(37,A1,0C,7A), V(59,F8,14,8E), V(EB,13,3C,89), \
+ V(CE,A9,27,EE), V(B7,61,C9,35), V(E1,1C,E5,ED), V(7A,47,B1,3C), \
+ V(9C,D2,DF,59), V(55,F2,73,3F), V(18,14,CE,79), V(73,C7,37,BF), \
+ V(53,F7,CD,EA), V(5F,FD,AA,5B), V(DF,3D,6F,14), V(78,44,DB,86), \
+ V(CA,AF,F3,81), V(B9,68,C4,3E), V(38,24,34,2C), V(C2,A3,40,5F), \
+ V(16,1D,C3,72), V(BC,E2,25,0C), V(28,3C,49,8B), V(FF,0D,95,41), \
+ V(39,A8,01,71), V(08,0C,B3,DE), V(D8,B4,E4,9C), V(64,56,C1,90), \
+ V(7B,CB,84,61), V(D5,32,B6,70), V(48,6C,5C,74), V(D0,B8,57,42)
+
+#define V(a,b,c,d) 0x##a##b##c##d
+static const grub_uint32_t RT0[256] = { RT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##d##a##b##c
+static const grub_uint32_t RT1[256] = { RT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##c##d##a##b
+static const grub_uint32_t RT2[256] = { RT };
+
+#undef V
+
+#define V(a,b,c,d) 0x##b##c##d##a
+static const grub_uint32_t RT3[256] = { RT };
+
+#undef V
+
+#undef RT
+
+/*
+ * Round constants
+ */
+static const grub_uint32_t RCON[10] = {
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000
+};
+
+static void
+aes_gen_tables (void)
+{
+}
+
+#endif
+
+/*
+ * Decryption key schedule tables
+ */
+static grub_uint32_t KT0[256];
+static grub_uint32_t KT1[256];
+static grub_uint32_t KT2[256];
+static grub_uint32_t KT3[256];
+
+/*
+ * AES key schedule
+ */
+static void
+aes_set_key (aes_context * ctx, const grub_uint8_t * key, int keysize)
+{
+ int i;
+ grub_uint32_t *RK, *SK;
+ static int ft_init = 0;
+ static int kt_init = 0;
+
+ if (ft_init == 0)
+ {
+ aes_gen_tables ();
+
+ ft_init = 1;
+ }
+
+ switch (keysize)
+ {
+ case 128:
+ ctx->nr = 10;
+ break;
+ case 192:
+ ctx->nr = 12;
+ break;
+ case 256:
+ ctx->nr = 14;
+ break;
+ default:
+ return;
+ }
+
+ RK = ctx->erk;
+
+ for (i = 0; i < (keysize >> 5); i++)
+ {
+ GET_UINT32_BE (RK[i], key, i << 2);
+ }
+
+ /*
+ * setup encryption round keys
+ */
+ switch (ctx->nr)
+ {
+ case 10:
+
+ for (i = 0; i < 10; i++, RK += 4)
+ {
+ RK[4] = RK[0] ^ RCON[i] ^
+ (FSb[(grub_uint8_t) (RK[3] >> 16)] << 24) ^
+ (FSb[(grub_uint8_t) (RK[3] >> 8)] << 16) ^
+ (FSb[(grub_uint8_t) (RK[3])] << 8) ^ (FSb[(grub_uint8_t) (RK[3] >> 24)]);
+
+ RK[5] = RK[1] ^ RK[4];
+ RK[6] = RK[2] ^ RK[5];
+ RK[7] = RK[3] ^ RK[6];
+ }
+ break;
+
+ case 12:
+
+ for (i = 0; i < 8; i++, RK += 6)
+ {
+ RK[6] = RK[0] ^ RCON[i] ^
+ (FSb[(grub_uint8_t) (RK[5] >> 16)] << 24) ^
+ (FSb[(grub_uint8_t) (RK[5] >> 8)] << 16) ^
+ (FSb[(grub_uint8_t) (RK[5])] << 8) ^ (FSb[(grub_uint8_t) (RK[5] >> 24)]);
+
+ RK[7] = RK[1] ^ RK[6];
+ RK[8] = RK[2] ^ RK[7];
+ RK[9] = RK[3] ^ RK[8];
+ RK[10] = RK[4] ^ RK[9];
+ RK[11] = RK[5] ^ RK[10];
+ }
+ break;
+
+ case 14:
+
+ for (i = 0; i < 7; i++, RK += 8)
+ {
+ RK[8] = RK[0] ^ RCON[i] ^
+ (FSb[(grub_uint8_t) (RK[7] >> 16)] << 24) ^
+ (FSb[(grub_uint8_t) (RK[7] >> 8)] << 16) ^
+ (FSb[(grub_uint8_t) (RK[7])] << 8) ^ (FSb[(grub_uint8_t) (RK[7] >> 24)]);
+
+ RK[9] = RK[1] ^ RK[8];
+ RK[10] = RK[2] ^ RK[9];
+ RK[11] = RK[3] ^ RK[10];
+
+ RK[12] = RK[4] ^
+ (FSb[(grub_uint8_t) (RK[11] >> 24)] << 24) ^
+ (FSb[(grub_uint8_t) (RK[11] >> 16)] << 16) ^
+ (FSb[(grub_uint8_t) (RK[11] >> 8)] << 8) ^ (FSb[(grub_uint8_t) (RK[11])]);
+
+ RK[13] = RK[5] ^ RK[12];
+ RK[14] = RK[6] ^ RK[13];
+ RK[15] = RK[7] ^ RK[14];
+ }
+ break;
+
+ default:
+
+ break;
+ }
+
+ /*
+ * setup decryption round keys
+ */
+ if (kt_init == 0)
+ {
+ for (i = 0; i < 256; i++)
+ {
+ KT0[i] = RT0[FSb[i]];
+ KT1[i] = RT1[FSb[i]];
+ KT2[i] = RT2[FSb[i]];
+ KT3[i] = RT3[FSb[i]];
+ }
+
+ kt_init = 1;
+ }
+
+ SK = ctx->drk;
+
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+
+ for (i = 1; i < ctx->nr; i++)
+ {
+ RK -= 8;
+
+ *SK++ = KT0[(grub_uint8_t) (*RK >> 24)] ^
+ KT1[(grub_uint8_t) (*RK >> 16)] ^
+ KT2[(grub_uint8_t) (*RK >> 8)] ^ KT3[(grub_uint8_t) (*RK)];
+ RK++;
+
+ *SK++ = KT0[(grub_uint8_t) (*RK >> 24)] ^
+ KT1[(grub_uint8_t) (*RK >> 16)] ^
+ KT2[(grub_uint8_t) (*RK >> 8)] ^ KT3[(grub_uint8_t) (*RK)];
+ RK++;
+
+ *SK++ = KT0[(grub_uint8_t) (*RK >> 24)] ^
+ KT1[(grub_uint8_t) (*RK >> 16)] ^
+ KT2[(grub_uint8_t) (*RK >> 8)] ^ KT3[(grub_uint8_t) (*RK)];
+ RK++;
+
+ *SK++ = KT0[(grub_uint8_t) (*RK >> 24)] ^
+ KT1[(grub_uint8_t) (*RK >> 16)] ^
+ KT2[(grub_uint8_t) (*RK >> 8)] ^ KT3[(grub_uint8_t) (*RK)];
+ RK++;
+ }
+
+ RK -= 8;
+
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+ *SK++ = *RK++;
+}
+
+/**
+ * AES block encryption (ECB mode)
+ */
+static void
+aes_encrypt (aes_context * ctx,
+ unsigned char input[16], unsigned char output[16])
+{
+ grub_uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->erk;
+
+ GET_UINT32_BE (X0, input, 0);
+ X0 ^= RK[0];
+ GET_UINT32_BE (X1, input, 4);
+ X1 ^= RK[1];
+ GET_UINT32_BE (X2, input, 8);
+ X2 ^= RK[2];
+ GET_UINT32_BE (X3, input, 12);
+ X3 ^= RK[3];
+
+#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ RK += 4; \
+ \
+ X0 = RK[0] ^ FT0[ (grub_uint8_t) ( Y0 >> 24 ) ] ^ \
+ FT1[ (grub_uint8_t) ( Y1 >> 16 ) ] ^ \
+ FT2[ (grub_uint8_t) ( Y2 >> 8 ) ] ^ \
+ FT3[ (grub_uint8_t) ( Y3 ) ]; \
+ \
+ X1 = RK[1] ^ FT0[ (grub_uint8_t) ( Y1 >> 24 ) ] ^ \
+ FT1[ (grub_uint8_t) ( Y2 >> 16 ) ] ^ \
+ FT2[ (grub_uint8_t) ( Y3 >> 8 ) ] ^ \
+ FT3[ (grub_uint8_t) ( Y0 ) ]; \
+ \
+ X2 = RK[2] ^ FT0[ (grub_uint8_t) ( Y2 >> 24 ) ] ^ \
+ FT1[ (grub_uint8_t) ( Y3 >> 16 ) ] ^ \
+ FT2[ (grub_uint8_t) ( Y0 >> 8 ) ] ^ \
+ FT3[ (grub_uint8_t) ( Y1 ) ]; \
+ \
+ X3 = RK[3] ^ FT0[ (grub_uint8_t) ( Y3 >> 24 ) ] ^ \
+ FT1[ (grub_uint8_t) ( Y0 >> 16 ) ] ^ \
+ FT2[ (grub_uint8_t) ( Y1 >> 8 ) ] ^ \
+ FT3[ (grub_uint8_t) ( Y2 ) ]; \
+}
+
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+
+ if (ctx->nr > 10)
+ {
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ }
+
+ if (ctx->nr > 12)
+ {
+ AES_FROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_FROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ }
+
+ RK += 4;
+
+ X0 = RK[0] ^ (FSb[(grub_uint8_t) (Y0 >> 24)] << 24) ^
+ (FSb[(grub_uint8_t) (Y1 >> 16)] << 16) ^
+ (FSb[(grub_uint8_t) (Y2 >> 8)] << 8) ^ (FSb[(grub_uint8_t) (Y3)]);
+
+ X1 = RK[1] ^ (FSb[(grub_uint8_t) (Y1 >> 24)] << 24) ^
+ (FSb[(grub_uint8_t) (Y2 >> 16)] << 16) ^
+ (FSb[(grub_uint8_t) (Y3 >> 8)] << 8) ^ (FSb[(grub_uint8_t) (Y0)]);
+
+ X2 = RK[2] ^ (FSb[(grub_uint8_t) (Y2 >> 24)] << 24) ^
+ (FSb[(grub_uint8_t) (Y3 >> 16)] << 16) ^
+ (FSb[(grub_uint8_t) (Y0 >> 8)] << 8) ^ (FSb[(grub_uint8_t) (Y1)]);
+
+ X3 = RK[3] ^ (FSb[(grub_uint8_t) (Y3 >> 24)] << 24) ^
+ (FSb[(grub_uint8_t) (Y0 >> 16)] << 16) ^
+ (FSb[(grub_uint8_t) (Y1 >> 8)] << 8) ^ (FSb[(grub_uint8_t) (Y2)]);
+
+ PUT_UINT32_BE (X0, output, 0);
+ PUT_UINT32_BE (X1, output, 4);
+ PUT_UINT32_BE (X2, output, 8);
+ PUT_UINT32_BE (X3, output, 12);
+}
+
+/*
+ * AES block decryption (ECB mode)
+ */
+static void
+aes_decrypt (aes_context * ctx,
+ unsigned char input[16], unsigned char output[16])
+{
+ grub_uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+
+ RK = ctx->drk;
+
+ GET_UINT32_BE (X0, input, 0);
+ X0 ^= RK[0];
+ GET_UINT32_BE (X1, input, 4);
+ X1 ^= RK[1];
+ GET_UINT32_BE (X2, input, 8);
+ X2 ^= RK[2];
+ GET_UINT32_BE (X3, input, 12);
+ X3 ^= RK[3];
+
+#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \
+{ \
+ RK += 4; \
+ \
+ X0 = RK[0] ^ RT0[ (grub_uint8_t) ( Y0 >> 24 ) ] ^ \
+ RT1[ (grub_uint8_t) ( Y3 >> 16 ) ] ^ \
+ RT2[ (grub_uint8_t) ( Y2 >> 8 ) ] ^ \
+ RT3[ (grub_uint8_t) ( Y1 ) ]; \
+ \
+ X1 = RK[1] ^ RT0[ (grub_uint8_t) ( Y1 >> 24 ) ] ^ \
+ RT1[ (grub_uint8_t) ( Y0 >> 16 ) ] ^ \
+ RT2[ (grub_uint8_t) ( Y3 >> 8 ) ] ^ \
+ RT3[ (grub_uint8_t) ( Y2 ) ]; \
+ \
+ X2 = RK[2] ^ RT0[ (grub_uint8_t) ( Y2 >> 24 ) ] ^ \
+ RT1[ (grub_uint8_t) ( Y1 >> 16 ) ] ^ \
+ RT2[ (grub_uint8_t) ( Y0 >> 8 ) ] ^ \
+ RT3[ (grub_uint8_t) ( Y3 ) ]; \
+ \
+ X3 = RK[3] ^ RT0[ (grub_uint8_t) ( Y3 >> 24 ) ] ^ \
+ RT1[ (grub_uint8_t) ( Y2 >> 16 ) ] ^ \
+ RT2[ (grub_uint8_t) ( Y1 >> 8 ) ] ^ \
+ RT3[ (grub_uint8_t) ( Y0 ) ]; \
+}
+
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+
+ if (ctx->nr > 10)
+ {
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ }
+
+ if (ctx->nr > 12)
+ {
+ AES_RROUND (X0, X1, X2, X3, Y0, Y1, Y2, Y3);
+ AES_RROUND (Y0, Y1, Y2, Y3, X0, X1, X2, X3);
+ }
+
+ RK += 4;
+
+ X0 = RK[0] ^ (RSb[(grub_uint8_t) (Y0 >> 24)] << 24) ^
+ (RSb[(grub_uint8_t) (Y3 >> 16)] << 16) ^
+ (RSb[(grub_uint8_t) (Y2 >> 8)] << 8) ^ (RSb[(grub_uint8_t) (Y1)]);
+
+ X1 = RK[1] ^ (RSb[(grub_uint8_t) (Y1 >> 24)] << 24) ^
+ (RSb[(grub_uint8_t) (Y0 >> 16)] << 16) ^
+ (RSb[(grub_uint8_t) (Y3 >> 8)] << 8) ^ (RSb[(grub_uint8_t) (Y2)]);
+
+ X2 = RK[2] ^ (RSb[(grub_uint8_t) (Y2 >> 24)] << 24) ^
+ (RSb[(grub_uint8_t) (Y1 >> 16)] << 16) ^
+ (RSb[(grub_uint8_t) (Y0 >> 8)] << 8) ^ (RSb[(grub_uint8_t) (Y3)]);
+
+ X3 = RK[3] ^ (RSb[(grub_uint8_t) (Y3 >> 24)] << 24) ^
+ (RSb[(grub_uint8_t) (Y2 >> 16)] << 16) ^
+ (RSb[(grub_uint8_t) (Y1 >> 8)] << 8) ^ (RSb[(grub_uint8_t) (Y0)]);
+
+ PUT_UINT32_BE (X0, output, 0);
+ PUT_UINT32_BE (X1, output, 4);
+ PUT_UINT32_BE (X2, output, 8);
+ PUT_UINT32_BE (X3, output, 12);
+}
+
+/*
+ * AES-CBC buffer encryption
+ */
+static void
+aes_cbc_encrypt (aes_context * ctx,
+ unsigned char iv[16],
+ unsigned char *input, unsigned char *output, int len)
+{
+ int i;
+
+ while (len > 0)
+ {
+ for (i = 0; i < 16; i++)
+ output[i] = input[i] ^ iv[i];
+
+ aes_encrypt (ctx, output, output);
+ grub_memcpy (iv, output, 16);
+
+ input += 16;
+ output += 16;
+ len -= 16;
+ }
+}
+
+/*
+ * AES-CBC buffer decryption
+ */
+static void
+aes_cbc_decrypt (aes_context * ctx,
+ unsigned char iv[16],
+ unsigned char *input, unsigned char *output, int len)
+{
+ int i;
+ unsigned char temp[16];
+
+ while (len > 0)
+ {
+ grub_memcpy (temp, input, 16);
+ aes_decrypt (ctx, input, output);
+
+ for (i = 0; i < 16; i++)
+ output[i] = output[i] ^ iv[i];
+
+ grub_memcpy (iv, temp, 16);
+
+ input += 16;
+ output += 16;
+ len -= 16;
+ }
+}
+
+static const char _aes_src[] = "_aes_src";
+
+#if defined(SELF_TEST)
+
+#include <stdio.h>
+
+/*
+ * AES-ECB test vectors (source: NIST, rijndael-vals.zip)
+ */
+static const grub_uint8_t aes_enc_test[3][16] = {
+ {0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73,
+ 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F},
+ {0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11,
+ 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14},
+ {0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D,
+ 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4}
+};
+
+static const grub_uint8_t aes_dec_test[3][16] = {
+ {0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58,
+ 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0},
+ {0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2,
+ 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4},
+ {0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D,
+ 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE}
+};
+
+/*
+ * Checkup routine
+ */
+int
+aes_self_test (int verbose)
+{
+ int i, j, u, v;
+ aes_context ctx;
+ unsigned char buf[32];
+
+ for (i = 0; i < 6; i++)
+ {
+ u = i >> 1;
+ v = i & 1;
+
+ if (verbose != 0)
+ printf (" AES-ECB-%3d (%s): ", 128 + u * 64,
+ (v == 0) ? "enc" : "dec");
+
+ memset (buf, 0, 32);
+ aes_set_key (&ctx, buf, 128 + u * 64);
+
+ for (j = 0; j < 10000; j++)
+ {
+ if (v == 0)
+ aes_encrypt (&ctx, buf, buf);
+ if (v == 1)
+ aes_decrypt (&ctx, buf, buf);
+ }
+
+ if ((v == 0 && memcmp (buf, aes_enc_test[u], 16) != 0) ||
+ (v == 1 && memcmp (buf, aes_dec_test[u], 16) != 0))
+ {
+ if (verbose != 0)
+ printf ("failed\n");
+
+ return (1);
+ }
+
+ if (verbose != 0)
+ printf ("passed\n");
+ }
+
+ if (verbose != 0)
+ printf ("\n");
+
+ return (0);
+}
+#endif
+
+/*** GNU GRUB2 interface ***/
+
+static grub_err_t
+grub_cipher_aes_init (grub_cipher_params_t params)
+{
+ params->private = grub_malloc (sizeof (aes_context));
+
+ if (!params->private)
+ return grub_errno;
+
+ params->keysize = 32;
+
+ return 0;
+}
+
+static grub_err_t
+grub_cipher_aes_cbc_init (grub_cipher_params_t params)
+{
+ grub_err_t err;
+
+ if ((err = grub_cipher_aes_init (params)))
+ return err;
+ if (!(params->u.cipher.iv = grub_malloc (16)))
+ return grub_errno;
+ grub_memset (params->u.cipher.iv, 0, 16);
+ params->u.cipher.iv_length = 16;
+ return 0;
+}
+
+static void
+grub_cipher_aes_deinit (grub_cipher_params_t params)
+{
+ grub_free (params->private);
+}
+
+static void
+grub_cipher_aes_cbc_deinit (grub_cipher_params_t params)
+{
+ grub_free (params->u.cipher.iv);
+ grub_cipher_aes_deinit (params);
+}
+
+static grub_err_t
+grub_cipher_aes_set_key (grub_cipher_params_t params, const char *key)
+{
+ aes_set_key (params->private, (grub_uint8_t *) key, params->keysize * 8);
+ return 0;
+}
+
+static grub_err_t
+grub_cipher_aes_decrypt_inplace (grub_cipher_params_t params,
+ char *buf, grub_size_t size)
+{
+ grub_size_t i;
+
+ if (size % 16 != 0)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Size must be multiple of 16");
+
+ for (i = 0; i < size; i += 16)
+ aes_decrypt (params->private, (unsigned char *) buf + i,
+ (unsigned char *) buf + i);
+
+ return 0;
+}
+
+static grub_err_t
+grub_cipher_aes_cbc_decrypt_inplace (grub_cipher_params_t params,
+ char *buf, grub_size_t size)
+{
+ if (params->u.cipher.iv_length != 16)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "IV length incorrect");
+
+ aes_cbc_decrypt (params->private, params->u.cipher.iv,
+ (unsigned char *) buf, (unsigned char *) buf, size);
+ return 0;
+}
+
+#define FIELDSOF(a) (sizeof(a) / sizeof(a[0]))
+
+static const unsigned int aes_keysizes[] = { 32 };
+
+static struct grub_cipher grub_cipher_aes = {
+ .name = "aes",
+ .type = GRUB_CIPHER_TYPE_CIPHER,
+ .keysizes = aes_keysizes,
+ .keysizes_length = FIELDSOF (aes_keysizes),
+
+ .init = grub_cipher_aes_init,
+ .deinit = grub_cipher_aes_deinit,
+ .u.cipher = {
+ .set_key = grub_cipher_aes_set_key,
+ .encrypt = NULL,
+ .decrypt = NULL,
+ .decrypt_inplace = grub_cipher_aes_decrypt_inplace,
+ .encrypt_inplace = NULL}
+};
+
+static struct grub_cipher grub_cipher_aes_cbc = {
+ .name = "aes-cbc",
+ .type = GRUB_CIPHER_TYPE_CIPHER,
+ .keysizes = aes_keysizes,
+ .keysizes_length = FIELDSOF (aes_keysizes),
+
+ .init = grub_cipher_aes_cbc_init,
+ .deinit = grub_cipher_aes_cbc_deinit,
+ .u.cipher = {
+ .set_key = grub_cipher_aes_set_key,
+ .encrypt = NULL,
+ .decrypt = NULL,
+ .decrypt_inplace = grub_cipher_aes_cbc_decrypt_inplace,
+ .encrypt_inplace = NULL}
+};
+
+GRUB_MOD_INIT (aes)
+{
+ grub_crypto_cipher_register (&grub_cipher_aes);
+ grub_crypto_cipher_register (&grub_cipher_aes_cbc);
+}
+
+GRUB_MOD_FINI (aes)
+{
+ grub_crypto_cipher_unregister (&grub_cipher_aes);
+ grub_crypto_cipher_unregister (&grub_cipher_aes_cbc);
+}
diff -u -urNp grub2-orig/crypto/crypto.c grub2/crypto/crypto.c
--- grub2-orig/crypto/crypto.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2/crypto/crypto.c 2008-02-03 18:00:07.685059082 +0100
@@ -0,0 +1,288 @@
+/*
+ * crypto.c - Strong cryptography API for GRUB
+ *
+ * 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/crypto.h>
+
+#define MAX(a, b) (a > b ? a : b)
+
+struct cipher_list
+{
+ grub_cipher_t cipher;
+ struct cipher_list *next;
+};
+
+static struct cipher_list *cipher_list = NULL;
+
+grub_err_t
+grub_crypto_hash (grub_cipher_params_t params, char *hash,
+ const char *payload, unsigned int size)
+{
+ return params->cipher->u.hash.fn (params, hash, payload, size);
+}
+
+static grub_cipher_t
+get_cipher (const char *name, grub_cipher_type_t type)
+{
+ struct cipher_list *i;
+
+ for (i = cipher_list; i != NULL; i = i->next)
+ if (!grub_strcmp (i->cipher->name, name) && i->cipher->type == type)
+ return i->cipher;
+
+ return NULL;
+}
+
+grub_err_t
+grub_crypto_new_cipher (grub_cipher_params_t * params, const char *name,
+ grub_cipher_type_t type)
+{
+ grub_cipher_t cipher = get_cipher (name, type);
+ grub_err_t err;
+
+ if (cipher == NULL)
+ {
+ const char *errstr = "Illegal cipher type";
+
+ switch (type)
+ {
+ case GRUB_CIPHER_TYPE_NONE:
+ break;
+
+ case GRUB_CIPHER_TYPE_CIPHER:
+ errstr = "Unknown cipher";
+ break;
+
+ case GRUB_CIPHER_TYPE_HASH:
+ errstr = "Unknown hash";
+ break;
+ }
+
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, errstr);
+ }
+
+ *params = grub_malloc (sizeof (struct grub_cipher_params));
+ if (*params == NULL)
+ return grub_errno;
+
+ if (cipher->init)
+ {
+ if ((err = cipher->init (*params)) != GRUB_ERR_NONE)
+ {
+ grub_free (*params);
+ return err;
+ }
+ }
+ else
+ {
+ unsigned int i, keysize = 0;
+
+ /* Set keysize to largest */
+ for (i = 0; i < cipher->keysizes_length; i++)
+ keysize = MAX (keysize, cipher->keysizes[i]);
+
+ (*params)->keysize = keysize;
+ }
+
+ (*params)->cipher = cipher;
+ return GRUB_ERR_NONE;
+}
+
+void
+grub_crypto_delete_cipher (grub_cipher_params_t params)
+{
+ if (params->cipher->deinit)
+ params->cipher->deinit (params);
+
+ grub_free (params);
+}
+
+int
+grub_crypto_cipher_iterate (grub_crypto_hook hook, void *data)
+{
+ struct cipher_list *i;
+
+ for (i = cipher_list; i != NULL; i = i->next)
+ if (hook (i->cipher, data))
+ return 1;
+
+ return 0;
+}
+
+void
+grub_crypto_cipher_register (grub_cipher_t cipher)
+{
+ struct cipher_list *newcipher = grub_malloc (sizeof (struct cipher_list));
+
+ if (!newcipher)
+ return; /* out of memory! */
+
+ newcipher->cipher = cipher;
+ newcipher->next = cipher_list;
+ cipher_list = newcipher;
+}
+
+void
+grub_crypto_cipher_unregister (grub_cipher_t cipher)
+{
+ struct cipher_list *i, **prev;
+
+ for (i = cipher_list, prev = &cipher_list; i != NULL;
+ prev = &i->next, i = i->next)
+ if (!grub_strcmp (i->cipher->name, cipher->name))
+ break;
+
+ if (!i)
+ {
+ grub_printf ("BUG: Trying to unregister a non-registered cipher!\n");
+ return;
+ }
+
+ /* Remove cipher from list */
+ *prev = i->next;
+ grub_free (i);
+}
+
+grub_err_t
+grub_crypto_set_key (grub_cipher_params_t params, const char *key)
+{
+ if (params->cipher->u.cipher.set_key)
+ return params->cipher->u.cipher.set_key (params, key);
+ else
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+grub_crypto_encrypt (grub_cipher_params_t params, char **out,
+ const char *in, grub_size_t * outsize,
+ grub_size_t insize)
+{
+ if (params->cipher->u.cipher.encrypt)
+ return params->cipher->u.cipher.encrypt (params, out, in, outsize,
+ insize);
+ else
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+grub_err_t
+grub_crypto_decrypt (grub_cipher_params_t params, char **out,
+ const char *in, grub_size_t * outsize,
+ grub_size_t insize)
+{
+ if (params->cipher->u.cipher.decrypt)
+ return params->cipher->u.cipher.decrypt (params, out, in, outsize,
+ insize);
+ else
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+grub_err_t
+grub_crypto_decrypt_inplace (grub_cipher_params_t params, char *buf,
+ grub_size_t size)
+{
+ if (params->cipher->u.cipher.decrypt_inplace)
+ return params->cipher->u.cipher.decrypt_inplace (params, buf, size);
+ else
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+grub_err_t
+grub_crypto_encrypt_inplace (grub_cipher_params_t params, char *buf,
+ grub_size_t size)
+{
+ if (params->cipher->u.cipher.encrypt_inplace)
+ return params->cipher->u.cipher.encrypt_inplace (params, buf, size);
+ else
+ return GRUB_ERR_NOT_IMPLEMENTED_YET;
+}
+
+/***** None cipher interface ***********************************************/
+
+static grub_err_t
+cipher_none_crypt (grub_cipher_params_t unused, char **out, const char *in,
+ grub_size_t * outsize, grub_size_t insize)
+{
+ (void) unused;
+ if (!(*out = grub_malloc (insize)))
+ return grub_errno;
+ *out = grub_memcpy (*out, in, insize);
+ *outsize = insize;
+ return 0;
+}
+
+static grub_err_t
+cipher_none_crypt_inplace (grub_cipher_params_t unused, char *buf,
+ grub_size_t size)
+{
+ (void) unused;
+ (void) buf;
+ (void) size;
+ return 0;
+}
+
+static grub_err_t
+hash_none_fn (grub_cipher_params_t params, char *out, const char *in,
+ grub_size_t insize)
+{
+ params->keysize = insize;
+ grub_memcpy (out, in, insize);
+ return 0;
+}
+
+static struct grub_cipher grub_cipher_none = {
+ .name = "none",
+ .type = GRUB_CIPHER_TYPE_CIPHER,
+ .keysizes_length = 0,
+
+ .u.cipher = {
+ .encrypt = cipher_none_crypt,
+ .decrypt = cipher_none_crypt,
+ .decrypt_inplace = cipher_none_crypt_inplace,
+ .encrypt_inplace = cipher_none_crypt_inplace}
+};
+
+static struct grub_cipher grub_hash_none = {
+ .name = "none",
+ .type = GRUB_CIPHER_TYPE_HASH,
+ .keysizes_length = 0,
+ .u.hash.fn = hash_none_fn
+};
+
+/***** GRUB module (de-)initialization *************************************/
+
+GRUB_MOD_INIT (crypto)
+{
+ grub_crypto_cipher_register (&grub_cipher_none);
+ grub_crypto_cipher_register (&grub_hash_none);
+}
+
+GRUB_MOD_FINI (crypto)
+{
+ grub_crypto_cipher_unregister (&grub_hash_none);
+ grub_crypto_cipher_unregister (&grub_cipher_none);
+}
diff -u -urNp grub2-orig/crypto/rmd160.c grub2/crypto/rmd160.c
--- grub2-orig/crypto/rmd160.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2/crypto/rmd160.c 2008-02-03 18:00:07.689058893 +0100
@@ -0,0 +1,437 @@
+/*
+ * 2007-09-01: Modified for GNU GRUB by Simon Peter <dn.tlp@gmx.net>.
+ */
+/********************************************************************\
+ *
+ * FILE: rmd160.c
+ *
+ * CONTENTS: A sample C-implementation of the RIPEMD-160
+ * hash-function.
+ * TARGET: any computer with an ANSI C compiler
+ *
+ * AUTHOR: Antoon Bosselaers, ESAT-COSIC
+ * DATE: 1 March 1996
+ * VERSION: 1.0
+ *
+ * Copyright (c) Katholieke Universiteit Leuven
+ * 1996, All Rights Reserved
+ *
+ * Conditions for use of the RIPEMD-160 Software
+ *
+ * The RIPEMD-160 software is freely available for use under the terms and
+ * conditions described hereunder, which shall be deemed to be accepted by
+ * any user of the software and applicable on any use of the software:
+ *
+ * 1. K.U.Leuven Department of Electrical Engineering-ESAT/COSIC shall for
+ * all purposes be considered the owner of the RIPEMD-160 software and of
+ * all copyright, trade secret, patent or other intellectual property
+ * rights therein.
+ * 2. The RIPEMD-160 software is provided on an "as is" basis without
+ * warranty of any sort, express or implied. K.U.Leuven makes no
+ * representation that the use of the software will not infringe any
+ * patent or proprietary right of third parties. User will indemnify
+ * K.U.Leuven and hold K.U.Leuven harmless from any claims or liabilities
+ * which may arise as a result of its use of the software. In no
+ * circumstances K.U.Leuven R&D will be held liable for any deficiency,
+ * fault or other mishappening with regard to the use or performance of
+ * the software.
+ * 3. User agrees to give due credit to K.U.Leuven in scientific publications
+ * or communications in relation with the use of the RIPEMD-160 software
+ * as follows: RIPEMD-160 software written by Antoon Bosselaers,
+ * available at http://www.esat.kuleuven.be/~cosicart/ps/AB-9601/.
+ *
+\********************************************************************/
+
+#include <grub/misc.h>
+#include <grub/mm.h>
+#include <grub/dl.h>
+#include <grub/crypto.h>
+
+/* typedef 8 and 32 bit types, resp. */
+/* adapt these, if necessary,
+ for your operating system and compiler */
+typedef unsigned char byte;
+typedef unsigned long dword;
+
+/* macro definitions */
+
+/* collect four bytes into one word: */
+#define BYTES_TO_DWORD(strptr) \
+ (((dword) *((strptr)+3) << 24) | \
+ ((dword) *((strptr)+2) << 16) | \
+ ((dword) *((strptr)+1) << 8) | \
+ ((dword) *(strptr)))
+
+/* ROL(x, n) cyclically rotates x over n bits to the left */
+/* x must be of an unsigned 32 bits type and 0 <= n < 32. */
+#define ROL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* the five basic functions F(), G() and H() */
+#define F(x, y, z) ((x) ^ (y) ^ (z))
+#define G(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define H(x, y, z) (((x) | ~(y)) ^ (z))
+#define I(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define J(x, y, z) ((x) ^ ((y) | ~(z)))
+
+/* the ten basic operations FF() through III() */
+#define FF(a, b, c, d, e, x, s) {\
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define GG(a, b, c, d, e, x, s) {\
+ (a) += G((b), (c), (d)) + (x) + 0x5a827999UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define HH(a, b, c, d, e, x, s) {\
+ (a) += H((b), (c), (d)) + (x) + 0x6ed9eba1UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define II(a, b, c, d, e, x, s) {\
+ (a) += I((b), (c), (d)) + (x) + 0x8f1bbcdcUL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define JJ(a, b, c, d, e, x, s) {\
+ (a) += J((b), (c), (d)) + (x) + 0xa953fd4eUL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define FFF(a, b, c, d, e, x, s) {\
+ (a) += F((b), (c), (d)) + (x);\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define GGG(a, b, c, d, e, x, s) {\
+ (a) += G((b), (c), (d)) + (x) + 0x7a6d76e9UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define HHH(a, b, c, d, e, x, s) {\
+ (a) += H((b), (c), (d)) + (x) + 0x6d703ef3UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define III(a, b, c, d, e, x, s) {\
+ (a) += I((b), (c), (d)) + (x) + 0x5c4dd124UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+#define JJJ(a, b, c, d, e, x, s) {\
+ (a) += J((b), (c), (d)) + (x) + 0x50a28be6UL;\
+ (a) = ROL((a), (s)) + (e);\
+ (c) = ROL((c), 10);\
+ }
+
+/********************************************************************/
+
+static void
+MDinit (dword * MDbuf)
+{
+ MDbuf[0] = 0x67452301UL;
+ MDbuf[1] = 0xefcdab89UL;
+ MDbuf[2] = 0x98badcfeUL;
+ MDbuf[3] = 0x10325476UL;
+ MDbuf[4] = 0xc3d2e1f0UL;
+
+ return;
+}
+
+/********************************************************************/
+
+static void
+compress (dword * MDbuf, dword * X)
+{
+ dword aa = MDbuf[0], bb = MDbuf[1], cc = MDbuf[2],
+ dd = MDbuf[3], ee = MDbuf[4];
+ dword aaa = MDbuf[0], bbb = MDbuf[1], ccc = MDbuf[2],
+ ddd = MDbuf[3], eee = MDbuf[4];
+
+ /* round 1 */
+ FF (aa, bb, cc, dd, ee, X[0], 11);
+ FF (ee, aa, bb, cc, dd, X[1], 14);
+ FF (dd, ee, aa, bb, cc, X[2], 15);
+ FF (cc, dd, ee, aa, bb, X[3], 12);
+ FF (bb, cc, dd, ee, aa, X[4], 5);
+ FF (aa, bb, cc, dd, ee, X[5], 8);
+ FF (ee, aa, bb, cc, dd, X[6], 7);
+ FF (dd, ee, aa, bb, cc, X[7], 9);
+ FF (cc, dd, ee, aa, bb, X[8], 11);
+ FF (bb, cc, dd, ee, aa, X[9], 13);
+ FF (aa, bb, cc, dd, ee, X[10], 14);
+ FF (ee, aa, bb, cc, dd, X[11], 15);
+ FF (dd, ee, aa, bb, cc, X[12], 6);
+ FF (cc, dd, ee, aa, bb, X[13], 7);
+ FF (bb, cc, dd, ee, aa, X[14], 9);
+ FF (aa, bb, cc, dd, ee, X[15], 8);
+
+ /* round 2 */
+ GG (ee, aa, bb, cc, dd, X[7], 7);
+ GG (dd, ee, aa, bb, cc, X[4], 6);
+ GG (cc, dd, ee, aa, bb, X[13], 8);
+ GG (bb, cc, dd, ee, aa, X[1], 13);
+ GG (aa, bb, cc, dd, ee, X[10], 11);
+ GG (ee, aa, bb, cc, dd, X[6], 9);
+ GG (dd, ee, aa, bb, cc, X[15], 7);
+ GG (cc, dd, ee, aa, bb, X[3], 15);
+ GG (bb, cc, dd, ee, aa, X[12], 7);
+ GG (aa, bb, cc, dd, ee, X[0], 12);
+ GG (ee, aa, bb, cc, dd, X[9], 15);
+ GG (dd, ee, aa, bb, cc, X[5], 9);
+ GG (cc, dd, ee, aa, bb, X[2], 11);
+ GG (bb, cc, dd, ee, aa, X[14], 7);
+ GG (aa, bb, cc, dd, ee, X[11], 13);
+ GG (ee, aa, bb, cc, dd, X[8], 12);
+
+ /* round 3 */
+ HH (dd, ee, aa, bb, cc, X[3], 11);
+ HH (cc, dd, ee, aa, bb, X[10], 13);
+ HH (bb, cc, dd, ee, aa, X[14], 6);
+ HH (aa, bb, cc, dd, ee, X[4], 7);
+ HH (ee, aa, bb, cc, dd, X[9], 14);
+ HH (dd, ee, aa, bb, cc, X[15], 9);
+ HH (cc, dd, ee, aa, bb, X[8], 13);
+ HH (bb, cc, dd, ee, aa, X[1], 15);
+ HH (aa, bb, cc, dd, ee, X[2], 14);
+ HH (ee, aa, bb, cc, dd, X[7], 8);
+ HH (dd, ee, aa, bb, cc, X[0], 13);
+ HH (cc, dd, ee, aa, bb, X[6], 6);
+ HH (bb, cc, dd, ee, aa, X[13], 5);
+ HH (aa, bb, cc, dd, ee, X[11], 12);
+ HH (ee, aa, bb, cc, dd, X[5], 7);
+ HH (dd, ee, aa, bb, cc, X[12], 5);
+
+ /* round 4 */
+ II (cc, dd, ee, aa, bb, X[1], 11);
+ II (bb, cc, dd, ee, aa, X[9], 12);
+ II (aa, bb, cc, dd, ee, X[11], 14);
+ II (ee, aa, bb, cc, dd, X[10], 15);
+ II (dd, ee, aa, bb, cc, X[0], 14);
+ II (cc, dd, ee, aa, bb, X[8], 15);
+ II (bb, cc, dd, ee, aa, X[12], 9);
+ II (aa, bb, cc, dd, ee, X[4], 8);
+ II (ee, aa, bb, cc, dd, X[13], 9);
+ II (dd, ee, aa, bb, cc, X[3], 14);
+ II (cc, dd, ee, aa, bb, X[7], 5);
+ II (bb, cc, dd, ee, aa, X[15], 6);
+ II (aa, bb, cc, dd, ee, X[14], 8);
+ II (ee, aa, bb, cc, dd, X[5], 6);
+ II (dd, ee, aa, bb, cc, X[6], 5);
+ II (cc, dd, ee, aa, bb, X[2], 12);
+
+ /* round 5 */
+ JJ (bb, cc, dd, ee, aa, X[4], 9);
+ JJ (aa, bb, cc, dd, ee, X[0], 15);
+ JJ (ee, aa, bb, cc, dd, X[5], 5);
+ JJ (dd, ee, aa, bb, cc, X[9], 11);
+ JJ (cc, dd, ee, aa, bb, X[7], 6);
+ JJ (bb, cc, dd, ee, aa, X[12], 8);
+ JJ (aa, bb, cc, dd, ee, X[2], 13);
+ JJ (ee, aa, bb, cc, dd, X[10], 12);
+ JJ (dd, ee, aa, bb, cc, X[14], 5);
+ JJ (cc, dd, ee, aa, bb, X[1], 12);
+ JJ (bb, cc, dd, ee, aa, X[3], 13);
+ JJ (aa, bb, cc, dd, ee, X[8], 14);
+ JJ (ee, aa, bb, cc, dd, X[11], 11);
+ JJ (dd, ee, aa, bb, cc, X[6], 8);
+ JJ (cc, dd, ee, aa, bb, X[15], 5);
+ JJ (bb, cc, dd, ee, aa, X[13], 6);
+
+ /* parallel round 1 */
+ JJJ (aaa, bbb, ccc, ddd, eee, X[5], 8);
+ JJJ (eee, aaa, bbb, ccc, ddd, X[14], 9);
+ JJJ (ddd, eee, aaa, bbb, ccc, X[7], 9);
+ JJJ (ccc, ddd, eee, aaa, bbb, X[0], 11);
+ JJJ (bbb, ccc, ddd, eee, aaa, X[9], 13);
+ JJJ (aaa, bbb, ccc, ddd, eee, X[2], 15);
+ JJJ (eee, aaa, bbb, ccc, ddd, X[11], 15);
+ JJJ (ddd, eee, aaa, bbb, ccc, X[4], 5);
+ JJJ (ccc, ddd, eee, aaa, bbb, X[13], 7);
+ JJJ (bbb, ccc, ddd, eee, aaa, X[6], 7);
+ JJJ (aaa, bbb, ccc, ddd, eee, X[15], 8);
+ JJJ (eee, aaa, bbb, ccc, ddd, X[8], 11);
+ JJJ (ddd, eee, aaa, bbb, ccc, X[1], 14);
+ JJJ (ccc, ddd, eee, aaa, bbb, X[10], 14);
+ JJJ (bbb, ccc, ddd, eee, aaa, X[3], 12);
+ JJJ (aaa, bbb, ccc, ddd, eee, X[12], 6);
+
+ /* parallel round 2 */
+ III (eee, aaa, bbb, ccc, ddd, X[6], 9);
+ III (ddd, eee, aaa, bbb, ccc, X[11], 13);
+ III (ccc, ddd, eee, aaa, bbb, X[3], 15);
+ III (bbb, ccc, ddd, eee, aaa, X[7], 7);
+ III (aaa, bbb, ccc, ddd, eee, X[0], 12);
+ III (eee, aaa, bbb, ccc, ddd, X[13], 8);
+ III (ddd, eee, aaa, bbb, ccc, X[5], 9);
+ III (ccc, ddd, eee, aaa, bbb, X[10], 11);
+ III (bbb, ccc, ddd, eee, aaa, X[14], 7);
+ III (aaa, bbb, ccc, ddd, eee, X[15], 7);
+ III (eee, aaa, bbb, ccc, ddd, X[8], 12);
+ III (ddd, eee, aaa, bbb, ccc, X[12], 7);
+ III (ccc, ddd, eee, aaa, bbb, X[4], 6);
+ III (bbb, ccc, ddd, eee, aaa, X[9], 15);
+ III (aaa, bbb, ccc, ddd, eee, X[1], 13);
+ III (eee, aaa, bbb, ccc, ddd, X[2], 11);
+
+ /* parallel round 3 */
+ HHH (ddd, eee, aaa, bbb, ccc, X[15], 9);
+ HHH (ccc, ddd, eee, aaa, bbb, X[5], 7);
+ HHH (bbb, ccc, ddd, eee, aaa, X[1], 15);
+ HHH (aaa, bbb, ccc, ddd, eee, X[3], 11);
+ HHH (eee, aaa, bbb, ccc, ddd, X[7], 8);
+ HHH (ddd, eee, aaa, bbb, ccc, X[14], 6);
+ HHH (ccc, ddd, eee, aaa, bbb, X[6], 6);
+ HHH (bbb, ccc, ddd, eee, aaa, X[9], 14);
+ HHH (aaa, bbb, ccc, ddd, eee, X[11], 12);
+ HHH (eee, aaa, bbb, ccc, ddd, X[8], 13);
+ HHH (ddd, eee, aaa, bbb, ccc, X[12], 5);
+ HHH (ccc, ddd, eee, aaa, bbb, X[2], 14);
+ HHH (bbb, ccc, ddd, eee, aaa, X[10], 13);
+ HHH (aaa, bbb, ccc, ddd, eee, X[0], 13);
+ HHH (eee, aaa, bbb, ccc, ddd, X[4], 7);
+ HHH (ddd, eee, aaa, bbb, ccc, X[13], 5);
+
+ /* parallel round 4 */
+ GGG (ccc, ddd, eee, aaa, bbb, X[8], 15);
+ GGG (bbb, ccc, ddd, eee, aaa, X[6], 5);
+ GGG (aaa, bbb, ccc, ddd, eee, X[4], 8);
+ GGG (eee, aaa, bbb, ccc, ddd, X[1], 11);
+ GGG (ddd, eee, aaa, bbb, ccc, X[3], 14);
+ GGG (ccc, ddd, eee, aaa, bbb, X[11], 14);
+ GGG (bbb, ccc, ddd, eee, aaa, X[15], 6);
+ GGG (aaa, bbb, ccc, ddd, eee, X[0], 14);
+ GGG (eee, aaa, bbb, ccc, ddd, X[5], 6);
+ GGG (ddd, eee, aaa, bbb, ccc, X[12], 9);
+ GGG (ccc, ddd, eee, aaa, bbb, X[2], 12);
+ GGG (bbb, ccc, ddd, eee, aaa, X[13], 9);
+ GGG (aaa, bbb, ccc, ddd, eee, X[9], 12);
+ GGG (eee, aaa, bbb, ccc, ddd, X[7], 5);
+ GGG (ddd, eee, aaa, bbb, ccc, X[10], 15);
+ GGG (ccc, ddd, eee, aaa, bbb, X[14], 8);
+
+ /* parallel round 5 */
+ FFF (bbb, ccc, ddd, eee, aaa, X[12], 8);
+ FFF (aaa, bbb, ccc, ddd, eee, X[15], 5);
+ FFF (eee, aaa, bbb, ccc, ddd, X[10], 12);
+ FFF (ddd, eee, aaa, bbb, ccc, X[4], 9);
+ FFF (ccc, ddd, eee, aaa, bbb, X[1], 12);
+ FFF (bbb, ccc, ddd, eee, aaa, X[5], 5);
+ FFF (aaa, bbb, ccc, ddd, eee, X[8], 14);
+ FFF (eee, aaa, bbb, ccc, ddd, X[7], 6);
+ FFF (ddd, eee, aaa, bbb, ccc, X[6], 8);
+ FFF (ccc, ddd, eee, aaa, bbb, X[2], 13);
+ FFF (bbb, ccc, ddd, eee, aaa, X[13], 6);
+ FFF (aaa, bbb, ccc, ddd, eee, X[14], 5);
+ FFF (eee, aaa, bbb, ccc, ddd, X[0], 15);
+ FFF (ddd, eee, aaa, bbb, ccc, X[3], 13);
+ FFF (ccc, ddd, eee, aaa, bbb, X[9], 11);
+ FFF (bbb, ccc, ddd, eee, aaa, X[11], 11);
+
+ /* combine results */
+ ddd += cc + MDbuf[1]; /* final result for MDbuf[0] */
+ MDbuf[1] = MDbuf[2] + dd + eee;
+ MDbuf[2] = MDbuf[3] + ee + aaa;
+ MDbuf[3] = MDbuf[4] + aa + bbb;
+ MDbuf[4] = MDbuf[0] + bb + ccc;
+ MDbuf[0] = ddd;
+
+ return;
+}
+
+/********************************************************************/
+
+static void
+MDfinish (dword * MDbuf, const byte * strptr, dword lswlen, dword mswlen)
+{
+ unsigned int i; /* counter */
+ dword X[16]; /* message words */
+
+ grub_memset (X, 0, 16 * sizeof (dword));
+
+ /* put bytes from strptr into X */
+ for (i = 0; i < (lswlen & 63); i++)
+ {
+ /* byte i goes into word X[i div 4] at pos. 8*(i mod 4) */
+ X[i >> 2] ^= (dword) * strptr++ << (8 * (i & 3));
+ }
+
+ /* append the bit m_n == 1 */
+ X[(lswlen >> 2) & 15] ^= (dword) 1 << (8 * (lswlen & 3) + 7);
+
+ if ((lswlen & 63) > 55)
+ {
+ /* length goes to next block */
+ compress (MDbuf, X);
+ grub_memset (X, 0, 16 * sizeof (dword));
+ }
+
+ /* append length in bits */
+ X[14] = lswlen << 3;
+ X[15] = (lswlen >> 29) | (mswlen << 3);
+ compress (MDbuf, X);
+
+ return;
+}
+
+/*** GNU GRUB2 interface ***/
+
+#define RMDsize 160
+
+static grub_err_t
+grub_hash_rmd160_fn (grub_cipher_params_t params, char *out,
+ const char *in, grub_size_t insize)
+{
+ dword MDbuf[RMDsize / 32]; /* contains (A, B, C, D(, E)) */
+ dword X[16]; /* current 16-word chunk */
+ unsigned int i; /* counter */
+ dword nbytes; /* # of bytes not yet processed */
+
+ /* initialize */
+ MDinit (MDbuf);
+
+ /* process message in 16-word chunks */
+ for (nbytes = insize; nbytes > 63; nbytes -= 64)
+ {
+ for (i = 0; i < 16; i++)
+ {
+ X[i] = BYTES_TO_DWORD (in);
+ in += 4;
+ }
+ compress (MDbuf, X);
+ } /* length mod 64 bytes left */
+
+ /* finish: */
+ MDfinish (MDbuf, (const byte *) in, insize, 0);
+
+ for (i = 0; i < RMDsize / 8; i += 4)
+ {
+ out[i] = MDbuf[i >> 2]; /* implicit cast to byte */
+ out[i + 1] = (MDbuf[i >> 2] >> 8); /* extracts the 8 least */
+ out[i + 2] = (MDbuf[i >> 2] >> 16); /* significant bits. */
+ out[i + 3] = (MDbuf[i >> 2] >> 24);
+ }
+
+ return GRUB_ERR_NONE;
+}
+
+static struct grub_cipher grub_cipher_rmd160 = {
+ .name = "ripemd160",
+ .type = GRUB_CIPHER_TYPE_HASH,
+ .keysizes = (const unsigned int[]) {20},
+ .keysizes_length = 1,
+
+ .u.hash = {
+ .fn = grub_hash_rmd160_fn}
+};
+
+GRUB_MOD_INIT (ripemd160)
+{
+ grub_crypto_cipher_register (&grub_cipher_rmd160);
+}
+
+GRUB_MOD_FINI (ripemd160)
+{
+ grub_crypto_cipher_unregister (&grub_cipher_rmd160);
+}
diff -u -urNp grub2-orig/disk/devmapper.c grub2/disk/devmapper.c
--- grub2-orig/disk/devmapper.c 1970-01-01 01:00:00.000000000 +0100
+++ grub2/disk/devmapper.c 2008-02-03 18:00:07.702058279 +0100
@@ -0,0 +1,416 @@
+/*
+ * 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/arg.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_cipher_params_t cipher;
+ grub_disk_t srcdisk;
+
+ 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_delete_cipher (dev->cipher);
+ grub_free (dev);
+
+ return GRUB_ERR_NONE;
+}
+
+/* Hashes a passphrase into a key and stores it with cipher. */
+static grub_err_t
+set_passphrase (grub_crypto_t dev, grub_cipher_params_t hashparams,
+ const char *passphrase)
+{
+ char hash[MAX_KEYSIZE * 2], *p, *key = hash;
+ grub_err_t err = GRUB_ERR_NONE;
+ unsigned int round, i, size = dev->cipher->keysize,
+ len = hashparams->keysize;
+
+ /* Need no passphrase if there's no key */
+ if (size == 0)
+ return err;
+
+ /* Hack to support the "none" hash */
+ if (!grub_strcmp (hashparams->cipher->name, "none"))
+ len = hashparams->keysize = grub_strlen (passphrase);
+
+ if (size > MAX_KEYSIZE || len > MAX_KEYSIZE)
+ return grub_error (GRUB_ERR_BAD_ARGUMENT, "Requested key size too large");
+
+ 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;
+
+ if ((err =
+ grub_crypto_hash (hashparams, key, p,
+ grub_strlen (p))) != GRUB_ERR_NONE)
+ goto err_out;
+ }
+
+ err = grub_crypto_set_key (dev->cipher, hash);
+
+err_out:
+ grub_free (p);
+ return err;
+}
+
+/***** GRUB command line interface *****************************************/
+
+static int
+cipher_print_hook (grub_cipher_t cipher, void *data)
+{
+ grub_cipher_type_t type = (grub_cipher_type_t) data;
+
+ if (cipher->type == type)
+ grub_printf ("%s\n", cipher->name);
+
+ return 0;
+}
+
+/* List all known ciphers and hashes */
+static void
+list_ciphers (void)
+{
+ grub_printf ("Known ciphers:\n");
+ grub_crypto_cipher_iterate (cipher_print_hook,
+ (void *) GRUB_CIPHER_TYPE_CIPHER);
+
+ grub_printf ("\nKnown hashes:\n");
+ grub_crypto_cipher_iterate (cipher_print_hook,
+ (void *) GRUB_CIPHER_TYPE_HASH);
+}
+
+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},
+ {"list", 'l', 0, "list known ciphers and hashes", 0, ARG_TYPE_NONE},
+ {"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 (struct grub_arg_list *state, int argc, char **args)
+{
+ grub_disk_t disk;
+ grub_crypto_t newdev;
+ const char *cipher, *hash;
+ grub_cipher_params_t hashparams;
+ grub_err_t err = GRUB_ERR_NONE;
+ char *passphrase = "", cmdphrase[MAX_PASSPHRASE];
+
+ /* Check whether cipher list is requested */
+ if (state[5].set)
+ {
+ list_ciphers ();
+ return 0;
+ }
+
+ 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 */
+ if (!(newdev = grub_malloc (sizeof (struct grub_crypto))))
+ return grub_errno;
+ if (!(newdev->devname = grub_strdup (args[0])))
+ {
+ err = grub_errno;
+ goto err_out;
+ }
+ if (!(newdev->source_devname = grub_strdup (args[1])))
+ {
+ err = grub_errno;
+ goto err2_out;
+ }
+ newdev->has_partitions = state[1].set;
+ err =
+ grub_crypto_new_cipher (&newdev->cipher, cipher, GRUB_CIPHER_TYPE_CIPHER);
+ if (err != GRUB_ERR_NONE)
+ goto err3_out;
+ err = grub_crypto_new_cipher (&hashparams, hash, GRUB_CIPHER_TYPE_HASH);
+ if (err != GRUB_ERR_NONE)
+ goto err4_out;
+ newdev->srcdisk = NULL;
+ if (state[6].set)
+ newdev->cipher->keysize = grub_strtoul (state[6].arg, NULL, 10);
+
+ /* Get passphrase */
+ if (state[4].set) /* Passphrase supplied on commandline */
+ passphrase = state[4].arg;
+ else
+ {
+ if (grub_strcmp (cipher, "none"))
+ {
+ grub_cmdline_get ("Passphrase: ", cmdphrase, MAX_PASSPHRASE, '*',
+ 0);
+ passphrase = cmdphrase;
+ }
+ }
+ if ((err =
+ set_passphrase (newdev, hashparams, passphrase)) != GRUB_ERR_NONE)
+ goto errp_out;
+
+ /* Add new entry to list and return */
+ newdev->next = crypto_list;
+ crypto_list = newdev;
+
+ /* Error conditions */
+errp_out:
+ grub_crypto_delete_cipher (hashparams);
+ if (err == GRUB_ERR_NONE)
+ return 0;
+err4_out:
+ grub_crypto_delete_cipher (newdev->cipher);
+err3_out:
+ grub_free (newdev->source_devname);
+err2_out:
+ grub_free (newdev->devname);
+err_out:
+ grub_free (newdev);
+ return err;
+}
+
+/***** 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_cipher_params_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 = sector + i;
+
+ /* Set IV from raw sector number (plain mode) */
+ grub_memset (cipher->u.cipher.iv, 0, cipher->u.cipher.iv_length);
+ grub_memcpy (cipher->u.cipher.iv, &s,
+ MIN (sizeof (grub_disk_addr_t),
+ cipher->u.cipher.iv_length));
+
+ grub_crypto_decrypt_inplace (cipher, buf + (i << GRUB_DISK_SECTOR_BITS),
+ GRUB_DISK_SECTOR_SIZE);
+ }
+
+ 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_CRYPTO_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 *************************************/
+
+GRUB_MOD_INIT (devmapper)
+{
+ grub_register_command ("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_command ("devmap");
+ grub_disk_dev_unregister (&grub_crypto_dev);
+}
diff -u -urNp grub2-orig/include/grub/crypto.h grub2/include/grub/crypto.h
--- grub2-orig/include/grub/crypto.h 1970-01-01 01:00:00.000000000 +0100
+++ grub2/include/grub/crypto.h 2008-02-03 18:00:07.706058090 +0100
@@ -0,0 +1,125 @@
+/*
+ * crypto.h - GRUB cryptographic API
+ *
+ * Copyright (C) 2007 Simon Peter <dn.tlp@gmx.net>
+ */
+/*
+ * 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/>.
+ */
+
+#ifndef CRYPTO_H
+#define CRYPTO_H
+
+#include <grub/types.h>
+
+enum grub_cipher_type
+{
+ GRUB_CIPHER_TYPE_NONE = 0,
+ GRUB_CIPHER_TYPE_CIPHER,
+ GRUB_CIPHER_TYPE_HASH
+};
+
+typedef enum grub_cipher_type grub_cipher_type_t;
+
+struct grub_cipher_params;
+typedef struct grub_cipher_params *grub_cipher_params_t;
+
+struct grub_cipher
+{
+ const char *name;
+ grub_cipher_type_t type;
+ const unsigned int *keysizes, keysizes_length;
+
+ grub_err_t (*init) (grub_cipher_params_t);
+ void (*deinit) (grub_cipher_params_t);
+
+ union
+ {
+ struct
+ {
+ const unsigned int *ivsizes, ivsizes_length;
+
+ grub_err_t (*set_key) (grub_cipher_params_t, const char *key);
+ grub_err_t (*encrypt) (grub_cipher_params_t, char **out,
+ const char *in, grub_size_t * outsize,
+ grub_size_t insize);
+ grub_err_t (*decrypt) (grub_cipher_params_t, char **out,
+ const char *in, grub_size_t * outsize,
+ grub_size_t insize);
+ grub_err_t (*decrypt_inplace) (grub_cipher_params_t, char *buf,
+ grub_size_t size);
+ grub_err_t (*encrypt_inplace) (grub_cipher_params_t, char *buf,
+ grub_size_t size);
+ } cipher;
+
+ struct
+ {
+ grub_err_t (*fn) (grub_cipher_params_t, char *out, const char *in,
+ grub_size_t insize);
+ } hash;
+ } u;
+};
+
+typedef struct grub_cipher *grub_cipher_t;
+
+struct grub_cipher_params
+{
+ grub_cipher_t cipher;
+ void *private;
+ unsigned int keysize;
+
+ union
+ {
+ struct
+ {
+ unsigned char *iv;
+ unsigned int iv_length;
+ } cipher;
+ } u;
+};
+
+typedef int (*grub_crypto_hook) (grub_cipher_t, void *);
+
+grub_err_t EXPORT_FUNC (grub_crypto_encrypt) (grub_cipher_params_t params,
+ char **out, const char *in,
+ grub_size_t * outsize,
+ grub_size_t insize);
+grub_err_t EXPORT_FUNC (grub_crypto_decrypt) (grub_cipher_params_t params,
+ char **out, const char *in,
+ grub_size_t * outsize,
+ grub_size_t insize);
+grub_err_t EXPORT_FUNC (grub_crypto_decrypt_inplace) (grub_cipher_params_t
+ params, char *buf,
+ grub_size_t size);
+grub_err_t EXPORT_FUNC (grub_crypto_encrypt_inplace) (grub_cipher_params_t
+ params, char *buf,
+ grub_size_t size);
+grub_err_t EXPORT_FUNC (grub_crypto_set_key) (grub_cipher_params_t params,
+ const char *key);
+int EXPORT_FUNC (grub_crypto_cipher_iterate) (grub_crypto_hook hook,
+ void *data);
+grub_err_t EXPORT_FUNC (grub_crypto_hash) (grub_cipher_params_t params,
+ char *hash, const char *payload,
+ unsigned int size);
+grub_err_t EXPORT_FUNC (grub_crypto_new_cipher) (grub_cipher_params_t *
+ params, const char *name,
+ grub_cipher_type_t type);
+void EXPORT_FUNC (grub_crypto_delete_cipher) (grub_cipher_params_t params);
+void EXPORT_FUNC (grub_crypto_cipher_register) (grub_cipher_t cipher);
+void EXPORT_FUNC (grub_crypto_cipher_unregister) (grub_cipher_t cipher);
+
+#endif
diff -u -urNp grub2-orig/include/grub/disk.h grub2/include/grub/disk.h
--- grub2-orig/include/grub/disk.h 2008-01-21 00:20:36.000000000 +0100
+++ grub2/include/grub/disk.h 2008-02-03 17:57:44.811804654 +0100
@@ -37,6 +37,7 @@ enum grub_disk_dev_id
GRUB_DISK_DEVICE_HOST_ID,
GRUB_DISK_DEVICE_ATA_ID,
GRUB_DISK_DEVICE_MEMDISK_ID,
+ GRUB_DISK_DEVICE_CRYPTO_ID,
};
struct grub_disk;
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fw: Re: Strong Crypto Support for GRUB2
2008-07-20 23:49 Fw: Re: Strong Crypto Support for GRUB2 Simon Peter
@ 2008-07-21 0:20 ` Pavel Roskin
2008-07-21 9:22 ` Michael Gorven
2008-07-21 13:48 ` Colin D Bennett
2 siblings, 0 replies; 6+ messages in thread
From: Pavel Roskin @ 2008-07-21 0:20 UTC (permalink / raw)
To: The development of GRUB 2
On Mon, 2008-07-21 at 01:49 +0200, Simon Peter wrote:
> Did the message below ever arrive on the list?
...
> Date: Sun, 3 Feb 2008 18:25:47 +0100
> From: Simon Peter <simon.peter@gmx.de>
> To: The development of GRUB 2 <grub-devel@gnu.org>
> Cc: Marco Gerards <mgerards@xs4all.nl>, Robert Millan <rmh@aybabtu.com>
> Subject: Re: Strong Crypto Support for GRUB2
I don't see it in the archives for February 2008:
http://lists.gnu.org/archive/html/grub-devel/2008-02/index.html
No idea why. But this message did arrive.
--
Regards,
Pavel Roskin
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Fw: Re: Strong Crypto Support for GRUB2
2008-07-20 23:49 Fw: Re: Strong Crypto Support for GRUB2 Simon Peter
2008-07-21 0:20 ` Pavel Roskin
@ 2008-07-21 9:22 ` Michael Gorven
2008-07-21 13:48 ` Colin D Bennett
2 siblings, 0 replies; 6+ messages in thread
From: Michael Gorven @ 2008-07-21 9:22 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]
On Monday 21 July 2008 01:49:52 Simon Peter wrote:
> I'm still interested in getting strong crypto into grub mainline and
> while it's still not in, I just saw you guys proposed this as a project
> for Google's summer of code. Are you going to point students at the
> code I already produced? Would be a shame if you have someone replicate
> the work already done.
Hi Simon
I've been working on a LUKS module[1] for GRUB, and have used your patch as a
starting point. I have added a few extra functions to the crypto module, and
implemented CBC in the crypto module itself. I have also added a number of
ciphers and hashes[2]. I am still waiting for a proper review of my patch,
and for some license issues to be resolved. I think that my changes have
broken the devmapper module, but I intend to implement that functionality in
the LUKS module some time.
Michael
[1] http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00127.html
[2] http://lists.gnu.org/archive/html/grub-devel/2008-05/msg00157.html
--
http://michael.gorven.za.net
PGP Key ID 6612FE85
S/MIME Key ID D33AEB31
[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Strong Crypto Support for GRUB2
2008-07-20 23:49 Fw: Re: Strong Crypto Support for GRUB2 Simon Peter
2008-07-21 0:20 ` Pavel Roskin
2008-07-21 9:22 ` Michael Gorven
@ 2008-07-21 13:48 ` Colin D Bennett
2008-07-21 20:38 ` Simon Peter
2 siblings, 1 reply; 6+ messages in thread
From: Colin D Bennett @ 2008-07-21 13:48 UTC (permalink / raw)
To: The development of GRUB 2; +Cc: dn.tlp
On Mon, 21 Jul 2008 01:49:52 +0200
Simon Peter <dn.tlp@gmx.net> wrote:
> Did the message below ever arrive on the list?
>
> I'm still interested in getting strong crypto into grub mainline and
> while it's still not in, I just saw you guys proposed this as a
> project for Google's summer of code. Are you going to point students
> at the code I already produced? Would be a shame if you have someone
> replicate the work already done.
>
> What's missing to get my code into GRUB2 mainline?
I think you'll have to assign copyright to the FSF.
Regards,
Colin
> Thanks!
> Simon
>
> Begin forwarded message:
>
> Date: Sun, 3 Feb 2008 18:25:47 +0100
> From: Simon Peter <simon.peter@gmx.de>
> To: The development of GRUB 2 <grub-devel@gnu.org>
> Cc: Marco Gerards <mgerards@xs4all.nl>, Robert Millan
> <rmh@aybabtu.com> Subject: Re: Strong Crypto Support for GRUB2
>
>
> > Sorry for the *very* late reply.
>
> Sorry for my late reply. I wasn't subscribed anymore (and I'm still
> not) and only now I found out that you replied...
>
> Attached is my patch against current CVS with the changes you proposed
> incorporated.
>
> I'd appreciate very much if you could review this complete patch
> again. Sorry for any inconvenience with my first weird double-patch.
>
> > > +int
> > > +aes_self_test (int verbose)
> > > {
> [...]
> > > + printf ("passed\n");
> > Where does printf come from?
>
> It's in a self-test routine that's actually never included in the GRUB
> source. Shall I remove the whole thing?
>
> Thanks!
> Simon
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Strong Crypto Support for GRUB2
2008-07-21 13:48 ` Colin D Bennett
@ 2008-07-21 20:38 ` Simon Peter
2008-07-22 22:12 ` Robert Millan
0 siblings, 1 reply; 6+ messages in thread
From: Simon Peter @ 2008-07-21 20:38 UTC (permalink / raw)
To: Colin D Bennett; +Cc: The development of GRUB 2
> > What's missing to get my code into GRUB2 mainline?
> I think you'll have to assign copyright to the FSF.
What part of it?
I learned that Michael Gorven already replaced the problematic parts
(RIPEMD and AES) with versions from libgcrypt. The rest of the code is
all GPL3. Is it about the extra copyright line with my name in it?
Simon
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Strong Crypto Support for GRUB2
2008-07-21 20:38 ` Simon Peter
@ 2008-07-22 22:12 ` Robert Millan
0 siblings, 0 replies; 6+ messages in thread
From: Robert Millan @ 2008-07-22 22:12 UTC (permalink / raw)
To: The development of GRUB 2; +Cc: Colin D Bennett
On Mon, Jul 21, 2008 at 10:38:37PM +0200, Simon Peter wrote:
> > > What's missing to get my code into GRUB2 mainline?
> > I think you'll have to assign copyright to the FSF.
>
> What part of it?
>
> I learned that Michael Gorven already replaced the problematic parts
> (RIPEMD and AES) with versions from libgcrypt.
That sounds very good. I think it was the stumbling block last time.
I expect Marco or Okuji will contact you soon about copyright assignment.
If they haven't already, you might want to mail them a reminder.
--
Robert Millan
<GPLv2> I know my rights; I want my phone call!
<DRM> What good is a phone call… if you are unable to speak?
(as seen on /.)
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-07-22 22:13 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-20 23:49 Fw: Re: Strong Crypto Support for GRUB2 Simon Peter
2008-07-21 0:20 ` Pavel Roskin
2008-07-21 9:22 ` Michael Gorven
2008-07-21 13:48 ` Colin D Bennett
2008-07-21 20:38 ` Simon Peter
2008-07-22 22:12 ` Robert Millan
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.