md5.cpp revision 6d5bb586830857ecd05ff82ef8d2545034bd0835
/* $Id$ */
/** @file
* IPRT - MD5 message digest functions.
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/* The code is virtually unchanged from the original version (see copyright
* notice below). Most changes are related to the function names and data
* types - in order to fit the code in the IPRT naming style. */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* RTMD5CONTEXT structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#if defined(RT_BIG_ENDIAN)
#endif
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/* The four core functions - F1 is optimized somewhat */
#if 1
/* #define F1(x, y, z) (x & y | ~x & z) */
# define F1(x, y, z) (z ^ (x & (y ^ z)))
# define F3(x, y, z) (x ^ y ^ z)
# define F4(x, y, z) (y ^ (x | ~z))
#else /* gcc 4.0.1 (x86) benefits from the explicitness of F1() here. */
{
register uint32_t r = y ^ z;
r &= x;
r ^= z;
return r;
}
{
register uint32_t r = x ^ y;
r ^= z;
return r;
}
{
register uint32_t r = ~z;
r |= x;
r ^= y;
return r;
}
#endif
/* This is the central step in the MD5 algorithm. */
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/**
* The core of the MD5 algorithm, this alters an existing MD5 hash to reflect
* the addition of 16 longwords of new data. RTMd5Update blocks the data and
* converts bytes into longwords for this routine.
*/
{
uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
/* fn, w, x, y, z, data, s) */
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
#ifdef RT_BIG_ENDIAN
/*
* Note: this code is harmless on little-endian machines.
*/
{
uint32_t t;
do {
t = *buf;
t = RT_LE2H_U32(t);
*buf = t;
buf++;
} while (--longs);
}
#else /* little endian - do nothing */
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
{
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
{
uint32_t t;
/* Update bitcount */
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
t = 64 - t;
if (len < t) {
return;
}
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
#ifndef RT_BIG_ENDIAN
{
while (len >= 64) {
buf += 64;
len -= 64;
}
}
else
#endif
{
while (len >= 64) {
buf += 64;
len -= 64;
}
}
/* Handle any remaining bytes of data */
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
{
unsigned int count;
uint8_t *p;
/* Compute number of bytes mod 64 */
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
/* Now fill the next block with 56 bytes */
} else {
/* Pad block to 56 bytes */
}
/* Append length in bits and transform */
}
{
#if 0
#else
#endif
for (;;)
{
break;
}
}