xref: /illumos-gate/usr/src/lib/libsasl/lib/md5.c (revision 1da57d55)
1*1da57d55SToomas Soome /*
27c478bd9Sstevel@tonic-gate  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /* Function names changed to avoid namespace collisions: Rob Siemborski */
107c478bd9Sstevel@tonic-gate 
117c478bd9Sstevel@tonic-gate /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
127c478bd9Sstevel@tonic-gate rights reserved.
137c478bd9Sstevel@tonic-gate 
147c478bd9Sstevel@tonic-gate License to copy and use this software is granted provided that it
157c478bd9Sstevel@tonic-gate is identified as the "RSA Data Security, Inc. MD5 Message-Digest
167c478bd9Sstevel@tonic-gate Algorithm" in all material mentioning or referencing this software
177c478bd9Sstevel@tonic-gate or this function.
187c478bd9Sstevel@tonic-gate 
197c478bd9Sstevel@tonic-gate License is also granted to make and use derivative works provided
207c478bd9Sstevel@tonic-gate that such works are identified as "derived from the RSA Data
217c478bd9Sstevel@tonic-gate Security, Inc. MD5 Message-Digest Algorithm" in all material
227c478bd9Sstevel@tonic-gate mentioning or referencing the derived work.
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate RSA Data Security, Inc. makes no representations concerning either
257c478bd9Sstevel@tonic-gate the merchantability of this software or the suitability of this
267c478bd9Sstevel@tonic-gate software for any particular purpose. It is provided "as is"
277c478bd9Sstevel@tonic-gate without express or implied warranty of any kind.
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate These notices must be retained in any copies of any part of this
307c478bd9Sstevel@tonic-gate documentation and/or software.
317c478bd9Sstevel@tonic-gate */
327c478bd9Sstevel@tonic-gate 
337c478bd9Sstevel@tonic-gate #include <config.h>
347c478bd9Sstevel@tonic-gate #include "md5global.h"
357c478bd9Sstevel@tonic-gate #ifdef _HAVE_LIB_MD5
367c478bd9Sstevel@tonic-gate /*
377c478bd9Sstevel@tonic-gate  * If libmd5 is available, we will use it.
387c478bd9Sstevel@tonic-gate  * sasl_hmac_md5* functions are still needed.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate #include "md5_private.h"
417c478bd9Sstevel@tonic-gate #else
427c478bd9Sstevel@tonic-gate #include "md5.h"
437c478bd9Sstevel@tonic-gate #endif /* _HAVE_LIB_MD5 */
447c478bd9Sstevel@tonic-gate #include "hmac-md5.h"
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #ifndef WIN32
477c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /* Constants for MD5Transform routine.
517c478bd9Sstevel@tonic-gate */
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #define S11 7
547c478bd9Sstevel@tonic-gate #define S12 12
557c478bd9Sstevel@tonic-gate #define S13 17
567c478bd9Sstevel@tonic-gate #define S14 22
577c478bd9Sstevel@tonic-gate #define S21 5
587c478bd9Sstevel@tonic-gate #define S22 9
597c478bd9Sstevel@tonic-gate #define S23 14
607c478bd9Sstevel@tonic-gate #define S24 20
617c478bd9Sstevel@tonic-gate #define S31 4
627c478bd9Sstevel@tonic-gate #define S32 11
637c478bd9Sstevel@tonic-gate #define S33 16
647c478bd9Sstevel@tonic-gate #define S34 23
657c478bd9Sstevel@tonic-gate #define S41 6
667c478bd9Sstevel@tonic-gate #define S42 10
677c478bd9Sstevel@tonic-gate #define S43 15
687c478bd9Sstevel@tonic-gate #define S44 21
697c478bd9Sstevel@tonic-gate 
707c478bd9Sstevel@tonic-gate #ifdef _HAVE_LIB_MD5
717c478bd9Sstevel@tonic-gate #define MD5_memcpy(s1, s2, n) memcpy(s1, s2, n)
727c478bd9Sstevel@tonic-gate #define MD5_memset(s1, c, n) memset(s1, c, n)
737c478bd9Sstevel@tonic-gate #else
747c478bd9Sstevel@tonic-gate static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
757c478bd9Sstevel@tonic-gate static void Encode PROTO_LIST
76*1da57d55SToomas Soome        ((unsigned char *, UINT4 *, unsigned int));
777c478bd9Sstevel@tonic-gate static void Decode PROTO_LIST
78*1da57d55SToomas Soome        ((UINT4 *, unsigned char *, unsigned int));
797c478bd9Sstevel@tonic-gate static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
807c478bd9Sstevel@tonic-gate static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate static unsigned char PADDING[64] = {
837c478bd9Sstevel@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*1da57d55SToomas Soome        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
857c478bd9Sstevel@tonic-gate };
867c478bd9Sstevel@tonic-gate #endif /* _HAVE_LIB_MD5 */
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate /* F, G, H and I are basic MD5 functions.
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate         */
917c478bd9Sstevel@tonic-gate #ifdef I
927c478bd9Sstevel@tonic-gate /* This might be defined via NANA */
937c478bd9Sstevel@tonic-gate #undef I
947c478bd9Sstevel@tonic-gate #endif
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
977c478bd9Sstevel@tonic-gate #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
987c478bd9Sstevel@tonic-gate #define H(x, y, z) ((x) ^ (y) ^ (z))
997c478bd9Sstevel@tonic-gate #define I(x, y, z) ((y) ^ ((x) | (~z)))
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /* ROTATE_LEFT rotates x left n bits.
1027c478bd9Sstevel@tonic-gate 
1037c478bd9Sstevel@tonic-gate         */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
1087c478bd9Sstevel@tonic-gate Rotation is separate from addition to prevent recomputation.
1097c478bd9Sstevel@tonic-gate */
1107c478bd9Sstevel@tonic-gate 
111*1da57d55SToomas Soome #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*1da57d55SToomas Soome #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*1da57d55SToomas Soome #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*1da57d55SToomas Soome #define II(a, b, c, d, x, s, ac) {        (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac);        (a) = ROTATE_LEFT ((a), (s));        (a) += (b);        }
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate /* MD5 initialization. Begins an MD5 operation, writing a new context.
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate #ifndef _HAVE_LIB_MD5
_sasl_MD5Init(context)1207c478bd9Sstevel@tonic-gate void _sasl_MD5Init (context)
1217c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
1227c478bd9Sstevel@tonic-gate {
123*1da57d55SToomas Soome        context->count[0] = context->count[1] = 0;
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate        /* Load magic initialization constants. */
126*1da57d55SToomas Soome        context->state[0] = 0x67452301;
127*1da57d55SToomas Soome        context->state[1] = 0xefcdab89;
128*1da57d55SToomas Soome        context->state[2] = 0x98badcfe;
129*1da57d55SToomas Soome        context->state[3] = 0x10325476;
1307c478bd9Sstevel@tonic-gate }
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate /* MD5 block update operation. Continues an MD5 message-digest
133*1da57d55SToomas Soome        operation, processing another message block, and updating the context.
1347c478bd9Sstevel@tonic-gate */
1357c478bd9Sstevel@tonic-gate 
_sasl_MD5Update(context,input,inputLen)1367c478bd9Sstevel@tonic-gate void _sasl_MD5Update (context, input, inputLen)
1377c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
1387c478bd9Sstevel@tonic-gate unsigned char *input; /* input block */
1397c478bd9Sstevel@tonic-gate unsigned int inputLen; /* length of input block */
1407c478bd9Sstevel@tonic-gate {
141*1da57d55SToomas Soome        unsigned int i, index, partLen;
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate          /* Compute number of bytes mod 64 */
1447c478bd9Sstevel@tonic-gate          index = (unsigned int)((context->count[0] >> 3) & 0x3F);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate          /* Update number of bits */
1477c478bd9Sstevel@tonic-gate          if ((context->count[0] += ((UINT4)inputLen << 3))
1487c478bd9Sstevel@tonic-gate           < ((UINT4)inputLen << 3))
1497c478bd9Sstevel@tonic-gate         context->count[1]++;
1507c478bd9Sstevel@tonic-gate          context->count[1] += ((UINT4)inputLen >> 29);
1517c478bd9Sstevel@tonic-gate 
152*1da57d55SToomas Soome        partLen = 64 - index;
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate          /* Transform as many times as possible.
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate */
157*1da57d55SToomas Soome        if (inputLen >= partLen) {
158*1da57d55SToomas Soome        MD5_memcpy
1597c478bd9Sstevel@tonic-gate        ((POINTER)&context->buffer[index], (POINTER)input, partLen); MD5Transform
160*1da57d55SToomas Soome        (context->state, context->buffer);
1617c478bd9Sstevel@tonic-gate 
162*1da57d55SToomas Soome        for (i = partLen; i + 63 < inputLen; i += 64)
163*1da57d55SToomas Soome        MD5Transform (context->state, &input[i]);
1647c478bd9Sstevel@tonic-gate 
165*1da57d55SToomas Soome        index = 0;
166*1da57d55SToomas Soome        }
167*1da57d55SToomas Soome        else
168*1da57d55SToomas Soome        i = 0;
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate          /* Buffer remaining input */
1717c478bd9Sstevel@tonic-gate          MD5_memcpy
1727c478bd9Sstevel@tonic-gate         ((POINTER)&context->buffer[index], (POINTER)&input[i],
1737c478bd9Sstevel@tonic-gate          inputLen-i);
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate 
1777c478bd9Sstevel@tonic-gate /* MD5 finalization. Ends an MD5 message-digest operation, writing the
178*1da57d55SToomas Soome        the message digest and zeroizing the context.
1797c478bd9Sstevel@tonic-gate */
1807c478bd9Sstevel@tonic-gate 
_sasl_MD5Final(digest,context)1817c478bd9Sstevel@tonic-gate void _sasl_MD5Final (digest, context)
1827c478bd9Sstevel@tonic-gate unsigned char digest[16]; /* message digest */
1837c478bd9Sstevel@tonic-gate MD5_CTX *context; /* context */
1847c478bd9Sstevel@tonic-gate {
185*1da57d55SToomas Soome        unsigned char bits[8];
186*1da57d55SToomas Soome        unsigned int index, padLen;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate          /* Save number of bits */
1897c478bd9Sstevel@tonic-gate          Encode (bits, context->count, 8);
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate          /* Pad out to 56 mod 64. */
192*1da57d55SToomas Soome 	 index = (unsigned int)((context->count[0] >> 3) & 0x3f);
193*1da57d55SToomas Soome 	 padLen = (index < 56) ? (56 - index) : (120 - index);
194*1da57d55SToomas Soome 	 _sasl_MD5Update (context, PADDING, padLen);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate          /* Append length (before padding) */
1977c478bd9Sstevel@tonic-gate          _sasl_MD5Update (context, bits, 8);
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate          /* Store state in digest */
2007c478bd9Sstevel@tonic-gate          Encode (digest, context->state, 16);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate          /* Zeroize sensitive information. */
203*1da57d55SToomas Soome        MD5_memset ((POINTER)context, 0, sizeof (*context));
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate /* MD5 basic transformation. Transforms state based on block. */
2077c478bd9Sstevel@tonic-gate 
MD5Transform(state,block)2087c478bd9Sstevel@tonic-gate static void MD5Transform (state, block)
2097c478bd9Sstevel@tonic-gate UINT4 state[4];
2107c478bd9Sstevel@tonic-gate unsigned char block[64];
2117c478bd9Sstevel@tonic-gate {
212*1da57d55SToomas Soome        UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
2137c478bd9Sstevel@tonic-gate 
214*1da57d55SToomas Soome        Decode (x, block, 64);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate          /* Round 1 */
2177c478bd9Sstevel@tonic-gate          FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
2187c478bd9Sstevel@tonic-gate          FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
2197c478bd9Sstevel@tonic-gate          FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
2207c478bd9Sstevel@tonic-gate          FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
2217c478bd9Sstevel@tonic-gate          FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
2227c478bd9Sstevel@tonic-gate          FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
2237c478bd9Sstevel@tonic-gate          FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
2247c478bd9Sstevel@tonic-gate          FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
2257c478bd9Sstevel@tonic-gate          FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
2267c478bd9Sstevel@tonic-gate          FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
2277c478bd9Sstevel@tonic-gate          FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
2287c478bd9Sstevel@tonic-gate          FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
2297c478bd9Sstevel@tonic-gate          FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
2307c478bd9Sstevel@tonic-gate          FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
2317c478bd9Sstevel@tonic-gate          FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
2327c478bd9Sstevel@tonic-gate          FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate         /* Round 2 */
2357c478bd9Sstevel@tonic-gate          GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
2367c478bd9Sstevel@tonic-gate          GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
2377c478bd9Sstevel@tonic-gate          GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
2387c478bd9Sstevel@tonic-gate          GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
2397c478bd9Sstevel@tonic-gate          GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
2407c478bd9Sstevel@tonic-gate          GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
2417c478bd9Sstevel@tonic-gate          GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
2427c478bd9Sstevel@tonic-gate          GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
2437c478bd9Sstevel@tonic-gate          GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
2447c478bd9Sstevel@tonic-gate          GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
2457c478bd9Sstevel@tonic-gate          GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
246*1da57d55SToomas Soome 	 GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
247*1da57d55SToomas Soome 	 GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
248*1da57d55SToomas Soome 	 GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
249*1da57d55SToomas Soome 	 GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
250*1da57d55SToomas Soome 	 GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate          /* Round 3 */
2537c478bd9Sstevel@tonic-gate          HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
2547c478bd9Sstevel@tonic-gate          HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
2557c478bd9Sstevel@tonic-gate          HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
2567c478bd9Sstevel@tonic-gate          HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
2577c478bd9Sstevel@tonic-gate          HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
2587c478bd9Sstevel@tonic-gate          HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
2597c478bd9Sstevel@tonic-gate          HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
2607c478bd9Sstevel@tonic-gate          HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
2617c478bd9Sstevel@tonic-gate          HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
2627c478bd9Sstevel@tonic-gate          HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
2637c478bd9Sstevel@tonic-gate          HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
2647c478bd9Sstevel@tonic-gate          HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
2657c478bd9Sstevel@tonic-gate          HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
2667c478bd9Sstevel@tonic-gate          HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
2677c478bd9Sstevel@tonic-gate          HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
2687c478bd9Sstevel@tonic-gate          HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate          /* Round 4 */
2717c478bd9Sstevel@tonic-gate          II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
2727c478bd9Sstevel@tonic-gate          II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
2737c478bd9Sstevel@tonic-gate          II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
2747c478bd9Sstevel@tonic-gate          II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
2757c478bd9Sstevel@tonic-gate          II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
2767c478bd9Sstevel@tonic-gate          II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
2777c478bd9Sstevel@tonic-gate          II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
2787c478bd9Sstevel@tonic-gate          II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
2797c478bd9Sstevel@tonic-gate          II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
2807c478bd9Sstevel@tonic-gate          II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
2817c478bd9Sstevel@tonic-gate          II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
2827c478bd9Sstevel@tonic-gate          II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
2837c478bd9Sstevel@tonic-gate          II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
2847c478bd9Sstevel@tonic-gate          II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
2857c478bd9Sstevel@tonic-gate          II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
2867c478bd9Sstevel@tonic-gate          II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
2877c478bd9Sstevel@tonic-gate 
288*1da57d55SToomas Soome        state[0] += a;
289*1da57d55SToomas Soome        state[1] += b;
290*1da57d55SToomas Soome        state[2] += c;
291*1da57d55SToomas Soome        state[3] += d;
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate          /* Zeroize sensitive information.
2947c478bd9Sstevel@tonic-gate 	 */
295*1da57d55SToomas Soome        MD5_memset ((POINTER)x, 0, sizeof (x));
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate /* Encodes input (UINT4) into output (unsigned char). Assumes len is
299*1da57d55SToomas Soome        a multiple of 4.
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate         */
3027c478bd9Sstevel@tonic-gate 
Encode(output,input,len)3037c478bd9Sstevel@tonic-gate static void Encode (output, input, len)
3047c478bd9Sstevel@tonic-gate unsigned char *output;
3057c478bd9Sstevel@tonic-gate UINT4 *input;
3067c478bd9Sstevel@tonic-gate unsigned int len;
3077c478bd9Sstevel@tonic-gate {
308*1da57d55SToomas Soome        unsigned int i, j;
309*1da57d55SToomas Soome 
310*1da57d55SToomas Soome        for (i = 0, j = 0; j < len; i++, j += 4) {
311*1da57d55SToomas Soome        output[j] = (unsigned char)(input[i] & 0xff);
312*1da57d55SToomas Soome        output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
313*1da57d55SToomas Soome        output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
314*1da57d55SToomas Soome        output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
315*1da57d55SToomas Soome        }
3167c478bd9Sstevel@tonic-gate }
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate /* Decodes input (unsigned char) into output (UINT4). Assumes len is
319*1da57d55SToomas Soome        a multiple of 4.
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate         */
3227c478bd9Sstevel@tonic-gate 
Decode(output,input,len)3237c478bd9Sstevel@tonic-gate static void Decode (output, input, len)
3247c478bd9Sstevel@tonic-gate UINT4 *output;
3257c478bd9Sstevel@tonic-gate unsigned char *input;
3267c478bd9Sstevel@tonic-gate unsigned int len;
3277c478bd9Sstevel@tonic-gate {
328*1da57d55SToomas Soome        unsigned int i, j;
3297c478bd9Sstevel@tonic-gate 
330*1da57d55SToomas Soome        for (i = 0, j = 0; j < len; i++, j += 4)
3317c478bd9Sstevel@tonic-gate        output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | (((UINT4)input[j+2]) << 16)
332*1da57d55SToomas Soome        | (((UINT4)input[j+3]) << 24);
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate /* Note: Replace "for loop" with standard memcpy if possible.
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate         */
3387c478bd9Sstevel@tonic-gate 
MD5_memcpy(output,input,len)3397c478bd9Sstevel@tonic-gate static void MD5_memcpy (output, input, len)
3407c478bd9Sstevel@tonic-gate POINTER output;
3417c478bd9Sstevel@tonic-gate POINTER input;
3427c478bd9Sstevel@tonic-gate unsigned int len;
3437c478bd9Sstevel@tonic-gate {
344*1da57d55SToomas Soome        unsigned int i;
3457c478bd9Sstevel@tonic-gate 
346*1da57d55SToomas Soome        for (i = 0; i < len; i++)
347*1da57d55SToomas Soome 	      output[i] = input[i];
3487c478bd9Sstevel@tonic-gate }
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate /* Note: Replace "for loop" with standard memset if possible.
3517c478bd9Sstevel@tonic-gate */
3527c478bd9Sstevel@tonic-gate 
MD5_memset(output,value,len)3537c478bd9Sstevel@tonic-gate static void MD5_memset (output, value, len)
3547c478bd9Sstevel@tonic-gate POINTER output;
3557c478bd9Sstevel@tonic-gate int value;
3567c478bd9Sstevel@tonic-gate unsigned int len;
3577c478bd9Sstevel@tonic-gate {
358*1da57d55SToomas Soome        unsigned int i;
3597c478bd9Sstevel@tonic-gate 
360*1da57d55SToomas Soome        for (i = 0; i < len; i++)
361*1da57d55SToomas Soome        ((char *)output)[i] = (char)value;
3627c478bd9Sstevel@tonic-gate }
3637c478bd9Sstevel@tonic-gate #endif /* !_HAVE_LIB_MD5 */
3647c478bd9Sstevel@tonic-gate 
_sasl_hmac_md5_init(HMAC_MD5_CTX * hmac,const unsigned char * key,int key_len)3657c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_init(HMAC_MD5_CTX *hmac,
3667c478bd9Sstevel@tonic-gate 			 const unsigned char *key,
3677c478bd9Sstevel@tonic-gate 			 int key_len)
3687c478bd9Sstevel@tonic-gate {
3697c478bd9Sstevel@tonic-gate   unsigned char k_ipad[65];    /* inner padding -
3707c478bd9Sstevel@tonic-gate 				* key XORd with ipad
3717c478bd9Sstevel@tonic-gate 				*/
3727c478bd9Sstevel@tonic-gate   unsigned char k_opad[65];    /* outer padding -
3737c478bd9Sstevel@tonic-gate 				* key XORd with opad
3747c478bd9Sstevel@tonic-gate 				*/
3757c478bd9Sstevel@tonic-gate   unsigned char tk[16];
3767c478bd9Sstevel@tonic-gate   int i;
3777c478bd9Sstevel@tonic-gate   /* if key is longer than 64 bytes reset it to key=MD5(key) */
3787c478bd9Sstevel@tonic-gate   if (key_len > 64) {
379*1da57d55SToomas Soome 
3807c478bd9Sstevel@tonic-gate     MD5_CTX      tctx;
3817c478bd9Sstevel@tonic-gate 
382*1da57d55SToomas Soome     _sasl_MD5Init(&tctx);
383*1da57d55SToomas Soome     _sasl_MD5Update(&tctx, key, key_len);
384*1da57d55SToomas Soome     _sasl_MD5Final(tk, &tctx);
3857c478bd9Sstevel@tonic-gate 
386*1da57d55SToomas Soome     key = tk;
387*1da57d55SToomas Soome     key_len = 16;
388*1da57d55SToomas Soome   }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate   /*
3917c478bd9Sstevel@tonic-gate    * the HMAC_MD5 transform looks like:
3927c478bd9Sstevel@tonic-gate    *
3937c478bd9Sstevel@tonic-gate    * MD5(K XOR opad, MD5(K XOR ipad, text))
3947c478bd9Sstevel@tonic-gate    *
3957c478bd9Sstevel@tonic-gate    * where K is an n byte key
3967c478bd9Sstevel@tonic-gate    * ipad is the byte 0x36 repeated 64 times
3977c478bd9Sstevel@tonic-gate    * opad is the byte 0x5c repeated 64 times
3987c478bd9Sstevel@tonic-gate    * and text is the data being protected
3997c478bd9Sstevel@tonic-gate    */
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate   /* start out by storing key in pads */
4027c478bd9Sstevel@tonic-gate   MD5_memset(k_ipad, '\0', sizeof k_ipad);
4037c478bd9Sstevel@tonic-gate   MD5_memset(k_opad, '\0', sizeof k_opad);
4047c478bd9Sstevel@tonic-gate   MD5_memcpy( k_ipad, key, key_len);
4057c478bd9Sstevel@tonic-gate   MD5_memcpy( k_opad, key, key_len);
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate   /* XOR key with ipad and opad values */
4087c478bd9Sstevel@tonic-gate   for (i=0; i<64; i++) {
4097c478bd9Sstevel@tonic-gate     k_ipad[i] ^= 0x36;
4107c478bd9Sstevel@tonic-gate     k_opad[i] ^= 0x5c;
4117c478bd9Sstevel@tonic-gate   }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate   _sasl_MD5Init(&hmac->ictx);                   /* init inner context */
4147c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&hmac->ictx, k_ipad, 64);     /* apply inner pad */
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate   _sasl_MD5Init(&hmac->octx);                   /* init outer context */
4177c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&hmac->octx, k_opad, 64);     /* apply outer pad */
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate   /* scrub the pads and key context (if used) */
4207c478bd9Sstevel@tonic-gate   MD5_memset(&k_ipad, 0, sizeof(k_ipad));
4217c478bd9Sstevel@tonic-gate   MD5_memset(&k_opad, 0, sizeof(k_opad));
4227c478bd9Sstevel@tonic-gate   MD5_memset(&tk, 0, sizeof(tk));
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate   /* and we're done. */
4257c478bd9Sstevel@tonic-gate }
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /* The precalc and import routines here rely on the fact that we pad
4287c478bd9Sstevel@tonic-gate  * the key out to 64 bytes and use that to initialize the md5
4297c478bd9Sstevel@tonic-gate  * contexts, and that updating an md5 context with 64 bytes of data
4307c478bd9Sstevel@tonic-gate  * leaves nothing left over; all of the interesting state is contained
4317c478bd9Sstevel@tonic-gate  * in the state field, and none of it is left over in the count and
4327c478bd9Sstevel@tonic-gate  * buffer fields.  So all we have to do is save the state field; we
4337c478bd9Sstevel@tonic-gate  * can zero the others when we reload it.  Which is why the decision
4347c478bd9Sstevel@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)4357c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_precalc(HMAC_MD5_STATE *state,
4367c478bd9Sstevel@tonic-gate 			    const unsigned char *key,
4377c478bd9Sstevel@tonic-gate 			    int key_len)
4387c478bd9Sstevel@tonic-gate {
4397c478bd9Sstevel@tonic-gate   HMAC_MD5_CTX hmac;
4407c478bd9Sstevel@tonic-gate   unsigned lupe;
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate   _sasl_hmac_md5_init(&hmac, key, key_len);
4437c478bd9Sstevel@tonic-gate   for (lupe = 0; lupe < 4; lupe++) {
4447c478bd9Sstevel@tonic-gate     state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
4457c478bd9Sstevel@tonic-gate     state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
4467c478bd9Sstevel@tonic-gate   }
4477c478bd9Sstevel@tonic-gate   MD5_memset(&hmac, 0, sizeof(hmac));
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 
_sasl_hmac_md5_import(HMAC_MD5_CTX * hmac,HMAC_MD5_STATE * state)4517c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_import(HMAC_MD5_CTX *hmac,
4527c478bd9Sstevel@tonic-gate 		     HMAC_MD5_STATE *state)
4537c478bd9Sstevel@tonic-gate {
4547c478bd9Sstevel@tonic-gate   unsigned lupe;
4557c478bd9Sstevel@tonic-gate   MD5_memset(hmac, 0, sizeof(HMAC_MD5_CTX));
4567c478bd9Sstevel@tonic-gate   for (lupe = 0; lupe < 4; lupe++) {
4577c478bd9Sstevel@tonic-gate     hmac->ictx.state[lupe] = ntohl(state->istate[lupe]);
4587c478bd9Sstevel@tonic-gate     hmac->octx.state[lupe] = ntohl(state->ostate[lupe]);
4597c478bd9Sstevel@tonic-gate   }
4607c478bd9Sstevel@tonic-gate   /* Init the counts to account for our having applied
4617c478bd9Sstevel@tonic-gate    * 64 bytes of key; this works out to 0x200 (64 << 3; see
4627c478bd9Sstevel@tonic-gate    * MD5Update above...) */
4637c478bd9Sstevel@tonic-gate   hmac->ictx.count[0] = hmac->octx.count[0] = 0x200;
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
_sasl_hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],HMAC_MD5_CTX * hmac)4667c478bd9Sstevel@tonic-gate void _sasl_hmac_md5_final(unsigned char digest[HMAC_MD5_SIZE],
4677c478bd9Sstevel@tonic-gate 			  HMAC_MD5_CTX *hmac)
4687c478bd9Sstevel@tonic-gate {
4697c478bd9Sstevel@tonic-gate   _sasl_MD5Final(digest, &hmac->ictx);  /* Finalize inner md5 */
4707c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&hmac->octx, digest, 16); /* Update outer ctx */
4717c478bd9Sstevel@tonic-gate   _sasl_MD5Final(digest, &hmac->octx); /* Finalize outer md5 */
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 
_sasl_hmac_md5(text,text_len,key,key_len,digest)4757c478bd9Sstevel@tonic-gate void _sasl_hmac_md5(text, text_len, key, key_len, digest)
4767c478bd9Sstevel@tonic-gate const unsigned char* text; /* pointer to data stream */
4777c478bd9Sstevel@tonic-gate int text_len; /* length of data stream */
4787c478bd9Sstevel@tonic-gate const unsigned char* key; /* pointer to authentication key */
4797c478bd9Sstevel@tonic-gate int key_len; /* length of authentication key */
4807c478bd9Sstevel@tonic-gate unsigned char *digest; /* caller digest to be filled in */
4817c478bd9Sstevel@tonic-gate {
482*1da57d55SToomas Soome   MD5_CTX context;
4837c478bd9Sstevel@tonic-gate 
4847c478bd9Sstevel@tonic-gate   unsigned char k_ipad[65];    /* inner padding -
4857c478bd9Sstevel@tonic-gate 				* key XORd with ipad
4867c478bd9Sstevel@tonic-gate 				*/
4877c478bd9Sstevel@tonic-gate   unsigned char k_opad[65];    /* outer padding -
4887c478bd9Sstevel@tonic-gate 				* key XORd with opad
4897c478bd9Sstevel@tonic-gate 				*/
4907c478bd9Sstevel@tonic-gate   unsigned char tk[16];
4917c478bd9Sstevel@tonic-gate   int i;
4927c478bd9Sstevel@tonic-gate   /* if key is longer than 64 bytes reset it to key=MD5(key) */
4937c478bd9Sstevel@tonic-gate   if (key_len > 64) {
494*1da57d55SToomas Soome 
4957c478bd9Sstevel@tonic-gate     MD5_CTX      tctx;
4967c478bd9Sstevel@tonic-gate 
497*1da57d55SToomas Soome     _sasl_MD5Init(&tctx);
498*1da57d55SToomas Soome     _sasl_MD5Update(&tctx, key, key_len);
499*1da57d55SToomas Soome     _sasl_MD5Final(tk, &tctx);
5007c478bd9Sstevel@tonic-gate 
501*1da57d55SToomas Soome     key = tk;
502*1da57d55SToomas Soome     key_len = 16;
503*1da57d55SToomas Soome   }
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate   /*
5067c478bd9Sstevel@tonic-gate    * the HMAC_MD5 transform looks like:
5077c478bd9Sstevel@tonic-gate    *
5087c478bd9Sstevel@tonic-gate    * MD5(K XOR opad, MD5(K XOR ipad, text))
5097c478bd9Sstevel@tonic-gate    *
5107c478bd9Sstevel@tonic-gate    * where K is an n byte key
5117c478bd9Sstevel@tonic-gate    * ipad is the byte 0x36 repeated 64 times
5127c478bd9Sstevel@tonic-gate    * opad is the byte 0x5c repeated 64 times
5137c478bd9Sstevel@tonic-gate    * and text is the data being protected
5147c478bd9Sstevel@tonic-gate    */
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate   /* start out by storing key in pads */
5177c478bd9Sstevel@tonic-gate   MD5_memset(k_ipad, '\0', sizeof k_ipad);
5187c478bd9Sstevel@tonic-gate   MD5_memset(k_opad, '\0', sizeof k_opad);
5197c478bd9Sstevel@tonic-gate   MD5_memcpy( k_ipad, key, key_len);
5207c478bd9Sstevel@tonic-gate   MD5_memcpy( k_opad, key, key_len);
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate   /* XOR key with ipad and opad values */
5237c478bd9Sstevel@tonic-gate   for (i=0; i<64; i++) {
5247c478bd9Sstevel@tonic-gate     k_ipad[i] ^= 0x36;
5257c478bd9Sstevel@tonic-gate     k_opad[i] ^= 0x5c;
5267c478bd9Sstevel@tonic-gate   }
5277c478bd9Sstevel@tonic-gate   /*
5287c478bd9Sstevel@tonic-gate    * perform inner MD5
5297c478bd9Sstevel@tonic-gate    */
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate   _sasl_MD5Init(&context);                   /* init context for 1st
5327c478bd9Sstevel@tonic-gate 					       * pass */
5337c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&context, k_ipad, 64);      /* start with inner pad */
5347c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&context, text, text_len); /* then text of datagram */
5357c478bd9Sstevel@tonic-gate   _sasl_MD5Final(digest, &context);          /* finish up 1st pass */
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate   /*
5387c478bd9Sstevel@tonic-gate    * perform outer MD5
5397c478bd9Sstevel@tonic-gate    */
5407c478bd9Sstevel@tonic-gate   _sasl_MD5Init(&context);                   /* init context for 2nd
5417c478bd9Sstevel@tonic-gate 					* pass */
5427c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&context, k_opad, 64);     /* start with outer pad */
5437c478bd9Sstevel@tonic-gate   _sasl_MD5Update(&context, digest, 16);     /* then results of 1st
5447c478bd9Sstevel@tonic-gate 					* hash */
5457c478bd9Sstevel@tonic-gate   _sasl_MD5Final(digest, &context);          /* finish up 2nd pass */
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate }
548