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