xref: /netbsd-src/external/bsd/iscsi/dist/src/lib/md5c.c (revision 5e01dafb5c1f3a68ee2f80136c3b6043ad89a0f3)
1 /*	$NetBSD: md5c.c,v 1.2 2009/06/30 02:44:52 agc Exp $	*/
2 
3 /*
4  * This file is derived from the RSA Data Security, Inc. MD5 Message-Digest
5  * Algorithm and has been modifed by Jason R. Thorpe <thorpej@NetBSD.ORG>
6  * for portability and formatting.
7  */
8 
9 /*
10  * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
11  * rights reserved.
12  *
13  * License to copy and use this software is granted provided that it
14  * is identified as the "RSA Data Security, Inc. MD5 Message-Digest
15  * Algorithm" in all material mentioning or referencing this software
16  * or this function.
17  *
18  * License is also granted to make and use derivative works provided
19  * that such works are identified as "derived from the RSA Data
20  * Security, Inc. MD5 Message-Digest Algorithm" in all material
21  * mentioning or referencing the derived work.
22  *
23  * RSA Data Security, Inc. makes no representations concerning either
24  * the merchantability of this software or the suitability of this
25  * software for any particular purpose. It is provided "as is"
26  * without express or implied warranty of any kind.
27  *
28  * These notices must be retained in any copies of any part of this
29  * documentation and/or software.
30  */
31 
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35 
36 #if defined(_KERNEL) || defined(_STANDALONE)
37 #include <lib/libkern/libkern.h>
38 #include <sys/param.h>
39 #include <sys/md5.h>
40 #define _DIAGASSERT(x)	(void)0
41 #else
42 /* #include "namespace.h" */
43 #include <assert.h>
44 #include <string.h>
45 #include "iscsi-md5.h"
46 #endif /* _KERNEL || _STANDALONE */
47 
48 #if defined(HAVE_MEMSET)
49 #define	ZEROIZE(d, l)		memset((d), 0, (l))
50 #else
51 # if defined(HAVE_BZERO)
52 #define ZEROIZE(d, l)		bzero((d), (l))
53 # else
54 #error You need either memset or bzero
55 # endif
56 #endif
57 
58 typedef unsigned char *POINTER;
59 typedef uint16_t UINT2;
60 typedef uint32_t UINT4;
61 
62 /*
63  * Constants for MD5Transform routine.
64  */
65 #define S11 7
66 #define S12 12
67 #define S13 17
68 #define S14 22
69 #define S21 5
70 #define S22 9
71 #define S23 14
72 #define S24 20
73 #define S31 4
74 #define S32 11
75 #define S33 16
76 #define S34 23
77 #define S41 6
78 #define S42 10
79 #define S43 15
80 #define S44 21
81 
82 #if 0
83 #if !defined(_KERNEL) && !defined(_STANDALONE) && defined(__weak_alias)
84 __weak_alias(iSCSI_MD5Init,_MD5Init)
85 __weak_alias(iSCSI_MD5Update,_MD5Update)
86 __weak_alias(iSCSI_MD5Final,_MD5Final)
87 #endif
88 #endif
89 
90 #ifndef _DIAGASSERT
91 #define _DIAGASSERT(cond)	assert(cond)
92 #endif
93 
94 static void iSCSI_MD5Transform(UINT4 [4], const unsigned char [64]);
95 
96 static void Encode(unsigned char *, UINT4 *, unsigned int);
97 static void Decode(UINT4 *, const unsigned char *, unsigned int);
98 
99 /*
100  * Encodes input (UINT4) into output (unsigned char).  Assumes len is
101  * a multiple of 4.
102  */
103 static void
Encode(output,input,len)104 Encode (output, input, len)
105 	unsigned char *output;
106 	UINT4 *input;
107 	unsigned int len;
108 {
109 	unsigned int i, j;
110 
111 	for (i = 0, j = 0; j < len; i++, j += 4) {
112 		output[j] = (unsigned char)(input[i] & 0xff);
113 		output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
114 		output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
115 		output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
116 	}
117 }
118 
119 /*
120  * Decodes input (unsigned char) into output (UINT4).  Assumes len is
121  * a multiple of 4.
122  */
123 static void
Decode(output,input,len)124 Decode (output, input, len)
125 	UINT4 *output;
126 	const unsigned char *input;
127 	unsigned int len;
128 {
129 	unsigned int i, j;
130 
131 	for (i = 0, j = 0; j < len; i++, j += 4)
132 		output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
133 		    (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
134 }
135 
136 static const unsigned char PADDING[64] = {
137 	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
138 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
140 };
141 
142 /*
143  * F, G, H and I are basic MD5 functions.
144  */
145 #define F(x, y, z)	(((x) & (y)) | ((~x) & (z)))
146 #define G(x, y, z)	(((x) & (z)) | ((y) & (~z)))
147 #define H(x, y, z)	((x) ^ (y) ^ (z))
148 #define I(x, y, z)	((y) ^ ((x) | (~z)))
149 
150 /*
151  * ROTATE_LEFT rotates x left n bits.
152  */
153 #define ROTATE_LEFT(x, n)	(((x) << (n)) | ((x) >> (32-(n))))
154 
155 /*
156  * FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
157  * Rotation is separate from addition to prevent recomputation.
158  */
159 #define FF(a, b, c, d, x, s, ac) { \
160 	(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
161 	(a) = ROTATE_LEFT ((a), (s)); \
162 	(a) += (b); \
163 }
164 
165 #define GG(a, b, c, d, x, s, ac) { \
166 	(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
167 	(a) = ROTATE_LEFT ((a), (s)); \
168 	(a) += (b); \
169 }
170 
171 #define HH(a, b, c, d, x, s, ac) { \
172 	(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
173 	(a) = ROTATE_LEFT ((a), (s)); \
174 	(a) += (b); \
175 }
176 
177 #define II(a, b, c, d, x, s, ac) { \
178 	(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
179 	(a) = ROTATE_LEFT ((a), (s)); \
180 	(a) += (b); \
181 }
182 
183 /*
184  * MD5 initialization. Begins an MD5 operation, writing a new context.
185  */
186 void
iSCSI_MD5Init(iSCSI_MD5_CTX * context)187 iSCSI_MD5Init(iSCSI_MD5_CTX *context)
188 {
189 
190 	_DIAGASSERT(context != 0);
191 
192 	context->count[0] = context->count[1] = 0;
193 
194 	/* Load magic initialization constants. */
195 	context->state[0] = 0x67452301;
196 	context->state[1] = 0xefcdab89;
197 	context->state[2] = 0x98badcfe;
198 	context->state[3] = 0x10325476;
199 }
200 
201 /*
202  * MD5 block update operation.  Continues an MD5 message-digest
203  * operation, processing another message block, and updating the
204  * context.
205  */
206 void
iSCSI_MD5Update(iSCSI_MD5_CTX * context,const uint8_t * input,size_t inputLen)207 iSCSI_MD5Update(iSCSI_MD5_CTX *context, const uint8_t *input, size_t inputLen)
208 {
209 	unsigned int i, idx, partLen;
210 
211 	_DIAGASSERT(context != 0);
212 	_DIAGASSERT(input != 0);
213 
214 	/* Compute number of bytes mod 64 */
215 	idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
216 
217 	/* Update number of bits */
218 	if ((context->count[0] += ((UINT4)inputLen << 3))
219 	    < ((UINT4)inputLen << 3))
220 		context->count[1]++;
221 	context->count[1] += ((UINT4)inputLen >> 29);
222 
223 	partLen = 64 - idx;
224 
225 	/* Transform as many times as possible. */
226 	if (inputLen >= partLen) {
227 		/* LINTED const castaway ok */
228 		memcpy((POINTER)&context->buffer[idx],
229 		    input, partLen);
230 		iSCSI_MD5Transform(context->state, context->buffer);
231 
232 		for (i = partLen; i + 63 < inputLen; i += 64)
233 			iSCSI_MD5Transform(context->state, &input[i]);
234 
235 		idx = 0;
236 	} else
237 		i = 0;
238 
239 	/* Buffer remaining input */
240 	/* LINTED const castaway ok */
241 	memcpy((POINTER)&context->buffer[idx], &input[i],
242 	    inputLen - i);
243 }
244 
245 /*
246  * MD5 finalization.  Ends an MD5 message-digest operation, writing the
247  * message digest and zeroing the context.
248  */
249 void
iSCSI_MD5Final(unsigned char digest[16],iSCSI_MD5_CTX * context)250 iSCSI_MD5Final(unsigned char digest[16], iSCSI_MD5_CTX *context)
251 {
252 	unsigned char bits[8];
253 	unsigned int idx;
254 	size_t padLen;
255 
256 	_DIAGASSERT(digest != 0);
257 	_DIAGASSERT(context != 0);
258 
259 	/* Save number of bits */
260 	Encode(bits, context->count, 8);
261 
262 	/* Pad out to 56 mod 64. */
263 	idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
264 	padLen = (idx < 56) ? (56 - idx) : (120 - idx);
265 	iSCSI_MD5Update (context, PADDING, padLen);
266 
267 	/* Append length (before padding) */
268 	iSCSI_MD5Update(context, bits, 8);
269 
270 	/* Store state in digest */
271 	Encode(digest, context->state, 16);
272 
273 	/* Zeroize sensitive information. */
274 	ZEROIZE((POINTER)(void *)context, sizeof(*context));
275 }
276 
277 /*
278  * MD5 basic transformation. Transforms state based on block.
279  */
280 static void
iSCSI_MD5Transform(state,block)281 iSCSI_MD5Transform(state, block)
282 	UINT4 state[4];
283 	const unsigned char block[64];
284 {
285 	UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
286 
287 	Decode(x, block, 64);
288 
289 	/* Round 1 */
290 	FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
291 	FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
292 	FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
293 	FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
294 	FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
295 	FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
296 	FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
297 	FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
298 	FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
299 	FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
300 	FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
301 	FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
302 	FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
303 	FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
304 	FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
305 	FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
306 
307 	/* Round 2 */
308 	GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
309 	GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
310 	GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
311 	GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
312 	GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
313 	GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
314 	GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
315 	GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
316 	GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
317 	GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
318 	GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
319 	GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
320 	GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
321 	GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
322 	GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
323 	GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
324 
325 	/* Round 3 */
326 	HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
327 	HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
328 	HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
329 	HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
330 	HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
331 	HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
332 	HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
333 	HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
334 	HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
335 	HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
336 	HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
337 	HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
338 	HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
339 	HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
340 	HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
341 	HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
342 
343 	/* Round 4 */
344 	II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
345 	II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
346 	II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
347 	II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
348 	II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
349 	II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
350 	II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
351 	II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
352 	II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
353 	II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
354 	II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
355 	II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
356 	II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
357 	II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
358 	II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
359 	II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
360 
361 	state[0] += a;
362 	state[1] += b;
363 	state[2] += c;
364 	state[3] += d;
365 
366 	/* Zeroize sensitive information. */
367 	ZEROIZE((POINTER)(void *)x, sizeof (x));
368 }
369