]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
XZ CRC64 and SHA256 support.
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 3 Nov 2011 14:13:30 +0000 (15:13 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Thu, 3 Nov 2011 14:13:30 +0000 (15:13 +0100)
* Makefile.util.def (libgrubmods): Add crc64.c.
* grub-core/Makefile.core.def (crc64): New module.
* grub-core/lib/crc64.c: New file.
* grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_hash)
[!GRUB_EMBED_DECOMPRESSOR]: Rename crc32_context to hash_context.
Fix the type.
(MAX_HASH_SIZE): New define.
(xz_dec) [!GRUB_EMBED_DECOMPRESSOR]: Add generic hash fields.
(dec_block) [!GRUB_EMBED_DECOMPRESSOR]: Handle non-crc32 hashes.
(index_update) [!GRUB_EMBED_DECOMPRESSOR]: Likewise.
(dec_index) [!GRUB_EMBED_DECOMPRESSOR]: Likewise.
(crc32_validate) [!GRUB_EMBED_DECOMPRESSOR]: Rename to ...
(hash_validate) [!GRUB_EMBED_DECOMPRESSOR]: ... this.
Handle non-crc32 hashes.
(hashes) [!GRUB_EMBED_DECOMPRESSOR]: New variable.
(dec_stream_header): Handle non-crc32 hashes.
(dec_stream_footer): Likewise.
(dec_block_header): Likewise.
(dec_main): Likewise.
(xz_dec_init): Likewise.
(xz_dec_reset): Likewise.
(xz_dec_end): Likewise.
* util/import_gcry.py: Add CRC64 line.

ChangeLog
Makefile.util.def
grub-core/Makefile.core.def
grub-core/lib/crc64.c [new file with mode: 0644]
grub-core/lib/xzembed/xz_dec_stream.c
util/import_gcry.py

index 9ec293ddaa5f00b26676f213942b30438eb387c1..983b7e9e523ba69d4ce48fbd04ceb9cee6f49c08 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,31 @@
+2011-11-03  Vladimir Serbinenko  <phcoder@gmail.com>
+
+       XZ CRC64 and SHA256 support.
+
+       * Makefile.util.def (libgrubmods): Add crc64.c.
+       * grub-core/Makefile.core.def (crc64): New module.
+       * grub-core/lib/crc64.c: New file.
+       * grub-core/lib/xzembed/xz_dec_stream.c (xz_dec_hash)
+       [!GRUB_EMBED_DECOMPRESSOR]: Rename crc32_context to hash_context.
+       Fix the type.
+       (MAX_HASH_SIZE): New define.
+       (xz_dec) [!GRUB_EMBED_DECOMPRESSOR]: Add generic hash fields.
+       (dec_block) [!GRUB_EMBED_DECOMPRESSOR]: Handle non-crc32 hashes.
+       (index_update) [!GRUB_EMBED_DECOMPRESSOR]: Likewise.
+       (dec_index) [!GRUB_EMBED_DECOMPRESSOR]: Likewise.
+       (crc32_validate) [!GRUB_EMBED_DECOMPRESSOR]: Rename to ...
+       (hash_validate) [!GRUB_EMBED_DECOMPRESSOR]: ... this.
+       Handle non-crc32 hashes.
+       (hashes) [!GRUB_EMBED_DECOMPRESSOR]: New variable.
+       (dec_stream_header): Handle non-crc32 hashes.
+       (dec_stream_footer): Likewise.
+       (dec_block_header): Likewise.
+       (dec_main): Likewise.
+       (xz_dec_init): Likewise.
+       (xz_dec_reset): Likewise.
+       (xz_dec_end): Likewise.
+       * util/import_gcry.py: Add CRC64 line.
+
 2011-11-03  Vladimir Serbinenko  <phcoder@gmail.com>
 
        * grub-core/fs/ufs.c (grub_ufs_mtime) [MODE_UFS2]: Check mtime field
