1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms.
4*7c478bd9Sstevel@tonic-gate */
5*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
6*7c478bd9Sstevel@tonic-gate
7*7c478bd9Sstevel@tonic-gate /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
8*7c478bd9Sstevel@tonic-gate */
9*7c478bd9Sstevel@tonic-gate
10*7c478bd9Sstevel@tonic-gate /* Function names changed to avoid namespace collisions: Rob Siemborski */
11*7c478bd9Sstevel@tonic-gate
12*7c478bd9Sstevel@tonic-gate /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13*7c478bd9Sstevel@tonic-gate rights reserved.
14*7c478bd9Sstevel@tonic-gate
15*7c478bd9Sstevel@tonic-gate License to copy and use this software is granted provided that it
16*7c478bd9Sstevel@tonic-gate is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17*7c478bd9Sstevel@tonic-gate Algorithm" in all material mentioning or referencing this software
18*7c478bd9Sstevel@tonic-gate or this function.
19*7c478bd9Sstevel@tonic-gate
20*7c478bd9Sstevel@tonic-gate License is also granted to make and use derivative works provided
21*7c478bd9Sstevel@tonic-gate that such works are identified as "derived from the RSA Data
22*7c478bd9Sstevel@tonic-gate Security, Inc. MD5 Message-Digest Algorithm" in all material
23*7c478bd9Sstevel@tonic-gate mentioning or referencing the derived work.
24*7c478bd9Sstevel@tonic-gate
25*7c478bd9Sstevel@tonic-gate RSA Data Security, Inc. makes no representations concerning either
26*7c478bd9Sstevel@tonic-gate the merchantability of this software or the suitability of this
27*7c478bd9Sstevel@tonic-gate software for any particular purpose. It is provided "as is"
28*7c478bd9Sstevel@tonic-gate without express or implied warranty of any kind.
29*7c478bd9Sstevel@tonic-gate
30*7c478bd9Sstevel@tonic-gate These notices must be retained in any copies of any part of this
31*7c478bd9Sstevel@tonic-gate documentation and/or software.
32*7c478bd9Sstevel@tonic-gate */
33*7c478bd9Sstevel@tonic-gate
34*7c478bd9Sstevel@tonic-gate #include <config.h>
35*7c478bd9Sstevel@tonic-gate #include "md5global.h"
36*7c478bd9Sstevel@tonic-gate #ifdef _HAVE_LIB_MD5
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate * If libmd5 is available, we will use it.
39*7c478bd9Sstevel@tonic-gate * sasl_hmac_md5* functions are still needed.
40*7c478bd9Sstevel@tonic-gate */
41*7c478bd9Sstevel@tonic-gate #include "md5_private.h"
42*7c478bd9Sstevel@tonic-gate #else
43*7c478bd9Sstevel@tonic-gate #include "md5.h"
44*7c478bd9Sstevel@tonic-gate #endif /* _HAVE_LIB_MD5 */
45*7c478bd9Sstevel@tonic-gate #include "hmac-md5.h"
46*7c478bd9Sstevel@tonic-gate
47*7c478bd9Sstevel@tonic-gate #ifndef WIN32
48*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
49*7c478bd9Sstevel@tonic-gate #endif
50*7c478bd9Sstevel@tonic-gate
51*7c478bd9Sstevel@tonic-gate /* Constants for MD5Transform routine.
52*7c478bd9Sstevel@tonic-gate */
53*7c478bd9Sstevel@tonic-gate
54*7c478bd9Sstevel@tonic-gate #define S11 7
55*7c478bd9Sstevel@tonic-gate #define S12 12
56*7c478bd9Sstevel@tonic-gate #define S13 17
57*7c478bd9Sstevel@tonic-gate #define S14 22
58*7c478bd9Sstevel@tonic-gate #define S21 5
59*7c478bd9Sstevel@tonic-gate #define S22 9
60*7c478bd9Sstevel@tonic-gate #define S23 14
61*7c478bd9Sstevel@tonic-gate #define S24 20
62*7c478bd9Sstevel@tonic-gate #define S31 4
63*7c478bd9Sstevel@tonic-gate #define S32 11
64*7c478bd9Sstevel@tonic-gate #define S33 16
65*7c478bd9Sstevel@tonic-gate #define S34 23
66*7c478bd9Sstevel@tonic-gate #define S41 6
67*7c478bd9Sstevel@tonic-gate #define S42 10
68*7c478bd9Sstevel@tonic-gate #define S43 15
69*7c478bd9Sstevel@tonic-gate #define S44 21
70*7c478bd9Sstevel@tonic-gate
71*7c478bd9Sstevel@tonic-gate #ifdef _HAVE_LIB_MD5
72*7c478bd9Sstevel@tonic-gate #define MD5_memcpy(s1, s2, n) memcpy(s1, s2, n)
73*7c478bd9Sstevel@tonic-gate #define MD5_memset(s1, c, n) memset(s1, c, n)
74*7c478bd9Sstevel@tonic-gate #else
75*7c478bd9Sstevel@tonic-gate static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
76*7c478bd9Sstevel@tonic-gate static void Encode PROTO_LIST
77*7c478bd9Sstevel@tonic-gate ((unsigned char *, UINT4 *, unsigned int));
78*7c478bd9Sstevel@tonic-gate static void Decode PROTO_LIST
79*7c478bd9Sstevel@tonic-gate ((UINT4 *, unsigned char *, unsigned int));
80*7c478bd9Sstevel@tonic-gate static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
81*7c478bd9Sstevel@tonic-gate static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
82*7c478bd9Sstevel@tonic-gate
83*7c478bd9Sstevel@tonic-gate static unsigned char PADDING[64] = {
84*7c478bd9Sstevel@tonic-gate 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
85*7c478bd9Sstevel@tonic-gate 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
86*7c478bd9Sstevel@tonic-gate };
87*7c478bd9Sstevel@tonic-gate #endif /* _HAVE_LIB_MD5 */
88*7c478bd9Sstevel@tonic-gate
89*7c478bd9Sstevel@tonic-gate /* F, G, H and I are basic MD5 functions.
90*7c478bd9Sstevel@tonic-gate
91*7c478bd9Sstevel@tonic-gate */
92*7c478bd9Sstevel@tonic-gate #ifdef I
93*7c478bd9Sstevel@tonic-gate /* This might be defined via NANA */
94*7c478bd9Sstevel@tonic-gate #undef I
95*7c478bd9Sstevel@tonic-gate #endif
96*7c478bd9Sstevel@tonic-gate
97*7c478bd9Sstevel@tonic-gate #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
98*7c478bd9Sstevel@tonic-gate #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
99*7c478bd9Sstevel@tonic-gate #define H(x, y, z) ((x) ^ (y) ^ (z))
100*7c478bd9Sstevel@tonic-gate #define I(x, y, z) ((y) ^ ((x) | (~z)))
101*7c478bd9Sstevel@tonic-gate
102*7c478bd9Sstevel@tonic-gate /* ROTATE_LEFT rotates x left n bits.
103*7c478bd9Sstevel@tonic-gate
104*7c478bd9Sstevel@tonic-gate */
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
107*7c478bd9Sstevel@tonic-gate
108*7c478bd9Sstevel@tonic-gate /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
109*7c478bd9Sstevel@tonic-gate Rotation is separate from addition to prevent recomputation.
110*7c478bd9Sstevel@tonic-gate */
111*7c478bd9Sstevel@tonic-gate
112*7c478bd9Sstevel@tonic-gate #define FF(a, b, c, d, x, s, ac) { (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
113*7c478bd9Sstevel@tonic-gate #define GG(a, b, c, d, x, s, ac) { (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
114*7c478bd9Sstevel@tonic-gate #define HH(a, b, c, d, x, s, ac) { (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
115*7c478bd9Sstevel@tonic-gate #define II(a, b, c, d, x, s, ac) { (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); (a) = ROTATE_LEFT ((a), (s)); (a) += (b); }
116*7c478bd9Sstevel@tonic-gate
117*7c478bd9Sstevel@tonic-gate /* MD5 initialization. Begins an MD5 operation, writing a new context.
118*7c478bd9Sstevel@tonic-gate */
119*7c478bd9Sstevel@tonic-gate
120*7c478bd9Sstevel@tonic-gate #ifndef _HAVE_LIB_MD5
_sasl_MD5Init(context)121*7c478bd9Sstevel@tonic-gate void _sasl_MD5Init (context)
122*7c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
123*7c478bd9Sstevel@tonic-gate {
124*7c478bd9Sstevel@tonic-gate context->count[0] = context->count[1] = 0;
125*7c478bd9Sstevel@tonic-gate
126*7c478bd9Sstevel@tonic-gate /* Load magic initialization constants. */
127*7c478bd9Sstevel@tonic-gate context->state[0] = 0x67452301;
128*7c478bd9Sstevel@tonic-gate context->state[1] = 0xefcdab89;
129*7c478bd9Sstevel@tonic-gate context->state[2] = 0x98badcfe;
130*7c478bd9Sstevel@tonic-gate context->state[3] = 0x10325476;
131*7c478bd9Sstevel@tonic-gate }
132*7c478bd9Sstevel@tonic-gate
133*7c478bd9Sstevel@tonic-gate /* MD5 block update operation. Continues an MD5 message-digest
134*7c478bd9Sstevel@tonic-gate operation, processing another message block, and updating the context.
135*7c478bd9Sstevel@tonic-gate */
136*7c478bd9Sstevel@tonic-gate
_sasl_MD5Update(context,input,inputLen)137*7c478bd9Sstevel@tonic-gate void _sasl_MD5Update (context, input, inputLen)
138*7c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
139*7c478bd9Sstevel@tonic-gate unsigned char *input; /* input block */
140*7c478bd9Sstevel@tonic-gate unsigned int inputLen; /* length of input block */
141*7c478bd9Sstevel@tonic-gate {
142*7c478bd9Sstevel@tonic-gate unsigned int i, index, partLen;
143*7c478bd9Sstevel@tonic-gate
144*7c478bd9Sstevel@tonic-gate /* Compute number of bytes mod 64 */
145*7c478bd9Sstevel@tonic-gate index = (unsigned int)((context->count[0] >> 3) & 0x3F);
146*7c478bd9Sstevel@tonic-gate
147*7c478bd9Sstevel@tonic-gate /* Update number of bits */
148*7c478bd9Sstevel@tonic-gate if ((context->count[0] += ((UINT4)inputLen << 3))
149*7c478bd9Sstevel@tonic-gate < ((UINT4)inputLen << 3))
150*7c478bd9Sstevel@tonic-gate context->count[1]++;
151*7c478bd9Sstevel@tonic-gate context->count[1] += ((UINT4)inputLen >> 29);
152*7c478bd9Sstevel@tonic-gate
153*7c478bd9Sstevel@tonic-gate partLen = 64 - index;
154*7c478bd9Sstevel@tonic-gate
155*7c478bd9Sstevel@tonic-gate /* Transform as many times as possible.
156*7c478bd9Sstevel@tonic-gate
157*7c478bd9Sstevel@tonic-gate */
158*7c478bd9Sstevel@tonic-gate if (inputLen >= partLen) {
159*7c478bd9Sstevel@tonic-gate MD5_memcpy
160*7c478bd9Sstevel@tonic-gate ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform
161*7c478bd9Sstevel@tonic-gate (context->state, context->buffer);
162*7c478bd9Sstevel@tonic-gate
163*7c478bd9Sstevel@tonic-gate for (i = partLen; i + 63 < inputLen; i += 64)
164*7c478bd9Sstevel@tonic-gate MD5Transform (context->state, &input[i]);
165*7c478bd9Sstevel@tonic-gate
166*7c478bd9Sstevel@tonic-gate index = 0;
167*7c478bd9Sstevel@tonic-gate }
168*7c478bd9Sstevel@tonic-gate else
169*7c478bd9Sstevel@tonic-gate i = 0;
170*7c478bd9Sstevel@tonic-gate
171*7c478bd9Sstevel@tonic-gate /* Buffer remaining input */
172*7c478bd9Sstevel@tonic-gate MD5_memcpy
173*7c478bd9Sstevel@tonic-gate ((POINTER)&context->buffer[index], (POINTER)&input[i],
174*7c478bd9Sstevel@tonic-gate inputLen-i);
175*7c478bd9Sstevel@tonic-gate
176*7c478bd9Sstevel@tonic-gate }
177*7c478bd9Sstevel@tonic-gate
178*7c478bd9Sstevel@tonic-gate /* MD5 finalization. Ends an MD5 message-digest operation, writing the
179*7c478bd9Sstevel@tonic-gate the message digest and zeroizing the context.
180*7c478bd9Sstevel@tonic-gate */
181*7c478bd9Sstevel@tonic-gate
_sasl_MD5Final(digest,context)182*7c478bd9Sstevel@tonic-gate void _sasl_MD5Final (digest, context)
183*7c478bd9Sstevel@tonic-gate unsigned char digest[16]; /* message digest */
184*7c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate unsigned char bits[8];
187*7c478bd9Sstevel@tonic-gate unsigned int index, padLen;
188*7c478bd9Sstevel@tonic-gate
189*7c478bd9Sstevel@tonic-gate /* Save number of bits */
190*7c478bd9Sstevel@tonic-gate Encode (bits, context->count, 8);
191*7c478bd9Sstevel@tonic-gate
192*7c478bd9Sstevel@tonic-gate /* Pad out to 56 mod 64. */
193*7c478bd9Sstevel@tonic-gate index = (unsigned int)((context->count[0] >> 3) & 0x3f);
194*7c478bd9Sstevel@tonic-gate padLen = (index < 56) ? (56 - index) : (120 - index);
195*7c478bd9Sstevel@tonic-gate _sasl_MD5Update (context, PADDING, padLen);
196*7c478bd9Sstevel@tonic-gate
197*7c478bd9Sstevel@tonic-gate /* Append length (before padding) */
198*7c478bd9Sstevel@tonic-gate _sasl_MD5Update (context, bits, 8);
199*7c478bd9Sstevel@tonic-gate
200*7c478bd9Sstevel@tonic-gate /* Store state in digest */
201*7c478bd9Sstevel@tonic-gate Encode (digest, context->state, 16);
202*7c478bd9Sstevel@tonic-gate
203*7c478bd9Sstevel@tonic-gate /* Zeroize sensitive information. */
204*7c478bd9Sstevel@tonic-gate MD5_memset ((POINTER)context, 0, sizeof (*context));
205*7c478bd9Sstevel@tonic-gate }
206*7c478bd9Sstevel@tonic-gate
207*7c478bd9Sstevel@tonic-gate /* MD5 basic transformation. Transforms state based on block. */
208*7c478bd9Sstevel@tonic-gate
MD5Transform(state,block)209*7c478bd9Sstevel@tonic-gate static void MD5Transform (state, block)
210*7c478bd9Sstevel@tonic-gate UINT4 state[4];
211*7c478bd9Sstevel@tonic-gate unsigned char block[64];
212*7c478bd9Sstevel@tonic-gate {
213*7c478bd9Sstevel@tonic-gate UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
214*7c478bd9Sstevel@tonic-gate
215*7c478bd9Sstevel@tonic-gate Decode (x, block, 64);
216*7c478bd9Sstevel@tonic-gate
217*7c478bd9Sstevel@tonic-gate /* Round 1 */
218*7c478bd9Sstevel@tonic-gate FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
219*7c478bd9Sstevel@tonic-gate FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
220*7c478bd9Sstevel@tonic-gate FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
221*7c478bd9Sstevel@tonic-gate FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
222*7c478bd9Sstevel@tonic-gate FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
223*7c478bd9Sstevel@tonic-gate FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
224*7c478bd9Sstevel@tonic-gate FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
225*7c478bd9Sstevel@tonic-gate FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
226*7c478bd9Sstevel@tonic-gate FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
227*7c478bd9Sstevel@tonic-gate FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
228*7c478bd9Sstevel@tonic-gate FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
229*7c478bd9Sstevel@tonic-gate FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
230*7c478bd9Sstevel@tonic-gate FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
231*7c478bd9Sstevel@tonic-gate FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
232*7c478bd9Sstevel@tonic-gate FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
233*7c478bd9Sstevel@tonic-gate FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
234*7c478bd9Sstevel@tonic-gate
235*7c478bd9Sstevel@tonic-gate /* Round 2 */
236*7c478bd9Sstevel@tonic-gate GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
237*7c478bd9Sstevel@tonic-gate GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
238*7c478bd9Sstevel@tonic-gate GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
239*7c478bd9Sstevel@tonic-gate GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
240*7c478bd9Sstevel@tonic-gate GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
241*7c478bd9Sstevel@tonic-gate GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
242*7c478bd9Sstevel@tonic-gate GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
243*7c478bd9Sstevel@tonic-gate GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
244*7c478bd9Sstevel@tonic-gate GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
245*7c478bd9Sstevel@tonic-gate GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
246*7c478bd9Sstevel@tonic-gate GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
247*7c478bd9Sstevel@tonic-gate GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
248*7c478bd9Sstevel@tonic-gate GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
249*7c478bd9Sstevel@tonic-gate GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
250*7c478bd9Sstevel@tonic-gate GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
251*7c478bd9Sstevel@tonic-gate GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
252*7c478bd9Sstevel@tonic-gate
253*7c478bd9Sstevel@tonic-gate /* Round 3 */
254*7c478bd9Sstevel@tonic-gate HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
255*7c478bd9Sstevel@tonic-gate HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
256*7c478bd9Sstevel@tonic-gate HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
257*7c478bd9Sstevel@tonic-gate HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
258*7c478bd9Sstevel@tonic-gate HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
259*7c478bd9Sstevel@tonic-gate HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
260*7c478bd9Sstevel@tonic-gate HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
261*7c478bd9Sstevel@tonic-gate HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
262*7c478bd9Sstevel@tonic-gate HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
263*7c478bd9Sstevel@tonic-gate HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
264*7c478bd9Sstevel@tonic-gate HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
265*7c478bd9Sstevel@tonic-gate HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
266*7c478bd9Sstevel@tonic-gate HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
267*7c478bd9Sstevel@tonic-gate HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
268*7c478bd9Sstevel@tonic-gate HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
269*7c478bd9Sstevel@tonic-gate HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
270*7c478bd9Sstevel@tonic-gate
271*7c478bd9Sstevel@tonic-gate /* Round 4 */
272*7c478bd9Sstevel@tonic-gate II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
273*7c478bd9Sstevel@tonic-gate II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
274*7c478bd9Sstevel@tonic-gate II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
275*7c478bd9Sstevel@tonic-gate II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
276*7c478bd9Sstevel@tonic-gate II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
277*7c478bd9Sstevel@tonic-gate II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
278*7c478bd9Sstevel@tonic-gate II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
279*7c478bd9Sstevel@tonic-gate II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
280*7c478bd9Sstevel@tonic-gate II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
281*7c478bd9Sstevel@tonic-gate II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
282*7c478bd9Sstevel@tonic-gate II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
283*7c478bd9Sstevel@tonic-gate II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
284*7c478bd9Sstevel@tonic-gate II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
285*7c478bd9Sstevel@tonic-gate II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
286*7c478bd9Sstevel@tonic-gate II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
287*7c478bd9Sstevel@tonic-gate II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
288*7c478bd9Sstevel@tonic-gate
289*7c478bd9Sstevel@tonic-gate state[0] += a;
290*7c478bd9Sstevel@tonic-gate state[1] += b;
291*7c478bd9Sstevel@tonic-gate state[2] += c;
292*7c478bd9Sstevel@tonic-gate state[3] += d;
293*7c478bd9Sstevel@tonic-gate
294*7c478bd9Sstevel@tonic-gate /* Zeroize sensitive information.
295*7c478bd9Sstevel@tonic-gate */
296*7c478bd9Sstevel@tonic-gate MD5_memset ((POINTER)x, 0, sizeof (x));
297*7c478bd9Sstevel@tonic-gate }
298*7c478bd9Sstevel@tonic-gate
299*7c478bd9Sstevel@tonic-gate /* Encodes input (UINT4) into output (unsigned char). Assumes len is
300*7c478bd9Sstevel@tonic-gate a multiple of 4.
301*7c478bd9Sstevel@tonic-gate
302*7c478bd9Sstevel@tonic-gate */
303*7c478bd9Sstevel@tonic-gate
Encode(output,input,len)304*7c478bd9Sstevel@tonic-gate static void Encode (output, input, len)
305*7c478bd9Sstevel@tonic-gate unsigned char *output;
306*7c478bd9Sstevel@tonic-gate UINT4 *input;
307*7c478bd9Sstevel@tonic-gate unsigned int len;
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate unsigned int i, j;
310*7c478bd9Sstevel@tonic-gate
311*7c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4) {
312*7c478bd9Sstevel@tonic-gate output[j] = (unsigned char)(input[i] & 0xff);
313*7c478bd9Sstevel@tonic-gate output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
314*7c478bd9Sstevel@tonic-gate output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
315*7c478bd9Sstevel@tonic-gate output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
316*7c478bd9Sstevel@tonic-gate }
317*7c478bd9Sstevel@tonic-gate }
318*7c478bd9Sstevel@tonic-gate
319*7c478bd9Sstevel@tonic-gate /* Decodes input (unsigned char) into output (UINT4). Assumes len is
320*7c478bd9Sstevel@tonic-gate a multiple of 4.
321*7c478bd9Sstevel@tonic-gate
322*7c478bd9Sstevel@tonic-gate */
323*7c478bd9Sstevel@tonic-gate
Decode(output,input,len)324*7c478bd9Sstevel@tonic-gate static void Decode (output, input, len)
325*7c478bd9Sstevel@tonic-gate UINT4 *output;
326*7c478bd9Sstevel@tonic-gate unsigned char *input;
327*7c478bd9Sstevel@tonic-gate unsigned int len;
328*7c478bd9Sstevel@tonic-gate {
329*7c478bd9Sstevel@tonic-gate unsigned int i, j;
330*7c478bd9Sstevel@tonic-gate
331*7c478bd9Sstevel@tonic-gate for (i = 0, j = 0; j < len; i++, j += 4)
332*7c478bd9Sstevel@tonic-gate output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
333*7c478bd9Sstevel@tonic-gate | (((UINT4)input[j+3]) << 24);
334*7c478bd9Sstevel@tonic-gate }
335*7c478bd9Sstevel@tonic-gate
336*7c478bd9Sstevel@tonic-gate /* Note: Replace "for loop" with standard memcpy if possible.
337*7c478bd9Sstevel@tonic-gate
338*7c478bd9Sstevel@tonic-gate */
339*7c478bd9Sstevel@tonic-gate
MD5_memcpy(output,input,len)340*7c478bd9Sstevel@tonic-gate static void MD5_memcpy (output, input, len)
341*7c478bd9Sstevel@tonic-gate POINTER output;
342*7c478bd9Sstevel@tonic-gate POINTER input;
343*7c478bd9Sstevel@tonic-gate unsigned int len;
344*7c478bd9Sstevel@tonic-gate {
345*7c478bd9Sstevel@tonic-gate unsigned int i;
346*7c478bd9Sstevel@tonic-gate
347*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++)
348*7c478bd9Sstevel@tonic-gate output[i] = input[i];
349*7c478bd9Sstevel@tonic-gate }
350*7c478bd9Sstevel@tonic-gate
351*7c478bd9Sstevel@tonic-gate /* Note: Replace "for loop" with standard memset if possible.
352*7c478bd9Sstevel@tonic-gate */
353*7c478bd9Sstevel@tonic-gate
MD5_memset(output,value,len)354*7c478bd9Sstevel@tonic-gate static void MD5_memset (output, value, len)
355*7c478bd9Sstevel@tonic-gate POINTER output;
356*7c478bd9Sstevel@tonic-gate int value;
357*7c478bd9Sstevel@tonic-gate unsigned int len;
358*7c478bd9Sstevel@tonic-gate {
359*7c478bd9Sstevel@tonic-gate unsigned int i;
360*7c478bd9Sstevel@tonic-gate
361*7c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++)
362*7c478bd9Sstevel@tonic-gate ((char *)output)[i] = (char)value;
363*7c478bd9Sstevel@tonic-gate }
364*7c478bd9Sstevel@tonic-gate #endif /* !_HAVE_LIB_MD5 */
365*7c478bd9Sstevel@tonic-gate
_sasl_hmac_md5_init(HMAC_MD5_CTX * hmac,const unsigned char * key,int key_len)366*7c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_init(HMAC_MD5_CTX *hmac,
367*7c478bd9Sstevel@tonic-gate const unsigned char *key,
368*7c478bd9Sstevel@tonic-gate int key_len)
369*7c478bd9Sstevel@tonic-gate {
370*7c478bd9Sstevel@tonic-gate unsigned char k_ipad[65]; /* inner padding -
371*7c478bd9Sstevel@tonic-gate * key XORd with ipad
372*7c478bd9Sstevel@tonic-gate */
373*7c478bd9Sstevel@tonic-gate unsigned char k_opad[65]; /* outer padding -
374*7c478bd9Sstevel@tonic-gate * key XORd with opad
375*7c478bd9Sstevel@tonic-gate */
376*7c478bd9Sstevel@tonic-gate unsigned char tk[16];
377*7c478bd9Sstevel@tonic-gate int i;
378*7c478bd9Sstevel@tonic-gate /* if key is longer than 64 bytes reset it to key=MD5(key) */
379*7c478bd9Sstevel@tonic-gate if (key_len > 64) {
380*7c478bd9Sstevel@tonic-gate
381*7c478bd9Sstevel@tonic-gate MD5_CTX tctx;
382*7c478bd9Sstevel@tonic-gate
383*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&tctx);
384*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&tctx, key, key_len);
385*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(tk, &tctx);
386*7c478bd9Sstevel@tonic-gate
387*7c478bd9Sstevel@tonic-gate key = tk;
388*7c478bd9Sstevel@tonic-gate key_len = 16;
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate
391*7c478bd9Sstevel@tonic-gate /*
392*7c478bd9Sstevel@tonic-gate * the HMAC_MD5 transform looks like:
393*7c478bd9Sstevel@tonic-gate *
394*7c478bd9Sstevel@tonic-gate * MD5(K XOR opad, MD5(K XOR ipad, text))
395*7c478bd9Sstevel@tonic-gate *
396*7c478bd9Sstevel@tonic-gate * where K is an n byte key
397*7c478bd9Sstevel@tonic-gate * ipad is the byte 0x36 repeated 64 times
398*7c478bd9Sstevel@tonic-gate * opad is the byte 0x5c repeated 64 times
399*7c478bd9Sstevel@tonic-gate * and text is the data being protected
400*7c478bd9Sstevel@tonic-gate */
401*7c478bd9Sstevel@tonic-gate
402*7c478bd9Sstevel@tonic-gate /* start out by storing key in pads */
403*7c478bd9Sstevel@tonic-gate MD5_memset(k_ipad, '\0', sizeof k_ipad);
404*7c478bd9Sstevel@tonic-gate MD5_memset(k_opad, '\0', sizeof k_opad);
405*7c478bd9Sstevel@tonic-gate MD5_memcpy( k_ipad, key, key_len);
406*7c478bd9Sstevel@tonic-gate MD5_memcpy( k_opad, key, key_len);
407*7c478bd9Sstevel@tonic-gate
408*7c478bd9Sstevel@tonic-gate /* XOR key with ipad and opad values */
409*7c478bd9Sstevel@tonic-gate for (i=0; i<64; i++) {
410*7c478bd9Sstevel@tonic-gate k_ipad[i] ^= 0x36;
411*7c478bd9Sstevel@tonic-gate k_opad[i] ^= 0x5c;
412*7c478bd9Sstevel@tonic-gate }
413*7c478bd9Sstevel@tonic-gate
414*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&hmac->ictx); /* init inner context */
415*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&hmac->ictx, k_ipad, 64); /* apply inner pad */
416*7c478bd9Sstevel@tonic-gate
417*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&hmac->octx); /* init outer context */
418*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */
419*7c478bd9Sstevel@tonic-gate
420*7c478bd9Sstevel@tonic-gate /* scrub the pads and key context (if used) */
421*7c478bd9Sstevel@tonic-gate MD5_memset(&k_ipad, 0, sizeof(k_ipad));
422*7c478bd9Sstevel@tonic-gate MD5_memset(&k_opad, 0, sizeof(k_opad));
423*7c478bd9Sstevel@tonic-gate MD5_memset(&tk, 0, sizeof(tk));
424*7c478bd9Sstevel@tonic-gate
425*7c478bd9Sstevel@tonic-gate /* and we're done. */
426*7c478bd9Sstevel@tonic-gate }
427*7c478bd9Sstevel@tonic-gate
428*7c478bd9Sstevel@tonic-gate /* The precalc and import routines here rely on the fact that we pad
429*7c478bd9Sstevel@tonic-gate * the key out to 64 bytes and use that to initialize the md5
430*7c478bd9Sstevel@tonic-gate * contexts, and that updating an md5 context with 64 bytes of data
431*7c478bd9Sstevel@tonic-gate * leaves nothing left over; all of the interesting state is contained
432*7c478bd9Sstevel@tonic-gate * in the state field, and none of it is left over in the count and
433*7c478bd9Sstevel@tonic-gate * buffer fields. So all we have to do is save the state field; we
434*7c478bd9Sstevel@tonic-gate * can zero the others when we reload it. Which is why the decision
435*7c478bd9Sstevel@tonic-gate * was made to pad the key out to 64 bytes in the first place. */
_sasl_hmac_md5_precalc(HMAC_MD5_STATE * state,const unsigned char * key,int key_len)436*7c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_precalc(HMAC_MD5_STATE *state,
437*7c478bd9Sstevel@tonic-gate const unsigned char *key,
438*7c478bd9Sstevel@tonic-gate int key_len)
439*7c478bd9Sstevel@tonic-gate {
440*7c478bd9Sstevel@tonic-gate HMAC_MD5_CTX hmac;
441*7c478bd9Sstevel@tonic-gate unsigned lupe;
442*7c478bd9Sstevel@tonic-gate
443*7c478bd9Sstevel@tonic-gate _sasl_hmac_md5_init(&hmac, key, key_len);
444*7c478bd9Sstevel@tonic-gate for (lupe = 0; lupe < 4; lupe++) {
445*7c478bd9Sstevel@tonic-gate state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
446*7c478bd9Sstevel@tonic-gate state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
447*7c478bd9Sstevel@tonic-gate }
448*7c478bd9Sstevel@tonic-gate MD5_memset(&hmac, 0, sizeof(hmac));
449*7c478bd9Sstevel@tonic-gate }
450*7c478bd9Sstevel@tonic-gate
451*7c478bd9Sstevel@tonic-gate
_sasl_hmac_md5_import(HMAC_MD5_CTX * hmac,HMAC_MD5_STATE * state)452*7c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_import(HMAC_MD5_CTX *hmac,
453*7c478bd9Sstevel@tonic-gate HMAC_MD5_STATE *state)
454*7c478bd9Sstevel@tonic-gate {
455*7c478bd9Sstevel@tonic-gate unsigned lupe;
456*7c478bd9Sstevel@tonic-gate MD5_memset(hmac, 0, sizeof(HMAC_MD5_CTX));
457*7c478bd9Sstevel@tonic-gate for (lupe = 0; lupe < 4; lupe++) {
458*7c478bd9Sstevel@tonic-gate hmac->ictx.state[lupe] = ntohl(state->istate[lupe]);
459*7c478bd9Sstevel@tonic-gate hmac->octx.state[lupe] = ntohl(state->ostate[lupe]);
460*7c478bd9Sstevel@tonic-gate }
461*7c478bd9Sstevel@tonic-gate /* Init the counts to account for our having applied
462*7c478bd9Sstevel@tonic-gate * 64 bytes of key; this works out to 0x200 (64 << 3; see
463*7c478bd9Sstevel@tonic-gate * MD5Update above...) */
464*7c478bd9Sstevel@tonic-gate hmac->ictx.count[0] = hmac->octx.count[0] = 0x200;
465*7c478bd9Sstevel@tonic-gate }
466*7c478bd9Sstevel@tonic-gate
_sasl_hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],HMAC_MD5_CTX * hmac)467*7c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
468*7c478bd9Sstevel@tonic-gate HMAC_MD5_CTX *hmac)
469*7c478bd9Sstevel@tonic-gate {
470*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(digest, &hmac->ictx); /* Finalize inner md5 */
471*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */
472*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(digest, &hmac->octx); /* Finalize outer md5 */
473*7c478bd9Sstevel@tonic-gate }
474*7c478bd9Sstevel@tonic-gate
475*7c478bd9Sstevel@tonic-gate
_sasl_hmac_md5(text,text_len,key,key_len,digest)476*7c478bd9Sstevel@tonic-gate void _sasl_hmac_md5(text, text_len, key, key_len, digest)
477*7c478bd9Sstevel@tonic-gate const unsigned char* text; /* pointer to data stream */
478*7c478bd9Sstevel@tonic-gate int text_len; /* length of data stream */
479*7c478bd9Sstevel@tonic-gate const unsigned char* key; /* pointer to authentication key */
480*7c478bd9Sstevel@tonic-gate int key_len; /* length of authentication key */
481*7c478bd9Sstevel@tonic-gate unsigned char *digest; /* caller digest to be filled in */
482*7c478bd9Sstevel@tonic-gate {
483*7c478bd9Sstevel@tonic-gate MD5_CTX context;
484*7c478bd9Sstevel@tonic-gate
485*7c478bd9Sstevel@tonic-gate unsigned char k_ipad[65]; /* inner padding -
486*7c478bd9Sstevel@tonic-gate * key XORd with ipad
487*7c478bd9Sstevel@tonic-gate */
488*7c478bd9Sstevel@tonic-gate unsigned char k_opad[65]; /* outer padding -
489*7c478bd9Sstevel@tonic-gate * key XORd with opad
490*7c478bd9Sstevel@tonic-gate */
491*7c478bd9Sstevel@tonic-gate unsigned char tk[16];
492*7c478bd9Sstevel@tonic-gate int i;
493*7c478bd9Sstevel@tonic-gate /* if key is longer than 64 bytes reset it to key=MD5(key) */
494*7c478bd9Sstevel@tonic-gate if (key_len > 64) {
495*7c478bd9Sstevel@tonic-gate
496*7c478bd9Sstevel@tonic-gate MD5_CTX tctx;
497*7c478bd9Sstevel@tonic-gate
498*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&tctx);
499*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&tctx, key, key_len);
500*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(tk, &tctx);
501*7c478bd9Sstevel@tonic-gate
502*7c478bd9Sstevel@tonic-gate key = tk;
503*7c478bd9Sstevel@tonic-gate key_len = 16;
504*7c478bd9Sstevel@tonic-gate }
505*7c478bd9Sstevel@tonic-gate
506*7c478bd9Sstevel@tonic-gate /*
507*7c478bd9Sstevel@tonic-gate * the HMAC_MD5 transform looks like:
508*7c478bd9Sstevel@tonic-gate *
509*7c478bd9Sstevel@tonic-gate * MD5(K XOR opad, MD5(K XOR ipad, text))
510*7c478bd9Sstevel@tonic-gate *
511*7c478bd9Sstevel@tonic-gate * where K is an n byte key
512*7c478bd9Sstevel@tonic-gate * ipad is the byte 0x36 repeated 64 times
513*7c478bd9Sstevel@tonic-gate * opad is the byte 0x5c repeated 64 times
514*7c478bd9Sstevel@tonic-gate * and text is the data being protected
515*7c478bd9Sstevel@tonic-gate */
516*7c478bd9Sstevel@tonic-gate
517*7c478bd9Sstevel@tonic-gate /* start out by storing key in pads */
518*7c478bd9Sstevel@tonic-gate MD5_memset(k_ipad, '\0', sizeof k_ipad);
519*7c478bd9Sstevel@tonic-gate MD5_memset(k_opad, '\0', sizeof k_opad);
520*7c478bd9Sstevel@tonic-gate MD5_memcpy( k_ipad, key, key_len);
521*7c478bd9Sstevel@tonic-gate MD5_memcpy( k_opad, key, key_len);
522*7c478bd9Sstevel@tonic-gate
523*7c478bd9Sstevel@tonic-gate /* XOR key with ipad and opad values */
524*7c478bd9Sstevel@tonic-gate for (i=0; i<64; i++) {
525*7c478bd9Sstevel@tonic-gate k_ipad[i] ^= 0x36;
526*7c478bd9Sstevel@tonic-gate k_opad[i] ^= 0x5c;
527*7c478bd9Sstevel@tonic-gate }
528*7c478bd9Sstevel@tonic-gate /*
529*7c478bd9Sstevel@tonic-gate * perform inner MD5
530*7c478bd9Sstevel@tonic-gate */
531*7c478bd9Sstevel@tonic-gate
532*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&context); /* init context for 1st
533*7c478bd9Sstevel@tonic-gate * pass */
534*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&context, k_ipad, 64); /* start with inner pad */
535*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&context, text, text_len); /* then text of datagram */
536*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(digest, &context); /* finish up 1st pass */
537*7c478bd9Sstevel@tonic-gate
538*7c478bd9Sstevel@tonic-gate /*
539*7c478bd9Sstevel@tonic-gate * perform outer MD5
540*7c478bd9Sstevel@tonic-gate */
541*7c478bd9Sstevel@tonic-gate _sasl_MD5Init(&context); /* init context for 2nd
542*7c478bd9Sstevel@tonic-gate * pass */
543*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&context, k_opad, 64); /* start with outer pad */
544*7c478bd9Sstevel@tonic-gate _sasl_MD5Update(&context, digest, 16); /* then results of 1st
545*7c478bd9Sstevel@tonic-gate * hash */
546*7c478bd9Sstevel@tonic-gate _sasl_MD5Final(digest, &context); /* finish up 2nd pass */
547*7c478bd9Sstevel@tonic-gate
548*7c478bd9Sstevel@tonic-gate }
549