]> git.saurik.com Git - apple/security.git/blob - SecureTransport/sslmd5.c
Security-30.1.tar.gz
[apple/security.git] / SecureTransport / sslmd5.c
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /* sslmd5.c - RSA Data Security, Inc., MD5 message-digest algorithm
20 */
21
22 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
23 rights reserved.
24
25 License to copy and use this software is granted provided that it
26 is identified as the "RSA Data Security, Inc. MD5 Message-Digest
27 Algorithm" in all material mentioning or referencing this software
28 or this function.
29
30 License is also granted to make and use derivative works provided
31 that such works are identified as "derived from the RSA Data
32 Security, Inc. MD5 Message-Digest Algorithm" in all material
33 mentioning or referencing the derived work.
34
35 RSA Data Security, Inc. makes no representations concerning either
36 the merchantability of this software or the suitability of this
37 software for any particular purpose. It is provided "as is"
38 without express or implied warranty of any kind.
39
40 These notices must be retained in any copies of any part of this
41 documentation and/or software.
42 */
43
44 #if 0
45 #ifdef BSAFE
46 #include "aglobal.h"
47 #else
48 #include "global.h"
49 #endif
50 #endif
51 #include "sslmd5.h"
52
53 /* Constants for MD5Transform routine.
54 */
55 #define S11 7
56 #define S12 12
57 #define S13 17
58 #define S14 22
59 #define S21 5
60 #define S22 9
61 #define S23 14
62 #define S24 20
63 #define S31 4
64 #define S32 11
65 #define S33 16
66 #define S34 23
67 #define S41 6
68 #define S42 10
69 #define S43 15
70 #define S44 21
71
72 static void MD5Transform PROTO_LIST ((UINT4 [4], const unsigned char [64]));
73 static void Encode PROTO_LIST
74 ((unsigned char *, UINT4 *, unsigned int));
75 static void Decode PROTO_LIST
76 ((UINT4 *, const unsigned char *, unsigned int));
77 static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
78 static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
79
80 static const unsigned char PADDING[64] = {
81 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
82 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
83 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
84 };
85
86 /* F, G, H and I are basic MD5 functions.
87 */
88 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
89 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
90 #define H(x, y, z) ((x) ^ (y) ^ (z))
91 #define I(x, y, z) ((y) ^ ((x) | (~z)))
92
93 /* ROTATE_LEFT rotates x left n bits.
94 */
95 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
96
97 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
98 Rotation is separate from addition to prevent recomputation.
99 */
100 #define FF(a, b, c, d, x, s, ac) { \
101 (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
102 (a) = ROTATE_LEFT ((a), (s)); \
103 (a) += (b); \
104 }
105 #define GG(a, b, c, d, x, s, ac) { \
106 (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
107 (a) = ROTATE_LEFT ((a), (s)); \
108 (a) += (b); \
109 }
110 #define HH(a, b, c, d, x, s, ac) { \
111 (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
112 (a) = ROTATE_LEFT ((a), (s)); \
113 (a) += (b); \
114 }
115 #define II(a, b, c, d, x, s, ac) { \
116 (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
117 (a) = ROTATE_LEFT ((a), (s)); \
118 (a) += (b); \
119 }
120
121 /* MD5 initialization. Begins an MD5 operation, writing a new context.
122 */
123 void SSLMD5Init (context)
124 MD5_CTX *context; /* context */
125 {
126 context->count[0] = context->count[1] = 0;
127 /* Load magic initialization constants.
128 */
129 context->state[0] = 0x67452301;
130 context->state[1] = 0xefcdab89;
131 context->state[2] = 0x98badcfe;
132 context->state[3] = 0x10325476;
133 }
134
135 /* MD5 block update operation. Continues an MD5 message-digest
136 operation, processing another message block, and updating the
137 context.
138 */
139 void SSLMD5Update (context, input, inputLen)
140 MD5_CTX *context; /* context */
141 unsigned const char *input; /* input block */
142 unsigned int inputLen; /* length of input block */
143 {
144 unsigned int i, index, partLen;
145
146 /* Compute number of bytes mod 64 */
147 index = (unsigned int)((context->count[0] >> 3) & 0x3F);
148
149 /* Update number of bits */
150 if ((context->count[0] += ((UINT4)inputLen << 3)) < ((UINT4)inputLen << 3))
151 context->count[1]++;
152 context->count[1] += ((UINT4)inputLen >> 29);
153
154 partLen = 64 - index;
155
156 /* Transform as many times as possible. */
157 if (inputLen >= partLen) {
158 MD5_memcpy ((POINTER)&context->buffer[index], (POINTER)input, partLen);
159 MD5Transform (context->state, context->buffer);
160
161 for (i = partLen; i + 63 < inputLen; i += 64)
162 MD5Transform (context->state, &input[i]);
163
164 index = 0;
165 }
166 else
167 i = 0;
168
169 /* Buffer remaining input */
170 MD5_memcpy
171 ((POINTER)&context->buffer[index], (POINTER)&input[i],
172 inputLen-i);
173 }
174
175 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
176 the message digest and zeroizing the context.
177 */
178 void SSLMD5Final (digest, context)
179 unsigned char digest[16]; /* message digest */
180 MD5_CTX *context; /* context */
181 {
182 unsigned char bits[8];
183 unsigned int index, padLen;
184
185 /* Save number of bits */
186 Encode (bits, context->count, 8);
187
188 /* Pad out to 56 mod 64.
189 */
190 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
191 padLen = (index < 56) ? (56 - index) : (120 - index);
192 SSLMD5Update (context, PADDING, padLen);
193
194 /* Append length (before padding) */
195 SSLMD5Update (context, bits, 8);
196
197 /* Store state in digest */
198 Encode (digest, context->state, 16);
199
200 /* Zeroize sensitive information.
201 */
202 MD5_memset ((POINTER)context, 0, sizeof (*context));
203 }
204
205 /* MD5 basic transformation. Transforms state based on block.
206 */
207 static void MD5Transform (state, block)
208 UINT4 state[4];
209 const unsigned char block[64];
210 {
211 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
212
213 Decode (x, block, 64);
214
215 /* Round 1 */
216 FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
217 FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
218 FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
219 FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
220 FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
221 FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
222 FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
223 FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
224 FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
225 FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
226 FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
227 FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
228 FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
229 FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
230 FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
231 FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
232
233 /* Round 2 */
234 GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
235 GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
236 GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
237 GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
238 GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
239 GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
240 GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
241 GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
242 GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
243 GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
244 GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
245 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
246 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
247 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
248 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
249 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
250
251 /* Round 3 */
252 HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
253 HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
254 HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
255 HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
256 HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
257 HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
258 HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
259 HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
260 HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
261 HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
262 HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
263 HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
264 HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
265 HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
266 HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
267 HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
268
269 /* Round 4 */
270 II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
271 II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
272 II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
273 II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
274 II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
275 II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
276 II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
277 II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
278 II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
279 II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
280 II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
281 II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
282 II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
283 II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
284 II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
285 II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
286
287 state[0] += a;
288 state[1] += b;
289 state[2] += c;
290 state[3] += d;
291
292 /* Zeroize sensitive information. */
293 MD5_memset ((POINTER)x, 0, sizeof (x));
294 }
295
296 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
297 a multiple of 4.
298 */
299 static void Encode (output, input, len)
300 unsigned char *output;
301 UINT4 *input;
302 unsigned int len;
303 {
304 unsigned int i, j;
305
306 for (i = 0, j = 0; j < len; i++, j += 4) {
307 output[j] = (unsigned char)(input[i] & 0xff);
308 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
309 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
310 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
311 }
312 }
313
314 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
315 a multiple of 4.
316 */
317 static void Decode (output, input, len)
318 UINT4 *output;
319 const unsigned char *input;
320 unsigned int len;
321 {
322 unsigned int i, j;
323
324 for (i = 0, j = 0; j < len; i++, j += 4)
325 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
326 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
327 }
328
329 /* Note: Replace "for loop" with standard memcpy if possible.
330 */
331
332 static void MD5_memcpy (output, input, len)
333 POINTER output;
334 POINTER input;
335 unsigned int len;
336 {
337 unsigned int i;
338
339 for (i = 0; i < len; i++)
340 output[i] = input[i];
341 }
342
343 /* Note: Replace "for loop" with standard memset if possible.
344 */
345 static void MD5_memset (output, value, len)
346 POINTER output;
347 int value;
348 unsigned int len;
349 {
350 unsigned int i;
351
352 for (i = 0; i < len; i++)
353 ((char *)output)[i] = (char)value;
354 }