index a839920d582aefd4f2879db49dbc768c94728bd9..17894b1d253a5bcc556ddc2a3b734949916279dc 100644 (file)
@@ -93,6 +93,7 @@ library = {
   common = grub-core/lib/LzmaEnc.c;
   common = grub-core/lib/crc.c;
   common = grub-core/lib/adler32.c;
+  common = grub-core/lib/crc64.c;
   common = grub-core/normal/datetime.c;
   common = grub-core/normal/misc.c;
   common = grub-core/partmap/acorn.c;
index 2b72d8429da965a05168ab4531d3f77037ff735c..b2e8e7aa2245c7eef86aa5074ddd6ead8387fbb3 100644 (file)
@@ -1698,3 +1698,8 @@ module = {
   name = adler32;
   common = lib/adler32.c;
 };
+
+module = {
+  name = crc64;
+  common = lib/crc64.c;
+};
diff --git a/grub-core/lib/crc64.c b/grub-core/lib/crc64.c
new file mode 100644 (file)
index 0000000..92c398d
--- /dev/null
@@ -0,0 +1,111 @@
+/* crc64.c - crc64 function  */
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2008,2011  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/dl.h>
+#include <grub/crypto.h>
+
+static grub_uint64_t crc64_table [256];
+
+static void
+init_crc64_table (void)
+{
+  auto grub_uint64_t reflect (grub_uint64_t ref, int len);
+  grub_uint64_t reflect (grub_uint64_t ref, int len)
+    {
+      grub_uint64_t result = 0;
+      int i;
+
+      for (i = 1; i <= len; i++)
+        {
+          if (ref & 1)
+            result |= 1ULL << (len - i);
+          ref >>= 1;
+        }
+
+      return result;
+    }
+
+  grub_uint64_t polynomial = 0x42f0e1eba9ea3693ULL;
+  int i, j;
+
+  for(i = 0; i < 256; i++)
+    {
+      crc64_table[i] = reflect(i, 8) << 56;
+      for (j = 0; j < 8; j++)
+       {
+         crc64_table[i] = (crc64_table[i] << 1) ^
+            (crc64_table[i] & (1ULL << 63) ? polynomial : 0);
+       }
+      crc64_table[i] = reflect(crc64_table[i], 64);
+    }
+}
+
+static void
+crc64_init (void *context)
+{
+  if (! crc64_table[1])
+    init_crc64_table ();
+  *(grub_uint64_t *) context = 0;
+}
+
+static void
+crc64_write (void *context, const void *buf, grub_size_t size)
+{
+  unsigned i;
+  const grub_uint8_t *data = buf;
+  grub_uint64_t crc = ~grub_le_to_cpu64 (*(grub_uint64_t *) context);
+
+  for (i = 0; i < size; i++)
+    {
+      crc = (crc >> 8) ^ crc64_table[(crc & 0xFF) ^ *data];
+      data++;
+    }
+
+  *(grub_uint64_t *) context = grub_cpu_to_le64 (~crc);
+}
+
+static grub_uint8_t *
+crc64_read (void *context)
+{
+  return context;
+}
+
+static void
+crc64_final (void *context __attribute__ ((unused)))
+{
+}
+
+gcry_md_spec_t _gcry_digest_spec_crc64 =
+  {
+    "CRC64", 0, 0, 0, 8,
+    crc64_init, crc64_write, crc64_final, crc64_read,
+    sizeof (grub_uint64_t),
+    .blocksize = 64
+  };
+
+GRUB_MOD_INIT(crc64)
+{
+  grub_md_register (&_gcry_digest_spec_crc64);
+}
+
+GRUB_MOD_FINI(crc64)
+{
+  grub_md_unregister (&_gcry_digest_spec_crc64);
+}
index 3bf201d5009f35fe9139a0eb88fbf167425efb66..383c29a2fc7290973fc7f8f01344422e2ff3d9d8 100644 (file)
@@ -32,10 +32,13 @@ struct xz_dec_hash {
        vli_type unpadded;
        vli_type uncompressed;
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       uint8_t *crc32_context;
+       uint64_t *hash_context;
 #endif
 };
 
+/* Enough for up to 512 bits.  */
+#define MAX_HASH_SIZE 64
+
 struct xz_dec {
        /* Position in dec_main() */
        enum {
@@ -62,11 +65,22 @@ struct xz_dec {
        size_t out_start;
 
        /* CRC32 value in Block or Index */
-       uint32_t crc32_temp; /* need for crc32_validate*/
-       uint8_t *crc32_context;
+#ifndef GRUB_EMBED_DECOMPRESSOR
+       uint8_t hash_value[MAX_HASH_SIZE]; /* need for crc32_validate*/
+#endif
+       int have_hash_value;
+#ifndef GRUB_EMBED_DECOMPRESSOR
+       uint64_t *hash_context;
+       uint64_t *crc32_context;
+#endif
 
-       /* True if CRC32 is calculated from uncompressed data */
-       bool has_crc32;
+       /* Hash function calculated from uncompressed data */
+#ifndef GRUB_EMBED_DECOMPRESSOR
+        const gcry_md_spec_t *hash;
+        const gcry_md_spec_t *crc32;
+#endif
+       grub_size_t hash_size;
+       grub_uint8_t hash_id;
 
        /* True if we are operating in single-call mode. */
        bool single_call;
@@ -250,9 +264,12 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
                return XZ_DATA_ERROR;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       if (s->has_crc32)
-         GRUB_MD_CRC32->write(s->crc32_context,b->out + s->out_start,
-                               b->out_pos - s->out_start);
+       if (s->hash)
+         s->hash->write(s->hash_context,b->out + s->out_start,
+                        b->out_pos - s->out_start);
+       if (s->crc32)
+         s->crc32->write(s->crc32_context,b->out + s->out_start,
+                         b->out_pos - s->out_start);
 #endif
 
        if (ret == XZ_STREAM_END) {
@@ -268,14 +285,15 @@ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
 
                s->block.hash.unpadded += s->block_header.size
                                + s->block.compressed;
-               if (s->has_crc32)
-                       s->block.hash.unpadded += 4;
+               s->block.hash.unpadded += s->hash_size;
 
                s->block.hash.uncompressed += s->block.uncompressed;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               GRUB_MD_CRC32->write(s->block.hash.crc32_context,
-                               (const uint8_t *)&s->block.hash, 2 * sizeof(vli_type));
+               if (s->hash)
+                       s->hash->write(s->block.hash.hash_context,
+                                      (const uint8_t *)&s->block.hash,
+                                      2 * sizeof(vli_type));
 #endif
 
                ++s->block.count;
@@ -290,7 +308,10 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b)
        size_t in_used = b->in_pos - s->in_start;
        s->index.size += in_used;
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       GRUB_MD_CRC32->write(s->crc32_context,b->in + s->in_start, in_used);
+       if (s->hash)
+               s->hash->write(s->hash_context,b->in + s->in_start, in_used);
+       if (s->crc32)
+               s->crc32->write(s->crc32_context,b->in + s->in_start, in_used);
 #endif
 }
 
@@ -337,8 +358,9 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
                        s->index.hash.uncompressed += s->vli;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-                       GRUB_MD_CRC32->write(s->index.hash.crc32_context,
-                                       (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type));
+                       if (s->hash)
+                               s->hash->write(s->index.hash.hash_context,
+                                              (const uint8_t *)&s->index.hash, 2 * sizeof(vli_type));
 #endif
 
                        --s->index.count;
@@ -354,13 +376,30 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
  * Validate that the next four input bytes match the value of s->crc32.
  * s->pos must be zero when starting to validate the first byte.
  */
-static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b)
+static enum xz_ret hash_validate(struct xz_dec *s, struct xz_buf *b,
+       int crc32)
 {
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       if(s->crc32_temp == 0)
+       const gcry_md_spec_t *hash = crc32 ? s->crc32 : s->hash;
+       grub_uint64_t *hash_context = crc32 ? s->crc32_context 
+               : s->hash_context;
+       if(!s->have_hash_value && hash
+               && sizeof (s->hash_value) >= hash->mdlen)
        {
-         GRUB_MD_CRC32->final(s->crc32_context);
-               s->crc32_temp = get_unaligned_be32(GRUB_MD_CRC32->read(s->crc32_context));
+               hash->final(hash_context);
+               grub_memcpy (s->hash_value, hash->read(hash_context),
+                            hash->mdlen);
+               s->have_hash_value = 1;
+               if (s->hash_id == 1 || crc32)
+               {
+                       grub_uint8_t t;
+                       t = s->hash_value[0];
+                       s->hash_value[0] = s->hash_value[3];
+                       s->hash_value[3] = t;
+                       t = s->hash_value[1];
+                       s->hash_value[1] = s->hash_value[2];
+                       s->hash_value[2] = t;
+               }
        }
 #endif
 
@@ -369,23 +408,38 @@ static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b)
                        return XZ_OK;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               if (((s->crc32_temp >> s->pos) & 0xFF) != b->in[b->in_pos++])
+               if (hash && s->hash_value[s->pos / 8] != b->in[b->in_pos++])
                        return XZ_DATA_ERROR;
 #endif
 
                s->pos += 8;
 
-       } while (s->pos < 32);
+       } while (s->pos < (crc32 ? 32 : s->hash_size * 8));
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       GRUB_MD_CRC32->init(s->crc32_context);
+       if (s->hash)
+               s->hash->init(s->hash_context);
+       if (s->crc32)
+               s->crc32->init(s->crc32_context);
 #endif
