From 8f327be75dbb072a9d8aeb5fbf6173b85fab6ad0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Denis-Courmont?= Date: Sun, 27 Nov 2011 15:27:47 +0200 Subject: [PATCH] Replace MD5 implementation with FSF LGPL'd one This was originally written by Ulrich Drepper for glibc. However, this particular version is copied from libgcrypt (simpler to adapt). --- include/vlc_md5.h | 49 ++-- modules/demux/mp4/drms.c | 12 +- src/misc/md5.c | 481 ++++++++++++++++++++++++--------------- src/misc/rand.c | 12 +- 4 files changed, 324 insertions(+), 230 deletions(-) diff --git a/include/vlc_md5.h b/include/vlc_md5.h index f32bccf5ea..6b1b8c951f 100644 --- a/include/vlc_md5.h +++ b/include/vlc_md5.h @@ -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 - * Sam Hocevar + * 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 @@ -27,20 +26,15 @@ /** * \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; } diff --git a/modules/demux/mp4/drms.c b/modules/demux/mp4/drms.c index d816758b55..39f4225f30 100644 --- a/modules/demux/mp4/drms.c +++ b/modules/demux/mp4/drms.c @@ -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; } diff --git a/src/misc/md5.c b/src/misc/md5.c index f4f93fff81..8909b00650 100644 --- a/src/misc/md5.c +++ b/src/misc/md5.c @@ -1,240 +1,349 @@ /***************************************************************************** * md5.c: not so strong MD5 hashing ***************************************************************************** - * Copyright (C) 2004-2005 the VideoLAN team - * $Id$ - * - * Authors: Jon Lech Johansen - * Sam Hocevar + * 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 , 1995. + * heavily modified for GnuPG by Werner Koch + */ + +/* 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 +#include #include #include #include -#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<>(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 ); +} diff --git a/src/misc/rand.c b/src/misc/rand.c index 5ee6dccb21..792bea6381 100644 --- a/src/misc/rand.c +++ b/src/misc/rand.c @@ -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; } } -- 2.39.2