-/* adler32.c - adler32 check. */
/*
* GRUB -- GRand Unified Bootloader
- * Copyright (C) 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2012 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
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <grub/types.h>
+
#include <grub/dl.h>
#include <grub/crypto.h>
GRUB_MOD_LICENSE ("GPLv3+");
-/* Based on adler32() from adler32.c of zlib-1.2.5 library. */
-
-#define BASE 65521UL
-#define NMAX 5552
-
-#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
-#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf) DO8(buf,0); DO8(buf,8);
-
-static grub_uint32_t
-update_adler32 (grub_uint32_t adler, const grub_uint8_t *buf, grub_size_t len)
+struct adler32_context
{
- unsigned long sum2;
- unsigned int n;
-
- sum2 = (adler >> 16) & 0xffff;
- adler &= 0xffff;
-
- if (len == 1)
- {
- adler += buf[0];
- if (adler >= BASE)
- adler -= BASE;
- sum2 += adler;
- if (sum2 >= BASE)
- sum2 -= BASE;
- return adler | (sum2 << 16);
- }
-
- if (len < 16)
- {
- while (len--)
- {
- adler += *buf++;
- sum2 += adler;
- }
- if (adler >= BASE)
- adler -= BASE;
- sum2 %= BASE;
- return adler | (sum2 << 16);
- }
-
- while (len >= NMAX)
- {
- len -= NMAX;
- n = NMAX / 16;
- do
- {
- DO16 (buf);
- buf += 16;
- }
- while (--n);
- adler %= BASE;
- sum2 %= BASE;
- }
+ grub_uint16_t a, b;
+ grub_uint32_t c;
+};
- if (len)
- {
- while (len >= 16)
- {
- len -= 16;
- DO16 (buf);
- buf += 16;
- }
- while (len--)
- {
- adler += *buf++;
- sum2 += adler;
- }
- adler %= BASE;
- sum2 %= BASE;
- }
+static void
+adler32_init (void *context)
+{
+ struct adler32_context *ctx = context;
- return adler | (sum2 << 16);
+ ctx->a = 1;
+ ctx->b = 0;
}
-typedef struct
+#define MOD 65521
+
+static grub_uint16_t
+mod_add (grub_uint16_t a, grub_uint16_t b)
{
- grub_uint32_t adler;
+ if ((grub_uint32_t) a + (grub_uint32_t) b >= MOD)
+ return a + b - MOD;
+ return a + b;
}
-adler32_context;
static void
-adler32_init (void *context)
+adler32_write (void *context, const void *inbuf, grub_size_t inlen)
{
- adler32_context *ctx = (adler32_context *) context;
- ctx->adler = 1;
+ struct adler32_context *ctx = context;
+ const grub_uint8_t *ptr = inbuf;
+
+ while (inlen)
+ {
+ ctx->a = mod_add (ctx->a, *ptr);
+ ctx->b = mod_add (ctx->a, ctx->b);
+ inlen--;
+ ptr++;
+ }
}
static void
-adler32_write (void *context, const void *inbuf, grub_size_t inlen)
+adler32_final (void *context __attribute__ ((unused)))
{
- adler32_context *ctx = (adler32_context *) context;
- if (!inbuf)
- return;
- ctx->adler = update_adler32 (ctx->adler, inbuf, inlen);
}
static grub_uint8_t *
adler32_read (void *context)
{
- adler32_context *ctx = (adler32_context *) context;
- return (grub_uint8_t *) &ctx->adler;
+ struct adler32_context *ctx = context;
+ if (ctx->a > MOD)
+ ctx->a -= MOD;
+ if (ctx->b > MOD)
+ ctx->b -= MOD;
+ ctx->c = grub_cpu_to_be32 (ctx->a | (ctx->b << 16));
+ return (grub_uint8_t *) &ctx->c;
}
-static void
-adler32_final (void *context __attribute__ ((unused)))
-{
-}
+static gcry_md_spec_t spec_adler32 =
+ {
+ "ADLER32", 0, 0, 0, 4,
+ adler32_init, adler32_write, adler32_final, adler32_read,
+ sizeof (struct adler32_context),
+#ifdef GRUB_UTIL
+ .modname = "adler32",
+#endif
+ .blocksize = 64
+ };
-gcry_md_spec_t _gcry_digest_spec_adler32 = {
- "ADLER32",0 , 0, 0 , 4,
- adler32_init, adler32_write, adler32_final, adler32_read,
- sizeof (adler32_context),
- .blocksize = 64
-};
GRUB_MOD_INIT(adler32)
{
- grub_md_register (&_gcry_digest_spec_adler32);
+ grub_md_register (&spec_adler32);
}
GRUB_MOD_FINI(adler32)
{
- grub_md_unregister (&_gcry_digest_spec_adler32);
+ grub_md_unregister (&spec_adler32);
}