-       s->crc32_temp = 0;
+       s->have_hash_value = 0;
        s->pos = 0;
 
        return XZ_STREAM_END;
 }
 
+#ifndef GRUB_EMBED_DECOMPRESSOR
+static struct
+{
+       const char *name;
+       grub_size_t size;
+} hashes[] = {
+       [0x01] = { "CRC32", 4},
+       [0x04] = { "CRC64", 8},
+       [0x0A] = { "SHA256", 32},
+};
+#endif
+
 /* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
 static enum xz_ret dec_stream_header(struct xz_dec *s)
 {
@@ -393,17 +447,27 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
                return XZ_FORMAT_ERROR;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
-
-       GRUB_MD_CRC32->init(crc32_context);
-       GRUB_MD_CRC32->write(crc32_context,s->temp.buf + HEADER_MAGIC_SIZE, 2);
-       GRUB_MD_CRC32->final(crc32_context);
-
-       uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
-       uint32_t readcrc = get_unaligned_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2);
-
-       if(resultcrc != readcrc)
-               return XZ_DATA_ERROR;
+       if (s->crc32)
+       {
+               uint64_t hash_context[(s->crc32->contextsize + 7) / 8];
+               uint8_t resulthash[s->crc32->mdlen];
+               uint8_t readhash[4];
+
+               s->crc32->init(hash_context);
+               s->crc32->write(hash_context,s->temp.buf + HEADER_MAGIC_SIZE, 2);
+               s->crc32->final(hash_context);
+
+               grub_memcpy (resulthash, s->crc32->read(hash_context),
+                            s->crc32->mdlen);
+               readhash[0] = s->temp.buf[HEADER_MAGIC_SIZE + 5];
+               readhash[1] = s->temp.buf[HEADER_MAGIC_SIZE + 4];
+               readhash[2] = s->temp.buf[HEADER_MAGIC_SIZE + 3];
+               readhash[3] = s->temp.buf[HEADER_MAGIC_SIZE + 2];
+
+               if(4 != s->crc32->mdlen
+                  || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0)
+                       return XZ_DATA_ERROR;
+       }
 #endif
 
        /*
@@ -411,10 +475,77 @@ static enum xz_ret dec_stream_header(struct xz_dec *s)
         * only none (Check ID = 0) and CRC32 (Check ID = 1).
         */
        if (s->temp.buf[HEADER_MAGIC_SIZE] != 0
-                       || s->temp.buf[HEADER_MAGIC_SIZE + 1] > 1)
+           || s->temp.buf[HEADER_MAGIC_SIZE + 1] >= ARRAY_SIZE (hashes)
+           || (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name == 0
+               && s->temp.buf[HEADER_MAGIC_SIZE + 1] != 0))
                return XZ_OPTIONS_ERROR;
 
