Commit 8f327be7 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont
Browse files

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).
parent 2f873669
/*****************************************************************************
* 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
......@@ -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;
}
......
......@@ -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;
}
......
/*****************************************************************************
* 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 */