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