-       s->has_crc32 = s->temp.buf[HEADER_MAGIC_SIZE + 1];
+       s->hash_id = s->temp.buf[HEADER_MAGIC_SIZE + 1];
+
+#ifndef GRUB_EMBED_DECOMPRESSOR
+       if (s->crc32)
+       {
+               s->crc32_context = kmalloc(s->crc32->contextsize, GFP_KERNEL);
+               if (s->crc32_context == NULL)
+                       return XZ_MEMLIMIT_ERROR;
+               s->crc32->init(s->crc32_context);
+       }
+#endif
+
+       if (s->temp.buf[HEADER_MAGIC_SIZE + 1])
+       {
+               s->hash_size = hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].size;
+#ifndef GRUB_EMBED_DECOMPRESSOR
+               s->hash = grub_crypto_lookup_md_by_name (hashes[s->temp.buf[HEADER_MAGIC_SIZE + 1]].name);
+               if (s->hash)
+               {
+                       if (s->hash->mdlen != s->hash_size)
+                               return XZ_OPTIONS_ERROR;
+                       s->hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL);
+                       if (s->hash_context == NULL)
+                       {
+                               kfree(s->crc32_context);
+                               return XZ_MEMLIMIT_ERROR;
+                       }
+                       
+                       s->index.hash.hash_context = kmalloc(s->hash->contextsize,
+                                                            GFP_KERNEL);
+                       if (s->index.hash.hash_context == NULL)
+                       {
+                               kfree(s->hash_context);
+                               kfree(s->crc32_context);
+                               return XZ_MEMLIMIT_ERROR;
+                       }
+                       
+                       s->block.hash.hash_context = kmalloc(s->hash->contextsize, GFP_KERNEL);
+                       if (s->block.hash.hash_context == NULL)
+                       {
+                               kfree(s->index.hash.hash_context);
+                               kfree(s->hash_context);
+                               kfree(s->crc32_context);
+                               return XZ_MEMLIMIT_ERROR;
+                       }
+
+                       s->hash->init(s->hash_context);
+                       s->hash->init(s->index.hash.hash_context);
+                       s->hash->init(s->block.hash.hash_context);
+               }
+#else
+               s->hash = 0;
+#endif
+#if 1
+               if (!s->hash)
+                       return XZ_OPTIONS_ERROR;
+#endif
+       }
+       else
+       {
+               s->hash = 0;
+               s->hash_size = 0;
+       }
+
+       s->have_hash_value = 0;
+
 
        return XZ_OK;
 }
