/*****************************************************************************
* md5.c: not so strong MD5 hashing
*****************************************************************************
- * Copyright (C) 2004-2005 the VideoLAN team
- * $Id$
- *
- * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
- * Sam Hocevar <sam@zoy.org>
+ * Copyright (C) 1995,1996,1998,1999,2001,2002,
+ * 2003 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 of the License, or
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, 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.
+ * GNU Lesser 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.
+ * You should have received a copy of the GNU Lesser 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.
*****************************************************************************/
+/* md5.c - MD5 Message-Digest Algorithm
+ *
+ * According to the definition of MD5 in RFC 1321 from April 1992.
+ * NOTE: This is *not* the same file as the one from glibc.
+ * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
+ * heavily modified for GnuPG by Werner Koch <wk@gnupg.org>
+ */
+
+/* Test values:
+ * "" D4 1D 8C D9 8F 00 B2 04 E9 80 09 98 EC F8 42 7E
+ * "a" 0C C1 75 B9 C0 F1 B6 A8 31 C3 99 E2 69 77 26 61
+ * "abc 90 01 50 98 3C D2 4F B0 D6 96 3F 7D 28 E1 7F 72
+ * "message digest" F9 6B 69 7D 7C B7 93 8D 52 5A 2F 31 AA F1 61 D0
+ */
+
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
-
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <vlc_common.h>
#include <vlc_md5.h>
-#ifdef WORDS_BIGENDIAN
-/*****************************************************************************
- * Reverse: reverse byte order
- *****************************************************************************/
-static inline void Reverse( uint32_t *p_buffer, int n )
+typedef uint32_t u32;
+typedef uint8_t byte;
+#define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) )
+
+typedef struct md5_s MD5_CONTEXT;
+
+
+static void
+md5_init( void *context )
{
- int i;
+ MD5_CONTEXT *ctx = context;
- for( i = 0; i < n; i++ )
- {
- p_buffer[ i ] = GetDWLE(&p_buffer[ i ]);
- }
+ ctx->A = 0x67452301;
+ ctx->B = 0xefcdab89;
+ ctx->C = 0x98badcfe;
+ ctx->D = 0x10325476;
+
+ ctx->nblocks = 0;
+ ctx->count = 0;
}
-# define REVERSE( p, n ) Reverse( p, n )
-#else
-# define REVERSE( p, n )
-#endif
-#define F1( x, y, z ) ((z) ^ ((x) & ((y) ^ (z))))
-#define F2( x, y, z ) F1((z), (x), (y))
-#define F3( x, y, z ) ((x) ^ (y) ^ (z))
-#define F4( x, y, z ) ((y) ^ ((x) | ~(z)))
-#define MD5_DO( f, w, x, y, z, data, s ) \
- ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
+/* 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))
-/*****************************************************************************
- * DigestMD5: update the MD5 digest with 64 bytes of data
- *****************************************************************************/
-static void DigestMD5( struct md5_s *p_md5, uint32_t *p_input )
-{
- uint32_t a, b, c, d;
-
- REVERSE( p_input, 16 );
-
- a = p_md5->p_digest[ 0 ];
- b = p_md5->p_digest[ 1 ];
- c = p_md5->p_digest[ 2 ];
- d = p_md5->p_digest[ 3 ];
-
- MD5_DO( F1, a, b, c, d, p_input[ 0 ] + 0xd76aa478, 7 );
- MD5_DO( F1, d, a, b, c, p_input[ 1 ] + 0xe8c7b756, 12 );
- MD5_DO( F1, c, d, a, b, p_input[ 2 ] + 0x242070db, 17 );
- MD5_DO( F1, b, c, d, a, p_input[ 3 ] + 0xc1bdceee, 22 );
- MD5_DO( F1, a, b, c, d, p_input[ 4 ] + 0xf57c0faf, 7 );
- MD5_DO( F1, d, a, b, c, p_input[ 5 ] + 0x4787c62a, 12 );
- MD5_DO( F1, c, d, a, b, p_input[ 6 ] + 0xa8304613, 17 );
- MD5_DO( F1, b, c, d, a, p_input[ 7 ] + 0xfd469501, 22 );
- MD5_DO( F1, a, b, c, d, p_input[ 8 ] + 0x698098d8, 7 );
- MD5_DO( F1, d, a, b, c, p_input[ 9 ] + 0x8b44f7af, 12 );
- MD5_DO( F1, c, d, a, b, p_input[ 10 ] + 0xffff5bb1, 17 );
- MD5_DO( F1, b, c, d, a, p_input[ 11 ] + 0x895cd7be, 22 );
- MD5_DO( F1, a, b, c, d, p_input[ 12 ] + 0x6b901122, 7 );
- MD5_DO( F1, d, a, b, c, p_input[ 13 ] + 0xfd987193, 12 );
- MD5_DO( F1, c, d, a, b, p_input[ 14 ] + 0xa679438e, 17 );
- MD5_DO( F1, b, c, d, a, p_input[ 15 ] + 0x49b40821, 22 );
-
- MD5_DO( F2, a, b, c, d, p_input[ 1 ] + 0xf61e2562, 5 );
- MD5_DO( F2, d, a, b, c, p_input[ 6 ] + 0xc040b340, 9 );
- MD5_DO( F2, c, d, a, b, p_input[ 11 ] + 0x265e5a51, 14 );
- MD5_DO( F2, b, c, d, a, p_input[ 0 ] + 0xe9b6c7aa, 20 );
- MD5_DO( F2, a, b, c, d, p_input[ 5 ] + 0xd62f105d, 5 );
- MD5_DO( F2, d, a, b, c, p_input[ 10 ] + 0x02441453, 9 );
- MD5_DO( F2, c, d, a, b, p_input[ 15 ] + 0xd8a1e681, 14 );
- MD5_DO( F2, b, c, d, a, p_input[ 4 ] + 0xe7d3fbc8, 20 );
- MD5_DO( F2, a, b, c, d, p_input[ 9 ] + 0x21e1cde6, 5 );
- MD5_DO( F2, d, a, b, c, p_input[ 14 ] + 0xc33707d6, 9 );
- MD5_DO( F2, c, d, a, b, p_input[ 3 ] + 0xf4d50d87, 14 );
- MD5_DO( F2, b, c, d, a, p_input[ 8 ] + 0x455a14ed, 20 );
- MD5_DO( F2, a, b, c, d, p_input[ 13 ] + 0xa9e3e905, 5 );
- MD5_DO( F2, d, a, b, c, p_input[ 2 ] + 0xfcefa3f8, 9 );
- MD5_DO( F2, c, d, a, b, p_input[ 7 ] + 0x676f02d9, 14 );
- MD5_DO( F2, b, c, d, a, p_input[ 12 ] + 0x8d2a4c8a, 20 );
-
- MD5_DO( F3, a, b, c, d, p_input[ 5 ] + 0xfffa3942, 4 );
- MD5_DO( F3, d, a, b, c, p_input[ 8 ] + 0x8771f681, 11 );
- MD5_DO( F3, c, d, a, b, p_input[ 11 ] + 0x6d9d6122, 16 );
- MD5_DO( F3, b, c, d, a, p_input[ 14 ] + 0xfde5380c, 23 );
- MD5_DO( F3, a, b, c, d, p_input[ 1 ] + 0xa4beea44, 4 );
- MD5_DO( F3, d, a, b, c, p_input[ 4 ] + 0x4bdecfa9, 11 );
- MD5_DO( F3, c, d, a, b, p_input[ 7 ] + 0xf6bb4b60, 16 );
- MD5_DO( F3, b, c, d, a, p_input[ 10 ] + 0xbebfbc70, 23 );
- MD5_DO( F3, a, b, c, d, p_input[ 13 ] + 0x289b7ec6, 4 );
- MD5_DO( F3, d, a, b, c, p_input[ 0 ] + 0xeaa127fa, 11 );
- MD5_DO( F3, c, d, a, b, p_input[ 3 ] + 0xd4ef3085, 16 );
- MD5_DO( F3, b, c, d, a, p_input[ 6 ] + 0x04881d05, 23 );
- MD5_DO( F3, a, b, c, d, p_input[ 9 ] + 0xd9d4d039, 4 );
- MD5_DO( F3, d, a, b, c, p_input[ 12 ] + 0xe6db99e5, 11 );
- MD5_DO( F3, c, d, a, b, p_input[ 15 ] + 0x1fa27cf8, 16 );
- MD5_DO( F3, b, c, d, a, p_input[ 2 ] + 0xc4ac5665, 23 );
-
- MD5_DO( F4, a, b, c, d, p_input[ 0 ] + 0xf4292244, 6 );
- MD5_DO( F4, d, a, b, c, p_input[ 7 ] + 0x432aff97, 10 );
- MD5_DO( F4, c, d, a, b, p_input[ 14 ] + 0xab9423a7, 15 );
- MD5_DO( F4, b, c, d, a, p_input[ 5 ] + 0xfc93a039, 21 );
- MD5_DO( F4, a, b, c, d, p_input[ 12 ] + 0x655b59c3, 6 );
- MD5_DO( F4, d, a, b, c, p_input[ 3 ] + 0x8f0ccc92, 10 );
- MD5_DO( F4, c, d, a, b, p_input[ 10 ] + 0xffeff47d, 15 );
- MD5_DO( F4, b, c, d, a, p_input[ 1 ] + 0x85845dd1, 21 );
- MD5_DO( F4, a, b, c, d, p_input[ 8 ] + 0x6fa87e4f, 6 );
- MD5_DO( F4, d, a, b, c, p_input[ 15 ] + 0xfe2ce6e0, 10 );
- MD5_DO( F4, c, d, a, b, p_input[ 6 ] + 0xa3014314, 15 );
- MD5_DO( F4, b, c, d, a, p_input[ 13 ] + 0x4e0811a1, 21 );
- MD5_DO( F4, a, b, c, d, p_input[ 4 ] + 0xf7537e82, 6 );
- MD5_DO( F4, d, a, b, c, p_input[ 11 ] + 0xbd3af235, 10 );
- MD5_DO( F4, c, d, a, b, p_input[ 2 ] + 0x2ad7d2bb, 15 );
- MD5_DO( F4, b, c, d, a, p_input[ 9 ] + 0xeb86d391, 21 );
-
- p_md5->p_digest[ 0 ] += a;
- p_md5->p_digest[ 1 ] += b;
- p_md5->p_digest[ 2 ] += c;
- p_md5->p_digest[ 3 ] += d;
-}
-/*****************************************************************************
- * InitMD5: initialise an MD5 message
- *****************************************************************************
- * The MD5 message-digest algorithm is described in RFC 1321
- *****************************************************************************/
-void InitMD5( struct md5_s *p_md5 )
+/****************
+ * transform n*64 bytes
+ */
+static void
+transform ( MD5_CONTEXT *ctx, const unsigned char *data )
{
- p_md5->p_digest[ 0 ] = 0x67452301;
- p_md5->p_digest[ 1 ] = 0xefcdab89;
- p_md5->p_digest[ 2 ] = 0x98badcfe;
- p_md5->p_digest[ 3 ] = 0x10325476;
+ u32 correct_words[16];
+ register u32 A = ctx->A;
+ register u32 B = ctx->B;
+ register u32 C = ctx->C;
+ register u32 D = ctx->D;
+ u32 *cwp = correct_words;
+
+#ifdef WORDS_BIGENDIAN
+ {
+ int i;
+ byte *p2, *p1;
+ for(i=0, p1=data, p2=(byte*)correct_words; i < 16; i++, p2 += 4 )
+ {
+ p2[3] = *p1++;
+ p2[2] = *p1++;
+ p2[1] = *p1++;
+ p2[0] = *p1++;
+ }
+ }
+#else
+ memcpy( correct_words, data, 64 );
+#endif
+
- memset( p_md5->p_data, 0, 64 );
- p_md5->i_bits = 0;
+#define OP(a, b, c, d, s, T) \
+ do \
+ { \
+ a += FF (b, c, d) + (*cwp++) + T; \
+ a = rol(a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Before we start, one word about 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, 0xd76aa478);
+ OP (D, A, B, C, 12, 0xe8c7b756);
+ OP (C, D, A, B, 17, 0x242070db);
+ OP (B, C, D, A, 22, 0xc1bdceee);
+ OP (A, B, C, D, 7, 0xf57c0faf);
+ OP (D, A, B, C, 12, 0x4787c62a);
+ OP (C, D, A, B, 17, 0xa8304613);
+ OP (B, C, D, A, 22, 0xfd469501);
+ OP (A, B, C, D, 7, 0x698098d8);
+ OP (D, A, B, C, 12, 0x8b44f7af);
+ OP (C, D, A, B, 17, 0xffff5bb1);
+ OP (B, C, D, A, 22, 0x895cd7be);
+ OP (A, B, C, D, 7, 0x6b901122);
+ OP (D, A, B, C, 12, 0xfd987193);
+ OP (C, D, A, B, 17, 0xa679438e);
+ OP (B, C, D, A, 22, 0x49b40821);
+
+#undef OP
+#define OP(f, a, b, c, d, k, s, T) \
+ do \
+ { \
+ a += f (b, c, d) + correct_words[k] + T; \
+ a = rol(a, s); \
+ a += b; \
+ } \
+ while (0)
+
+ /* Round 2. */
+ OP (FG, A, B, C, D, 1, 5, 0xf61e2562);
+ OP (FG, D, A, B, C, 6, 9, 0xc040b340);
+ OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+ OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+ OP (FG, A, B, C, D, 5, 5, 0xd62f105d);
+ OP (FG, D, A, B, C, 10, 9, 0x02441453);
+ OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+ OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+ OP (FG, A, B, C, D, 9, 5, 0x21e1cde6);
+ OP (FG, D, A, B, C, 14, 9, 0xc33707d6);
+ OP (FG, C, D, A, B, 3, 14, 0xf4d50d87);
+ OP (FG, B, C, D, A, 8, 20, 0x455a14ed);
+ OP (FG, A, B, C, D, 13, 5, 0xa9e3e905);
+ OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+ OP (FG, C, D, A, B, 7, 14, 0x676f02d9);
+ OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+ /* Round 3. */
+ OP (FH, A, B, C, D, 5, 4, 0xfffa3942);
+ OP (FH, D, A, B, C, 8, 11, 0x8771f681);
+ OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+ OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+ OP (FH, A, B, C, D, 1, 4, 0xa4beea44);
+ OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+ OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+ OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+ OP (FH, A, B, C, D, 13, 4, 0x289b7ec6);
+ OP (FH, D, A, B, C, 0, 11, 0xeaa127fa);
+ OP (FH, C, D, A, B, 3, 16, 0xd4ef3085);
+ OP (FH, B, C, D, A, 6, 23, 0x04881d05);
+ OP (FH, A, B, C, D, 9, 4, 0xd9d4d039);
+ OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+ OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+ OP (FH, B, C, D, A, 2, 23, 0xc4ac5665);
+
+ /* Round 4. */
+ OP (FI, A, B, C, D, 0, 6, 0xf4292244);
+ OP (FI, D, A, B, C, 7, 10, 0x432aff97);
+ OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+ OP (FI, B, C, D, A, 5, 21, 0xfc93a039);
+ OP (FI, A, B, C, D, 12, 6, 0x655b59c3);
+ OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+ OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+ OP (FI, B, C, D, A, 1, 21, 0x85845dd1);
+ OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+ OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+ OP (FI, C, D, A, B, 6, 15, 0xa3014314);
+ OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+ OP (FI, A, B, C, D, 4, 6, 0xf7537e82);
+ OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+ OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+ OP (FI, B, C, D, A, 9, 21, 0xeb86d391);
+
+ /* Put checksum in context given as argument. */
+ ctx->A += A;
+ ctx->B += B;
+ ctx->C += C;
+ ctx->D += D;
}
-/*****************************************************************************
- * AddMD5: add i_len bytes to an MD5 message
- *****************************************************************************/
-void AddMD5( struct md5_s *p_md5, const void *p_src, size_t i_len )
-{
- unsigned int i_current; /* Current bytes in the spare buffer */
- size_t i_offset = 0;
- i_current = (p_md5->i_bits / 8) & 63;
- p_md5->i_bits += 8 * i_len;
+/* The routine updates the message-digest context to
+ * account for the presence of each of the characters inBuf[0..inLen-1]
+ * in the message whose digest is being computed.
+ */
+static void
+md5_write( void *context, const void *inbuf_arg , size_t inlen)
+{
+ const unsigned char *inbuf = inbuf_arg;
+ MD5_CONTEXT *hd = context;
- /* If we can complete our spare buffer to 64 bytes, do it and add the
- * resulting buffer to the MD5 message */
- if( i_len >= (64 - i_current) )
+ if( hd->count == 64 ) /* flush the buffer */
{
- memcpy( ((uint8_t *)p_md5->p_data) + i_current, p_src,
- (64 - i_current) );
- DigestMD5( p_md5, p_md5->p_data );
+ transform( hd, hd->buf );
+ hd->count = 0;
+ hd->nblocks++;
+ }
+ if( !inbuf )
+ return;
- i_offset += (64 - i_current);
- i_len -= (64 - i_current);
- i_current = 0;
+ if( hd->count )
+ {
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
+ md5_write( hd, NULL, 0 );
+ if( !inlen )
+ return;
}
- /* Add as many entire 64 bytes blocks as we can to the MD5 message */
- while( i_len >= 64 )
+ while( inlen >= 64 )
{
- uint32_t p_tmp[ 16 ];
- memcpy( p_tmp, ((const uint8_t *)p_src) + i_offset, 64 );
- DigestMD5( p_md5, p_tmp );
- i_offset += 64;
- i_len -= 64;
+ transform( hd, inbuf );
+ hd->count = 0;
+ hd->nblocks++;
+ inlen -= 64;
+ inbuf += 64;
}
+ for( ; inlen && hd->count < 64; inlen-- )
+ hd->buf[hd->count++] = *inbuf++;
- /* Copy our remaining data to the message's spare buffer */
- memcpy( ((uint8_t *)p_md5->p_data) + i_current,
- ((const uint8_t *)p_src) + i_offset, i_len );
}
-/*****************************************************************************
- * EndMD5: finish an MD5 message
- *****************************************************************************
- * This function adds adequate padding to the end of the message, and appends
- * the bit count so that we end at a block boundary.
- *****************************************************************************/
-void EndMD5( struct md5_s *p_md5 )
-{
- unsigned int i_current;
- i_current = (p_md5->i_bits / 8) & 63;
- /* Append 0x80 to our buffer. No boundary check because the temporary
- * buffer cannot be full, otherwise AddMD5 would have emptied it. */
- ((uint8_t *)p_md5->p_data)[ i_current++ ] = 0x80;
+/* The routine final terminates the message-digest computation and
+ * ends with the desired message digest in mdContext->digest[0...15].
+ * The handle is prepared for a new MD5 cycle.
+ * Returns 16 bytes representing the digest.
+ */
- /* If less than 8 bytes are available at the end of the block, complete
- * this 64 bytes block with zeros and add it to the message. We'll add
- * our length at the end of the next block. */
- if( i_current > 56 )
+static void
+md5_final( void *context)
+{
+ MD5_CONTEXT *hd = context;
+ u32 t, msb, lsb;
+ byte *p;
+
+ md5_write(hd, NULL, 0); /* flush */;
+
+ t = hd->nblocks;
+ /* multiply by 64 to make a byte count */
+ lsb = t << 6;
+ msb = t >> 26;
+ /* add the count */
+ t = lsb;
+ if( (lsb += hd->count) < t )
+ msb++;
+ /* multiply by 8 to make a bit count */
+ t = lsb;
+ lsb <<= 3;
+ msb <<= 3;
+ msb |= t >> 29;
+
+ if( hd->count < 56 ) /* enough room */
{
- memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (64 - i_current) );
- DigestMD5( p_md5, p_md5->p_data );
- i_current = 0;
+ hd->buf[hd->count++] = 0x80; /* pad */
+ while( hd->count < 56 )
+ hd->buf[hd->count++] = 0; /* pad */
}
+ else /* need one extra block */
+ {
+ hd->buf[hd->count++] = 0x80; /* pad character */
+ while( hd->count < 64 )
+ hd->buf[hd->count++] = 0;
+ md5_write(hd, NULL, 0); /* flush */;
+ memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+ }
+ /* append the 64 bit count */
+ hd->buf[56] = lsb ;
+ hd->buf[57] = lsb >> 8;
+ hd->buf[58] = lsb >> 16;
+ hd->buf[59] = lsb >> 24;
+ hd->buf[60] = msb ;
+ hd->buf[61] = msb >> 8;
+ hd->buf[62] = msb >> 16;
+ hd->buf[63] = msb >> 24;
+ transform( hd, hd->buf );
+
+ p = hd->buf;
+#ifdef WORDS_BIGENDIAN
+#define X(a) do { *p++ = hd->a ; *p++ = hd->a >> 8; \
+ *p++ = hd->a >> 16; *p++ = hd->a >> 24; } while(0)
+#else /* little endian */
+#define X(a) do { *(u32*)p = (*hd).a ; p += 4; } while(0)
+#endif
+ X(A);
+ X(B);
+ X(C);
+ X(D);
+#undef X
- /* Fill the unused space in our last block with zeroes and put the
- * message length at the end. */
- memset( ((uint8_t *)p_md5->p_data) + i_current, 0, (56 - i_current) );
- p_md5->p_data[ 14 ] = p_md5->i_bits & 0xffffffff;
- p_md5->p_data[ 15 ] = (p_md5->i_bits >> 32);
- REVERSE( &p_md5->p_data[ 14 ], 2 );
+}
- DigestMD5( p_md5, p_md5->p_data );
+#if 0
+static byte *
+md5_read( void *context )
+{
+ MD5_CONTEXT *hd = (MD5_CONTEXT *) context;
+ return hd->buf;
}
+#endif
+void InitMD5( struct md5_s *h )
+{
+ md5_init( h );
+}
+
+void AddMD5( struct md5_s *restrict h, const void *data, size_t len )
+{
+ md5_write( h, data, len );
+}
+void EndMD5( struct md5_s *h )
+{
+ md5_final( h );
+}