xref: /minix3/external/bsd/bind/dist/lib/isc/md5.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: md5.c,v 1.7 2015/07/08 17:28:59 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek /*
4*00b67f09SDavid van Moolenbroek  * Copyright (C) 2004, 2005, 2007, 2009, 2014  Internet Systems Consortium, Inc. ("ISC")
5*00b67f09SDavid van Moolenbroek  * Copyright (C) 2000, 2001  Internet Software Consortium.
6*00b67f09SDavid van Moolenbroek  *
7*00b67f09SDavid van Moolenbroek  * Permission to use, copy, modify, and/or distribute this software for any
8*00b67f09SDavid van Moolenbroek  * purpose with or without fee is hereby granted, provided that the above
9*00b67f09SDavid van Moolenbroek  * copyright notice and this permission notice appear in all copies.
10*00b67f09SDavid van Moolenbroek  *
11*00b67f09SDavid van Moolenbroek  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12*00b67f09SDavid van Moolenbroek  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13*00b67f09SDavid van Moolenbroek  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14*00b67f09SDavid van Moolenbroek  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*00b67f09SDavid van Moolenbroek  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16*00b67f09SDavid van Moolenbroek  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*00b67f09SDavid van Moolenbroek  * PERFORMANCE OF THIS SOFTWARE.
18*00b67f09SDavid van Moolenbroek  */
19*00b67f09SDavid van Moolenbroek 
20*00b67f09SDavid van Moolenbroek /* Id: md5.c,v 1.16 2009/02/06 23:47:42 tbox Exp  */
21*00b67f09SDavid van Moolenbroek 
22*00b67f09SDavid van Moolenbroek /*! \file
23*00b67f09SDavid van Moolenbroek  * This code implements the MD5 message-digest algorithm.
24*00b67f09SDavid van Moolenbroek  * The algorithm is due to Ron Rivest.  This code was
25*00b67f09SDavid van Moolenbroek  * written by Colin Plumb in 1993, no copyright is claimed.
26*00b67f09SDavid van Moolenbroek  * This code is in the public domain; do with it what you wish.
27*00b67f09SDavid van Moolenbroek  *
28*00b67f09SDavid van Moolenbroek  * Equivalent code is available from RSA Data Security, Inc.
29*00b67f09SDavid van Moolenbroek  * This code has been tested against that, and is equivalent,
30*00b67f09SDavid van Moolenbroek  * except that you don't need to include two pages of legalese
31*00b67f09SDavid van Moolenbroek  * with every copy.
32*00b67f09SDavid van Moolenbroek  *
33*00b67f09SDavid van Moolenbroek  * To compute the message digest of a chunk of bytes, declare an
34*00b67f09SDavid van Moolenbroek  * MD5Context structure, pass it to MD5Init, call MD5Update as
35*00b67f09SDavid van Moolenbroek  * needed on buffers full of bytes, and then call MD5Final, which
36*00b67f09SDavid van Moolenbroek  * will fill a supplied 16-byte array with the digest.
37*00b67f09SDavid van Moolenbroek  */
38*00b67f09SDavid van Moolenbroek 
39*00b67f09SDavid van Moolenbroek #include "config.h"
40*00b67f09SDavid van Moolenbroek 
41*00b67f09SDavid van Moolenbroek #include <isc/assertions.h>
42*00b67f09SDavid van Moolenbroek #include <isc/md5.h>
43*00b67f09SDavid van Moolenbroek #include <isc/platform.h>
44*00b67f09SDavid van Moolenbroek #include <isc/string.h>
45*00b67f09SDavid van Moolenbroek #include <isc/types.h>
46*00b67f09SDavid van Moolenbroek 
47*00b67f09SDavid van Moolenbroek #if PKCS11CRYPTO
48*00b67f09SDavid van Moolenbroek #include <pk11/internal.h>
49*00b67f09SDavid van Moolenbroek #include <pk11/pk11.h>
50*00b67f09SDavid van Moolenbroek #endif
51*00b67f09SDavid van Moolenbroek 
52*00b67f09SDavid van Moolenbroek #include <isc/util.h>
53*00b67f09SDavid van Moolenbroek 
54*00b67f09SDavid van Moolenbroek #ifdef ISC_PLATFORM_OPENSSLHASH
55*00b67f09SDavid van Moolenbroek void
isc_md5_init(isc_md5_t * ctx)56*00b67f09SDavid van Moolenbroek isc_md5_init(isc_md5_t *ctx) {
57*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(EVP_DigestInit(ctx, EVP_md5()) == 1);
58*00b67f09SDavid van Moolenbroek }
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek void
isc_md5_invalidate(isc_md5_t * ctx)61*00b67f09SDavid van Moolenbroek isc_md5_invalidate(isc_md5_t *ctx) {
62*00b67f09SDavid van Moolenbroek 	EVP_MD_CTX_cleanup(ctx);
63*00b67f09SDavid van Moolenbroek }
64*00b67f09SDavid van Moolenbroek 
65*00b67f09SDavid van Moolenbroek void
isc_md5_update(isc_md5_t * ctx,const unsigned char * buf,unsigned int len)66*00b67f09SDavid van Moolenbroek isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
67*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(EVP_DigestUpdate(ctx,
68*00b67f09SDavid van Moolenbroek 				       (const void *) buf,
69*00b67f09SDavid van Moolenbroek 				       (size_t) len) == 1);
70*00b67f09SDavid van Moolenbroek }
71*00b67f09SDavid van Moolenbroek 
72*00b67f09SDavid van Moolenbroek void
isc_md5_final(isc_md5_t * ctx,unsigned char * digest)73*00b67f09SDavid van Moolenbroek isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
74*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(EVP_DigestFinal(ctx, digest, NULL) == 1);
75*00b67f09SDavid van Moolenbroek }
76*00b67f09SDavid van Moolenbroek 
77*00b67f09SDavid van Moolenbroek #elif PKCS11CRYPTO
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek void
isc_md5_init(isc_md5_t * ctx)80*00b67f09SDavid van Moolenbroek isc_md5_init(isc_md5_t *ctx) {
81*00b67f09SDavid van Moolenbroek 	CK_RV rv;
82*00b67f09SDavid van Moolenbroek 	CK_MECHANISM mech = { CKM_MD5, NULL, 0 };
83*00b67f09SDavid van Moolenbroek 
84*00b67f09SDavid van Moolenbroek 	RUNTIME_CHECK(pk11_get_session(ctx, OP_DIGEST, ISC_TRUE, ISC_FALSE,
85*00b67f09SDavid van Moolenbroek 				       ISC_FALSE, NULL, 0) == ISC_R_SUCCESS);
86*00b67f09SDavid van Moolenbroek 	PK11_FATALCHECK(pkcs_C_DigestInit, (ctx->session, &mech));
87*00b67f09SDavid van Moolenbroek }
88*00b67f09SDavid van Moolenbroek 
89*00b67f09SDavid van Moolenbroek void
isc_md5_invalidate(isc_md5_t * ctx)90*00b67f09SDavid van Moolenbroek isc_md5_invalidate(isc_md5_t *ctx) {
91*00b67f09SDavid van Moolenbroek 	CK_BYTE garbage[ISC_MD5_DIGESTLENGTH];
92*00b67f09SDavid van Moolenbroek 	CK_ULONG len = ISC_MD5_DIGESTLENGTH;
93*00b67f09SDavid van Moolenbroek 
94*00b67f09SDavid van Moolenbroek 	if (ctx->handle == NULL)
95*00b67f09SDavid van Moolenbroek 		return;
96*00b67f09SDavid van Moolenbroek 	(void) pkcs_C_DigestFinal(ctx->session, garbage, &len);
97*00b67f09SDavid van Moolenbroek 	memset(garbage, 0, sizeof(garbage));
98*00b67f09SDavid van Moolenbroek 	pk11_return_session(ctx);
99*00b67f09SDavid van Moolenbroek }
100*00b67f09SDavid van Moolenbroek 
101*00b67f09SDavid van Moolenbroek void
isc_md5_update(isc_md5_t * ctx,const unsigned char * buf,unsigned int len)102*00b67f09SDavid van Moolenbroek isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
103*00b67f09SDavid van Moolenbroek 	CK_RV rv;
104*00b67f09SDavid van Moolenbroek 	CK_BYTE_PTR pPart;
105*00b67f09SDavid van Moolenbroek 
106*00b67f09SDavid van Moolenbroek 	DE_CONST(buf, pPart);
107*00b67f09SDavid van Moolenbroek 	PK11_FATALCHECK(pkcs_C_DigestUpdate,
108*00b67f09SDavid van Moolenbroek 			(ctx->session, pPart, (CK_ULONG) len));
109*00b67f09SDavid van Moolenbroek }
110*00b67f09SDavid van Moolenbroek 
111*00b67f09SDavid van Moolenbroek void
isc_md5_final(isc_md5_t * ctx,unsigned char * digest)112*00b67f09SDavid van Moolenbroek isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
113*00b67f09SDavid van Moolenbroek 	CK_RV rv;
114*00b67f09SDavid van Moolenbroek 	CK_ULONG len = ISC_MD5_DIGESTLENGTH;
115*00b67f09SDavid van Moolenbroek 
116*00b67f09SDavid van Moolenbroek 	PK11_FATALCHECK(pkcs_C_DigestFinal,
117*00b67f09SDavid van Moolenbroek 			(ctx->session, (CK_BYTE_PTR) digest, &len));
118*00b67f09SDavid van Moolenbroek 	pk11_return_session(ctx);
119*00b67f09SDavid van Moolenbroek }
120*00b67f09SDavid van Moolenbroek 
121*00b67f09SDavid van Moolenbroek #else
122*00b67f09SDavid van Moolenbroek 
123*00b67f09SDavid van Moolenbroek static void
byteSwap(isc_uint32_t * buf,unsigned words)124*00b67f09SDavid van Moolenbroek byteSwap(isc_uint32_t *buf, unsigned words)
125*00b67f09SDavid van Moolenbroek {
126*00b67f09SDavid van Moolenbroek 	unsigned char *p = (unsigned char *)buf;
127*00b67f09SDavid van Moolenbroek 
128*00b67f09SDavid van Moolenbroek 	do {
129*00b67f09SDavid van Moolenbroek 		*buf++ = (isc_uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
130*00b67f09SDavid van Moolenbroek 			((unsigned)p[1] << 8 | p[0]);
131*00b67f09SDavid van Moolenbroek 		p += 4;
132*00b67f09SDavid van Moolenbroek 	} while (--words);
133*00b67f09SDavid van Moolenbroek }
134*00b67f09SDavid van Moolenbroek 
135*00b67f09SDavid van Moolenbroek /*!
136*00b67f09SDavid van Moolenbroek  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
137*00b67f09SDavid van Moolenbroek  * initialization constants.
138*00b67f09SDavid van Moolenbroek  */
139*00b67f09SDavid van Moolenbroek void
isc_md5_init(isc_md5_t * ctx)140*00b67f09SDavid van Moolenbroek isc_md5_init(isc_md5_t *ctx) {
141*00b67f09SDavid van Moolenbroek 	ctx->buf[0] = 0x67452301;
142*00b67f09SDavid van Moolenbroek 	ctx->buf[1] = 0xefcdab89;
143*00b67f09SDavid van Moolenbroek 	ctx->buf[2] = 0x98badcfe;
144*00b67f09SDavid van Moolenbroek 	ctx->buf[3] = 0x10325476;
145*00b67f09SDavid van Moolenbroek 
146*00b67f09SDavid van Moolenbroek 	ctx->bytes[0] = 0;
147*00b67f09SDavid van Moolenbroek 	ctx->bytes[1] = 0;
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek 
150*00b67f09SDavid van Moolenbroek void
isc_md5_invalidate(isc_md5_t * ctx)151*00b67f09SDavid van Moolenbroek isc_md5_invalidate(isc_md5_t *ctx) {
152*00b67f09SDavid van Moolenbroek 	memset(ctx, 0, sizeof(isc_md5_t));
153*00b67f09SDavid van Moolenbroek }
154*00b67f09SDavid van Moolenbroek 
155*00b67f09SDavid van Moolenbroek /*@{*/
156*00b67f09SDavid van Moolenbroek /*! The four core functions - F1 is optimized somewhat */
157*00b67f09SDavid van Moolenbroek 
158*00b67f09SDavid van Moolenbroek /* #define F1(x, y, z) (x & y | ~x & z) */
159*00b67f09SDavid van Moolenbroek #define F1(x, y, z) (z ^ (x & (y ^ z)))
160*00b67f09SDavid van Moolenbroek #define F2(x, y, z) F1(z, x, y)
161*00b67f09SDavid van Moolenbroek #define F3(x, y, z) (x ^ y ^ z)
162*00b67f09SDavid van Moolenbroek #define F4(x, y, z) (y ^ (x | ~z))
163*00b67f09SDavid van Moolenbroek /*@}*/
164*00b67f09SDavid van Moolenbroek 
165*00b67f09SDavid van Moolenbroek /*! This is the central step in the MD5 algorithm. */
166*00b67f09SDavid van Moolenbroek #define MD5STEP(f,w,x,y,z,in,s) \
167*00b67f09SDavid van Moolenbroek 	 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek /*!
170*00b67f09SDavid van Moolenbroek  * The core of the MD5 algorithm, this alters an existing MD5 hash to
171*00b67f09SDavid van Moolenbroek  * reflect the addition of 16 longwords of new data.  MD5Update blocks
172*00b67f09SDavid van Moolenbroek  * the data and converts bytes into longwords for this routine.
173*00b67f09SDavid van Moolenbroek  */
174*00b67f09SDavid van Moolenbroek static void
transform(isc_uint32_t buf[4],isc_uint32_t const in[16])175*00b67f09SDavid van Moolenbroek transform(isc_uint32_t buf[4], isc_uint32_t const in[16]) {
176*00b67f09SDavid van Moolenbroek 	register isc_uint32_t a, b, c, d;
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek 	a = buf[0];
179*00b67f09SDavid van Moolenbroek 	b = buf[1];
180*00b67f09SDavid van Moolenbroek 	c = buf[2];
181*00b67f09SDavid van Moolenbroek 	d = buf[3];
182*00b67f09SDavid van Moolenbroek 
183*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
184*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
185*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
186*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
187*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
188*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
189*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
190*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
191*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
192*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
193*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
194*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
195*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
196*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
197*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
198*00b67f09SDavid van Moolenbroek 	MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
201*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
202*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
203*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
204*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
205*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
206*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
207*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
208*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
209*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
210*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
211*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
212*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
213*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
214*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
215*00b67f09SDavid van Moolenbroek 	MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
216*00b67f09SDavid van Moolenbroek 
217*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
218*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
219*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
220*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
221*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
222*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
223*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
224*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
225*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
226*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
227*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
228*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
229*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
230*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
231*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
232*00b67f09SDavid van Moolenbroek 	MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
233*00b67f09SDavid van Moolenbroek 
234*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
235*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
236*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
237*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
238*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
239*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
240*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
241*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
242*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
243*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
244*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
245*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
246*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
247*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
248*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
249*00b67f09SDavid van Moolenbroek 	MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
250*00b67f09SDavid van Moolenbroek 
251*00b67f09SDavid van Moolenbroek 	buf[0] += a;
252*00b67f09SDavid van Moolenbroek 	buf[1] += b;
253*00b67f09SDavid van Moolenbroek 	buf[2] += c;
254*00b67f09SDavid van Moolenbroek 	buf[3] += d;
255*00b67f09SDavid van Moolenbroek }
256*00b67f09SDavid van Moolenbroek 
257*00b67f09SDavid van Moolenbroek /*!
258*00b67f09SDavid van Moolenbroek  * Update context to reflect the concatenation of another buffer full
259*00b67f09SDavid van Moolenbroek  * of bytes.
260*00b67f09SDavid van Moolenbroek  */
261*00b67f09SDavid van Moolenbroek void
isc_md5_update(isc_md5_t * ctx,const unsigned char * buf,unsigned int len)262*00b67f09SDavid van Moolenbroek isc_md5_update(isc_md5_t *ctx, const unsigned char *buf, unsigned int len) {
263*00b67f09SDavid van Moolenbroek 	isc_uint32_t t;
264*00b67f09SDavid van Moolenbroek 
265*00b67f09SDavid van Moolenbroek 	/* Update byte count */
266*00b67f09SDavid van Moolenbroek 
267*00b67f09SDavid van Moolenbroek 	t = ctx->bytes[0];
268*00b67f09SDavid van Moolenbroek 	if ((ctx->bytes[0] = t + len) < t)
269*00b67f09SDavid van Moolenbroek 		ctx->bytes[1]++;	/* Carry from low to high */
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek 	t = 64 - (t & 0x3f);	/* Space available in ctx->in (at least 1) */
272*00b67f09SDavid van Moolenbroek 	if (t > len) {
273*00b67f09SDavid van Moolenbroek 		memmove((unsigned char *)ctx->in + 64 - t, buf, len);
274*00b67f09SDavid van Moolenbroek 		return;
275*00b67f09SDavid van Moolenbroek 	}
276*00b67f09SDavid van Moolenbroek 	/* First chunk is an odd size */
277*00b67f09SDavid van Moolenbroek 	memmove((unsigned char *)ctx->in + 64 - t, buf, t);
278*00b67f09SDavid van Moolenbroek 	byteSwap(ctx->in, 16);
279*00b67f09SDavid van Moolenbroek 	transform(ctx->buf, ctx->in);
280*00b67f09SDavid van Moolenbroek 	buf += t;
281*00b67f09SDavid van Moolenbroek 	len -= t;
282*00b67f09SDavid van Moolenbroek 
283*00b67f09SDavid van Moolenbroek 	/* Process data in 64-byte chunks */
284*00b67f09SDavid van Moolenbroek 	while (len >= 64) {
285*00b67f09SDavid van Moolenbroek 		memmove(ctx->in, buf, 64);
286*00b67f09SDavid van Moolenbroek 		byteSwap(ctx->in, 16);
287*00b67f09SDavid van Moolenbroek 		transform(ctx->buf, ctx->in);
288*00b67f09SDavid van Moolenbroek 		buf += 64;
289*00b67f09SDavid van Moolenbroek 		len -= 64;
290*00b67f09SDavid van Moolenbroek 	}
291*00b67f09SDavid van Moolenbroek 
292*00b67f09SDavid van Moolenbroek 	/* Handle any remaining bytes of data. */
293*00b67f09SDavid van Moolenbroek 	memmove(ctx->in, buf, len);
294*00b67f09SDavid van Moolenbroek }
295*00b67f09SDavid van Moolenbroek 
296*00b67f09SDavid van Moolenbroek /*!
297*00b67f09SDavid van Moolenbroek  * Final wrapup - pad to 64-byte boundary with the bit pattern
298*00b67f09SDavid van Moolenbroek  * 1 0* (64-bit count of bits processed, MSB-first)
299*00b67f09SDavid van Moolenbroek  */
300*00b67f09SDavid van Moolenbroek void
isc_md5_final(isc_md5_t * ctx,unsigned char * digest)301*00b67f09SDavid van Moolenbroek isc_md5_final(isc_md5_t *ctx, unsigned char *digest) {
302*00b67f09SDavid van Moolenbroek 	int count = ctx->bytes[0] & 0x3f;    /* Number of bytes in ctx->in */
303*00b67f09SDavid van Moolenbroek 	unsigned char *p = (unsigned char *)ctx->in + count;
304*00b67f09SDavid van Moolenbroek 
305*00b67f09SDavid van Moolenbroek 	/* Set the first char of padding to 0x80.  There is always room. */
306*00b67f09SDavid van Moolenbroek 	*p++ = 0x80;
307*00b67f09SDavid van Moolenbroek 
308*00b67f09SDavid van Moolenbroek 	/* Bytes of padding needed to make 56 bytes (-8..55) */
309*00b67f09SDavid van Moolenbroek 	count = 56 - 1 - count;
310*00b67f09SDavid van Moolenbroek 
311*00b67f09SDavid van Moolenbroek 	if (count < 0) {	/* Padding forces an extra block */
312*00b67f09SDavid van Moolenbroek 		memset(p, 0, count + 8);
313*00b67f09SDavid van Moolenbroek 		byteSwap(ctx->in, 16);
314*00b67f09SDavid van Moolenbroek 		transform(ctx->buf, ctx->in);
315*00b67f09SDavid van Moolenbroek 		p = (unsigned char *)ctx->in;
316*00b67f09SDavid van Moolenbroek 		count = 56;
317*00b67f09SDavid van Moolenbroek 	}
318*00b67f09SDavid van Moolenbroek 	memset(p, 0, count);
319*00b67f09SDavid van Moolenbroek 	byteSwap(ctx->in, 14);
320*00b67f09SDavid van Moolenbroek 
321*00b67f09SDavid van Moolenbroek 	/* Append length in bits and transform */
322*00b67f09SDavid van Moolenbroek 	ctx->in[14] = ctx->bytes[0] << 3;
323*00b67f09SDavid van Moolenbroek 	ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
324*00b67f09SDavid van Moolenbroek 	transform(ctx->buf, ctx->in);
325*00b67f09SDavid van Moolenbroek 
326*00b67f09SDavid van Moolenbroek 	byteSwap(ctx->buf, 4);
327*00b67f09SDavid van Moolenbroek 	memmove(digest, ctx->buf, 16);
328*00b67f09SDavid van Moolenbroek 	memset(ctx, 0, sizeof(isc_md5_t));	/* In case it's sensitive */
329*00b67f09SDavid van Moolenbroek }
330*00b67f09SDavid van Moolenbroek #endif
331