@@ -426,19 +557,30 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s)
                return XZ_DATA_ERROR;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
-
-       GRUB_MD_CRC32->init(crc32_context);
-       GRUB_MD_CRC32->write(crc32_context, s->temp.buf + 4, 6);
-       GRUB_MD_CRC32->final(crc32_context);
-
-       uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
-       uint32_t readcrc = get_unaligned_le32(s->temp.buf);
-
-       if(resultcrc != readcrc)
-               return XZ_DATA_ERROR;
+       if (s->crc32)
+       {
+               uint64_t hash_context[(s->crc32->contextsize + 7) / 8];
+               uint8_t resulthash[s->crc32->mdlen];
+               uint8_t readhash[4];
+
+               s->crc32->init(hash_context);
+               s->crc32->write(hash_context,s->temp.buf + 4, 6);
+               s->crc32->final(hash_context);
+
+               grub_memcpy (resulthash, s->crc32->read(hash_context),
+                            s->crc32->mdlen);
+               readhash[0] = s->temp.buf[3];
+               readhash[1] = s->temp.buf[2];
+               readhash[2] = s->temp.buf[1];
+               readhash[3] = s->temp.buf[0];
+
+               if(4 != s->crc32->mdlen
+                  || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0)
+                       return XZ_DATA_ERROR;
+       }
 #endif
 
