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