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