+
        /*
         * Validate Backward Size. Note that we never added the size of the
         * Index CRC32 field to s->index.size, thus we use s->index.size / 4
@@ -447,7 +589,7 @@ static enum xz_ret dec_stream_footer(struct xz_dec *s)
        if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
                return XZ_DATA_ERROR;
 
-       if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->has_crc32)
+       if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->hash_id)
                return XZ_DATA_ERROR;
 
        /*
@@ -468,17 +610,27 @@ static enum xz_ret dec_block_header(struct xz_dec *s)
         */
        s->temp.size -= 4;
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       uint8_t crc32_context[GRUB_MD_CRC32->contextsize];
-
-       GRUB_MD_CRC32->init(crc32_context);
-       GRUB_MD_CRC32->write(crc32_context, s->temp.buf, s->temp.size);
-       GRUB_MD_CRC32->final(crc32_context);
-
-       uint32_t resultcrc = get_unaligned_be32(GRUB_MD_CRC32->read(crc32_context));
-       uint32_t readcrc = get_unaligned_le32(s->temp.buf + s->temp.size);
-
-       if (resultcrc != readcrc)
-               return XZ_DATA_ERROR;
+       if (s->crc32)
+       {
+               uint64_t hash_context[(s->crc32->contextsize + 7) / 8];
+               uint8_t resulthash[s->crc32->mdlen];
+               uint8_t readhash[4];
+
+               s->crc32->init(hash_context);
+               s->crc32->write(hash_context,s->temp.buf, s->temp.size);
+               s->crc32->final(hash_context);
+
+               grub_memcpy (resulthash, s->crc32->read(hash_context),
+                            s->crc32->mdlen);
+               readhash[3] = s->temp.buf[s->temp.size];
+               readhash[2] = s->temp.buf[s->temp.size + 1];
+               readhash[1] = s->temp.buf[s->temp.size + 2];
+               readhash[0] = s->temp.buf[s->temp.size + 3];
+
+               if(4 != s->crc32->mdlen
+                  || grub_memcmp (readhash, resulthash, s->crc32->mdlen) != 0)
+                       return XZ_DATA_ERROR;
+       }
 #endif
 
        s->temp.pos = 2;
@@ -659,11 +811,9 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
                        s->sequence = SEQ_BLOCK_CHECK;
 
                case SEQ_BLOCK_CHECK:
-                       if (s->has_crc32) {
-                               ret = crc32_validate(s, b);
-                               if (ret != XZ_STREAM_END)
-                                       return ret;
-                       }
+                       ret = hash_validate(s, b, 0);
+                       if (ret != XZ_STREAM_END)
+                               return ret;
 
                        s->sequence = SEQ_BLOCK_START;
                        break;
@@ -691,24 +841,31 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
                        index_update(s, b);
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-                       /* Compare the hashes to validate the Index field. */
-                       GRUB_MD_CRC32->final(s->block.hash.crc32_context);
-                       GRUB_MD_CRC32->final(s->index.hash.crc32_context);
-                       uint32_t block_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->block.hash.crc32_context);
-                       uint32_t index_crc = *(uint32_t*)GRUB_MD_CRC32->read(s->index.hash.crc32_context);
-
-                       if (s->block.hash.unpadded != s->index.hash.unpadded
-                           || s->block.hash.uncompressed != s->index.hash.uncompressed
-                           || block_crc != index_crc)
+                       if (s->hash)
                        {
-                               return XZ_DATA_ERROR;
+                               uint8_t block_hash[s->hash->mdlen];
+                               uint8_t index_hash[s->hash->mdlen];
+                               /* Compare the hashes to validate the Index field. */
+                               s->hash->final(s->block.hash.hash_context);
+                               s->hash->final(s->index.hash.hash_context);
+                               grub_memcpy (block_hash,
+                                            s->hash->read(s->block.hash.hash_context),
+                                       s->hash->mdlen);
+                               grub_memcpy (index_hash,
+                                            s->hash->read(s->index.hash.hash_context),
+                                       s->hash->mdlen);
+
+                               if (s->block.hash.unpadded != s->index.hash.unpadded
+                                   || s->block.hash.uncompressed != s->index.hash.uncompressed
+                                   || grub_memcmp (block_hash, index_hash, s->hash->mdlen) != 0)
+                                       return XZ_DATA_ERROR;
                        }
 #endif
 
                        s->sequence = SEQ_INDEX_CRC32;
 
                case SEQ_INDEX_CRC32:
-                       ret = crc32_validate(s, b);
+                       ret = hash_validate(s, b, 1);
                        if (ret != XZ_STREAM_END)
                                return ret;
 
