/* adler32.c - adler32 check. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 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 . */ #include #include #include /* 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) { 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; } if (len) { while (len >= 16) { len -= 16; DO16 (buf); buf += 16; } while (len--) { adler += *buf++; sum2 += adler; } adler %= BASE; sum2 %= BASE; } return adler | (sum2 << 16); } typedef struct { grub_uint32_t adler; } adler32_context; static void adler32_init (void *context) { adler32_context *ctx = (adler32_context *) context; ctx->adler = 1; } static void adler32_write (void *context, const void *inbuf, grub_size_t inlen) { 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; } static void adler32_final (void *context __attribute__ ((unused))) { } 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_MOD_FINI(adler32) { grub_md_unregister (&_gcry_digest_spec_adler32); }