]>
git.saurik.com Git - apple/security.git/blob - SecureTransport/sslmd5.c
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
19 /* sslmd5.c - RSA Data Security, Inc., MD5 message-digest algorithm
22 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
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
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.
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.
40 These notices must be retained in any copies of any part of this
41 documentation and/or software.
53 /* Constants for MD5Transform routine.
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));
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
86 /* F, G, H and I are basic MD5 functions.
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)))
93 /* ROTATE_LEFT rotates x left n bits.
95 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
97 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
98 Rotation is separate from addition to prevent recomputation.
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)); \
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)); \
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)); \
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)); \
121 /* MD5 initialization. Begins an MD5 operation, writing a new context.
123 void SSLMD5Init (context
)
124 MD5_CTX
*context
; /* context */
126 context
->count
[0] = context
->count
[1] = 0;
127 /* Load magic initialization constants.
129 context
->state
[0] = 0x67452301;
130 context
->state
[1] = 0xefcdab89;
131 context
->state
[2] = 0x98badcfe;
132 context
->state
[3] = 0x10325476;
135 /* MD5 block update operation. Continues an MD5 message-digest
136 operation, processing another message block, and updating the
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 */
144 unsigned int i
, index
, partLen
;
146 /* Compute number of bytes mod 64 */
147 index
= (unsigned int)((context
->count
[0] >> 3) & 0x3F);
149 /* Update number of bits */
150 if ((context
->count
[0] += ((UINT4
)inputLen
<< 3)) < ((UINT4
)inputLen
<< 3))
152 context
->count
[1] += ((UINT4
)inputLen
>> 29);
154 partLen
= 64 - index
;
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
);
161 for (i
= partLen
; i
+ 63 < inputLen
; i
+= 64)
162 MD5Transform (context
->state
, &input
[i
]);
169 /* Buffer remaining input */
171 ((POINTER
)&context
->buffer
[index
], (POINTER
)&input
[i
],
175 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
176 the message digest and zeroizing the context.
178 void SSLMD5Final (digest
, context
)
179 unsigned char digest
[16]; /* message digest */
180 MD5_CTX
*context
; /* context */
182 unsigned char bits
[8];
183 unsigned int index
, padLen
;
185 /* Save number of bits */
186 Encode (bits
, context
->count
, 8);
188 /* Pad out to 56 mod 64.
190 index
= (unsigned int)((context
->count
[0] >> 3) & 0x3f);
191 padLen
= (index
< 56) ? (56 - index
) : (120 - index
);
192 SSLMD5Update (context
, PADDING
, padLen
);
194 /* Append length (before padding) */
195 SSLMD5Update (context
, bits
, 8);
197 /* Store state in digest */
198 Encode (digest
, context
->state
, 16);
200 /* Zeroize sensitive information.
202 MD5_memset ((POINTER
)context
, 0, sizeof (*context
));
205 /* MD5 basic transformation. Transforms state based on block.
207 static void MD5Transform (state
, block
)
209 const unsigned char block
[64];
211 UINT4 a
= state
[0], b
= state
[1], c
= state
[2], d
= state
[3], x
[16];
213 Decode (x
, block
, 64);
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 */
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 */
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 */
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 */
292 /* Zeroize sensitive information. */
293 MD5_memset ((POINTER
)x
, 0, sizeof (x
));
296 /* Encodes input (UINT4) into output (unsigned char). Assumes len is
299 static void Encode (output
, input
, len
)
300 unsigned char *output
;
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);
314 /* Decodes input (unsigned char) into output (UINT4). Assumes len is
317 static void Decode (output
, input
, len
)
319 const unsigned char *input
;
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);
329 /* Note: Replace "for loop" with standard memcpy if possible.
332 static void MD5_memcpy (output
, input
, len
)
339 for (i
= 0; i
< len
; i
++)
340 output
[i
] = input
[i
];
343 /* Note: Replace "for loop" with standard memset if possible.
345 static void MD5_memset (output
, value
, len
)
352 for (i
= 0; i
< len
; i
++)
353 ((char *)output
)[i
] = (char)value
;