@@ -802,46 +959,12 @@ struct xz_dec * xz_dec_init(uint32_t dict_max)
                return NULL;
 #endif
 
-#ifndef GRUB_EMBED_DECOMPRESSOR
-       /* prepare CRC32 calculators */
-       if(GRUB_MD_CRC32 == NULL)
-       {
-               kfree(s);
-               return NULL;
-       }
-
-       s->crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
-       if (s->crc32_context == NULL)
-       {
-               kfree(s);
-               return NULL;
-       }
-
-       s->index.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
-       if (s->index.hash.crc32_context == NULL)
-       {
-               kfree(s->crc32_context);
-               kfree(s);
-               return NULL;
-       }
+       memset (s, 0, sizeof (*s));
 
-       s->block.hash.crc32_context = kmalloc(GRUB_MD_CRC32->contextsize, GFP_KERNEL);
-       if (s->block.hash.crc32_context == NULL)
-       {
-               kfree(s->index.hash.crc32_context);
-               kfree(s->crc32_context);
-               kfree(s);
-               return NULL;
-       }
-
-
-       GRUB_MD_CRC32->init(s->crc32_context);
-       GRUB_MD_CRC32->init(s->index.hash.crc32_context);
-       GRUB_MD_CRC32->init(s->block.hash.crc32_context);
+#ifndef GRUB_EMBED_DECOMPRESSOR
+       s->crc32 = grub_crypto_lookup_md_by_name ("CRC32");
 #endif
 
-       s->crc32_temp = 0;
-
        s->single_call = dict_max == 0;
 
 #ifdef XZ_DEC_BCJ
@@ -876,28 +999,31 @@ void xz_dec_reset(struct xz_dec *s)
 
        {
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               uint8_t *t;
-               t = s->block.hash.crc32_context;
+               uint64_t *t;
+               t = s->block.hash.hash_context;
 #endif
                memzero(&s->block, sizeof(s->block));
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               s->block.hash.crc32_context = t;
-               t = s->index.hash.crc32_context;
+               s->block.hash.hash_context = t;
+               t = s->index.hash.hash_context;
 #endif
                memzero(&s->index, sizeof(s->index));
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               s->index.hash.crc32_context = t;
+               s->index.hash.hash_context = t;
 #endif
        }
        s->temp.pos = 0;
        s->temp.size = STREAM_HEADER_SIZE;
 
 #ifndef GRUB_EMBED_DECOMPRESSOR
-       GRUB_MD_CRC32->init(s->crc32_context);
-       GRUB_MD_CRC32->init(s->index.hash.crc32_context);
-       GRUB_MD_CRC32->init(s->block.hash.crc32_context);
+       if (s->hash)
+       {
+               s->hash->init(s->hash_context);
+               s->hash->init(s->index.hash.hash_context);
+               s->hash->init(s->block.hash.hash_context);
+       }
 #endif
-       s->crc32_temp = 0;
+       s->have_hash_value = 0;
 }
 
 void xz_dec_end(struct xz_dec *s)
@@ -905,8 +1031,9 @@ void xz_dec_end(struct xz_dec *s)
        if (s != NULL) {
                xz_dec_lzma2_end(s->lzma2);
 #ifndef GRUB_EMBED_DECOMPRESSOR
-               kfree(s->index.hash.crc32_context);
-               kfree(s->block.hash.crc32_context);
+               kfree(s->index.hash.hash_context);
+               kfree(s->block.hash.hash_context);
+               kfree(s->hash_context);
                kfree(s->crc32_context);
 #endif
 #ifdef XZ_DEC_BCJ
index 7591d8f0efefa4fd072bb70a7dcf958c7bd63fcc..ec34d16b5985fb69dad8db6761c76fecde5bec52 100644 (file)
@@ -83,6 +83,7 @@ cryptolist.write ("AES-192: gcry_rijndael\n");
 cryptolist.write ("AES-256: gcry_rijndael\n");
 
 cryptolist.write ("ADLER32: adler32\n");
+cryptolist.write ("CRC64: crc64\n");
 
 for cipher_file in cipher_files:
     infile = os.path.join (cipher_dir_in, cipher_file)