xref: /illumos-gate/usr/src/lib/libsasl/lib/md5.c (revision 7c478bd9)
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
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 
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 
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 
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 
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 
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 
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 
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 
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. */
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 
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 
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 
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