From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with archive (Exim 4.43) id 1NA1wS-0005Iw-TJ for mharc-grub-devel@gnu.org; Mon, 16 Nov 2009 08:48:28 -0500 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NA1wP-0005IR-SI for grub-devel@gnu.org; Mon, 16 Nov 2009 08:48:25 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NA1wK-0005FQ-Vz for grub-devel@gnu.org; Mon, 16 Nov 2009 08:48:25 -0500 Received: from [199.232.76.173] (port=33968 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NA1wK-0005FN-Ph for grub-devel@gnu.org; Mon, 16 Nov 2009 08:48:20 -0500 Received: from mail-fx0-f225.google.com ([209.85.220.225]:42343) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1NA1wJ-0006U8-CV for grub-devel@gnu.org; Mon, 16 Nov 2009 08:48:20 -0500 Received: by fxm25 with SMTP id 25so568999fxm.26 for ; Mon, 16 Nov 2009 05:48:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:subject:x-enigmail-version:content-type; bh=GL7T2BzcyiFZMkEXMB9nUitoNjATV14GDRV9by1Pj9k=; b=MJNp9tz6uRD/KsPk77UwQrEOZ05JshYr92MpdKZzekn8aCEOQ0umg1BQh7uo7P1lLF w4KSpg3bM6rArg5RO2dmb4u6pmH1mrt3vYGuCHLtm6r6kzXTA0JyxrcErWU+G8qqveJr LeiS1DI04fsIPv9Z/N2LGZGVIJJ0EfmG6e+Ug= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:subject :x-enigmail-version:content-type; b=nVrs4wU9RSV8jmYb/M9a9R9ct8GVy4Go8LYupQBYFRt25aWP/xt4Q8ZBL/ZPWMksZa 052p1Oy7zndDuX+iV/LaPrxE8HJF0CN2GEFHrl1UHaiKEW7pzQCCE44g5sHIJONJkugN MxKT4L8QYF7muERuI3imzsWMMFV+ae+enxZWM= Received: by 10.216.85.213 with SMTP id u63mr697859wee.15.1258379297399; Mon, 16 Nov 2009 05:48:17 -0800 (PST) Received: from debian.bg45.phnet (gprs25.swisscom-mobile.ch [193.247.250.25]) by mx.google.com with ESMTPS id 5sm4581831eyf.10.2009.11.16.05.48.14 (version=TLSv1/SSLv3 cipher=RC4-MD5); Mon, 16 Nov 2009 05:48:16 -0800 (PST) Message-ID: <4B015812.3040808@gmail.com> Date: Mon, 16 Nov 2009 14:48:02 +0100 From: Vladimir 'phcoder' Serbinenko User-Agent: Mozilla-Thunderbird 2.0.0.22 (X11/20091109) MIME-Version: 1.0 To: The development of GRUB 2 X-Enigmail-Version: 0.95.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="------------enig8D0190306784532FEEC90432" X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Subject: [PATCH] Cryptography X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: The development of GNU GRUB List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Nov 2009 13:48:26 -0000 This is an OpenPGP/MIME signed message (RFC 2440 and 3156) --------------enig8D0190306784532FEEC90432 Content-Type: multipart/mixed; boundary="------------050900020706070405070005" This is a multi-part message in MIME format. --------------050900020706070405070005 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable 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 . 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 --=20 Regards Vladimir 'phcoder' Serbinenko --------------050900020706070405070005 Content-Type: text/x-diff; name="crypto.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline; filename="crypto.diff" =3D=3D=3D 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 =3D=3D=3D 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 @@ */ =20 #include +#include #include #include #include @@ -26,18 +27,20 @@ =20 static grub_dl_t my_mod; =20 +#define MAX_PASSLEN 1024 + static grub_err_t check_password (const char *user, void *password) { - char entered[1024]; + char entered[MAX_PASSLEN]; =20 grub_memset (entered, 0, sizeof (entered)); =20 if (!GRUB_GET_PASSWORD (entered, sizeof (entered) - 1)) return GRUB_ACCESS_DENIED; =20 - if (grub_auth_strcmp (entered, password) !=3D 0) + if (grub_crypto_memcmp (entered, password, MAX_PASSLEN) !=3D 0) return GRUB_ACCESS_DENIED; =20 grub_auth_authenticate (user); @@ -51,13 +54,18 @@ { grub_err_t err; char *pass; + int copylen; =20 if (argc !=3D 2) return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.")= ; =20 - pass =3D grub_strdup (args[1]); + pass =3D grub_zalloc (MAX_PASSLEN); if (!pass) return grub_errno; + copylen =3D grub_strlen (args[1]); + if (copylen >=3D MAX_PASSLEN) + copylen =3D MAX_PASSLEN - 1; + grub_memcpy (pass, args[1], copylen); =20 err =3D grub_auth_register_authentication (args[0], check_password, pa= ss); if (err) =3D=3D=3D 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 = + * + * 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 . + */ + +#include +#include +#include +#include +#include +#include +#include + +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 =3D 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 =3D grub_malloc (pass->buflen); + if (!buf) + return grub_crypto_gcry_error (GPG_ERR_OUT_OF_MEMORY); + + err =3D 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) !=3D 0) + return GRUB_ACCESS_DENIED; + + grub_auth_authenticate (user); + + return GRUB_ERR_NONE; +} + +static inline int +hex2val (char hex) +{ + if ('0' <=3D hex && hex <=3D '9') + return hex - '0'; + if ('a' <=3D hex && hex <=3D 'f') + return hex - 'a' + 10; + if ('A' <=3D hex && hex <=3D '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 !=3D 2) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Two arguments expected.")= ; + + if (grub_memcmp (args[1], "grub.pbkdf2.sha512.", + sizeof ("grub.pbkdf2.sha512.") - 1) !=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 password= =2E"); + + ptr =3D args[1] + sizeof ("grub.pbkdf2.sha512.") - 1; + + pass =3D grub_malloc (sizeof (*pass)); + if (!pass) + return grub_errno; + + pass->c =3D grub_strtoul (ptr, &ptr, 0); + if (*ptr !=3D '.') + { + grub_free (pass); + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Incorrect PBKDF2 passwo= rd."); + } + ptr++; + + ptr2 =3D 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 passwo= rd."); + } + + pass->saltlen =3D (ptr2 - ptr) >> 1; + pass->buflen =3D grub_strlen (ptr2 + 1) >> 1; + ptro =3D pass->salt =3D grub_malloc (pass->saltlen); + if (!ptro) + { + grub_free (pass); + return grub_errno; + } + while (ptr < ptr2) + { + int hex1, hex2; + hex1 =3D hex2val (*ptr); + ptr++; + hex2 =3D 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 =3D (hex1 << 4) | hex2; + ptro++; + } + + ptro =3D pass->expected =3D grub_malloc (pass->buflen); + if (!ptro) + { + grub_free (pass->salt); + grub_free (pass); + return grub_errno; + } + ptr =3D ptr2 + 1; + ptr2 +=3D grub_strlen (ptr2);=20 + while (ptr < ptr2) + { + int hex1, hex2; + hex1 =3D hex2val (*ptr); + ptr++; + hex2 =3D 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 =3D (hex1 << 4) | hex2; + ptro++; + } + + err =3D grub_auth_register_authentication (args[0], check_password, pa= ss); + if (err) + { + grub_free (pass); + return err; + } + grub_dl_ref (my_mod); + return GRUB_ERR_NONE; +} + +static grub_command_t cmd; +=0C +GRUB_MOD_INIT(password_pbkdf2) +{ + my_mod =3D mod; + cmd =3D 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); +} =3D=3D=3D 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 #include #include - -struct tohash -{ - grub_uint8_t prefix[16]; - grub_uint64_t serial; -} __attribute__ ((packed)); +#include =20 /* This prefix is used by xnu and boot-132 to hash=20 together with volume serial. */ @@ -44,311 +39,27 @@ =3D {0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6,=20 0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC}; =20 -#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 =3D context; - - ctx->A =3D 0x67452301; - ctx->B =3D 0xefcdab89; - ctx->C =3D 0x98badcfe; - ctx->D =3D 0x10325476; - - ctx->nblocks =3D 0; - ctx->count =3D 0; -} - -/* These are the four functions used in the four steps of the MD5 algori= thm - and defined in the RFC 1321. The first function is a little bit opti= mized - (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 =3D ctx->A; - register grub_uint32_t B =3D ctx->B; - register grub_uint32_t C =3D ctx->C; - register grub_uint32_t D =3D ctx->D; - grub_uint32_t *cwp =3D correct_words; - -#ifdef GRUB_CPU_WORDS_BIGENDIAN - { - int i; - const grub_uint32_t *p =3D (const grub_uint32_t *) data; - - for (i =3D 0; i < 16; i++) - correct_words[i] =3D grub_le_to_cpu32 (p[i]); - } -#else - grub_memcpy (correct_words, data, 64); -#endif - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a +=3D FF (b, c, d) + (*cwp++) + T; \ - a =3D rol(a, s); \ - a +=3D b; \ - } \ - while (0) - - /* Before we start, one word about the strange constants. - They are defined in RFC 1321 as - - T[i] =3D (int) (4294967296.0 * fabs (sin (i))), i=3D1..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 +=3D f (b, c, d) + correct_words[k] + T; \ - a =3D rol(a, s); \ - a +=3D 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 +=3D A; - ctx->B +=3D B; - ctx->C +=3D C; - ctx->D +=3D 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 =3D inbuf_arg; - MD5_CONTEXT *hd =3D context; - - if( hd->count =3D=3D 64 ) /* flush the buffer */ - { - transform( hd, hd->buf ); - // _gcry_burn_stack (80+6*sizeof(void*)); - hd->count =3D 0; - hd->nblocks++; - } - if( !inbuf ) - return; - - if( hd->count ) - { - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] =3D *inbuf++; - md5_write( hd, NULL, 0 ); - if( !inlen ) - return; - } - // _gcry_burn_stack (80+6*sizeof(void*)); - - while( inlen >=3D 64 )=20 - { - transform( hd, inbuf ); - hd->count =3D 0; - hd->nblocks++; - inlen -=3D 64; - inbuf +=3D 64; - } - for( ; inlen && hd->count < 64; inlen-- ) - hd->buf[hd->count++] =3D *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 =3D context; - grub_uint32_t t, msb, lsb; - grub_uint32_t *p; - - md5_write(hd, NULL, 0); /* flush */; - - t =3D hd->nblocks; - /* multiply by 64 to make a grub_uint8_t count */ - lsb =3D t << 6; - msb =3D t >> 26; - /* add the count */ - t =3D lsb; - if( (lsb +=3D hd->count) < t ) - msb++; - /* multiply by 8 to make a bit count */ - t =3D lsb; - lsb <<=3D 3; - msb <<=3D 3; - msb |=3D t >> 29; - - if( hd->count < 56 ) /* enough room */ - { - hd->buf[hd->count++] =3D 0x80; /* pad */ - while( hd->count < 56 ) - hd->buf[hd->count++] =3D 0; /* pad */ - } - else /* need one extra block */ - { - hd->buf[hd->count++] =3D 0x80; /* pad character */ - while( hd->count < 64 ) - hd->buf[hd->count++] =3D 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] =3D lsb ; - hd->buf[57] =3D lsb >> 8; - hd->buf[58] =3D lsb >> 16; - hd->buf[59] =3D lsb >> 24; - hd->buf[60] =3D msb ; - hd->buf[61] =3D msb >> 8; - hd->buf[62] =3D msb >> 16; - hd->buf[63] =3D msb >> 24; - transform( hd, hd->buf ); - // _gcry_burn_stack (80+6*sizeof(void*)); - - p =3D (grub_uint32_t *) hd->buf; -#define X(a) do { *p =3D 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]; =20 if (argc < 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "UUID required"); =20 - hashme.serial =3D 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 =3D 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 =3D 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], =3D=3D=3D 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 =3D lib/$(target_cpu)/setjmp.S setjmp_mod_ASFLAGS =3D $(COMMON_ASFLAGS) setjmp_mod_LDFLAGS =3D $(COMMON_LDFLAGS) + +pkglib_MODULES +=3D crypto.mod +crypto_mod_SOURCES =3D lib/crypto.c +crypto_mod_CFLAGS =3D $(COMMON_CFLAGS) +crypto_mod_LDFLAGS =3D $(COMMON_LDFLAGS) + +pkglib_MODULES +=3D devmapper.mod +devmapper_mod_SOURCES =3D disk/devmapper.c +devmapper_mod_CFLAGS =3D $(COMMON_CFLAGS) +devmapper_mod_LDFLAGS =3D $(COMMON_LDFLAGS) + +pkglib_MODULES +=3D pbkdf2.mod +pbkdf2_mod_SOURCES =3D lib/pbkdf2.c +pbkdf2_mod_CFLAGS =3D $(COMMON_CFLAGS) +pbkdf2_mod_LDFLAGS =3D $(COMMON_LDFLAGS) + +# For password_pbkdf2.mod. +pkglib_MODULES +=3D password_pbkdf2.mod +password_pbkdf2_mod_SOURCES =3D commands/password_pbkdf2.c +password_pbkdf2_mod_CFLAGS =3D $(COMMON_CFLAGS) +password_pbkdf2_mod_LDFLAGS =3D $(COMMON_LDFLAGS) + +bin_UTILITIES +=3D grub-pbkdf2 +grub_pbkdf2_SOURCES =3D util/grub-pbkdf2.c lib/crypto.c gcry/cipher/sha5= 12.c lib/pbkdf2.c util/misc.c kern/err.c + +include $(srcdir)/conf/gcry.mk =3D=3D=3D 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 \ =3D=3D=3D 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 \ =3D=3D=3D 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 \ =3D=3D=3D 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 \ =3D=3D=3D 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= =2Ec \ normal/menu.c \ normal/menu_text.c \ normal/menu_entry.c normal/menu_viewer.c \ =3D=3D=3D 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= =2Ec \ normal/menu.c \ normal/menu_text.c \ normal/menu_entry.c normal/menu_viewer.c \ =3D=3D=3D 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 \ =3D=3D=3D 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 + * Thanks to Raoul Boenisch 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 . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D 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 =3D crypto_list, prev =3D &crypto_list; dev; + prev =3D &dev->next, dev =3D dev->next) + if (grub_strcmp (dev->devname, name) =3D=3D 0) + break; + + if (!dev) + return grub_error (GRUB_ERR_BAD_DEVICE, "Device not found"); + + /* Remove the device from the list */ + *prev =3D 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 =3D hash; + char *p; + unsigned int round, i, size =3D dev->keysize; + unsigned int len; + + /* Need no passphrase if there's no key */ + if (size =3D=3D 0) + return GPG_ERR_INV_KEYLEN; + + /* Hack to support the "none" hash */ + if (hashparams) + len =3D hashparams->mdlen; + else + len =3D grub_strlen (passphrase); + + if (size > MAX_KEYSIZE || len > MAX_KEYSIZE) + return GPG_ERR_INV_KEYLEN; + + p =3D grub_malloc (grub_strlen (passphrase) + 2 + size / len); + if (!p) + return grub_errno; + + for (round =3D 0; size; round++, key +=3D len, size -=3D len) + { + /* hack from hashalot to avoid null bytes in key */ + for (i =3D 0; i < round; i++) + p[i] =3D 'A'; + + grub_strcpy (p + i, passphrase); + + if (len > size) + len =3D 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[] =3D { + {"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=3D" DEFAULT_CIPHER ")", 0, + ARG_TYPE_STRING}, + {"hash", 'h', 0, "set hash function (default=3D" 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 =3D GRUB_ERR_NONE; + char *passphrase =3D ""; + /* char cmdphrase[MAX_PASSPHRASE]; */ + const gcry_cipher_spec_t *ciph; + struct grub_arg_list *state =3D 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 requir= ed"); + + /*** Create device is requested ***/ + + /* Choke on already existing devices */ + for (newdev =3D crypto_list; newdev !=3D NULL; newdev =3D newdev->next= ) + if (grub_strcmp (newdev->devname, args[0]) =3D=3D 0) + return grub_error (GRUB_ERR_BAD_ARGUMENT, "Device already exists")= ; + + /* Check whether source device can be opened */ + disk =3D grub_disk_open (args[1]); + if (!disk) + return grub_errno; + grub_disk_close (disk); + + /* Parse remaining options */ + if (state[2].set) + cipher =3D state[2].arg; + else + cipher =3D DEFAULT_CIPHER; + if (state[3].set) + hash =3D state[3].arg; + else + hash =3D DEFAULT_HASH; + + /* Create new device entry */ + newdev =3D grub_malloc (sizeof (struct grub_crypto)); + if (!newdev) + return grub_errno; + newdev->devname =3D grub_strdup (args[0]); + if (!newdev->devname) + { + grub_free (newdev); + return grub_errno; + } + newdev->source_devname =3D grub_strdup (args[1]); + if (!newdev->source_devname) + { + grub_free (newdev->devname); + grub_free (newdev); + return grub_errno; + } + newdev->has_partitions =3D state[1].set; + ciph =3D 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 =3D grub_crypto_cipher_open (ciph); + if (!newdev->cipher) + { + grub_free (newdev->source_devname); + grub_free (newdev->devname); + grub_free (newdev); + return grub_errno; + } + hashparams =3D 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 =3D NULL; + if (state[5].set) + newdev->keysize =3D grub_strtoul (state[5].arg, NULL, 10); + else + newdev->keysize =3D 16; + + /* Get passphrase */ + if (state[4].set) /* Passphrase supplied on commandline */ + passphrase =3D state[4].arg; + else + { +#if 1 + return 0; +#else + if (grub_strcmp (cipher, "none")) + { + grub_cmdline_get ("Passphrase: ", cmdphrase, MAX_PASSPHRASE, '*', + 0); + passphrase =3D cmdphrase; + } +#endif + } + err =3D 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 =3D crypto_list; + crypto_list =3D 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 =3D crypto_list; i !=3D NULL; i =3D 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 =3D crypto_list; dev !=3D NULL; dev =3D dev->next) + if (grub_strcmp (dev->devname, name) =3D=3D 0) + break; + + if (!dev) + return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "Can't open device"); + + /* Setup crypto private structure */ + if (!(private =3D grub_malloc (sizeof (struct crypto_private)))) + return grub_errno; + private->crypto =3D dev; + + /* Open underlying device */ + private->srcdisk =3D grub_disk_open (dev->source_devname); + if (!private->srcdisk) + { + return grub_errno; + } + + /* Populate requested disk */ + disk->total_sectors =3D grub_disk_get_size (private->srcdisk); + disk->id =3D (int) dev; + disk->has_partitions =3D dev->has_partitions; + disk->data =3D private; + + return 0; +} + +static void +grub_crypto_close (grub_disk_t disk) +{ + crypto_private_t private =3D (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 =3D (crypto_private_t) disk->data; + grub_err_t err; + grub_crypto_cipher_handle_t cipher =3D private->crypto->cipher; + grub_size_t i; + + /* Read sectors from underlying disk */ + err =3D + grub_disk_read (private->srcdisk, sector, 0, + size << GRUB_DISK_SECTOR_BITS, buf); + if (err) + return err; + + /* Decrypt sectors */ + for (i =3D 0; i < size; i++) + { + grub_disk_addr_t s =3D 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 =3D 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 =3D { + .name =3D "crypto", + .id =3D GRUB_DISK_DEVICE_DEVMAP_ID, + .iterate =3D grub_crypto_iterate, + .open =3D grub_crypto_open, + .close =3D grub_crypto_close, + .read =3D grub_crypto_read, + .write =3D grub_crypto_write, + .next =3D 0 +}; + +/***** GRUB module (de-)initialization *********************************= ****/ + +static grub_extcmd_t cmd; + +GRUB_MOD_INIT (devmapper) +{ + cmd =3D 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); +} =3D=3D=3D 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 . +#* + +import re +import sys +import os +import datetime + +if len (sys.argv) < 3: + print ("Usage: %s SOURCE DESTINATION" % sys.argv[0]) + exit (0) +indir =3D sys.argv[1] +outdir =3D sys.argv[2] + +basedir =3D os.path.join (outdir, "gcry") +try: + os.makedirs (basedir) +except: + print ("WARNING: %s already exists" % basedir) +cipher_dir_in =3D os.path.join (indir, "cipher") +cipher_dir_out =3D os.path.join (basedir, "cipher") +try: + os.makedirs (cipher_dir_out) +except: + print ("WARNING: %s already exists" % cipher_dir_out) + +cipher_files =3D os.listdir (cipher_dir_in) +conf =3D open (os.path.join (outdir, "conf", "gcry.rmk"), "w") +conf.write ("# -*- makefile -*-\n\n") +chlog =3D "" + +# 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 =3D {"_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 =3D os.path.join (cipher_dir_in, cipher_file) + outfile =3D os.path.join (cipher_dir_out, cipher_file) + if cipher_file =3D=3D "ChangeLog": + continue + chlognew =3D " * %s" % cipher_file + nch =3D False + if re.match (".*\.[ch]$", cipher_file): + isc =3D re.match (".*\.c$", cipher_file) + f =3D open (infile, "r") + fw =3D open (outfile, "w") + fw.write ("/* This file was automatically imported with \n") + fw.write (" import_gcry.py. Please don't modify it */\n"); + ciphernames =3D [] + mdnames =3D [] + hold =3D False + skip =3D False + skip2 =3D False + ismd =3D False + iscomma =3D False + for line in f: + if skip: + if line[0] =3D=3D "}": + skip =3D False + continue + if skip2: + if not re.search (" *};", line) is None: + skip2 =3D 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 =3D %s\n" % mdblocksizes [= mdname]) + ismd =3D False + iscomma =3D not re.search (",$", line) is None + if hold: + hold =3D False + # We're optimising for size. + if not re.match ("(run_selftests|selftest|_gcry_aes_c.._= =2E.c|_gcry_[a-z0-9]*_hash_buffer)", line) is None: + skip =3D True + fname =3D re.match ("[a-zA-Z0-9_]*", line).group () + chmsg =3D "(%s): Removed." % fname + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s %s" % (chlognew, chmsg) + nch =3D True + continue + else: + fw.write (holdline) + m =3D re.match ("#include <.*>", line) + if not m is None: + chmsg =3D "Removed including of %s" % \ + m.group () [len ("#include <"):len (m.group ()) - 1] + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s: %s" % (chlognew, chmsg) + nch =3D True + continue + m =3D re.match ("gcry_cipher_spec_t", line) + if isc and not m is None: + ciphername =3D line [len ("gcry_cipher_spec_t"):].strip = () + ciphername =3D re.match("[a-zA-Z0-9_]*",ciphername).grou= p () + ciphernames.append (ciphername) + m =3D re.match ("gcry_md_spec_t", line) + if isc and not m is None: + assert (not ismd) + mdname =3D line [len ("gcry_md_spec_t"):].strip () + mdname =3D re.match("[a-zA-Z0-9_]*",mdname).group () + mdnames.append (mdname) + ismd =3D True + m =3D re.match ("static const char \*selftest.*;$", line) + if not m is None: + fname =3D line[len ("static const char \*"):] + fname =3D re.match ("[a-zA-Z0-9_]*", fname).group () + chmsg =3D "(%s): Removed declaration." % fname + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s %s" % (chlognew, chmsg) + nch =3D True + continue + m =3D re.match ("(static const char( |)\*|static gpg_err_cod= e_t|void)$", line) + if not m is None: + hold =3D True + holdline =3D line + continue + m =3D re.match ("cipher_extra_spec_t", line) + if isc and not m is None: + skip2 =3D True + fname =3D line[len ("cipher_extra_spec_t "):] + fname =3D re.match ("[a-zA-Z0-9_]*", fname).group () + chmsg =3D "(%s): Removed." % fname + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s %s" % (chlognew, chmsg) + nch =3D True + continue + m =3D re.match ("md_extra_spec_t", line) + if isc and not m is None: + skip2 =3D True + fname =3D line[len ("md_extra_spec_t "):] + fname =3D re.match ("[a-zA-Z0-9_]*", fname).group () + chmsg =3D "(%s): Removed." % fname + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s %s" % (chlognew, chmsg) + nch =3D True + continue + fw.write (line) + if len (ciphernames) > 0 or len (mdnames) > 0: + modname =3D cipher_file [0:len(cipher_file) - 2] + if re.match (".*-glue$", modname): + modfiles =3D "gcry/cipher/%s gcry/cipher/%s" \ + % (cipher_file, cipher_file.replace ("-glue.c", ".c"= )) + modname =3D modname.replace ("-glue", "") + else: + modfiles =3D "gcry/cipher/%s" % cipher_file + modname =3D "gcry_%s" % modname + chmsg =3D "(GRUB_MOD_INIT(%s)): New function\n" % modname + if nch: + chlognew =3D "%s\n %s" % (chlognew, chmsg) + else: + chlognew =3D "%s%s" % (chlognew, chmsg) + nch =3D True + fw.write ("\n\nGRUB_MOD_INIT(%s)\n" % modname) + fw.write ("{\n") + for ciphername in ciphernames: + chmsg =3D "Register cipher %s" % ciphername + chlognew =3D "%s\n %s" % (chlognew, chmsg) + fw.write (" grub_cipher_register (&%s);\n" % ciphername= ) + for mdname in mdnames: + chmsg =3D "Register digest %s" % mdname + chlognew =3D "%s\n %s" % (chlognew, chmsg) + fw.write (" grub_md_register (&%s);\n" % mdname) + fw.write ("}") + chmsg =3D "(GRUB_MOD_FINI(%s)): New function\n" % modname + chlognew =3D "%s\n %s" % (chlognew, chmsg) + fw.write ("\n\nGRUB_MOD_FINI(%s)\n" % modname) + fw.write ("{\n") + for ciphername in ciphernames: + chmsg =3D "Unregister cipher %s" % ciphername + chlognew =3D "%s\n %s" % (chlognew, chmsg) + fw.write (" grub_cipher_unregister (&%s);\n" % cipherna= me) + for mdname in mdnames: + chmsg =3D "Unregister MD %s" % mdname + chlognew =3D "%s\n %s" % (chlognew, chmsg) + fw.write (" grub_md_unregister (&%s);\n" % mdname) + fw.write ("}\n") + conf.write ("pkglib_MODULES +=3D %s.mod\n" % modname) + conf.write ("%s_mod_SOURCES =3D %s\n" %\ + (modname, modfiles)) + conf.write ("%s_mod_CFLAGS =3D $(COMMON_CFLAGS) -Wno-missing= -field-initializers -Wno-error\n" % modname) + conf.write ("%s_mod_LDFLAGS =3D $(COMMON_LDFLAGS)\n\n" % mod= name) + elif isc and cipher_file !=3D "camellia.c": + print ("WARNING: C file isn't a module: %s" % cipher_file) + f.close () + fw.close () + if nch: + chlog =3D "%s%s\n" % (chlog, chlognew) + continue + if re.match ("(Manifest|Makefile\.am)$", cipher_file): + chlog =3D "%s%sRemoved\n" % (chlog, chlognew) + continue + # Autogenerated files. Not even worth mentionning in ChangeLog + if re.match ("Makefile\.in$", cipher_file): + chlog =3D "%s%sRemoved\n" % (chlog, chlognew) + continue + chlog =3D "%s%sSkipped unknown file\n" % (chlog, chlognew) + print ("WARNING: unknown file %s" % cipher_file) + +outfile =3D os.path.join (cipher_dir_out, "types.h") +fw=3Dopen (outfile, "w") +fw.write ("#include \n") +fw.write ("#include \n") +chlog =3D "%s * types.h: New file.\n" % chlog +fw.close () + +outfile =3D os.path.join (cipher_dir_out, "memory.h") +fw=3Dopen (outfile, "w") +fw.write ("#include \n") +chlog =3D "%s * memory.h: New file.\n" % chlog +fw.close () + + +outfile =3D os.path.join (cipher_dir_out, "cipher.h") +fw=3Dopen (outfile, "w") +fw.write ("#include \n") +fw.write ("#include \n") +chlog =3D "%s * cipher.h: Likewise.\n" % chlog +fw.close () + +outfile =3D os.path.join (cipher_dir_out, "g10lib.h") +fw=3Dopen (outfile, "w") +fw.write ("#include \n") +chlog =3D "%s * g10lib.h: Likewise.\n" % chlog +fw.close () + +infile =3D os.path.join (cipher_dir_in, "ChangeLog") +outfile =3D os.path.join (cipher_dir_out, "ChangeLog") + + +f=3Dopen (infile, "r") +fw=3Dopen (outfile, "w") +dt =3D 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 () =3D=3D=3D 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 . */ -#ifndef GRUB_AURH_HEADER +#ifndef GRUB_AUTH_HEADER #define GRUB_AUTH_HEADER 1 =20 #include @@ -26,11 +26,6 @@ string, len, \ '*', 0, 0) =20 -/* 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 *); =20 grub_err_t grub_auth_register_authentication (const char *user, =3D=3D=3D 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 . + */ + +#ifndef GRUB_GCRY_WRAP_HEADER +#define GRUB_GCRY_WRAP_HEADER 1 + +#include +#include +#include +#include +#include + +#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 =3D=3D=3D 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 . + */ + +/* 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 +#include +#include +/* For GRUB_ACCESS_DENIED. */ +#include + +typedef enum=20 + { + 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=20 + { + GCRY_CIPHER_MODE_NONE =3D 0, /* Not yet specified. */ + GCRY_CIPHER_MODE_ECB =3D 1, /* Electronic codebook. */ + GCRY_CIPHER_MODE_CFB =3D 2, /* Cipher feedback. */ + GCRY_CIPHER_MODE_CBC =3D 3, /* Cipher block chaining. */ + GCRY_CIPHER_MODE_STREAM =3D 4, /* Used with stream ciphers. */ + GCRY_CIPHER_MODE_OFB =3D 5, /* Outer feedback. */ + GCRY_CIPHER_MODE_CTR =3D 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 n= bytes); + +/* 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=20 +grub_cipher_register (gcry_cipher_spec_t *cipher); +void +grub_cipher_unregister (gcry_cipher_spec_t *cipher); +void=20 +grub_md_register (gcry_md_spec_t *digest); +void=20 +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_sha2= 56) +#define GRUB_MD_SHA512 ((const gcry_md_spec_t *) &_gcry_digest_spec_sha5= 12) + +/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC vari= ant + 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 =3D=3D=3D 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 }; =20 struct grub_disk; =3D=3D=3D 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; =20 =3D=3D=3D 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 . + */ + +#include +#include +#include + +struct grub_crypto_hmac_handle +{ + const struct gcry_md_spec *md; + void *ctx; + void *opad; +}; + +static gcry_cipher_spec_t *grub_ciphers =3D NULL; +static gcry_md_spec_t *grub_digests =3D 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=20 +grub_cipher_register (gcry_cipher_spec_t *cipher) +{ + cipher->next =3D grub_ciphers; + grub_ciphers =3D cipher; +} + +void +grub_cipher_unregister (gcry_cipher_spec_t *cipher) +{ + gcry_cipher_spec_t **ciph; + for (ciph =3D &grub_ciphers; *ciph; ciph =3D &((*ciph)->next)) + if (*ciph =3D=3D cipher) + *ciph =3D (*ciph)->next; +} + +void=20 +grub_md_register (gcry_md_spec_t *digest) +{ + digest->next =3D grub_digests; + grub_digests =3D digest; +} + +void=20 +grub_md_unregister (gcry_md_spec_t *cipher) +{ + gcry_md_spec_t **ciph; + for (ciph =3D &grub_digests; *ciph; ciph =3D &((*ciph)->next)) + if (*ciph =3D=3D cipher) + *ciph =3D (*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 =3D grub_digests; md; md =3D md->next) + if (grub_strcasecmp (name, md->name) =3D=3D 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 =3D grub_ciphers; ciph; ciph =3D ciph->next) + { + const char **alias; + if (grub_strcasecmp (name, ciph->name) =3D=3D 0) + return ciph; + if (!ciph->aliases) + continue; + for (alias =3D ciph->aliases; *alias; alias++) + if (grub_strcasecmp (name, *alias) =3D=3D 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 =3D grub_malloc (sizeof (*ret) + cipher->contextsize); + if (!ret) + return NULL; + ret->cipher =3D 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 =3D in1, *in2ptr =3D in2; + grub_uint8_t *outptr =3D out; + while (size--) + { + *outptr =3D *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 !=3D 0) + return GPG_ERR_INV_ARG; + end =3D (grub_uint8_t *) in + size; + for (inptr =3D in, outptr =3D out; inptr < end; + inptr +=3D cipher->cipher->blocksize, outptr +=3D 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 !=3D 0) + return GPG_ERR_INV_ARG; + end =3D (grub_uint8_t *) in + size; + for (inptr =3D in, outptr =3D out; inptr < end; + inptr +=3D cipher->cipher->blocksize, outptr +=3D 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 !=3D 0) + return GPG_ERR_INV_ARG; + end =3D (grub_uint8_t *) in + size; + iv =3D iv_in; + for (inptr =3D in, outptr =3D out; inptr < end; + inptr +=3D cipher->cipher->blocksize, outptr +=3D cipher->cipher-= >blocksize) + { + grub_crypto_xor (outptr, inptr, iv, cipher->cipher->blocksize); + cipher->cipher->encrypt (cipher->ctx, outptr, outptr); + iv =3D 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 !=3D 0) + return GPG_ERR_INV_ARG; + end =3D (grub_uint8_t *) in + size; + for (inptr =3D in, outptr =3D out; inptr < end; + inptr +=3D cipher->cipher->blocksize, outptr +=3D 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 =3D NULL; + grub_uint8_t *ipad =3D NULL, *opad =3D NULL; + void *ctx =3D NULL; + struct grub_crypto_hmac_handle *ret =3D NULL; + unsigned i; + + if (md->mdlen > md->blocksize) + return NULL; + + ctx =3D grub_malloc (md->contextsize); + if (!ctx) + goto err; + + if ( keylen > md->blocksize )=20 + { + helpkey =3D grub_malloc (md->mdlen); + if (!helpkey) + goto err; + grub_crypto_hash (md, helpkey, key, keylen); + + key =3D helpkey; + keylen =3D md->mdlen; + } + + ipad =3D grub_zalloc (md->blocksize); + if (!ipad) + goto err; + + opad =3D grub_zalloc (md->blocksize); + if (!opad) + goto err; + + grub_memcpy ( ipad, key, keylen ); + grub_memcpy ( opad, key, keylen ); + for (i=3D0; i < md->blocksize; i++ )=20 + { + ipad[i] ^=3D 0x36; + opad[i] ^=3D 0x5c; + } + grub_free (helpkey); + helpkey =3D NULL; + + md->init (ctx); + + md->write (ctx, ipad, md->blocksize); /* inner pad */ + grub_memset (ipad, 0, md->blocksize); + grub_free (ipad); + ipad =3D NULL; + + ret =3D grub_malloc (sizeof (*ret)); + if (!ret) + goto err; + + ret->md =3D md; + ret->ctx =3D ctx; + ret->opad =3D 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 =3D grub_malloc (hnd->md->contextsize); + if (!ctx2) + return GPG_ERR_OUT_OF_MEMORY; + + hnd->md->final (hnd->ctx); + hnd->md->read (hnd->ctx); + p =3D 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 =3D 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 =3D=3D 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 =3D 0; + grub_uint8_t *pa, *pb; + + for (pa =3D a, pb =3D b; n; pa++, pb++, n--) + { + if (*pa !=3D *pb) + counter++; + } + + return !!counter; +} =3D=3D=3D 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 Founda= tion, 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 Foundatio= n, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *= / + +/* Written by Simon Josefsson. */ + +#include +#include +#include + +/* Implement PKCS#5 PBKDF2 as per RFC 2898. The PRF to use is HMAC vari= ant + 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 =3D 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 =3D Slen + 4; + + if (c =3D=3D 0) + return GPG_ERR_INV_ARG; + + if (dkLen =3D=3D 0) + return GPG_ERR_INV_ARG; + + if (dkLen > 4294967295U) + return GPG_ERR_INV_ARG; + + l =3D ((dkLen - 1) / hLen) + 1; + r =3D dkLen - (l - 1) * hLen; + + tmp =3D grub_malloc (tmplen); + if (tmp =3D=3D NULL) + return GPG_ERR_OUT_OF_MEMORY; + + grub_memcpy (tmp, S, Slen); + + for (i =3D 1; i <=3D l; i++) + { + grub_memset (T, 0, hLen); + + for (u =3D 1; u <=3D c; u++) + { + if (u =3D=3D 1) + { + tmp[Slen + 0] =3D (i & 0xff000000) >> 24; + tmp[Slen + 1] =3D (i & 0x00ff0000) >> 16; + tmp[Slen + 2] =3D (i & 0x0000ff00) >> 8; + tmp[Slen + 3] =3D (i & 0x000000ff) >> 0; + + rc =3D grub_crypto_hmac_buffer (md, P, Plen, tmp, tmplen, U); + } + else + rc =3D grub_crypto_hmac_buffer (md, P, Plen, U, hLen, U); + + if (rc !=3D GPG_ERR_NO_ERROR) + { + grub_free (tmp); + return rc; + } + + for (k =3D 0; k < hLen; k++) + T[k] ^=3D U[k]; + } + + grub_memcpy (DK + (i - 1) * hLen, T, i =3D=3D l ? r : hLen); + } + + grub_free (tmp); + + return GPG_ERR_NO_ERROR; +} =3D=3D=3D 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 @@ =20 struct grub_auth_user *users =3D NULL; =20 -int -grub_auth_strcmp (const char *s1, const char *s2) -{ - int ret; - grub_uint64_t end; - - end =3D grub_get_time_ms () + 100; - ret =3D 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 =3D=3D ',' || c =3D=3D ';' || c =3D=3D '= |' || c =3D=3D '&'); -} - -int -grub_auth_strword (const char *haystack, const char *needle) -{ - const char *n_pos =3D needle; - int found =3D 0; - - while (grub_iswordseparator (*haystack)) - haystack++; - - while (*haystack) - { - int ok =3D 1; - /* Crawl both the needle and the haystack word we're on. */ - while(*haystack && !grub_iswordseparator (*haystack)) - { - if (*haystack =3D=3D *n_pos && ok) - n_pos++; - else - ok =3D 0; - - haystack++; - } - - if (ok) - found =3D 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 =3D ((struct grub_auth_user *) item)->name; =20 - return (userlist && grub_auth_strword (userlist, name)) - || grub_auth_strword (superusers, name); + return (userlist && grub_strword (userlist, name)) + || grub_strword (superusers, name); } =20 superusers =3D 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)= =3D=3D 0) + if (grub_strcmp (login, ((struct grub_auth_user *) item)->name) =3D=3D= 0) cur =3D (struct grub_auth_user *) item; return 0; } =3D=3D=3D 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 Found= ation, 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 . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +/* 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=20 +grub_vprintf (const char *fmt, va_list args) +{ + return vprintf (fmt, args); +} + +int=20 +grub_vsprintf (char *str, const char *fmt, va_list args) +{ + return vsprintf (str, fmt, args); +} + +void +grub_abort (void) +{ + abort (); +} + +static struct option options[] =3D + { + {"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=3Dnumber Number of PBKDF2 iterations\= n\ + -l number, --buflen=3Dnumber Length of generated hash\n\ + -s number, --salt=3Dnumber 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 =3D ((*bin & 0xf0) >> 4) + '0'; + else + *hex =3D ((*bin & 0xf0) >> 4) + 'A' - 10; + hex++; + + if ((*bin & 0xf) < 10) + *hex =3D (*bin & 0xf) + '0'; + else + *hex =3D (*bin & 0xf) + 'A' - 10; + hex++; + bin++; + } + *hex =3D 0; +} + +int +main (int argc, char *argv[]) +{ + unsigned int c =3D 10000, buflen =3D 64, saltlen =3D 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 =3D "grub-pbkdf2"; + + /* Check for options. */ + while (1) + { + int c =3D getopt_long (argc, argv, "c:l:s:hvV", options, 0); + + if (c =3D=3D -1) + break; + + switch (c) + { + case 'c': + c =3D strtoul (optarg, NULL, 0); + break; + + case 'l': + buflen =3D strtoul (optarg, NULL, 0); + break; + + case 's': + saltlen =3D strtoul (optarg, NULL, 0); + break; + + case 'h': + usage (0); + return 0; + =20 + case 'V': + printf ("%s (%s) %s\n", progname, + PACKAGE_NAME, PACKAGE_VERSION); + return 0; + =20 + default: + usage (1); + return 1; + } + } + + bufhex =3D malloc (buflen * 2 + 1); + if (!bufhex) + grub_util_error ("Out of memory"); + buf =3D malloc (buflen); + if (!buf) + { + free (bufhex); + grub_util_error ("Out of memory"); + } + + salt =3D malloc (saltlen); + if (!salt) + { + free (bufhex); + free (buf); + grub_util_error ("Out of memory"); + } + salthex =3D malloc (saltlen * 2 + 1); + if (!salthex) + { + free (salt); + free (bufhex); + free (buf); + grub_util_error ("Out of memory"); + } + + /* Disable echoing. Based on glibc. */ + in =3D fopen ("/dev/tty", "w+c"); + if (in =3D=3D NULL) + { + in =3D stdin; + out =3D stderr; + } + else + out =3D in; + + if (tcgetattr (fileno (in), &t) =3D=3D 0) + { + /* Save the old one. */ + s =3D t; + /* Tricky, tricky. */ + t.c_lflag &=3D ~(ECHO|ISIG); + tty_changed =3D (tcsetattr (fileno (in), TCSAFLUSH, &t) =3D=3D 0);= + } + else + tty_changed =3D 0; + =20 + printf ("Enter password: "); + pass1 =3D NULL; + { + grub_size_t n; + nr =3D 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 >=3D 1 && pass1[nr-1] =3D=3D '\n') + pass1[nr-1] =3D 0; + + printf ("\nReenter password: "); + pass2 =3D NULL; + { + grub_size_t n; + nr =3D 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 >=3D 1 && pass2[nr-1] =3D=3D '\n') + pass2[nr-1] =3D 0; + + if (strcmp (pass1, pass2) !=3D 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 =3D 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 =3D fread (salt, 1, saltlen, f); + if (rd !=3D 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 =3D 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, bu= fhex); + 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; +} --------------050900020706070405070005-- --------------enig8D0190306784532FEEC90432 Content-Type: application/pgp-signature; name="signature.asc" Content-Description: OpenPGP digital signature Content-Disposition: attachment; filename="signature.asc" -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iF4EAREKAAYFAksBWBoACgkQNak7dOguQgnNKgD/WSsFIqAvrLeI4d3lyOQhJgro iu2Zno7GgOc7olKPVOoA/1S3uwJhpVDzH2eBJVaziSzOMhZ3S6kgz6BhDRIkw0kv =iNIT -----END PGP SIGNATURE----- --------------enig8D0190306784532FEEC90432--