Blame nss/lib/freebl/md5.c

Packit 40b132
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit 40b132
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit 40b132
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit 40b132
Packit 40b132
#ifdef FREEBL_NO_DEPEND
Packit 40b132
#include "stubs.h"
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#include "prerr.h"
Packit 40b132
#include "secerr.h"
Packit 40b132
Packit 40b132
#include "prtypes.h"
Packit 40b132
#include "prlong.h"
Packit 40b132
Packit 40b132
#include "blapi.h"
Packit 40b132
Packit 40b132
#define MD5_HASH_LEN 16
Packit 40b132
#define MD5_BUFFER_SIZE 64
Packit 40b132
#define MD5_END_BUFFER (MD5_BUFFER_SIZE - 8)
Packit 40b132
Packit 40b132
#define CV0_1 0x67452301
Packit 40b132
#define CV0_2 0xefcdab89
Packit 40b132
#define CV0_3 0x98badcfe
Packit 40b132
#define CV0_4 0x10325476
Packit 40b132
Packit 40b132
#define T1_0  0xd76aa478
Packit 40b132
#define T1_1  0xe8c7b756
Packit 40b132
#define T1_2  0x242070db
Packit 40b132
#define T1_3  0xc1bdceee
Packit 40b132
#define T1_4  0xf57c0faf
Packit 40b132
#define T1_5  0x4787c62a
Packit 40b132
#define T1_6  0xa8304613
Packit 40b132
#define T1_7  0xfd469501
Packit 40b132
#define T1_8  0x698098d8
Packit 40b132
#define T1_9  0x8b44f7af
Packit 40b132
#define T1_10 0xffff5bb1
Packit 40b132
#define T1_11 0x895cd7be
Packit 40b132
#define T1_12 0x6b901122
Packit 40b132
#define T1_13 0xfd987193
Packit 40b132
#define T1_14 0xa679438e
Packit 40b132
#define T1_15 0x49b40821
Packit 40b132
Packit 40b132
#define T2_0  0xf61e2562
Packit 40b132
#define T2_1  0xc040b340
Packit 40b132
#define T2_2  0x265e5a51
Packit 40b132
#define T2_3  0xe9b6c7aa
Packit 40b132
#define T2_4  0xd62f105d
Packit 40b132
#define T2_5  0x02441453
Packit 40b132
#define T2_6  0xd8a1e681
Packit 40b132
#define T2_7  0xe7d3fbc8
Packit 40b132
#define T2_8  0x21e1cde6
Packit 40b132
#define T2_9  0xc33707d6
Packit 40b132
#define T2_10 0xf4d50d87
Packit 40b132
#define T2_11 0x455a14ed
Packit 40b132
#define T2_12 0xa9e3e905
Packit 40b132
#define T2_13 0xfcefa3f8
Packit 40b132
#define T2_14 0x676f02d9
Packit 40b132
#define T2_15 0x8d2a4c8a
Packit 40b132
Packit 40b132
#define T3_0  0xfffa3942
Packit 40b132
#define T3_1  0x8771f681
Packit 40b132
#define T3_2  0x6d9d6122
Packit 40b132
#define T3_3  0xfde5380c
Packit 40b132
#define T3_4  0xa4beea44
Packit 40b132
#define T3_5  0x4bdecfa9
Packit 40b132
#define T3_6  0xf6bb4b60
Packit 40b132
#define T3_7  0xbebfbc70
Packit 40b132
#define T3_8  0x289b7ec6
Packit 40b132
#define T3_9  0xeaa127fa
Packit 40b132
#define T3_10 0xd4ef3085
Packit 40b132
#define T3_11 0x04881d05
Packit 40b132
#define T3_12 0xd9d4d039
Packit 40b132
#define T3_13 0xe6db99e5
Packit 40b132
#define T3_14 0x1fa27cf8
Packit 40b132
#define T3_15 0xc4ac5665
Packit 40b132
Packit 40b132
#define T4_0  0xf4292244
Packit 40b132
#define T4_1  0x432aff97
Packit 40b132
#define T4_2  0xab9423a7
Packit 40b132
#define T4_3  0xfc93a039
Packit 40b132
#define T4_4  0x655b59c3
Packit 40b132
#define T4_5  0x8f0ccc92
Packit 40b132
#define T4_6  0xffeff47d
Packit 40b132
#define T4_7  0x85845dd1
Packit 40b132
#define T4_8  0x6fa87e4f
Packit 40b132
#define T4_9  0xfe2ce6e0
Packit 40b132
#define T4_10 0xa3014314
Packit 40b132
#define T4_11 0x4e0811a1
Packit 40b132
#define T4_12 0xf7537e82
Packit 40b132
#define T4_13 0xbd3af235
Packit 40b132
#define T4_14 0x2ad7d2bb
Packit 40b132
#define T4_15 0xeb86d391
Packit 40b132
Packit 40b132
#define R1B0  0
Packit 40b132
#define R1B1  1
Packit 40b132
#define R1B2  2
Packit 40b132
#define R1B3  3
Packit 40b132
#define R1B4  4
Packit 40b132
#define R1B5  5
Packit 40b132
#define R1B6  6
Packit 40b132
#define R1B7  7
Packit 40b132
#define R1B8  8
Packit 40b132
#define R1B9  9
Packit 40b132
#define R1B10 10
Packit 40b132
#define R1B11 11
Packit 40b132
#define R1B12 12
Packit 40b132
#define R1B13 13
Packit 40b132
#define R1B14 14
Packit 40b132
#define R1B15 15
Packit 40b132
Packit 40b132
#define R2B0  1
Packit 40b132
#define R2B1  6
Packit 40b132
#define R2B2  11
Packit 40b132
#define R2B3  0
Packit 40b132
#define R2B4  5
Packit 40b132
#define R2B5  10
Packit 40b132
#define R2B6  15
Packit 40b132
#define R2B7  4
Packit 40b132
#define R2B8  9
Packit 40b132
#define R2B9  14
Packit 40b132
#define R2B10 3 
Packit 40b132
#define R2B11 8 
Packit 40b132
#define R2B12 13
Packit 40b132
#define R2B13 2 
Packit 40b132
#define R2B14 7 
Packit 40b132
#define R2B15 12
Packit 40b132
Packit 40b132
#define R3B0  5
Packit 40b132
#define R3B1  8
Packit 40b132
#define R3B2  11
Packit 40b132
#define R3B3  14
Packit 40b132
#define R3B4  1
Packit 40b132
#define R3B5  4
Packit 40b132
#define R3B6  7
Packit 40b132
#define R3B7  10
Packit 40b132
#define R3B8  13
Packit 40b132
#define R3B9  0
Packit 40b132
#define R3B10 3 
Packit 40b132
#define R3B11 6 
Packit 40b132
#define R3B12 9 
Packit 40b132
#define R3B13 12
Packit 40b132
#define R3B14 15
Packit 40b132
#define R3B15 2 
Packit 40b132
Packit 40b132
#define R4B0  0
Packit 40b132
#define R4B1  7
Packit 40b132
#define R4B2  14
Packit 40b132
#define R4B3  5
Packit 40b132
#define R4B4  12
Packit 40b132
#define R4B5  3
Packit 40b132
#define R4B6  10
Packit 40b132
#define R4B7  1
Packit 40b132
#define R4B8  8
Packit 40b132
#define R4B9  15
Packit 40b132
#define R4B10 6 
Packit 40b132
#define R4B11 13
Packit 40b132
#define R4B12 4 
Packit 40b132
#define R4B13 11
Packit 40b132
#define R4B14 2 
Packit 40b132
#define R4B15 9 
Packit 40b132
Packit 40b132
#define S1_0 7
Packit 40b132
#define S1_1 12
Packit 40b132
#define S1_2 17
Packit 40b132
#define S1_3 22
Packit 40b132
Packit 40b132
#define S2_0 5
Packit 40b132
#define S2_1 9
Packit 40b132
#define S2_2 14
Packit 40b132
#define S2_3 20
Packit 40b132
Packit 40b132
#define S3_0 4
Packit 40b132
#define S3_1 11
Packit 40b132
#define S3_2 16
Packit 40b132
#define S3_3 23
Packit 40b132
Packit 40b132
#define S4_0 6
Packit 40b132
#define S4_1 10
Packit 40b132
#define S4_2 15
Packit 40b132
#define S4_3 21
Packit 40b132
Packit 40b132
struct MD5ContextStr {
Packit 40b132
	PRUint32      lsbInput;
Packit 40b132
	PRUint32      msbInput;
Packit 40b132
	PRUint32      cv[4];
Packit 40b132
	union {
Packit 40b132
		PRUint8 b[64];
Packit 40b132
		PRUint32 w[16];
Packit 40b132
	} u;
Packit 40b132
};
Packit 40b132
Packit 40b132
#define inBuf u.b
Packit 40b132
Packit 40b132
SECStatus 
Packit 40b132
MD5_Hash(unsigned char *dest, const char *src)
Packit 40b132
{
Packit 40b132
	return MD5_HashBuf(dest, (const unsigned char *)src, PORT_Strlen(src));
Packit 40b132
}
Packit 40b132
Packit 40b132
SECStatus 
Packit 40b132
MD5_HashBuf(unsigned char *dest, const unsigned char *src, PRUint32 src_length)
Packit 40b132
{
Packit 40b132
	unsigned int len;
Packit 40b132
	MD5Context cx;
Packit 40b132
Packit 40b132
	MD5_Begin(&cx;;
Packit 40b132
	MD5_Update(&cx, src, src_length);
Packit 40b132
	MD5_End(&cx, dest, &len, MD5_HASH_LEN);
Packit 40b132
	memset(&cx, 0, sizeof cx);
Packit 40b132
	return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
MD5Context *
Packit 40b132
MD5_NewContext(void)
Packit 40b132
{
Packit 40b132
	/* no need to ZAlloc, MD5_Begin will init the context */
Packit 40b132
	MD5Context *cx = (MD5Context *)PORT_Alloc(sizeof(MD5Context));
Packit 40b132
	if (cx == NULL) {
Packit 40b132
		PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
Packit 40b132
		return NULL;
Packit 40b132
	}
Packit 40b132
	return cx;
Packit 40b132
}
Packit 40b132
Packit 40b132
void 
Packit 40b132
MD5_DestroyContext(MD5Context *cx, PRBool freeit)
Packit 40b132
{
Packit 40b132
	memset(cx, 0, sizeof *cx);
Packit 40b132
	if (freeit) {
Packit 40b132
	    PORT_Free(cx);
Packit 40b132
	}
Packit 40b132
}
Packit 40b132
Packit 40b132
void 
Packit 40b132
MD5_Begin(MD5Context *cx)
Packit 40b132
{
Packit 40b132
	cx->lsbInput = 0;
Packit 40b132
	cx->msbInput = 0;
Packit 40b132
/*	memset(cx->inBuf, 0, sizeof(cx->inBuf)); */
Packit 40b132
	cx->cv[0] = CV0_1;
Packit 40b132
	cx->cv[1] = CV0_2;
Packit 40b132
	cx->cv[2] = CV0_3;
Packit 40b132
	cx->cv[3] = CV0_4;
Packit 40b132
}
Packit 40b132
Packit 40b132
#define cls(i32, s) (tmp = i32, tmp << s | tmp >> (32 - s))
Packit 40b132
Packit 40b132
#if defined(SOLARIS) || defined(HPUX)
Packit 40b132
#define addto64(sumhigh, sumlow, addend) \
Packit 40b132
	sumlow += addend; sumhigh += (sumlow < addend);
Packit 40b132
#else
Packit 40b132
#define addto64(sumhigh, sumlow, addend) \
Packit 40b132
	sumlow += addend; if (sumlow < addend) ++sumhigh;
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#define MASK 0x00ff00ff
Packit 40b132
#ifdef IS_LITTLE_ENDIAN
Packit 40b132
#define lendian(i32) \
Packit 40b132
	(i32)
Packit 40b132
#else
Packit 40b132
#define lendian(i32) \
Packit 40b132
	(tmp = i32 >> 16 | i32 << 16, (tmp & MASK) << 8 | tmp >> 8 & MASK)
Packit 40b132
#endif
Packit 40b132
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
Packit 40b132
#define lebytes(b4) \
Packit 40b132
	((b4)[3] << 24 | (b4)[2] << 16 | (b4)[1] << 8 | (b4)[0])
Packit 40b132
Packit 40b132
static void
Packit 40b132
md5_prep_state_le(MD5Context *cx)
Packit 40b132
{
Packit 40b132
	PRUint32 tmp;
Packit 40b132
	cx->u.w[0] = lendian(cx->u.w[0]);
Packit 40b132
	cx->u.w[1] = lendian(cx->u.w[1]);
Packit 40b132
	cx->u.w[2] = lendian(cx->u.w[2]);
Packit 40b132
	cx->u.w[3] = lendian(cx->u.w[3]);
Packit 40b132
	cx->u.w[4] = lendian(cx->u.w[4]);
Packit 40b132
	cx->u.w[5] = lendian(cx->u.w[5]);
Packit 40b132
	cx->u.w[6] = lendian(cx->u.w[6]);
Packit 40b132
	cx->u.w[7] = lendian(cx->u.w[7]);
Packit 40b132
	cx->u.w[8] = lendian(cx->u.w[8]);
Packit 40b132
	cx->u.w[9] = lendian(cx->u.w[9]);
Packit 40b132
	cx->u.w[10] = lendian(cx->u.w[10]);
Packit 40b132
	cx->u.w[11] = lendian(cx->u.w[11]);
Packit 40b132
	cx->u.w[12] = lendian(cx->u.w[12]);
Packit 40b132
	cx->u.w[13] = lendian(cx->u.w[13]);
Packit 40b132
	cx->u.w[14] = lendian(cx->u.w[14]);
Packit 40b132
	cx->u.w[15] = lendian(cx->u.w[15]);
Packit 40b132
}
Packit 40b132
Packit 40b132
static void
Packit 40b132
md5_prep_buffer_le(MD5Context *cx, const PRUint8 *beBuf)
Packit 40b132
{
Packit 40b132
	cx->u.w[0] = lebytes(&beBuf[0]);
Packit 40b132
	cx->u.w[1] = lebytes(&beBuf[4]);
Packit 40b132
	cx->u.w[2] = lebytes(&beBuf[8]);
Packit 40b132
	cx->u.w[3] = lebytes(&beBuf[12]);
Packit 40b132
	cx->u.w[4] = lebytes(&beBuf[16]);
Packit 40b132
	cx->u.w[5] = lebytes(&beBuf[20]);
Packit 40b132
	cx->u.w[6] = lebytes(&beBuf[24]);
Packit 40b132
	cx->u.w[7] = lebytes(&beBuf[28]);
Packit 40b132
	cx->u.w[8] = lebytes(&beBuf[32]);
Packit 40b132
	cx->u.w[9] = lebytes(&beBuf[36]);
Packit 40b132
	cx->u.w[10] = lebytes(&beBuf[40]);
Packit 40b132
	cx->u.w[11] = lebytes(&beBuf[44]);
Packit 40b132
	cx->u.w[12] = lebytes(&beBuf[48]);
Packit 40b132
	cx->u.w[13] = lebytes(&beBuf[52]);
Packit 40b132
	cx->u.w[14] = lebytes(&beBuf[56]);
Packit 40b132
	cx->u.w[15] = lebytes(&beBuf[60]);
Packit 40b132
}
Packit 40b132
#endif
Packit 40b132
Packit 40b132
Packit 40b132
#define F(X, Y, Z) \
Packit 40b132
	((X & Y) | ((~X) & Z))
Packit 40b132
Packit 40b132
#define G(X, Y, Z) \
Packit 40b132
	((X & Z) | (Y & (~Z)))
Packit 40b132
Packit 40b132
#define H(X, Y, Z) \
Packit 40b132
	(X ^ Y ^ Z)
Packit 40b132
Packit 40b132
#define I(X, Y, Z) \
Packit 40b132
	(Y ^ (X | (~Z)))
Packit 40b132
Packit 40b132
#define FF(a, b, c, d, bufint, s, ti) \
Packit 40b132
	a = b + cls(a + F(b, c, d) + bufint + ti, s)
Packit 40b132
Packit 40b132
#define GG(a, b, c, d, bufint, s, ti) \
Packit 40b132
	a = b + cls(a + G(b, c, d) + bufint + ti, s)
Packit 40b132
Packit 40b132
#define HH(a, b, c, d, bufint, s, ti) \
Packit 40b132
	a = b + cls(a + H(b, c, d) + bufint + ti, s)
Packit 40b132
Packit 40b132
#define II(a, b, c, d, bufint, s, ti) \
Packit 40b132
	a = b + cls(a + I(b, c, d) + bufint + ti, s)
Packit 40b132
Packit 40b132
static void
Packit 40b132
md5_compress(MD5Context *cx, const PRUint32 *wBuf)
Packit 40b132
{
Packit 40b132
	PRUint32 a, b, c, d;
Packit 40b132
	PRUint32 tmp;
Packit 40b132
	a = cx->cv[0];
Packit 40b132
	b = cx->cv[1];
Packit 40b132
	c = cx->cv[2];
Packit 40b132
	d = cx->cv[3];
Packit 40b132
	FF(a, b, c, d, wBuf[R1B0 ], S1_0, T1_0);
Packit 40b132
	FF(d, a, b, c, wBuf[R1B1 ], S1_1, T1_1);
Packit 40b132
	FF(c, d, a, b, wBuf[R1B2 ], S1_2, T1_2);
Packit 40b132
	FF(b, c, d, a, wBuf[R1B3 ], S1_3, T1_3);
Packit 40b132
	FF(a, b, c, d, wBuf[R1B4 ], S1_0, T1_4);
Packit 40b132
	FF(d, a, b, c, wBuf[R1B5 ], S1_1, T1_5);
Packit 40b132
	FF(c, d, a, b, wBuf[R1B6 ], S1_2, T1_6);
Packit 40b132
	FF(b, c, d, a, wBuf[R1B7 ], S1_3, T1_7);
Packit 40b132
	FF(a, b, c, d, wBuf[R1B8 ], S1_0, T1_8);
Packit 40b132
	FF(d, a, b, c, wBuf[R1B9 ], S1_1, T1_9);
Packit 40b132
	FF(c, d, a, b, wBuf[R1B10], S1_2, T1_10);
Packit 40b132
	FF(b, c, d, a, wBuf[R1B11], S1_3, T1_11);
Packit 40b132
	FF(a, b, c, d, wBuf[R1B12], S1_0, T1_12);
Packit 40b132
	FF(d, a, b, c, wBuf[R1B13], S1_1, T1_13);
Packit 40b132
	FF(c, d, a, b, wBuf[R1B14], S1_2, T1_14);
Packit 40b132
	FF(b, c, d, a, wBuf[R1B15], S1_3, T1_15);
Packit 40b132
	GG(a, b, c, d, wBuf[R2B0 ], S2_0, T2_0);
Packit 40b132
	GG(d, a, b, c, wBuf[R2B1 ], S2_1, T2_1);
Packit 40b132
	GG(c, d, a, b, wBuf[R2B2 ], S2_2, T2_2);
Packit 40b132
	GG(b, c, d, a, wBuf[R2B3 ], S2_3, T2_3);
Packit 40b132
	GG(a, b, c, d, wBuf[R2B4 ], S2_0, T2_4);
Packit 40b132
	GG(d, a, b, c, wBuf[R2B5 ], S2_1, T2_5);
Packit 40b132
	GG(c, d, a, b, wBuf[R2B6 ], S2_2, T2_6);
Packit 40b132
	GG(b, c, d, a, wBuf[R2B7 ], S2_3, T2_7);
Packit 40b132
	GG(a, b, c, d, wBuf[R2B8 ], S2_0, T2_8);
Packit 40b132
	GG(d, a, b, c, wBuf[R2B9 ], S2_1, T2_9);
Packit 40b132
	GG(c, d, a, b, wBuf[R2B10], S2_2, T2_10);
Packit 40b132
	GG(b, c, d, a, wBuf[R2B11], S2_3, T2_11);
Packit 40b132
	GG(a, b, c, d, wBuf[R2B12], S2_0, T2_12);
Packit 40b132
	GG(d, a, b, c, wBuf[R2B13], S2_1, T2_13);
Packit 40b132
	GG(c, d, a, b, wBuf[R2B14], S2_2, T2_14);
Packit 40b132
	GG(b, c, d, a, wBuf[R2B15], S2_3, T2_15);
Packit 40b132
	HH(a, b, c, d, wBuf[R3B0 ], S3_0, T3_0);
Packit 40b132
	HH(d, a, b, c, wBuf[R3B1 ], S3_1, T3_1);
Packit 40b132
	HH(c, d, a, b, wBuf[R3B2 ], S3_2, T3_2);
Packit 40b132
	HH(b, c, d, a, wBuf[R3B3 ], S3_3, T3_3);
Packit 40b132
	HH(a, b, c, d, wBuf[R3B4 ], S3_0, T3_4);
Packit 40b132
	HH(d, a, b, c, wBuf[R3B5 ], S3_1, T3_5);
Packit 40b132
	HH(c, d, a, b, wBuf[R3B6 ], S3_2, T3_6);
Packit 40b132
	HH(b, c, d, a, wBuf[R3B7 ], S3_3, T3_7);
Packit 40b132
	HH(a, b, c, d, wBuf[R3B8 ], S3_0, T3_8);
Packit 40b132
	HH(d, a, b, c, wBuf[R3B9 ], S3_1, T3_9);
Packit 40b132
	HH(c, d, a, b, wBuf[R3B10], S3_2, T3_10);
Packit 40b132
	HH(b, c, d, a, wBuf[R3B11], S3_3, T3_11);
Packit 40b132
	HH(a, b, c, d, wBuf[R3B12], S3_0, T3_12);
Packit 40b132
	HH(d, a, b, c, wBuf[R3B13], S3_1, T3_13);
Packit 40b132
	HH(c, d, a, b, wBuf[R3B14], S3_2, T3_14);
Packit 40b132
	HH(b, c, d, a, wBuf[R3B15], S3_3, T3_15);
Packit 40b132
	II(a, b, c, d, wBuf[R4B0 ], S4_0, T4_0);
Packit 40b132
	II(d, a, b, c, wBuf[R4B1 ], S4_1, T4_1);
Packit 40b132
	II(c, d, a, b, wBuf[R4B2 ], S4_2, T4_2);
Packit 40b132
	II(b, c, d, a, wBuf[R4B3 ], S4_3, T4_3);
Packit 40b132
	II(a, b, c, d, wBuf[R4B4 ], S4_0, T4_4);
Packit 40b132
	II(d, a, b, c, wBuf[R4B5 ], S4_1, T4_5);
Packit 40b132
	II(c, d, a, b, wBuf[R4B6 ], S4_2, T4_6);
Packit 40b132
	II(b, c, d, a, wBuf[R4B7 ], S4_3, T4_7);
Packit 40b132
	II(a, b, c, d, wBuf[R4B8 ], S4_0, T4_8);
Packit 40b132
	II(d, a, b, c, wBuf[R4B9 ], S4_1, T4_9);
Packit 40b132
	II(c, d, a, b, wBuf[R4B10], S4_2, T4_10);
Packit 40b132
	II(b, c, d, a, wBuf[R4B11], S4_3, T4_11);
Packit 40b132
	II(a, b, c, d, wBuf[R4B12], S4_0, T4_12);
Packit 40b132
	II(d, a, b, c, wBuf[R4B13], S4_1, T4_13);
Packit 40b132
	II(c, d, a, b, wBuf[R4B14], S4_2, T4_14);
Packit 40b132
	II(b, c, d, a, wBuf[R4B15], S4_3, T4_15);
Packit 40b132
	cx->cv[0] += a;
Packit 40b132
	cx->cv[1] += b;
Packit 40b132
	cx->cv[2] += c;
Packit 40b132
	cx->cv[3] += d;
Packit 40b132
}
Packit 40b132
Packit 40b132
void 
Packit 40b132
MD5_Update(MD5Context *cx, const unsigned char *input, unsigned int inputLen)
Packit 40b132
{
Packit 40b132
	PRUint32 bytesToConsume;
Packit 40b132
	PRUint32 inBufIndex = cx->lsbInput & 63;
Packit 40b132
	const PRUint32 *wBuf;
Packit 40b132
Packit 40b132
	/* Add the number of input bytes to the 64-bit input counter. */
Packit 40b132
	addto64(cx->msbInput, cx->lsbInput, inputLen);
Packit 40b132
	if (inBufIndex) {
Packit 40b132
		/* There is already data in the buffer.  Fill with input. */
Packit 40b132
		bytesToConsume = PR_MIN(inputLen, MD5_BUFFER_SIZE - inBufIndex);
Packit 40b132
		memcpy(&cx->inBuf[inBufIndex], input, bytesToConsume);
Packit 40b132
		if (inBufIndex + bytesToConsume >= MD5_BUFFER_SIZE) {
Packit 40b132
			/* The buffer is filled.  Run the compression function. */
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
			md5_prep_state_le(cx);
Packit 40b132
#endif
Packit 40b132
			md5_compress(cx, cx->u.w);
Packit 40b132
		}
Packit 40b132
		/* Remaining input. */
Packit 40b132
		inputLen -= bytesToConsume;
Packit 40b132
		input += bytesToConsume;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* Iterate over 64-byte chunks of the message. */
Packit 40b132
	while (inputLen >= MD5_BUFFER_SIZE) {
Packit 40b132
#ifdef IS_LITTLE_ENDIAN
Packit 40b132
#ifdef NSS_X86_OR_X64
Packit 40b132
		/* x86 can handle arithmetic on non-word-aligned buffers */
Packit 40b132
		wBuf = (PRUint32 *)input;
Packit 40b132
#else
Packit 40b132
		if ((ptrdiff_t)input & 0x3) {
Packit 40b132
			/* buffer not aligned, copy it to force alignment */
Packit 40b132
			memcpy(cx->inBuf, input, MD5_BUFFER_SIZE);
Packit 40b132
			wBuf = cx->u.w;
Packit 40b132
		} else {
Packit 40b132
			/* buffer is aligned */
Packit 40b132
			wBuf = (PRUint32 *)input;
Packit 40b132
		}
Packit 40b132
#endif
Packit 40b132
#else
Packit 40b132
		md5_prep_buffer_le(cx, input);
Packit 40b132
		wBuf = cx->u.w;
Packit 40b132
#endif
Packit 40b132
		md5_compress(cx, wBuf);
Packit 40b132
		inputLen -= MD5_BUFFER_SIZE;
Packit 40b132
		input += MD5_BUFFER_SIZE;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* Tail of message (message bytes mod 64). */
Packit 40b132
	if (inputLen)
Packit 40b132
		memcpy(cx->inBuf, input, inputLen);
Packit 40b132
}
Packit 40b132
Packit 40b132
static const unsigned char padbytes[] = {
Packit 40b132
	0x80, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
Packit 40b132
	0x00, 0x00, 0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00
Packit 40b132
};
Packit 40b132
Packit 40b132
void 
Packit 40b132
MD5_End(MD5Context *cx, unsigned char *digest,
Packit 40b132
        unsigned int *digestLen, unsigned int maxDigestLen)
Packit 40b132
{
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
	PRUint32 tmp;
Packit 40b132
#endif
Packit 40b132
	PRUint32 lowInput, highInput;
Packit 40b132
	PRUint32 inBufIndex = cx->lsbInput & 63;
Packit 40b132
Packit 40b132
	if (maxDigestLen < MD5_HASH_LEN) {
Packit 40b132
		PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
		return;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* Copy out the length of bits input before padding. */
Packit 40b132
	lowInput = cx->lsbInput; 
Packit 40b132
	highInput = (cx->msbInput << 3) | (lowInput >> 29);
Packit 40b132
	lowInput <<= 3;
Packit 40b132
Packit 40b132
	if (inBufIndex < MD5_END_BUFFER) {
Packit 40b132
		MD5_Update(cx, padbytes, MD5_END_BUFFER - inBufIndex);
Packit 40b132
	} else {
Packit 40b132
		MD5_Update(cx, padbytes, 
Packit 40b132
		           MD5_END_BUFFER + MD5_BUFFER_SIZE - inBufIndex);
Packit 40b132
	}
Packit 40b132
Packit 40b132
	/* Store the number of bytes input (before padding) in final 64 bits. */
Packit 40b132
	cx->u.w[14] = lendian(lowInput);
Packit 40b132
	cx->u.w[15] = lendian(highInput);
Packit 40b132
Packit 40b132
	/* Final call to compress. */
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
	md5_prep_state_le(cx);
Packit 40b132
#endif
Packit 40b132
	md5_compress(cx, cx->u.w);
Packit 40b132
Packit 40b132
	/* Copy the resulting values out of the chain variables into return buf. */
Packit 40b132
	if (digestLen)
Packit 40b132
		*digestLen = MD5_HASH_LEN;
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
	cx->cv[0] = lendian(cx->cv[0]);
Packit 40b132
	cx->cv[1] = lendian(cx->cv[1]);
Packit 40b132
	cx->cv[2] = lendian(cx->cv[2]);
Packit 40b132
	cx->cv[3] = lendian(cx->cv[3]);
Packit 40b132
#endif
Packit 40b132
	memcpy(digest, cx->cv, MD5_HASH_LEN);
Packit 40b132
}
Packit 40b132
Packit 40b132
void
Packit 40b132
MD5_EndRaw(MD5Context *cx, unsigned char *digest,
Packit 40b132
           unsigned int *digestLen, unsigned int maxDigestLen)
Packit 40b132
{
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
	PRUint32 tmp;
Packit 40b132
#endif
Packit 40b132
	PRUint32 cv[4];
Packit 40b132
Packit 40b132
	if (maxDigestLen < MD5_HASH_LEN) {
Packit 40b132
		PORT_SetError(SEC_ERROR_INVALID_ARGS);
Packit 40b132
		return;
Packit 40b132
	}
Packit 40b132
Packit 40b132
	memcpy(cv, cx->cv, sizeof(cv));
Packit 40b132
#ifndef IS_LITTLE_ENDIAN
Packit 40b132
	cv[0] = lendian(cv[0]);
Packit 40b132
	cv[1] = lendian(cv[1]);
Packit 40b132
	cv[2] = lendian(cv[2]);
Packit 40b132
	cv[3] = lendian(cv[3]);
Packit 40b132
#endif
Packit 40b132
	memcpy(digest, cv, MD5_HASH_LEN);
Packit 40b132
	if (digestLen)
Packit 40b132
		*digestLen = MD5_HASH_LEN;
Packit 40b132
}
Packit 40b132
Packit 40b132
unsigned int 
Packit 40b132
MD5_FlattenSize(MD5Context *cx)
Packit 40b132
{
Packit 40b132
	return sizeof(*cx);
Packit 40b132
}
Packit 40b132
Packit 40b132
SECStatus 
Packit 40b132
MD5_Flatten(MD5Context *cx, unsigned char *space)
Packit 40b132
{
Packit 40b132
	memcpy(space, cx, sizeof(*cx));
Packit 40b132
	return SECSuccess;
Packit 40b132
}
Packit 40b132
Packit 40b132
MD5Context * 
Packit 40b132
MD5_Resurrect(unsigned char *space, void *arg)
Packit 40b132
{
Packit 40b132
	MD5Context *cx = MD5_NewContext();
Packit 40b132
	if (cx)
Packit 40b132
		memcpy(cx, space, sizeof(*cx));
Packit 40b132
	return cx;
Packit 40b132
}
Packit 40b132
Packit 40b132
void MD5_Clone(MD5Context *dest, MD5Context *src) 
Packit 40b132
{
Packit 40b132
	memcpy(dest, src, sizeof *dest);
Packit 40b132
}
Packit 40b132
Packit 40b132
void 
Packit 40b132
MD5_TraceState(MD5Context *cx)
Packit 40b132
{
Packit 40b132
	PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
Packit 40b132
}