From 7f680f12774c0cece7c2da22b868c1db9639cc68 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Tue, 24 Sep 2024 15:34:44 -0400 Subject: [PATCH] debugedit: switch to xxhash for buildid recomputation When debugedit recomputes build-id (due to -i), it previously used md5 or sha1 (depending on length of incoming buildid). This patch replaces both those (including the code that does all the hashing) with a 128-bit xxhash. The 128-bit hash is truncated or padded to whatever the incoming ELF note width was. xxhash is much faster (8x over sha1) than either of those crypto-flavoured hashes, and still produces fairly collision-free values. This was confirmed informally with a bulk build-id recomputation of a few million binaries in the debuginfod server corpus, yielding zero unexpected collisions. Signed-off-by: Frank Ch. Eigler --- Makefile.am | 8 +- configure.ac | 1 + tests/debugedit.at | 40 +++++ tools/debugedit.c | 78 ++++---- tools/md5.c | 440 --------------------------------------------- tools/md5.h | 154 ---------------- tools/sha1.c | 414 ------------------------------------------ tools/sha1.h | 145 --------------- 8 files changed, 76 insertions(+), 1204 deletions(-) delete mode 100644 tools/md5.c delete mode 100644 tools/md5.h delete mode 100644 tools/sha1.c delete mode 100644 tools/sha1.h diff --git a/Makefile.am b/Makefile.am index 4a5092d..c590edf 100644 --- a/Makefile.am +++ b/Makefile.am @@ -41,9 +41,7 @@ find-debuginfo: $(top_srcdir)/scripts/find-debuginfo.in Makefile chmod +x "$@" debugedit_SOURCES = tools/debugedit.c \ - tools/hashtab.c \ - tools/md5.c \ - tools/sha1.c + tools/hashtab.c debugedit_CFLAGS = @LIBELF_CFLAGS@ @LIBDW_CFLAGS@ $(AM_CFLAGS) debugedit_LDADD = @LIBELF_LIBS@ @LIBDW_LIBS@ @@ -85,8 +83,6 @@ find-debuginfo.1: $(top_srcdir)/scripts/find-debuginfo.in configure.ac find-debu esac noinst_HEADERS= tools/ansidecl.h \ - tools/hashtab.h \ - tools/md5.h \ - tools/sha1.h + tools/hashtab.h EXTRA_DIST = README COPYING COPYING3 COPYING.LIB scripts/find-debuginfo.in diff --git a/configure.ac b/configure.ac index 79803dc..f0065c9 100644 --- a/configure.ac +++ b/configure.ac @@ -75,6 +75,7 @@ AC_SYS_LARGEFILE PKG_PROG_PKG_CONFIG PKG_CHECK_MODULES([LIBELF], [libelf]) PKG_CHECK_MODULES([LIBDW], [libdw]) +PKG_CHECK_MODULES([XXHASH], [libxxhash >= 0.8.0]) # Checks for header files. AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h malloc.h stddef.h stdint.h stdlib.h string.h unistd.h]) diff --git a/tests/debugedit.at b/tests/debugedit.at index f67747a..94b0cae 100644 --- a/tests/debugedit.at +++ b/tests/debugedit.at @@ -748,3 +748,43 @@ $CC $CFLAGS -gdwarf-5 -o main main.c AT_CHECK([[debugedit -l sources.list main]]) AT_CHECK([[grep -q main.c sources.list]]) AT_CLEANUP + + +# === +# build-id recomputation +# === +AT_SETUP([debugedit build-id recompute]) +AT_KEYWORDS([debuginfo] [debugedit] [build-id]) + +# compile a test program and extract its linker-assigned build-id +echo "int main () { }" > main.c +$CC $CFLAGS -Wl,--build-id -o main main.c +AT_CHECK([[$READELF -n main | grep Build.ID: | awk '{print $3}']], [0], [stdout], [ignore]) +bid="`cat stdout`" +AT_CHECK([[expr "$bid" : '[0-9a-f]*']], [0], [ignore]) + +# run debugedit to recompute build-id +AT_CHECK([[debugedit -i -s deadbeef main]], [0], [stdout]) +bid2a="`cat stdout`" +AT_CHECK([[expr "$bid2a" : '[0-9a-f]*']], [0], [ignore]) +AT_CHECK([[test "$bid" != "$bid2a"]]) + +# check that debugedit's stdout matches readelf -n note +AT_CHECK([[$READELF -n main | grep Build.ID: | awk '{print $3}']], [0], [stdout], [ignore]) +bid2b="`cat stdout`" +AT_CHECK([[expr "$bid2b" : '[0-9a-f]*']], [0], [ignore]) +AT_CHECK([[test "$bid2a" == "$bid2b"]]) + +# run debugedit to recompute build-id, check for idempotence +AT_CHECK([[debugedit -i -s deadbeef main]], [0], [stdout]) +bid2c="`cat stdout`" +AT_CHECK([[expr "$bid2c" : '[0-9a-f]*']], [0], [ignore]) +AT_CHECK([[test "$bid2a" == "$bid2c"]]) + +# check that debugedit -i with different -s seed results in different valid build-id +AT_CHECK([[debugedit -i -s zoofoo main]], [0], [stdout]) +bid3="`cat stdout`" +AT_CHECK([[expr "$bid3" : '[0-9a-f]*']], [0], [ignore]) +AT_CHECK([[test "$bid3" != "$bid2a"]]) + +AT_CLEANUP diff --git a/tools/debugedit.c b/tools/debugedit.c index 7162009..6712f0f 100644 --- a/tools/debugedit.c +++ b/tools/debugedit.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,9 @@ #ifndef MAX #define MAX(m, n) ((m) < (n) ? (n) : (m)) #endif +#ifndef MIN +#define MIN(m, n) ((m) > (n) ? (n) : (m)) +#endif /* Unfortunately strtab manipulation functions were only officially added @@ -77,8 +81,8 @@ typedef struct Ebl_Strtab Strtab; #include "tools/hashtab.h" -#include "tools/md5.h" -#include "tools/sha1.h" +#define XXH_INLINE_ALL +#include "xxhash.h" #define DW_TAG_partial_unit 0x3c #define DW_FORM_sec_offset 0x17 @@ -3431,10 +3435,10 @@ static void handle_build_id (DSO *dso, Elf_Data *build_id, size_t build_id_offset, size_t build_id_size) { - /* For now we only handle 16 byte (128 bits) with md5 or 20 bytes - (160 bits) with sha1. */ - - if (build_id_size != 16 && build_id_size != 20) + /* Accept any build_id_size > 0. Hashes will be truncated or padded + to the incoming note size, as debugedit cannot change their + size. */ + if (build_id_size <= 0) { error (1, 0, "Cannot handle %zu-byte build ID", build_id_size); } @@ -3444,25 +3448,24 @@ handle_build_id (DSO *dso, Elf_Data *build_id, || (! dirty_elf && build_id_seed == NULL)) goto print; - /* Clear the old bits so they do not affect the new hash. */ - memset ((char *) build_id->d_buf + build_id_offset, 0, build_id_size); - - struct md5_ctx md5_ctx; - struct sha1_ctx sha1_ctx; + /* Clear the bits about to be recomputed, so they do not affect the + new hash. Extra bits left over from wider-than-128-bit hash are + preserved for extra entropy. This computation should be + idempotent, so repeated rehashes (with the same seed) should + result in the same hash. */ + XXH128_canonical_t result_canon; + memset ((char *) build_id->d_buf + build_id_offset, 0, + MIN (build_id_size, sizeof(result_canon))); - if (build_id_size == 16) - md5_init_ctx (&md5_ctx); - else - sha1_init_ctx (&sha1_ctx); + XXH3_state_t* state = XXH3_createState(); + if (!state) + error (1, errno, "Failed to create xxhash state"); + XXH3_128bits_reset (state); /* If a seed string was given use it to prime the hash. */ if (build_id_seed != NULL) - { - if (build_id_size == 16) - md5_process_bytes (build_id_seed, strlen (build_id_seed), &md5_ctx); - else - sha1_process_bytes (build_id_seed, strlen (build_id_seed), &sha1_ctx); - } + /* Another choice is XXH3_generateSecret. */ + XXH3_128bits_update (state, build_id_seed, strlen (build_id_seed)); /* Slurp the relevant header bits and section contents and feed them into the hash function. The only bits we ignore are the offset @@ -3501,10 +3504,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id, if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL) goto bad; - if (build_id_size == 16) - md5_process_bytes (x.d_buf, x.d_size, &md5_ctx); - else - sha1_process_bytes (x.d_buf, x.d_size, &sha1_ctx); + XXH3_128bits_update (state, x.d_buf, x.d_size); } x.d_type = ELF_T_SHDR; @@ -3517,10 +3517,7 @@ handle_build_id (DSO *dso, Elf_Data *build_id, if (elf64_xlatetom (&x, &x, dso->ehdr.e_ident[EI_DATA]) == NULL) goto bad; - if (build_id_size == 16) - md5_process_bytes (x.d_buf, x.d_size, &md5_ctx); - else - sha1_process_bytes (x.d_buf, x.d_size, &sha1_ctx); + XXH3_128bits_update (state, x.d_buf, x.d_size); if (dso->shdr[i].sh_type != SHT_NOBITS) { @@ -3528,26 +3525,17 @@ handle_build_id (DSO *dso, Elf_Data *build_id, if (d == NULL) goto bad; - if (build_id_size == 16) - md5_process_bytes (d->d_buf, d->d_size, &md5_ctx); - else - sha1_process_bytes (d->d_buf, d->d_size, &sha1_ctx); + XXH3_128bits_update (state, d->d_buf, d->d_size); } } } - /* Allocate the memory first to make sure alignment is correct. */ - void *digest = malloc (build_id_size); - if (digest == NULL) - goto bad; - - if (build_id_size == 16) - md5_finish_ctx (&md5_ctx, digest); - else - sha1_finish_ctx (&sha1_ctx, digest); - - memcpy((unsigned char *)build_id->d_buf + build_id_offset, digest, build_id_size); - free(digest); + XXH128_hash_t result = XXH3_128bits_digest (state); + XXH3_freeState (state); + /* Use canonical-endianness output. */ + XXH128_canonicalFromHash (&result_canon, result); + memcpy((unsigned char *)build_id->d_buf + build_id_offset, &result_canon, + MIN (build_id_size, sizeof(result_canon))); elf_flagdata (build_id, ELF_C_SET, ELF_F_DIRTY); diff --git a/tools/md5.c b/tools/md5.c deleted file mode 100644 index a8c8de2..0000000 --- a/tools/md5.c +++ /dev/null @@ -1,440 +0,0 @@ -/* md5.c - Functions to compute MD5 message digest of files or memory blocks - according to the definition of MD5 in RFC 1321 from April 1992. - Copyright (C) 1995-2021 Free Software Foundation, Inc. - - NOTE: This source is derived from an old version taken from the GNU C - Library (glibc). - - 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 Foundation, - Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Ulrich Drepper , 1995. */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#if STDC_HEADERS || defined _LIBC -# include -# include -#else -# ifndef HAVE_MEMCPY -# define memcpy(d, s, n) bcopy ((s), (d), (n)) -# endif -#endif - -#include "ansidecl.h" -#include "md5.h" - -#ifdef _LIBC -# include -# if __BYTE_ORDER == __BIG_ENDIAN -# define WORDS_BIGENDIAN 1 -# endif -#endif - -#ifdef WORDS_BIGENDIAN -# define SWAP(n) \ - (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -#else -# define SWAP(n) (n) -#endif - - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -void -md5_init_ctx (struct md5_ctx *ctx) -{ - ctx->A = (md5_uint32) 0x67452301; - ctx->B = (md5_uint32) 0xefcdab89; - ctx->C = (md5_uint32) 0x98badcfe; - ctx->D = (md5_uint32) 0x10325476; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Put result from CTX in first 16 bytes following RESBUF. The result - must be in little endian byte order. - - IMPORTANT: RESBUF may not be aligned as strongly as MD5_UNIT32 so we - put things in a local (aligned) buffer first, then memcpy into RESBUF. */ -void * -md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) -{ - md5_uint32 buffer[4]; - - buffer[0] = SWAP (ctx->A); - buffer[1] = SWAP (ctx->B); - buffer[2] = SWAP (ctx->C); - buffer[3] = SWAP (ctx->D); - - memcpy (resbuf, buffer, 16); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -void * -md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) -{ - /* Take yet unprocessed bytes into account. */ - md5_uint32 bytes = ctx->buflen; - md5_uint32 swap_bytes; - size_t pad; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; - memcpy (&ctx->buffer[bytes], fillbuf, pad); - - /* Put the 64-bit file length in *bits* at the end of the buffer. - Use memcpy to avoid aliasing problems. On most systems, this - will be optimized away to the same code. */ - swap_bytes = SWAP (ctx->total[0] << 3); - memcpy (&ctx->buffer[bytes + pad], &swap_bytes, sizeof (swap_bytes)); - swap_bytes = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - memcpy (&ctx->buffer[bytes + pad + 4], &swap_bytes, sizeof (swap_bytes)); - - /* Process last bytes. */ - md5_process_block (ctx->buffer, bytes + pad + 8, ctx); - - return md5_read_ctx (ctx, resbuf); -} - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -int -md5_stream (FILE *stream, void *resblock) -{ - /* Important: BLOCKSIZE must be a multiple of 64. */ -#define BLOCKSIZE 4096 - struct md5_ctx ctx; - char buffer[BLOCKSIZE + 72]; - size_t sum; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Iterate over full file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - do - { - n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - } - while (sum < BLOCKSIZE && n != 0); - if (n == 0 && ferror (stream)) - return 1; - - /* If end of file is reached, end the loop. */ - if (n == 0) - break; - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - md5_process_block (buffer, BLOCKSIZE, &ctx); - } - - /* Add the last bytes if necessary. */ - if (sum > 0) - md5_process_bytes (buffer, sum, &ctx); - - /* Construct result in desired memory. */ - md5_finish_ctx (&ctx, resblock); - return 0; -} - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -md5_buffer (const char *buffer, size_t len, void *resblock) -{ - struct md5_ctx ctx; - - /* Initialize the computation context. */ - md5_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - md5_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return md5_finish_ctx (&ctx, resblock); -} - - -void -md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&ctx->buffer[left_over], buffer, add); - ctx->buflen += add; - - if (left_over + add > 64) - { - md5_process_block (ctx->buffer, (left_over + add) & ~63, ctx); - /* The regions in the following copy operation cannot overlap. */ - memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], - (left_over + add) & 63); - ctx->buflen = (left_over + add) & 63; - } - - buffer = (const void *) ((const char *) buffer + add); - len -= add; - } - - /* Process available complete blocks. */ - if (len > 64) - { -#if !_STRING_ARCH_unaligned || defined UBSAN_BOOTSTRAP -/* To check alignment gcc has an appropriate operator. Other - compilers don't. */ -# if __GNUC__ >= 2 -# define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) -# else -# define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0) -# endif - if (UNALIGNED_P (buffer)) - while (len > 64) - { - memcpy (ctx->buffer, buffer, 64); - md5_process_block (ctx->buffer, 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - else -#endif - { - md5_process_block (buffer, len & ~63, ctx); - buffer = (const void *) ((const char *) buffer + (len & ~63)); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - memcpy (ctx->buffer, buffer, len); - ctx->buflen = len; - } -} - - -/* These are the four functions used in the four steps of the MD5 algorithm - and defined in the RFC 1321. The first function is a little bit optimized - (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)) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. */ - -void -md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) -{ - md5_uint32 correct_words[16]; - const md5_uint32 *words = (const md5_uint32 *) buffer; - size_t nwords = len / sizeof (md5_uint32); - const md5_uint32 *endp = words + nwords; - md5_uint32 A = ctx->A; - md5_uint32 B = ctx->B; - md5_uint32 C = ctx->C; - md5_uint32 D = ctx->D; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - ctx->total[1] += ((len >> 31) >> 1) + (ctx->total[0] < len); - - /* Process all bytes in the buffer with 64 bytes in each round of - the loop. */ - while (words < endp) - { - md5_uint32 *cwp = correct_words; - md5_uint32 A_save = A; - md5_uint32 B_save = B; - md5_uint32 C_save = C; - md5_uint32 D_save = D; - - /* First round: using the given function, the context and a constant - the next context is computed. Because the algorithms processing - unit is a 32-bit word and it is determined to work on words in - little endian byte order we perhaps have to change the byte order - before the computation. To reduce the work for the next steps - we store the swapped words in the array CORRECT_WORDS. */ - -#define OP(a, b, c, d, s, T) \ - do \ - { \ - a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ - ++words; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - - /* It is unfortunate that C does not provide an operator for - cyclic rotation. Hope the C compiler is smart enough. */ -#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) - - /* Before we start, one word to the strange constants. - They are defined in RFC 1321 as - - T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 - */ - - /* Round 1. */ - OP (A, B, C, D, 7, (md5_uint32) 0xd76aa478); - OP (D, A, B, C, 12, (md5_uint32) 0xe8c7b756); - OP (C, D, A, B, 17, (md5_uint32) 0x242070db); - OP (B, C, D, A, 22, (md5_uint32) 0xc1bdceee); - OP (A, B, C, D, 7, (md5_uint32) 0xf57c0faf); - OP (D, A, B, C, 12, (md5_uint32) 0x4787c62a); - OP (C, D, A, B, 17, (md5_uint32) 0xa8304613); - OP (B, C, D, A, 22, (md5_uint32) 0xfd469501); - OP (A, B, C, D, 7, (md5_uint32) 0x698098d8); - OP (D, A, B, C, 12, (md5_uint32) 0x8b44f7af); - OP (C, D, A, B, 17, (md5_uint32) 0xffff5bb1); - OP (B, C, D, A, 22, (md5_uint32) 0x895cd7be); - OP (A, B, C, D, 7, (md5_uint32) 0x6b901122); - OP (D, A, B, C, 12, (md5_uint32) 0xfd987193); - OP (C, D, A, B, 17, (md5_uint32) 0xa679438e); - OP (B, C, D, A, 22, (md5_uint32) 0x49b40821); - - /* For the second to fourth round we have the possibly swapped words - in CORRECT_WORDS. Redefine the macro to take an additional first - argument specifying the function to use. */ -#undef OP -#define OP(a, b, c, d, k, s, T) \ - do \ - { \ - a += FX (b, c, d) + correct_words[k] + T; \ - CYCLIC (a, s); \ - a += b; \ - } \ - while (0) - -#define FX(b, c, d) FG (b, c, d) - - /* Round 2. */ - OP (A, B, C, D, 1, 5, (md5_uint32) 0xf61e2562); - OP (D, A, B, C, 6, 9, (md5_uint32) 0xc040b340); - OP (C, D, A, B, 11, 14, (md5_uint32) 0x265e5a51); - OP (B, C, D, A, 0, 20, (md5_uint32) 0xe9b6c7aa); - OP (A, B, C, D, 5, 5, (md5_uint32) 0xd62f105d); - OP (D, A, B, C, 10, 9, (md5_uint32) 0x02441453); - OP (C, D, A, B, 15, 14, (md5_uint32) 0xd8a1e681); - OP (B, C, D, A, 4, 20, (md5_uint32) 0xe7d3fbc8); - OP (A, B, C, D, 9, 5, (md5_uint32) 0x21e1cde6); - OP (D, A, B, C, 14, 9, (md5_uint32) 0xc33707d6); - OP (C, D, A, B, 3, 14, (md5_uint32) 0xf4d50d87); - OP (B, C, D, A, 8, 20, (md5_uint32) 0x455a14ed); - OP (A, B, C, D, 13, 5, (md5_uint32) 0xa9e3e905); - OP (D, A, B, C, 2, 9, (md5_uint32) 0xfcefa3f8); - OP (C, D, A, B, 7, 14, (md5_uint32) 0x676f02d9); - OP (B, C, D, A, 12, 20, (md5_uint32) 0x8d2a4c8a); - -#undef FX -#define FX(b, c, d) FH (b, c, d) - - /* Round 3. */ - OP (A, B, C, D, 5, 4, (md5_uint32) 0xfffa3942); - OP (D, A, B, C, 8, 11, (md5_uint32) 0x8771f681); - OP (C, D, A, B, 11, 16, (md5_uint32) 0x6d9d6122); - OP (B, C, D, A, 14, 23, (md5_uint32) 0xfde5380c); - OP (A, B, C, D, 1, 4, (md5_uint32) 0xa4beea44); - OP (D, A, B, C, 4, 11, (md5_uint32) 0x4bdecfa9); - OP (C, D, A, B, 7, 16, (md5_uint32) 0xf6bb4b60); - OP (B, C, D, A, 10, 23, (md5_uint32) 0xbebfbc70); - OP (A, B, C, D, 13, 4, (md5_uint32) 0x289b7ec6); - OP (D, A, B, C, 0, 11, (md5_uint32) 0xeaa127fa); - OP (C, D, A, B, 3, 16, (md5_uint32) 0xd4ef3085); - OP (B, C, D, A, 6, 23, (md5_uint32) 0x04881d05); - OP (A, B, C, D, 9, 4, (md5_uint32) 0xd9d4d039); - OP (D, A, B, C, 12, 11, (md5_uint32) 0xe6db99e5); - OP (C, D, A, B, 15, 16, (md5_uint32) 0x1fa27cf8); - OP (B, C, D, A, 2, 23, (md5_uint32) 0xc4ac5665); - -#undef FX -#define FX(b, c, d) FI (b, c, d) - - /* Round 4. */ - OP (A, B, C, D, 0, 6, (md5_uint32) 0xf4292244); - OP (D, A, B, C, 7, 10, (md5_uint32) 0x432aff97); - OP (C, D, A, B, 14, 15, (md5_uint32) 0xab9423a7); - OP (B, C, D, A, 5, 21, (md5_uint32) 0xfc93a039); - OP (A, B, C, D, 12, 6, (md5_uint32) 0x655b59c3); - OP (D, A, B, C, 3, 10, (md5_uint32) 0x8f0ccc92); - OP (C, D, A, B, 10, 15, (md5_uint32) 0xffeff47d); - OP (B, C, D, A, 1, 21, (md5_uint32) 0x85845dd1); - OP (A, B, C, D, 8, 6, (md5_uint32) 0x6fa87e4f); - OP (D, A, B, C, 15, 10, (md5_uint32) 0xfe2ce6e0); - OP (C, D, A, B, 6, 15, (md5_uint32) 0xa3014314); - OP (B, C, D, A, 13, 21, (md5_uint32) 0x4e0811a1); - OP (A, B, C, D, 4, 6, (md5_uint32) 0xf7537e82); - OP (D, A, B, C, 11, 10, (md5_uint32) 0xbd3af235); - OP (C, D, A, B, 2, 15, (md5_uint32) 0x2ad7d2bb); - OP (B, C, D, A, 9, 21, (md5_uint32) 0xeb86d391); - - /* Add the starting values of the context. */ - A += A_save; - B += B_save; - C += C_save; - D += D_save; - } - - /* Put checksum in context given as argument. */ - ctx->A = A; - ctx->B = B; - ctx->C = C; - ctx->D = D; -} diff --git a/tools/md5.h b/tools/md5.h deleted file mode 100644 index 03f7d29..0000000 --- a/tools/md5.h +++ /dev/null @@ -1,154 +0,0 @@ -/* md5.h - Declaration of functions and data types used for MD5 sum - computing library functions. - Copyright (C) 1995-2021 Free Software Foundation, Inc. - NOTE: The canonical source of this file is maintained with the GNU C - Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. - - 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 Foundation, - Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef _MD5_H -#define _MD5_H 1 - -#include - -#if defined HAVE_LIMITS_H || _LIBC -# include -#endif - -#include "ansidecl.h" - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - doing that would require that the configure script compile and *run* - the resulting executable. Locally running cross-compiled executables - is usually not possible. */ - -#ifdef _LIBC -# include -typedef u_int32_t md5_uint32; -typedef uintptr_t md5_uintptr; -#elif defined (HAVE_SYS_TYPES_H) && defined (HAVE_STDINT_H) -#include -#include -typedef uint32_t md5_uint32; -typedef uintptr_t md5_uintptr; -#else -# define INT_MAX_32_BITS 2147483647 - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -# ifndef INT_MAX -# define INT_MAX INT_MAX_32_BITS -# endif - -# if INT_MAX == INT_MAX_32_BITS - typedef unsigned int md5_uint32; -# else -# if SHRT_MAX == INT_MAX_32_BITS - typedef unsigned short md5_uint32; -# else -# if LONG_MAX == INT_MAX_32_BITS - typedef unsigned long md5_uint32; -# else - /* The following line is intended to evoke an error. - Using #error is not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -# endif -/* We have to make a guess about the integer type equivalent in size - to pointers which should always be correct. */ -typedef unsigned long int md5_uintptr; -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structure to save state of computation between the single steps. */ -struct md5_ctx -{ - md5_uint32 A; - md5_uint32 B; - md5_uint32 C; - md5_uint32 D; - - md5_uint32 total[2]; - md5_uint32 buflen; - char buffer[128] ATTRIBUTE_ALIGNED_ALIGNOF(md5_uint32); -}; - -/* - * The following three functions are build up the low level used in - * the functions `md5_stream' and `md5_buffer'. - */ - -/* Initialize structure containing state of computation. - (RFC 1321, 3.3: Step 3) */ -extern void md5_init_ctx (struct md5_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void md5_process_block (const void *buffer, size_t len, - struct md5_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void md5_process_bytes (const void *buffer, size_t len, - struct md5_ctx *ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 16 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); - - -/* Put result from CTX in first 16 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); - - -/* Compute MD5 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -extern int md5_stream (FILE *stream, void *resblock); - -/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *md5_buffer (const char *buffer, size_t len, void *resblock); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/tools/sha1.c b/tools/sha1.c deleted file mode 100644 index 7d15d48..0000000 --- a/tools/sha1.c +++ /dev/null @@ -1,414 +0,0 @@ -/* sha1.c - Functions to compute SHA1 message digest of files or - memory blocks according to the NIST specification FIPS-180-1. - - Copyright (C) 2000-2021 Free Software Foundation, 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 Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Scott G. Miller - Credits: - Robert Klep -- Expansion function fix -*/ - -#include - -#include "sha1.h" - -#include -#include - -#if USE_UNLOCKED_IO -# include "unlocked-io.h" -#endif - -#ifdef WORDS_BIGENDIAN -# define SWAP(n) (n) -#else -# define SWAP(n) \ - (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) -#endif - -#define BLOCKSIZE 4096 -#if BLOCKSIZE % 64 != 0 -# error "invalid BLOCKSIZE" -#endif - -/* This array contains the bytes used to pad the buffer to the next - 64-byte boundary. (RFC 1321, 3.1: Step 1) */ -static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; - - -/* Take a pointer to a 160 bit block of data (five 32 bit ints) and - initialize it to the start constants of the SHA1 algorithm. This - must be called before using hash in the call to sha1_hash. */ -void -sha1_init_ctx (struct sha1_ctx *ctx) -{ - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - ctx->E = 0xc3d2e1f0; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Put result from CTX in first 20 bytes following RESBUF. The result - must be in little endian byte order. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32-bit value. */ -void * -sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf) -{ - ((sha1_uint32 *) resbuf)[0] = SWAP (ctx->A); - ((sha1_uint32 *) resbuf)[1] = SWAP (ctx->B); - ((sha1_uint32 *) resbuf)[2] = SWAP (ctx->C); - ((sha1_uint32 *) resbuf)[3] = SWAP (ctx->D); - ((sha1_uint32 *) resbuf)[4] = SWAP (ctx->E); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32-bit value. */ -void * -sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf) -{ - /* Take yet unprocessed bytes into account. */ - sha1_uint32 bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if (ctx->total[0] < bytes) - ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer[size - 2] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - ctx->buffer[size - 1] = SWAP (ctx->total[0] << 3); - - memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha1_process_block (ctx->buffer, size * 4, ctx); - - return sha1_read_ctx (ctx, resbuf); -} - -/* Compute SHA1 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 16 bytes - beginning at RESBLOCK. */ -int -sha1_stream (FILE *stream, void *resblock) -{ - struct sha1_ctx ctx; - char buffer[BLOCKSIZE + 72]; - size_t sum; - - /* Initialize the computation context. */ - sha1_init_ctx (&ctx); - - /* Iterate over full file contents. */ - while (1) - { - /* We read the file in blocks of BLOCKSIZE bytes. One call of the - computation function processes the whole buffer so that with the - next round of the loop another block can be read. */ - size_t n; - sum = 0; - - /* Read block. Take care for partial reads. */ - while (1) - { - n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); - - sum += n; - - if (sum == BLOCKSIZE) - break; - - if (n == 0) - { - /* Check for the error flag IFF N == 0, so that we don't - exit the loop after a partial read due to e.g., EAGAIN - or EWOULDBLOCK. */ - if (ferror (stream)) - return 1; - goto process_partial_block; - } - - /* We've read at least one byte, so ignore errors. But always - check for EOF, since feof may be true even though N > 0. - Otherwise, we could end up calling fread after EOF. */ - if (feof (stream)) - goto process_partial_block; - } - - /* Process buffer with BLOCKSIZE bytes. Note that - BLOCKSIZE % 64 == 0 - */ - sha1_process_block (buffer, BLOCKSIZE, &ctx); - } - - process_partial_block:; - - /* Process any remaining bytes. */ - if (sum > 0) - sha1_process_bytes (buffer, sum, &ctx); - - /* Construct result in desired memory. */ - sha1_finish_ctx (&ctx, resblock); - return 0; -} - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void * -sha1_buffer (const char *buffer, size_t len, void *resblock) -{ - struct sha1_ctx ctx; - - /* Initialize the computation context. */ - sha1_init_ctx (&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha1_process_bytes (buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha1_finish_ctx (&ctx, resblock); -} - -void -sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx) -{ - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if (ctx->buflen != 0) - { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if (ctx->buflen > 64) - { - sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap. */ - memcpy (ctx->buffer, - &((char *) ctx->buffer)[(left_over + add) & ~63], - ctx->buflen); - } - - buffer = (const char *) buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if (len >= 64) - { -#if !_STRING_ARCH_unaligned -# define alignof(type) offsetof (struct { char c; type x; }, x) -# define UNALIGNED_P(p) (((size_t) p) % alignof (sha1_uint32) != 0) - if (UNALIGNED_P (buffer)) - while (len > 64) - { - sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); - buffer = (const char *) buffer + 64; - len -= 64; - } - else -#endif - { - sha1_process_block (buffer, len & ~63, ctx); - buffer = (const char *) buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if (len > 0) - { - size_t left_over = ctx->buflen; - - memcpy (&((char *) ctx->buffer)[left_over], buffer, len); - left_over += len; - if (left_over >= 64) - { - sha1_process_block (ctx->buffer, 64, ctx); - left_over -= 64; - memmove (ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between md5.c and sha1.c --- */ - -/* SHA1 round constants */ -#define K1 0x5a827999 -#define K2 0x6ed9eba1 -#define K3 0x8f1bbcdc -#define K4 0xca62c1d6 - -/* Round functions. Note that F2 is the same as F4. */ -#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) -#define F2(B,C,D) (B ^ C ^ D) -#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) -#define F4(B,C,D) (B ^ C ^ D) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void -sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx) -{ - const sha1_uint32 *words = (const sha1_uint32*) buffer; - size_t nwords = len / sizeof (sha1_uint32); - const sha1_uint32 *endp = words + nwords; - sha1_uint32 x[16]; - sha1_uint32 a = ctx->A; - sha1_uint32 b = ctx->B; - sha1_uint32 c = ctx->C; - sha1_uint32 d = ctx->D; - sha1_uint32 e = ctx->E; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += len; - ctx->total[1] += ((len >> 31) >> 1) + (ctx->total[0] < len); - -#define rol(x, n) (((x) << (n)) | ((sha1_uint32) (x) >> (32 - (n)))) - -#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ - ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ - , (x[I&0x0f] = rol(tm, 1)) ) - -#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ - + F( B, C, D ) \ - + K \ - + M; \ - B = rol( B, 30 ); \ - } while(0) - - while (words < endp) - { - sha1_uint32 tm; - int t; - for (t = 0; t < 16; t++) - { - x[t] = SWAP (*words); - words++; - } - - R( a, b, c, d, e, F1, K1, x[ 0] ); - R( e, a, b, c, d, F1, K1, x[ 1] ); - R( d, e, a, b, c, F1, K1, x[ 2] ); - R( c, d, e, a, b, F1, K1, x[ 3] ); - R( b, c, d, e, a, F1, K1, x[ 4] ); - R( a, b, c, d, e, F1, K1, x[ 5] ); - R( e, a, b, c, d, F1, K1, x[ 6] ); - R( d, e, a, b, c, F1, K1, x[ 7] ); - R( c, d, e, a, b, F1, K1, x[ 8] ); - R( b, c, d, e, a, F1, K1, x[ 9] ); - R( a, b, c, d, e, F1, K1, x[10] ); - R( e, a, b, c, d, F1, K1, x[11] ); - R( d, e, a, b, c, F1, K1, x[12] ); - R( c, d, e, a, b, F1, K1, x[13] ); - R( b, c, d, e, a, F1, K1, x[14] ); - R( a, b, c, d, e, F1, K1, x[15] ); - R( e, a, b, c, d, F1, K1, M(16) ); - R( d, e, a, b, c, F1, K1, M(17) ); - R( c, d, e, a, b, F1, K1, M(18) ); - R( b, c, d, e, a, F1, K1, M(19) ); - R( a, b, c, d, e, F2, K2, M(20) ); - R( e, a, b, c, d, F2, K2, M(21) ); - R( d, e, a, b, c, F2, K2, M(22) ); - R( c, d, e, a, b, F2, K2, M(23) ); - R( b, c, d, e, a, F2, K2, M(24) ); - R( a, b, c, d, e, F2, K2, M(25) ); - R( e, a, b, c, d, F2, K2, M(26) ); - R( d, e, a, b, c, F2, K2, M(27) ); - R( c, d, e, a, b, F2, K2, M(28) ); - R( b, c, d, e, a, F2, K2, M(29) ); - R( a, b, c, d, e, F2, K2, M(30) ); - R( e, a, b, c, d, F2, K2, M(31) ); - R( d, e, a, b, c, F2, K2, M(32) ); - R( c, d, e, a, b, F2, K2, M(33) ); - R( b, c, d, e, a, F2, K2, M(34) ); - R( a, b, c, d, e, F2, K2, M(35) ); - R( e, a, b, c, d, F2, K2, M(36) ); - R( d, e, a, b, c, F2, K2, M(37) ); - R( c, d, e, a, b, F2, K2, M(38) ); - R( b, c, d, e, a, F2, K2, M(39) ); - R( a, b, c, d, e, F3, K3, M(40) ); - R( e, a, b, c, d, F3, K3, M(41) ); - R( d, e, a, b, c, F3, K3, M(42) ); - R( c, d, e, a, b, F3, K3, M(43) ); - R( b, c, d, e, a, F3, K3, M(44) ); - R( a, b, c, d, e, F3, K3, M(45) ); - R( e, a, b, c, d, F3, K3, M(46) ); - R( d, e, a, b, c, F3, K3, M(47) ); - R( c, d, e, a, b, F3, K3, M(48) ); - R( b, c, d, e, a, F3, K3, M(49) ); - R( a, b, c, d, e, F3, K3, M(50) ); - R( e, a, b, c, d, F3, K3, M(51) ); - R( d, e, a, b, c, F3, K3, M(52) ); - R( c, d, e, a, b, F3, K3, M(53) ); - R( b, c, d, e, a, F3, K3, M(54) ); - R( a, b, c, d, e, F3, K3, M(55) ); - R( e, a, b, c, d, F3, K3, M(56) ); - R( d, e, a, b, c, F3, K3, M(57) ); - R( c, d, e, a, b, F3, K3, M(58) ); - R( b, c, d, e, a, F3, K3, M(59) ); - R( a, b, c, d, e, F4, K4, M(60) ); - R( e, a, b, c, d, F4, K4, M(61) ); - R( d, e, a, b, c, F4, K4, M(62) ); - R( c, d, e, a, b, F4, K4, M(63) ); - R( b, c, d, e, a, F4, K4, M(64) ); - R( a, b, c, d, e, F4, K4, M(65) ); - R( e, a, b, c, d, F4, K4, M(66) ); - R( d, e, a, b, c, F4, K4, M(67) ); - R( c, d, e, a, b, F4, K4, M(68) ); - R( b, c, d, e, a, F4, K4, M(69) ); - R( a, b, c, d, e, F4, K4, M(70) ); - R( e, a, b, c, d, F4, K4, M(71) ); - R( d, e, a, b, c, F4, K4, M(72) ); - R( c, d, e, a, b, F4, K4, M(73) ); - R( b, c, d, e, a, F4, K4, M(74) ); - R( a, b, c, d, e, F4, K4, M(75) ); - R( e, a, b, c, d, F4, K4, M(76) ); - R( d, e, a, b, c, F4, K4, M(77) ); - R( c, d, e, a, b, F4, K4, M(78) ); - R( b, c, d, e, a, F4, K4, M(79) ); - - a = ctx->A += a; - b = ctx->B += b; - c = ctx->C += c; - d = ctx->D += d; - e = ctx->E += e; - } -} diff --git a/tools/sha1.h b/tools/sha1.h deleted file mode 100644 index ebeda44..0000000 --- a/tools/sha1.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Declarations of functions and data types used for SHA1 sum - library functions. - Copyright (C) 2000-2021 Free Software Foundation, 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 3, 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 Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -#ifndef SHA1_H -# define SHA1_H 1 - -#include - -#if defined HAVE_LIMITS_H || _LIBC -# include -#endif - -#include "ansidecl.h" - -/* The following contortions are an attempt to use the C preprocessor - to determine an unsigned integral type that is 32 bits wide. An - alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but - doing that would require that the configure script compile and *run* - the resulting executable. Locally running cross-compiled executables - is usually not possible. */ - -#ifdef _LIBC -# include -typedef u_int32_t sha1_uint32; -typedef uintptr_t sha1_uintptr; -#elif defined (HAVE_SYS_TYPES_H) && defined (HAVE_STDINT_H) -#include -#include -typedef uint32_t sha1_uint32; -typedef uintptr_t sha1_uintptr; -#else -# define INT_MAX_32_BITS 2147483647 - -/* If UINT_MAX isn't defined, assume it's a 32-bit type. - This should be valid for all systems GNU cares about because - that doesn't include 16-bit systems, and only modern systems - (that certainly have ) have 64+-bit integral types. */ - -# ifndef INT_MAX -# define INT_MAX INT_MAX_32_BITS -# endif - -# if INT_MAX == INT_MAX_32_BITS - typedef unsigned int sha1_uint32; -# else -# if SHRT_MAX == INT_MAX_32_BITS - typedef unsigned short sha1_uint32; -# else -# if LONG_MAX == INT_MAX_32_BITS - typedef unsigned long sha1_uint32; -# else - /* The following line is intended to evoke an error. - Using #error is not portable enough. */ - "Cannot determine unsigned 32-bit data type." -# endif -# endif -# endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/* Structure to save state of computation between the single steps. */ -struct sha1_ctx -{ - sha1_uint32 A; - sha1_uint32 B; - sha1_uint32 C; - sha1_uint32 D; - sha1_uint32 E; - - sha1_uint32 total[2]; - sha1_uint32 buflen; - sha1_uint32 buffer[32]; -}; - - -/* Initialize structure containing state of computation. */ -extern void sha1_init_ctx (struct sha1_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha1_process_block (const void *buffer, size_t len, - struct sha1_ctx *ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha1_process_bytes (const void *buffer, size_t len, - struct sha1_ctx *ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 20 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF be correctly - aligned for a 32 bits value. */ -extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf); - - -/* Put result from CTX in first 20 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf); - - -/* Compute SHA1 message digest for bytes read from STREAM. The - resulting message digest number will be written into the 20 bytes - beginning at RESBLOCK. */ -extern int sha1_stream (FILE *stream, void *resblock); - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void *sha1_buffer (const char *buffer, size_t len, void *resblock); - -#ifdef __cplusplus -} -#endif - -#endif -- 2.43.5