]> git.sesse.net Git - vlc/commitdiff
Replace MD5 implementation with FSF LGPL'd one
authorRémi Denis-Courmont <remi@remlab.net>
Sun, 27 Nov 2011 13:27:47 +0000 (15:27 +0200)
committerRémi Denis-Courmont <remi@remlab.net>
Sun, 27 Nov 2011 13:32:19 +0000 (15:32 +0200)
This was originally written by Ulrich Drepper for glibc. However, this
particular version is copied from libgcrypt (simpler to adapt).

include/vlc_md5.h
modules/demux/mp4/drms.c
src/misc/md5.c
src/misc/rand.c

index f32bccf5ea851fcf29378055f981519bf8004e25..6b1b8c951f2f5133c351c426f10be69c6b243167 100644 (file)
@@ -1,25 +1,24 @@
 /*****************************************************************************
  * vlc_md5.h: MD5 hash
  *****************************************************************************
- * Copyright (C) 2004-2005 the VideoLAN team
- * $Id$
+ * Copyright (C) 2004-2011 the VideoLAN team
  *
- * Authors: Jon Lech Johansen <jon-vl@nanocrew.net>
- *          Sam Hocevar <sam@zoy.org>
+ * Authors: Rémi Denis-Courmont
+ *          Rafaël Carré
  *
  * 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.
  *****************************************************************************/
 
 #ifndef VLC_MD5_H
 
 /**
  * \file
- * This file defines functions and structures for handling md5 checksums
+ * This file defines functions and structures to compute MD5 digests
  */
 
-/*****************************************************************************
- * md5_s: MD5 message structure
- *****************************************************************************
- * This structure stores the static information needed to compute an MD5
- * hash. It has an extra data buffer to allow non-aligned writes.
- *****************************************************************************/
 struct md5_s
 {
-    uint64_t i_bits;      /* Total written bits */
-    uint32_t p_digest[4]; /* The MD5 digest */
-    uint32_t p_data[16];  /* Buffer to cache non-aligned writes */
+    uint32_t A, B, C, D;          /* chaining variables */
+    uint32_t nblocks;
+    uint8_t buf[64];
+    int count;
 };
 
 VLC_API void InitMD5( struct md5_s * );
@@ -54,20 +48,11 @@ VLC_API void EndMD5( struct md5_s * );
 static inline char * psz_md5_hash( struct md5_s *md5_s )
 {
     char *psz = malloc( 33 ); /* md5 string is 32 bytes + NULL character */
-    if( !psz ) return NULL;
-
-    int i;
-    for ( i = 0; i < 4; i++ )
+    if( likely(psz) )
     {
-        sprintf( &psz[8*i], "%02x%02x%02x%02x",
-            md5_s->p_digest[i] & 0xff,
-            ( md5_s->p_digest[i] >> 8 ) & 0xff,
-            ( md5_s->p_digest[i] >> 16 ) & 0xff,
-            md5_s->p_digest[i] >> 24
-        );
+        for( int i = 0; i < 16; i++ )
+            sprintf( &psz[2*i], "%02"PRIx8, md5_s->buf[i] );
     }
-    psz[32] = '\0';
-
     return psz;
 }
 
index d816758b55f83a887241bb102d6c608f9f21a356..39f4225f30f66088e37b8c17ae2029154c79f5c5 100644 (file)
@@ -354,7 +354,7 @@ int drms_init( void *_p_drms, uint32_t i_type,
             InitAES( &p_drms->aes, p_drms->p_key );
 
             memcpy( p_priv, p_info, 64 );
-            memcpy( p_drms->p_key, md5.p_digest, 16 );
+            memcpy( p_drms->p_key, md5.buf, 16 );
             drms_decrypt( p_drms, p_priv, 64, NULL );
             REVERSE( p_priv, 64 );
 
@@ -511,8 +511,8 @@ static void InitShuffle( struct shuffle_s *p_shuffle, uint32_t *p_sys_key,
 
         p_secret1[ 3 ]++;
 
-        REVERSE( md5.p_digest, 1 );
-        i_hash = ((int32_t)U32_AT(md5.p_digest)) % 1024;
+        REVERSE( (void *)md5.buf, 1 ); /* FIXME */
+        i_hash = ((int32_t)U32_AT(md5.buf)) % 1024;
 
         p_shuffle->p_commands[ i ] = i_hash < 0 ? i_hash * -1 : i_hash;
     }
@@ -624,7 +624,7 @@ static void DoShuffle( struct shuffle_s *p_shuffle,
     /* XOR our buffer with the computed checksum */
     for( i = 0; i < i_size; i++ )
     {
-        p_buffer[ i ] ^= md5.p_digest[ i ];
+        p_buffer[ i ] ^= U32_AT(md5.buf + (4 * i));
     }
 }
 
@@ -1330,7 +1330,7 @@ static int GetSystemKey( uint32_t *p_sys_key, bool b_ipod )
 
     EndMD5( &md5 );
 
-    memcpy( p_sys_key, md5.p_digest, 16 );
+    memcpy( p_sys_key, md5.buf, 16 );
 
     return 0;
 }
@@ -1707,7 +1707,7 @@ static int HashSystemInfo( uint32_t *p_system_hash )
 #endif
 
     EndMD5( &md5 );
-    memcpy( p_system_hash, md5.p_digest, 16 );
+    memcpy( p_system_hash, md5.buf, 16 );
 
     return i_ret;
 }
index f4f93fff818bfdfb1e7c1c35d86fb6d1fa735494..8909b006509f07bb179b6a57f83e48bdcc609cb5 100644 (file)
 /*****************************************************************************
  * 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 );
+}
index 5ee6dccb21480e29e173064fd52e6d3f11b51b90..792bea6381b5f3609b07d5628ffac178c66274d4 100644 (file)
@@ -107,18 +107,18 @@ void vlc_rand_bytes (void *buf, size_t len)
         AddMD5 (&mdi, &stamp, sizeof (stamp));
         AddMD5 (&mdi, &val, sizeof (val));
         EndMD5 (&mdi);
-        AddMD5 (&mdo, mdi.p_digest, sizeof (mdi.p_digest));
+        AddMD5 (&mdo, mdi.buf, 16);
         EndMD5 (&mdo);
 
-        if (len < sizeof (mdo.p_digest))
+        if (len < 16)
         {
-            memcpy (buf, mdo.p_digest, len);
+            memcpy (buf, mdo.buf, len);
             break;
         }
 
-        memcpy (buf, mdo.p_digest, sizeof (mdo.p_digest));
-        len -= sizeof (mdo.p_digest);
-        buf = ((uint8_t *)buf) + sizeof (mdo.p_digest);
+        memcpy (buf, mdo.buf, 16);
+        len -= 16;
+        buf = ((uint8_t *)buf) + 16;
     }
 }