2N/A/* adler32.c - adler32 check. */
2N/A/*
2N/A * GRUB -- GRand Unified Bootloader
2N/A * Copyright (C) 2011 Free Software Foundation, Inc.
2N/A *
2N/A * GRUB is free software: you can redistribute it and/or modify
2N/A * it under the terms of the GNU General Public License as published by
2N/A * the Free Software Foundation, either version 3 of the License, or
2N/A * (at your option) any later version.
2N/A *
2N/A * GRUB is distributed in the hope that it will be useful,
2N/A * but WITHOUT ANY WARRANTY; without even the implied warranty of
2N/A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2N/A * GNU General Public License for more details.
2N/A *
2N/A * You should have received a copy of the GNU General Public License
2N/A * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
2N/A */
2N/A
2N/A#include <grub/types.h>
2N/A#include <grub/dl.h>
2N/A#include <grub/crypto.h>
2N/A
2N/AGRUB_MOD_LICENSE ("GPLv3+");
2N/A
2N/A/* Based on adler32() from adler32.c of zlib-1.2.5 library. */
2N/A
2N/A#define BASE 65521UL
2N/A#define NMAX 5552
2N/A
2N/A#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
2N/A#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
2N/A#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
2N/A#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
2N/A#define DO16(buf) DO8(buf,0); DO8(buf,8);
2N/A
2N/Astatic grub_uint32_t
2N/Aupdate_adler32 (grub_uint32_t adler, const grub_uint8_t *buf, grub_size_t len)
2N/A{
2N/A unsigned long sum2;
2N/A unsigned int n;
2N/A
2N/A sum2 = (adler >> 16) & 0xffff;
2N/A adler &= 0xffff;
2N/A
2N/A if (len == 1)
2N/A {
2N/A adler += buf[0];
2N/A if (adler >= BASE)
2N/A adler -= BASE;
2N/A sum2 += adler;
2N/A if (sum2 >= BASE)
2N/A sum2 -= BASE;
2N/A return adler | (sum2 << 16);
2N/A }
2N/A
2N/A if (len < 16)
2N/A {
2N/A while (len--)
2N/A {
2N/A adler += *buf++;
2N/A sum2 += adler;
2N/A }
2N/A if (adler >= BASE)
2N/A adler -= BASE;
2N/A sum2 %= BASE;
2N/A return adler | (sum2 << 16);
2N/A }
2N/A
2N/A while (len >= NMAX)
2N/A {
2N/A len -= NMAX;
2N/A n = NMAX / 16;
2N/A do
2N/A {
2N/A DO16 (buf);
2N/A buf += 16;
2N/A }
2N/A while (--n);
2N/A adler %= BASE;
2N/A sum2 %= BASE;
2N/A }
2N/A
2N/A if (len)
2N/A {
2N/A while (len >= 16)
2N/A {
2N/A len -= 16;
2N/A DO16 (buf);
2N/A buf += 16;
2N/A }
2N/A while (len--)
2N/A {
2N/A adler += *buf++;
2N/A sum2 += adler;
2N/A }
2N/A adler %= BASE;
2N/A sum2 %= BASE;
2N/A }
2N/A
2N/A return adler | (sum2 << 16);
2N/A}
2N/A
2N/Atypedef struct
2N/A{
2N/A grub_uint32_t adler;
2N/A}
2N/Aadler32_context;
2N/A
2N/Astatic void
2N/Aadler32_init (void *context)
2N/A{
2N/A adler32_context *ctx = (adler32_context *) context;
2N/A ctx->adler = 1;
2N/A}
2N/A
2N/Astatic void
2N/Aadler32_write (void *context, const void *inbuf, grub_size_t inlen)
2N/A{
2N/A adler32_context *ctx = (adler32_context *) context;
2N/A if (!inbuf)
2N/A return;
2N/A ctx->adler = update_adler32 (ctx->adler, inbuf, inlen);
2N/A}
2N/A
2N/Astatic grub_uint8_t *
2N/Aadler32_read (void *context)
2N/A{
2N/A adler32_context *ctx = (adler32_context *) context;
2N/A return (grub_uint8_t *) &ctx->adler;
2N/A}
2N/A
2N/Astatic void
2N/Aadler32_final (void *context __attribute__ ((unused)))
2N/A{
2N/A}
2N/A
2N/Agcry_md_spec_t _gcry_digest_spec_adler32 = {
2N/A "ADLER32",0 , 0, 0 , 4,
2N/A adler32_init, adler32_write, adler32_final, adler32_read,
2N/A sizeof (adler32_context),
2N/A .blocksize = 64
2N/A};
2N/A
2N/AGRUB_MOD_INIT(adler32)
2N/A{
2N/A grub_md_register (&_gcry_digest_spec_adler32);
2N/A}
2N/A
2N/AGRUB_MOD_FINI(adler32)
2N/A{
2N/A grub_md_unregister (&_gcry_digest_spec_adler32);
2N/A}