diff options
| author | Paul Eggert | 2011-02-18 00:07:03 -0800 |
|---|---|---|
| committer | Paul Eggert | 2011-02-18 00:07:03 -0800 |
| commit | 942f733fd1251da4486cf1d72ec5569532dfd19d (patch) | |
| tree | 7c04854c15370219b6282c302ebcaed75a2f0eb8 /lib | |
| parent | 37b3d30244ad822e049b6b20c2eadf5946cb02cc (diff) | |
| download | emacs-942f733fd1251da4486cf1d72ec5569532dfd19d.tar.gz emacs-942f733fd1251da4486cf1d72ec5569532dfd19d.zip | |
Import crypto/md5 module from gnulib.
* Makefile.in (MAKEFILE_MODULES): Add crypto/md5.
* admin/notes/copyright: Remove src/md5.c and src/md5.h as
special cases.
* src/Makefile.in (base_obj): Remove md5.o, since this file
is in lib now.
* src/deps.mk (md5.o): Remove.
* aclocal.m4, configure, lib/Makefile.in, lib/gnulib.mk, m4/gl-comp.m4:
Regenerate.
* lib/md5.c: Regenerate. This renames the file from src/md5.c,
and adds some porting improvements from gnulib.
* lib/md5.h: Regenerate, likwise; rename from src/md5.h.
* m4/md5.m4: New file, from gnulib.
2011-02-18 Paul Eggert <eggert@cs.ucla.edu>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/Makefile.in | 30 | ||||
| -rw-r--r-- | lib/gnulib.mk | 11 | ||||
| -rw-r--r-- | lib/md5.c | 462 | ||||
| -rw-r--r-- | lib/md5.h | 161 |
4 files changed, 649 insertions, 15 deletions
diff --git a/lib/Makefile.in b/lib/Makefile.in index 82e23967865..b0fd92237cd 100644 --- a/lib/Makefile.in +++ b/lib/Makefile.in | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | # the same distribution terms as the rest of that program. | 24 | # the same distribution terms as the rest of that program. |
| 25 | # | 25 | # |
| 26 | # Generated by gnulib-tool. | 26 | # Generated by gnulib-tool. |
| 27 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getloadavg getopt-gnu ignore-value mktime strftime | 27 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr getloadavg getopt-gnu ignore-value mktime strftime |
| 28 | 28 | ||
| 29 | VPATH = @srcdir@ | 29 | VPATH = @srcdir@ |
| 30 | pkgdatadir = $(datadir)/@PACKAGE@ | 30 | pkgdatadir = $(datadir)/@PACKAGE@ |
| @@ -53,13 +53,13 @@ am__aclocal_m4_deps = $(top_srcdir)/m4/00gnulib.m4 \ | |||
| 53 | $(top_srcdir)/m4/c-strtod.m4 $(top_srcdir)/m4/extensions.m4 \ | 53 | $(top_srcdir)/m4/c-strtod.m4 $(top_srcdir)/m4/extensions.m4 \ |
| 54 | $(top_srcdir)/m4/getloadavg.m4 $(top_srcdir)/m4/getopt.m4 \ | 54 | $(top_srcdir)/m4/getloadavg.m4 $(top_srcdir)/m4/getopt.m4 \ |
| 55 | $(top_srcdir)/m4/gl-comp.m4 $(top_srcdir)/m4/gnulib-common.m4 \ | 55 | $(top_srcdir)/m4/gl-comp.m4 $(top_srcdir)/m4/gnulib-common.m4 \ |
| 56 | $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/mktime.m4 \ | 56 | $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/md5.m4 \ |
| 57 | $(top_srcdir)/m4/multiarch.m4 $(top_srcdir)/m4/stdbool.m4 \ | 57 | $(top_srcdir)/m4/mktime.m4 $(top_srcdir)/m4/multiarch.m4 \ |
| 58 | $(top_srcdir)/m4/stddef_h.m4 $(top_srcdir)/m4/stdlib_h.m4 \ | 58 | $(top_srcdir)/m4/stdbool.m4 $(top_srcdir)/m4/stddef_h.m4 \ |
| 59 | $(top_srcdir)/m4/strftime.m4 $(top_srcdir)/m4/time_h.m4 \ | 59 | $(top_srcdir)/m4/stdlib_h.m4 $(top_srcdir)/m4/strftime.m4 \ |
| 60 | $(top_srcdir)/m4/time_r.m4 $(top_srcdir)/m4/tm_gmtoff.m4 \ | 60 | $(top_srcdir)/m4/time_h.m4 $(top_srcdir)/m4/time_r.m4 \ |
| 61 | $(top_srcdir)/m4/unistd_h.m4 $(top_srcdir)/m4/wchar_t.m4 \ | 61 | $(top_srcdir)/m4/tm_gmtoff.m4 $(top_srcdir)/m4/unistd_h.m4 \ |
| 62 | $(top_srcdir)/configure.in | 62 | $(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/configure.in |
| 63 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ | 63 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ |
| 64 | $(ACLOCAL_M4) | 64 | $(ACLOCAL_M4) |
| 65 | mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs | 65 | mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs |
| @@ -536,10 +536,11 @@ x_default_search_path = @x_default_search_path@ | |||
| 536 | BUILT_SOURCES = arg-nonnull.h c++defs.h $(GETOPT_H) $(STDBOOL_H) \ | 536 | BUILT_SOURCES = arg-nonnull.h c++defs.h $(GETOPT_H) $(STDBOOL_H) \ |
| 537 | $(STDDEF_H) stdlib.h time.h unistd.h warn-on-use.h | 537 | $(STDDEF_H) stdlib.h time.h unistd.h warn-on-use.h |
| 538 | EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \ | 538 | EXTRA_DIST = $(top_srcdir)/./arg-nonnull.h $(top_srcdir)/./c++defs.h \ |
| 539 | ftoastr.c ftoastr.h getloadavg.c getopt.c getopt.in.h \ | 539 | md5.c md5.h ftoastr.c ftoastr.h getloadavg.c getopt.c \ |
| 540 | getopt1.c getopt_int.h intprops.h mktime-internal.h mktime.c \ | 540 | getopt.in.h getopt1.c getopt_int.h intprops.h \ |
| 541 | stdbool.in.h stddef.in.h stdlib.in.h strftime.c strftime.h \ | 541 | mktime-internal.h mktime.c stdbool.in.h stddef.in.h \ |
| 542 | time.in.h time_r.c unistd.in.h $(top_srcdir)/./warn-on-use.h | 542 | stdlib.in.h strftime.c strftime.h time.in.h time_r.c \ |
| 543 | unistd.in.h $(top_srcdir)/./warn-on-use.h | ||
| 543 | MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \ | 544 | MOSTLYCLEANFILES = core *.stackdump arg-nonnull.h arg-nonnull.h-t \ |
| 544 | c++defs.h c++defs.h-t getopt.h getopt.h-t stdbool.h \ | 545 | c++defs.h c++defs.h-t getopt.h getopt.h-t stdbool.h \ |
| 545 | stdbool.h-t stddef.h stddef.h-t stdlib.h stdlib.h-t time.h \ | 546 | stdbool.h-t stddef.h stddef.h-t stdlib.h stdlib.h-t time.h \ |
| @@ -549,8 +550,8 @@ DEFAULT_INCLUDES = -I. -I../src -I$(top_srcdir)/src | |||
| 549 | libgnu_a_SOURCES = dtoastr.c gettext.h ignore-value.h | 550 | libgnu_a_SOURCES = dtoastr.c gettext.h ignore-value.h |
| 550 | libgnu_a_LIBADD = $(gl_LIBOBJS) | 551 | libgnu_a_LIBADD = $(gl_LIBOBJS) |
| 551 | libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) | 552 | libgnu_a_DEPENDENCIES = $(gl_LIBOBJS) |
| 552 | EXTRA_libgnu_a_SOURCES = ftoastr.c getloadavg.c getopt.c getopt1.c \ | 553 | EXTRA_libgnu_a_SOURCES = md5.c ftoastr.c getloadavg.c getopt.c \ |
| 553 | mktime.c strftime.c time_r.c | 554 | getopt1.c mktime.c strftime.c time_r.c |
| 554 | ARG_NONNULL_H = arg-nonnull.h | 555 | ARG_NONNULL_H = arg-nonnull.h |
| 555 | CXXDEFS_H = c++defs.h | 556 | CXXDEFS_H = c++defs.h |
| 556 | WARN_ON_USE_H = warn-on-use.h | 557 | WARN_ON_USE_H = warn-on-use.h |
| @@ -608,6 +609,7 @@ distclean-compile: | |||
| 608 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getloadavg.Po@am__quote@ | 609 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getloadavg.Po@am__quote@ |
| 609 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ | 610 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt.Po@am__quote@ |
| 610 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ | 611 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getopt1.Po@am__quote@ |
| 612 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ | ||
| 611 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@ | 613 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mktime.Po@am__quote@ |
| 612 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strftime.Po@am__quote@ | 614 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/strftime.Po@am__quote@ |
| 613 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@ | 615 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/time_r.Po@am__quote@ |
diff --git a/lib/gnulib.mk b/lib/gnulib.mk index 0e7263a002b..31f0fd0328e 100644 --- a/lib/gnulib.mk +++ b/lib/gnulib.mk | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | # the same distribution terms as the rest of that program. | 9 | # the same distribution terms as the rest of that program. |
| 10 | # | 10 | # |
| 11 | # Generated by gnulib-tool. | 11 | # Generated by gnulib-tool. |
| 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files dtoastr getloadavg getopt-gnu ignore-value mktime strftime | 12 | # Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=lib --m4-base=m4 --doc-base=doc --tests-base=tests --aux-dir=. --makefile-name=gnulib.mk --no-libtool --macro-prefix=gl --no-vc-files crypto/md5 dtoastr getloadavg getopt-gnu ignore-value mktime strftime |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | MOSTLYCLEANFILES += core *.stackdump | 15 | MOSTLYCLEANFILES += core *.stackdump |
| @@ -69,6 +69,15 @@ EXTRA_DIST += $(top_srcdir)/./c++defs.h | |||
| 69 | 69 | ||
| 70 | ## end gnulib module c++defs | 70 | ## end gnulib module c++defs |
| 71 | 71 | ||
| 72 | ## begin gnulib module crypto/md5 | ||
| 73 | |||
| 74 | |||
| 75 | EXTRA_DIST += md5.c md5.h | ||
| 76 | |||
| 77 | EXTRA_libgnu_a_SOURCES += md5.c | ||
| 78 | |||
| 79 | ## end gnulib module crypto/md5 | ||
| 80 | |||
| 72 | ## begin gnulib module dtoastr | 81 | ## begin gnulib module dtoastr |
| 73 | 82 | ||
| 74 | libgnu_a_SOURCES += dtoastr.c | 83 | libgnu_a_SOURCES += dtoastr.c |
diff --git a/lib/md5.c b/lib/md5.c new file mode 100644 index 00000000000..7a172e35aa7 --- /dev/null +++ b/lib/md5.c | |||
| @@ -0,0 +1,462 @@ | |||
| 1 | /* Functions to compute MD5 message digest of files or memory blocks. | ||
| 2 | according to the definition of MD5 in RFC 1321 from April 1992. | ||
| 3 | Copyright (C) 1995-1997, 1999-2001, 2005-2006, 2008-2011 Free Software | ||
| 4 | Foundation, Inc. | ||
| 5 | This file is part of the GNU C Library. | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify it | ||
| 8 | under the terms of the GNU General Public License as published by the | ||
| 9 | Free Software Foundation; either version 3, or (at your option) any | ||
| 10 | later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software Foundation, | ||
| 19 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
| 20 | |||
| 21 | /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ | ||
| 22 | |||
| 23 | #include <config.h> | ||
| 24 | |||
| 25 | #include "md5.h" | ||
| 26 | |||
| 27 | #include <stddef.h> | ||
| 28 | #include <stdlib.h> | ||
| 29 | #include <string.h> | ||
| 30 | #include <sys/types.h> | ||
| 31 | |||
| 32 | #if USE_UNLOCKED_IO | ||
| 33 | # include "unlocked-io.h" | ||
| 34 | #endif | ||
| 35 | |||
| 36 | #ifdef _LIBC | ||
| 37 | # include <endian.h> | ||
| 38 | # if __BYTE_ORDER == __BIG_ENDIAN | ||
| 39 | # define WORDS_BIGENDIAN 1 | ||
| 40 | # endif | ||
| 41 | /* We need to keep the namespace clean so define the MD5 function | ||
| 42 | protected using leading __ . */ | ||
| 43 | # define md5_init_ctx __md5_init_ctx | ||
| 44 | # define md5_process_block __md5_process_block | ||
| 45 | # define md5_process_bytes __md5_process_bytes | ||
| 46 | # define md5_finish_ctx __md5_finish_ctx | ||
| 47 | # define md5_read_ctx __md5_read_ctx | ||
| 48 | # define md5_stream __md5_stream | ||
| 49 | # define md5_buffer __md5_buffer | ||
| 50 | #endif | ||
| 51 | |||
| 52 | #ifdef WORDS_BIGENDIAN | ||
| 53 | # define SWAP(n) \ | ||
| 54 | (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24)) | ||
| 55 | #else | ||
| 56 | # define SWAP(n) (n) | ||
| 57 | #endif | ||
| 58 | |||
| 59 | #define BLOCKSIZE 32768 | ||
| 60 | #if BLOCKSIZE % 64 != 0 | ||
| 61 | # error "invalid BLOCKSIZE" | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* This array contains the bytes used to pad the buffer to the next | ||
| 65 | 64-byte boundary. (RFC 1321, 3.1: Step 1) */ | ||
| 66 | static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; | ||
| 67 | |||
| 68 | |||
| 69 | /* Initialize structure containing state of computation. | ||
| 70 | (RFC 1321, 3.3: Step 3) */ | ||
| 71 | void | ||
| 72 | md5_init_ctx (struct md5_ctx *ctx) | ||
| 73 | { | ||
| 74 | ctx->A = 0x67452301; | ||
| 75 | ctx->B = 0xefcdab89; | ||
| 76 | ctx->C = 0x98badcfe; | ||
| 77 | ctx->D = 0x10325476; | ||
| 78 | |||
| 79 | ctx->total[0] = ctx->total[1] = 0; | ||
| 80 | ctx->buflen = 0; | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Copy the 4 byte value from v into the memory location pointed to by *cp, | ||
| 84 | If your architecture allows unaligned access this is equivalent to | ||
| 85 | * (md5_uint32 *) cp = v */ | ||
| 86 | static inline void | ||
| 87 | set_uint32 (char *cp, md5_uint32 v) | ||
| 88 | { | ||
| 89 | memcpy (cp, &v, sizeof v); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Put result from CTX in first 16 bytes following RESBUF. The result | ||
| 93 | must be in little endian byte order. */ | ||
| 94 | void * | ||
| 95 | md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) | ||
| 96 | { | ||
| 97 | char *r = resbuf; | ||
| 98 | set_uint32 (r + 0 * sizeof ctx->A, SWAP (ctx->A)); | ||
| 99 | set_uint32 (r + 1 * sizeof ctx->B, SWAP (ctx->B)); | ||
| 100 | set_uint32 (r + 2 * sizeof ctx->C, SWAP (ctx->C)); | ||
| 101 | set_uint32 (r + 3 * sizeof ctx->D, SWAP (ctx->D)); | ||
| 102 | |||
| 103 | return resbuf; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* Process the remaining bytes in the internal buffer and the usual | ||
| 107 | prolog according to the standard and write the result to RESBUF. */ | ||
| 108 | void * | ||
| 109 | md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) | ||
| 110 | { | ||
| 111 | /* Take yet unprocessed bytes into account. */ | ||
| 112 | md5_uint32 bytes = ctx->buflen; | ||
| 113 | size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; | ||
| 114 | |||
| 115 | /* Now count remaining bytes. */ | ||
| 116 | ctx->total[0] += bytes; | ||
| 117 | if (ctx->total[0] < bytes) | ||
| 118 | ++ctx->total[1]; | ||
| 119 | |||
| 120 | /* Put the 64-bit file length in *bits* at the end of the buffer. */ | ||
| 121 | ctx->buffer[size - 2] = SWAP (ctx->total[0] << 3); | ||
| 122 | ctx->buffer[size - 1] = SWAP ((ctx->total[1] << 3) | (ctx->total[0] >> 29)); | ||
| 123 | |||
| 124 | memcpy (&((char *) ctx->buffer)[bytes], fillbuf, (size - 2) * 4 - bytes); | ||
| 125 | |||
| 126 | /* Process last bytes. */ | ||
| 127 | md5_process_block (ctx->buffer, size * 4, ctx); | ||
| 128 | |||
| 129 | return md5_read_ctx (ctx, resbuf); | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Compute MD5 message digest for bytes read from STREAM. The | ||
| 133 | resulting message digest number will be written into the 16 bytes | ||
| 134 | beginning at RESBLOCK. */ | ||
| 135 | int | ||
| 136 | md5_stream (FILE *stream, void *resblock) | ||
| 137 | { | ||
| 138 | struct md5_ctx ctx; | ||
| 139 | size_t sum; | ||
| 140 | |||
| 141 | char *buffer = malloc (BLOCKSIZE + 72); | ||
| 142 | if (!buffer) | ||
| 143 | return 1; | ||
| 144 | |||
| 145 | /* Initialize the computation context. */ | ||
| 146 | md5_init_ctx (&ctx); | ||
| 147 | |||
| 148 | /* Iterate over full file contents. */ | ||
| 149 | while (1) | ||
| 150 | { | ||
| 151 | /* We read the file in blocks of BLOCKSIZE bytes. One call of the | ||
| 152 | computation function processes the whole buffer so that with the | ||
| 153 | next round of the loop another block can be read. */ | ||
| 154 | size_t n; | ||
| 155 | sum = 0; | ||
| 156 | |||
| 157 | /* Read block. Take care for partial reads. */ | ||
| 158 | while (1) | ||
| 159 | { | ||
| 160 | n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream); | ||
| 161 | |||
| 162 | sum += n; | ||
| 163 | |||
| 164 | if (sum == BLOCKSIZE) | ||
| 165 | break; | ||
| 166 | |||
| 167 | if (n == 0) | ||
| 168 | { | ||
| 169 | /* Check for the error flag IFF N == 0, so that we don't | ||
| 170 | exit the loop after a partial read due to e.g., EAGAIN | ||
| 171 | or EWOULDBLOCK. */ | ||
| 172 | if (ferror (stream)) | ||
| 173 | { | ||
| 174 | free (buffer); | ||
| 175 | return 1; | ||
| 176 | } | ||
| 177 | goto process_partial_block; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* We've read at least one byte, so ignore errors. But always | ||
| 181 | check for EOF, since feof may be true even though N > 0. | ||
| 182 | Otherwise, we could end up calling fread after EOF. */ | ||
| 183 | if (feof (stream)) | ||
| 184 | goto process_partial_block; | ||
| 185 | } | ||
| 186 | |||
| 187 | /* Process buffer with BLOCKSIZE bytes. Note that | ||
| 188 | BLOCKSIZE % 64 == 0 | ||
| 189 | */ | ||
| 190 | md5_process_block (buffer, BLOCKSIZE, &ctx); | ||
| 191 | } | ||
| 192 | |||
| 193 | process_partial_block: | ||
| 194 | |||
| 195 | /* Process any remaining bytes. */ | ||
| 196 | if (sum > 0) | ||
| 197 | md5_process_bytes (buffer, sum, &ctx); | ||
| 198 | |||
| 199 | /* Construct result in desired memory. */ | ||
| 200 | md5_finish_ctx (&ctx, resblock); | ||
| 201 | free (buffer); | ||
| 202 | return 0; | ||
| 203 | } | ||
| 204 | |||
| 205 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The | ||
| 206 | result is always in little endian byte order, so that a byte-wise | ||
| 207 | output yields to the wanted ASCII representation of the message | ||
| 208 | digest. */ | ||
| 209 | void * | ||
| 210 | md5_buffer (const char *buffer, size_t len, void *resblock) | ||
| 211 | { | ||
| 212 | struct md5_ctx ctx; | ||
| 213 | |||
| 214 | /* Initialize the computation context. */ | ||
| 215 | md5_init_ctx (&ctx); | ||
| 216 | |||
| 217 | /* Process whole buffer but last len % 64 bytes. */ | ||
| 218 | md5_process_bytes (buffer, len, &ctx); | ||
| 219 | |||
| 220 | /* Put result in desired memory area. */ | ||
| 221 | return md5_finish_ctx (&ctx, resblock); | ||
| 222 | } | ||
| 223 | |||
| 224 | |||
| 225 | void | ||
| 226 | md5_process_bytes (const void *buffer, size_t len, struct md5_ctx *ctx) | ||
| 227 | { | ||
| 228 | /* When we already have some bits in our internal buffer concatenate | ||
| 229 | both inputs first. */ | ||
| 230 | if (ctx->buflen != 0) | ||
| 231 | { | ||
| 232 | size_t left_over = ctx->buflen; | ||
| 233 | size_t add = 128 - left_over > len ? len : 128 - left_over; | ||
| 234 | |||
| 235 | memcpy (&((char *) ctx->buffer)[left_over], buffer, add); | ||
| 236 | ctx->buflen += add; | ||
| 237 | |||
| 238 | if (ctx->buflen > 64) | ||
| 239 | { | ||
| 240 | md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); | ||
| 241 | |||
| 242 | ctx->buflen &= 63; | ||
| 243 | /* The regions in the following copy operation cannot overlap. */ | ||
| 244 | memcpy (ctx->buffer, | ||
| 245 | &((char *) ctx->buffer)[(left_over + add) & ~63], | ||
| 246 | ctx->buflen); | ||
| 247 | } | ||
| 248 | |||
| 249 | buffer = (const char *) buffer + add; | ||
| 250 | len -= add; | ||
| 251 | } | ||
| 252 | |||
| 253 | /* Process available complete blocks. */ | ||
| 254 | if (len >= 64) | ||
| 255 | { | ||
| 256 | #if !_STRING_ARCH_unaligned | ||
| 257 | # define alignof(type) offsetof (struct { char c; type x; }, x) | ||
| 258 | # define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0) | ||
| 259 | if (UNALIGNED_P (buffer)) | ||
| 260 | while (len > 64) | ||
| 261 | { | ||
| 262 | md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); | ||
| 263 | buffer = (const char *) buffer + 64; | ||
| 264 | len -= 64; | ||
| 265 | } | ||
| 266 | else | ||
| 267 | #endif | ||
| 268 | { | ||
| 269 | md5_process_block (buffer, len & ~63, ctx); | ||
| 270 | buffer = (const char *) buffer + (len & ~63); | ||
| 271 | len &= 63; | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | /* Move remaining bytes in internal buffer. */ | ||
| 276 | if (len > 0) | ||
| 277 | { | ||
| 278 | size_t left_over = ctx->buflen; | ||
| 279 | |||
| 280 | memcpy (&((char *) ctx->buffer)[left_over], buffer, len); | ||
| 281 | left_over += len; | ||
| 282 | if (left_over >= 64) | ||
| 283 | { | ||
| 284 | md5_process_block (ctx->buffer, 64, ctx); | ||
| 285 | left_over -= 64; | ||
| 286 | memcpy (ctx->buffer, &ctx->buffer[16], left_over); | ||
| 287 | } | ||
| 288 | ctx->buflen = left_over; | ||
| 289 | } | ||
| 290 | } | ||
| 291 | |||
| 292 | |||
| 293 | /* These are the four functions used in the four steps of the MD5 algorithm | ||
| 294 | and defined in the RFC 1321. The first function is a little bit optimized | ||
| 295 | (as found in Colin Plumbs public domain implementation). */ | ||
| 296 | /* #define FF(b, c, d) ((b & c) | (~b & d)) */ | ||
| 297 | #define FF(b, c, d) (d ^ (b & (c ^ d))) | ||
| 298 | #define FG(b, c, d) FF (d, b, c) | ||
| 299 | #define FH(b, c, d) (b ^ c ^ d) | ||
| 300 | #define FI(b, c, d) (c ^ (b | ~d)) | ||
| 301 | |||
| 302 | /* Process LEN bytes of BUFFER, accumulating context into CTX. | ||
| 303 | It is assumed that LEN % 64 == 0. */ | ||
| 304 | |||
| 305 | void | ||
| 306 | md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx) | ||
| 307 | { | ||
| 308 | md5_uint32 correct_words[16]; | ||
| 309 | const md5_uint32 *words = buffer; | ||
| 310 | size_t nwords = len / sizeof (md5_uint32); | ||
| 311 | const md5_uint32 *endp = words + nwords; | ||
| 312 | md5_uint32 A = ctx->A; | ||
| 313 | md5_uint32 B = ctx->B; | ||
| 314 | md5_uint32 C = ctx->C; | ||
| 315 | md5_uint32 D = ctx->D; | ||
| 316 | |||
| 317 | /* First increment the byte count. RFC 1321 specifies the possible | ||
| 318 | length of the file up to 2^64 bits. Here we only compute the | ||
| 319 | number of bytes. Do a double word increment. */ | ||
| 320 | ctx->total[0] += len; | ||
| 321 | if (ctx->total[0] < len) | ||
| 322 | ++ctx->total[1]; | ||
| 323 | |||
| 324 | /* Process all bytes in the buffer with 64 bytes in each round of | ||
| 325 | the loop. */ | ||
| 326 | while (words < endp) | ||
| 327 | { | ||
| 328 | md5_uint32 *cwp = correct_words; | ||
| 329 | md5_uint32 A_save = A; | ||
| 330 | md5_uint32 B_save = B; | ||
| 331 | md5_uint32 C_save = C; | ||
| 332 | md5_uint32 D_save = D; | ||
| 333 | |||
| 334 | /* First round: using the given function, the context and a constant | ||
| 335 | the next context is computed. Because the algorithms processing | ||
| 336 | unit is a 32-bit word and it is determined to work on words in | ||
| 337 | little endian byte order we perhaps have to change the byte order | ||
| 338 | before the computation. To reduce the work for the next steps | ||
| 339 | we store the swapped words in the array CORRECT_WORDS. */ | ||
| 340 | |||
| 341 | #define OP(a, b, c, d, s, T) \ | ||
| 342 | do \ | ||
| 343 | { \ | ||
| 344 | a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ | ||
| 345 | ++words; \ | ||
| 346 | CYCLIC (a, s); \ | ||
| 347 | a += b; \ | ||
| 348 | } \ | ||
| 349 | while (0) | ||
| 350 | |||
| 351 | /* It is unfortunate that C does not provide an operator for | ||
| 352 | cyclic rotation. Hope the C compiler is smart enough. */ | ||
| 353 | #define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s))) | ||
| 354 | |||
| 355 | /* Before we start, one word to the strange constants. | ||
| 356 | They are defined in RFC 1321 as | ||
| 357 | |||
| 358 | T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64 | ||
| 359 | |||
| 360 | Here is an equivalent invocation using Perl: | ||
| 361 | |||
| 362 | perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' | ||
| 363 | */ | ||
| 364 | |||
| 365 | /* Round 1. */ | ||
| 366 | OP (A, B, C, D, 7, 0xd76aa478); | ||
| 367 | OP (D, A, B, C, 12, 0xe8c7b756); | ||
| 368 | OP (C, D, A, B, 17, 0x242070db); | ||
| 369 | OP (B, C, D, A, 22, 0xc1bdceee); | ||
| 370 | OP (A, B, C, D, 7, 0xf57c0faf); | ||
| 371 | OP (D, A, B, C, 12, 0x4787c62a); | ||
| 372 | OP (C, D, A, B, 17, 0xa8304613); | ||
| 373 | OP (B, C, D, A, 22, 0xfd469501); | ||
| 374 | OP (A, B, C, D, 7, 0x698098d8); | ||
| 375 | OP (D, A, B, C, 12, 0x8b44f7af); | ||
| 376 | OP (C, D, A, B, 17, 0xffff5bb1); | ||
| 377 | OP (B, C, D, A, 22, 0x895cd7be); | ||
| 378 | OP (A, B, C, D, 7, 0x6b901122); | ||
| 379 | OP (D, A, B, C, 12, 0xfd987193); | ||
| 380 | OP (C, D, A, B, 17, 0xa679438e); | ||
| 381 | OP (B, C, D, A, 22, 0x49b40821); | ||
| 382 | |||
| 383 | /* For the second to fourth round we have the possibly swapped words | ||
| 384 | in CORRECT_WORDS. Redefine the macro to take an additional first | ||
| 385 | argument specifying the function to use. */ | ||
| 386 | #undef OP | ||
| 387 | #define OP(f, a, b, c, d, k, s, T) \ | ||
| 388 | do \ | ||
| 389 | { \ | ||
| 390 | a += f (b, c, d) + correct_words[k] + T; \ | ||
| 391 | CYCLIC (a, s); \ | ||
| 392 | a += b; \ | ||
| 393 | } \ | ||
| 394 | while (0) | ||
| 395 | |||
| 396 | /* Round 2. */ | ||
| 397 | OP (FG, A, B, C, D, 1, 5, 0xf61e2562); | ||
| 398 | OP (FG, D, A, B, C, 6, 9, 0xc040b340); | ||
| 399 | OP (FG, C, D, A, B, 11, 14, 0x265e5a51); | ||
| 400 | OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); | ||
| 401 | OP (FG, A, B, C, D, 5, 5, 0xd62f105d); | ||
| 402 | OP (FG, D, A, B, C, 10, 9, 0x02441453); | ||
| 403 | OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); | ||
| 404 | OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); | ||
| 405 | OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); | ||
| 406 | OP (FG, D, A, B, C, 14, 9, 0xc33707d6); | ||
| 407 | OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); | ||
| 408 | OP (FG, B, C, D, A, 8, 20, 0x455a14ed); | ||
| 409 | OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); | ||
| 410 | OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); | ||
| 411 | OP (FG, C, D, A, B, 7, 14, 0x676f02d9); | ||
| 412 | OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); | ||
| 413 | |||
| 414 | /* Round 3. */ | ||
| 415 | OP (FH, A, B, C, D, 5, 4, 0xfffa3942); | ||
| 416 | OP (FH, D, A, B, C, 8, 11, 0x8771f681); | ||
| 417 | OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); | ||
| 418 | OP (FH, B, C, D, A, 14, 23, 0xfde5380c); | ||
| 419 | OP (FH, A, B, C, D, 1, 4, 0xa4beea44); | ||
| 420 | OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); | ||
| 421 | OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); | ||
| 422 | OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); | ||
| 423 | OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); | ||
| 424 | OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); | ||
| 425 | OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); | ||
| 426 | OP (FH, B, C, D, A, 6, 23, 0x04881d05); | ||
| 427 | OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); | ||
| 428 | OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); | ||
| 429 | OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); | ||
| 430 | OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); | ||
| 431 | |||
| 432 | /* Round 4. */ | ||
| 433 | OP (FI, A, B, C, D, 0, 6, 0xf4292244); | ||
| 434 | OP (FI, D, A, B, C, 7, 10, 0x432aff97); | ||
| 435 | OP (FI, C, D, A, B, 14, 15, 0xab9423a7); | ||
| 436 | OP (FI, B, C, D, A, 5, 21, 0xfc93a039); | ||
| 437 | OP (FI, A, B, C, D, 12, 6, 0x655b59c3); | ||
| 438 | OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); | ||
| 439 | OP (FI, C, D, A, B, 10, 15, 0xffeff47d); | ||
| 440 | OP (FI, B, C, D, A, 1, 21, 0x85845dd1); | ||
| 441 | OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); | ||
| 442 | OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); | ||
| 443 | OP (FI, C, D, A, B, 6, 15, 0xa3014314); | ||
| 444 | OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); | ||
| 445 | OP (FI, A, B, C, D, 4, 6, 0xf7537e82); | ||
| 446 | OP (FI, D, A, B, C, 11, 10, 0xbd3af235); | ||
| 447 | OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); | ||
| 448 | OP (FI, B, C, D, A, 9, 21, 0xeb86d391); | ||
| 449 | |||
| 450 | /* Add the starting values of the context. */ | ||
| 451 | A += A_save; | ||
| 452 | B += B_save; | ||
| 453 | C += C_save; | ||
| 454 | D += D_save; | ||
| 455 | } | ||
| 456 | |||
| 457 | /* Put checksum in context given as argument. */ | ||
| 458 | ctx->A = A; | ||
| 459 | ctx->B = B; | ||
| 460 | ctx->C = C; | ||
| 461 | ctx->D = D; | ||
| 462 | } | ||
diff --git a/lib/md5.h b/lib/md5.h new file mode 100644 index 00000000000..332b036590a --- /dev/null +++ b/lib/md5.h | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | /* Declaration of functions and data types used for MD5 sum computing | ||
| 2 | library functions. | ||
| 3 | Copyright (C) 1995-1997, 1999-2001, 2004-2006, 2008-2011 Free Software | ||
| 4 | Foundation, Inc. | ||
| 5 | This file is part of the GNU C Library. | ||
| 6 | |||
| 7 | This program is free software; you can redistribute it and/or modify it | ||
| 8 | under the terms of the GNU General Public License as published by the | ||
| 9 | Free Software Foundation; either version 3, or (at your option) any | ||
| 10 | later version. | ||
| 11 | |||
| 12 | This program is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with this program; if not, write to the Free Software Foundation, | ||
| 19 | Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ | ||
| 20 | |||
| 21 | #ifndef _MD5_H | ||
| 22 | #define _MD5_H 1 | ||
| 23 | |||
| 24 | #include <stdio.h> | ||
| 25 | |||
| 26 | #define MD5_DIGEST_SIZE 16 | ||
| 27 | #define MD5_BLOCK_SIZE 64 | ||
| 28 | |||
| 29 | #ifndef __GNUC_PREREQ | ||
| 30 | # if defined __GNUC__ && defined __GNUC_MINOR__ | ||
| 31 | # define __GNUC_PREREQ(maj, min) \ | ||
| 32 | ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) | ||
| 33 | # else | ||
| 34 | # define __GNUC_PREREQ(maj, min) 0 | ||
| 35 | # endif | ||
| 36 | #endif | ||
| 37 | |||
| 38 | #ifndef __THROW | ||
| 39 | # if defined __cplusplus && __GNUC_PREREQ (2,8) | ||
| 40 | # define __THROW throw () | ||
| 41 | # else | ||
| 42 | # define __THROW | ||
| 43 | # endif | ||
| 44 | #endif | ||
| 45 | |||
| 46 | #ifndef _LIBC | ||
| 47 | # define __md5_buffer md5_buffer | ||
| 48 | # define __md5_finish_ctx md5_finish_ctx | ||
| 49 | # define __md5_init_ctx md5_init_ctx | ||
| 50 | # define __md5_process_block md5_process_block | ||
| 51 | # define __md5_process_bytes md5_process_bytes | ||
| 52 | # define __md5_read_ctx md5_read_ctx | ||
| 53 | # define __md5_stream md5_stream | ||
| 54 | #endif | ||
| 55 | |||
| 56 | # ifdef __cplusplus | ||
| 57 | extern "C" { | ||
| 58 | # endif | ||
| 59 | |||
| 60 | /* The following contortions are an attempt to use the C preprocessor | ||
| 61 | to determine an unsigned integral type that is 32 bits wide. An | ||
| 62 | alternative approach is to use autoconf's AC_CHECK_SIZEOF macro, but | ||
| 63 | doing that would require that the configure script compile and *run* | ||
| 64 | the resulting executable. Locally running cross-compiled executables | ||
| 65 | is usually not possible. */ | ||
| 66 | |||
| 67 | #if defined _LIBC | ||
| 68 | # include <stdint.h> | ||
| 69 | typedef uint32_t md5_uint32; | ||
| 70 | #else | ||
| 71 | # if defined __STDC__ && __STDC__ | ||
| 72 | # define UINT_MAX_32_BITS 4294967295U | ||
| 73 | # else | ||
| 74 | # define UINT_MAX_32_BITS 0xFFFFFFFF | ||
| 75 | # endif | ||
| 76 | |||
| 77 | # include <limits.h> | ||
| 78 | |||
| 79 | # if UINT_MAX == UINT_MAX_32_BITS | ||
| 80 | typedef unsigned int md5_uint32; | ||
| 81 | # else | ||
| 82 | # if USHRT_MAX == UINT_MAX_32_BITS | ||
| 83 | typedef unsigned short md5_uint32; | ||
| 84 | # else | ||
| 85 | # if ULONG_MAX == UINT_MAX_32_BITS | ||
| 86 | typedef unsigned long md5_uint32; | ||
| 87 | # else | ||
| 88 | /* A machine this weird should have <stdint.h>. */ | ||
| 89 | # include <stdint.h> | ||
| 90 | typedef uint32_t md5_uint32; | ||
| 91 | # endif | ||
| 92 | # endif | ||
| 93 | # endif | ||
| 94 | #endif | ||
| 95 | |||
| 96 | /* Structure to save state of computation between the single steps. */ | ||
| 97 | struct md5_ctx | ||
| 98 | { | ||
| 99 | md5_uint32 A; | ||
| 100 | md5_uint32 B; | ||
| 101 | md5_uint32 C; | ||
| 102 | md5_uint32 D; | ||
| 103 | |||
| 104 | md5_uint32 total[2]; | ||
| 105 | md5_uint32 buflen; | ||
| 106 | md5_uint32 buffer[32]; | ||
| 107 | }; | ||
| 108 | |||
| 109 | /* | ||
| 110 | * The following three functions are build up the low level used in | ||
| 111 | * the functions `md5_stream' and `md5_buffer'. | ||
| 112 | */ | ||
| 113 | |||
| 114 | /* Initialize structure containing state of computation. | ||
| 115 | (RFC 1321, 3.3: Step 3) */ | ||
| 116 | extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW; | ||
| 117 | |||
| 118 | /* Starting with the result of former calls of this function (or the | ||
| 119 | initialization function update the context for the next LEN bytes | ||
| 120 | starting at BUFFER. | ||
| 121 | It is necessary that LEN is a multiple of 64!!! */ | ||
| 122 | extern void __md5_process_block (const void *buffer, size_t len, | ||
| 123 | struct md5_ctx *ctx) __THROW; | ||
| 124 | |||
| 125 | /* Starting with the result of former calls of this function (or the | ||
| 126 | initialization function update the context for the next LEN bytes | ||
| 127 | starting at BUFFER. | ||
| 128 | It is NOT required that LEN is a multiple of 64. */ | ||
| 129 | extern void __md5_process_bytes (const void *buffer, size_t len, | ||
| 130 | struct md5_ctx *ctx) __THROW; | ||
| 131 | |||
| 132 | /* Process the remaining bytes in the buffer and put result from CTX | ||
| 133 | in first 16 bytes following RESBUF. The result is always in little | ||
| 134 | endian byte order, so that a byte-wise output yields to the wanted | ||
| 135 | ASCII representation of the message digest. */ | ||
| 136 | extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW; | ||
| 137 | |||
| 138 | |||
| 139 | /* Put result from CTX in first 16 bytes following RESBUF. The result is | ||
| 140 | always in little endian byte order, so that a byte-wise output yields | ||
| 141 | to the wanted ASCII representation of the message digest. */ | ||
| 142 | extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW; | ||
| 143 | |||
| 144 | |||
| 145 | /* Compute MD5 message digest for bytes read from STREAM. The | ||
| 146 | resulting message digest number will be written into the 16 bytes | ||
| 147 | beginning at RESBLOCK. */ | ||
| 148 | extern int __md5_stream (FILE *stream, void *resblock) __THROW; | ||
| 149 | |||
| 150 | /* Compute MD5 message digest for LEN bytes beginning at BUFFER. The | ||
| 151 | result is always in little endian byte order, so that a byte-wise | ||
| 152 | output yields to the wanted ASCII representation of the message | ||
| 153 | digest. */ | ||
| 154 | extern void *__md5_buffer (const char *buffer, size_t len, | ||
| 155 | void *resblock) __THROW; | ||
| 156 | |||
| 157 | # ifdef __cplusplus | ||
| 158 | } | ||
| 159 | # endif | ||
| 160 | |||
| 161 | #endif /* md5.h */ | ||