1*734b6a94Sdarrenm /* 2*734b6a94Sdarrenm * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3*734b6a94Sdarrenm * Use is subject to license terms. 4*734b6a94Sdarrenm */ 5*734b6a94Sdarrenm 6*734b6a94Sdarrenm #pragma ident "%Z%%M% %I% %E% SMI" 7*734b6a94Sdarrenm 8*734b6a94Sdarrenm /* 9*734b6a94Sdarrenm * MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm 10*734b6a94Sdarrenm */ 11*734b6a94Sdarrenm 12*734b6a94Sdarrenm /* 13*734b6a94Sdarrenm * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 14*734b6a94Sdarrenm * 15*734b6a94Sdarrenm * License to copy and use this software is granted provided that it 16*734b6a94Sdarrenm * is identified as the "RSA Data Security, Inc. MD4 Message-Digest 17*734b6a94Sdarrenm * Algorithm" in all material mentioning or referencing this software 18*734b6a94Sdarrenm * or this function. 19*734b6a94Sdarrenm * 20*734b6a94Sdarrenm * License is also granted to make and use derivative works provided 21*734b6a94Sdarrenm * that such works are identified as "derived from the RSA Data 22*734b6a94Sdarrenm * Security, Inc. MD4 Message-Digest Algorithm" in all material 23*734b6a94Sdarrenm * mentioning or referencing the derived work. 24*734b6a94Sdarrenm * 25*734b6a94Sdarrenm * RSA Data Security, Inc. makes no representations concerning either 26*734b6a94Sdarrenm * the merchantability of this software or the suitability of this 27*734b6a94Sdarrenm * software for any particular purpose. It is provided "as is" 28*734b6a94Sdarrenm * without express or implied warranty of any kind. 29*734b6a94Sdarrenm * 30*734b6a94Sdarrenm * These notices must be retained in any copies of any part of this 31*734b6a94Sdarrenm * documentation and/or software. 32*734b6a94Sdarrenm */ 33*734b6a94Sdarrenm 34*734b6a94Sdarrenm #include <strings.h> 35*734b6a94Sdarrenm #include <sys/types.h> 36*734b6a94Sdarrenm 37*734b6a94Sdarrenm #include "md4.h" 38*734b6a94Sdarrenm 39*734b6a94Sdarrenm /* 40*734b6a94Sdarrenm * Constants for MD4Transform routine. 41*734b6a94Sdarrenm */ 42*734b6a94Sdarrenm #define S11 3 43*734b6a94Sdarrenm #define S12 7 44*734b6a94Sdarrenm #define S13 11 45*734b6a94Sdarrenm #define S14 19 46*734b6a94Sdarrenm #define S21 3 47*734b6a94Sdarrenm #define S22 5 48*734b6a94Sdarrenm #define S23 9 49*734b6a94Sdarrenm #define S24 13 50*734b6a94Sdarrenm #define S31 3 51*734b6a94Sdarrenm #define S32 9 52*734b6a94Sdarrenm #define S33 11 53*734b6a94Sdarrenm #define S34 15 54*734b6a94Sdarrenm 55*734b6a94Sdarrenm static void MD4Transform(ulong_t [4], unsigned char [64]); 56*734b6a94Sdarrenm static void Encode(unsigned char *, ulong_t *, unsigned int); 57*734b6a94Sdarrenm static void Decode(ulong_t *, unsigned char *, unsigned int); 58*734b6a94Sdarrenm 59*734b6a94Sdarrenm static unsigned char PADDING[64] = { 60*734b6a94Sdarrenm 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61*734b6a94Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 62*734b6a94Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 63*734b6a94Sdarrenm }; 64*734b6a94Sdarrenm 65*734b6a94Sdarrenm /* 66*734b6a94Sdarrenm * F, G and H are basic MD4 functions. 67*734b6a94Sdarrenm */ 68*734b6a94Sdarrenm #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 69*734b6a94Sdarrenm #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 70*734b6a94Sdarrenm #define H(x, y, z) ((x) ^ (y) ^ (z)) 71*734b6a94Sdarrenm 72*734b6a94Sdarrenm /* 73*734b6a94Sdarrenm * ROTATE_LEFT rotates x left n bits. 74*734b6a94Sdarrenm */ 75*734b6a94Sdarrenm #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 76*734b6a94Sdarrenm 77*734b6a94Sdarrenm /* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 78*734b6a94Sdarrenm /* Rotation is separate from addition to prevent recomputation */ 79*734b6a94Sdarrenm 80*734b6a94Sdarrenm #define FF(a, b, c, d, x, s) { \ 81*734b6a94Sdarrenm (a) += F((b), (c), (d)) + (x); \ 82*734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 83*734b6a94Sdarrenm } 84*734b6a94Sdarrenm #define GG(a, b, c, d, x, s) { \ 85*734b6a94Sdarrenm (a) += G((b), (c), (d)) + (x) + (ulong_t)0x5a827999; \ 86*734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 87*734b6a94Sdarrenm } 88*734b6a94Sdarrenm #define HH(a, b, c, d, x, s) { \ 89*734b6a94Sdarrenm (a) += H((b), (c), (d)) + (x) + (ulong_t)0x6ed9eba1; \ 90*734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 91*734b6a94Sdarrenm } 92*734b6a94Sdarrenm 93*734b6a94Sdarrenm /* 94*734b6a94Sdarrenm * MD4 initialization. Begins an MD4 operation, writing a new context. 95*734b6a94Sdarrenm */ 96*734b6a94Sdarrenm void 97*734b6a94Sdarrenm MD4Init(context) 98*734b6a94Sdarrenm MD4_CTX *context; /* context */ 99*734b6a94Sdarrenm { 100*734b6a94Sdarrenm context->count[0] = context->count[1] = 0; 101*734b6a94Sdarrenm 102*734b6a94Sdarrenm /* 103*734b6a94Sdarrenm * Load magic initialization constants. 104*734b6a94Sdarrenm */ 105*734b6a94Sdarrenm context->state[0] = 0x67452301UL; 106*734b6a94Sdarrenm context->state[1] = 0xefcdab89UL; 107*734b6a94Sdarrenm context->state[2] = 0x98badcfeUL; 108*734b6a94Sdarrenm context->state[3] = 0x10325476UL; 109*734b6a94Sdarrenm } 110*734b6a94Sdarrenm 111*734b6a94Sdarrenm 112*734b6a94Sdarrenm /* 113*734b6a94Sdarrenm * MD4 block update operation. Continues an MD4 message-digest 114*734b6a94Sdarrenm * operation, processing another message block, and updating the 115*734b6a94Sdarrenm * context. 116*734b6a94Sdarrenm */ 117*734b6a94Sdarrenm void 118*734b6a94Sdarrenm MD4Update(MD4_CTX *context, const void *_RESTRICT_KYWD inptr, size_t inputLen) 119*734b6a94Sdarrenm { 120*734b6a94Sdarrenm unsigned int i, index, partLen; 121*734b6a94Sdarrenm uchar_t *input = (uchar_t *)inptr; 122*734b6a94Sdarrenm 123*734b6a94Sdarrenm /* Compute number of bytes mod 64 */ 124*734b6a94Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3F); 125*734b6a94Sdarrenm /* Update number of bits */ 126*734b6a94Sdarrenm if ((context->count[0] += ((ulong_t)inputLen << 3)) 127*734b6a94Sdarrenm < ((ulong_t)inputLen << 3)) 128*734b6a94Sdarrenm context->count[1]++; 129*734b6a94Sdarrenm context->count[1] += ((ulong_t)inputLen >> 29); 130*734b6a94Sdarrenm 131*734b6a94Sdarrenm partLen = 64 - index; 132*734b6a94Sdarrenm 133*734b6a94Sdarrenm /* 134*734b6a94Sdarrenm * Transform as many times as possible. 135*734b6a94Sdarrenm */ 136*734b6a94Sdarrenm if (inputLen >= partLen) { 137*734b6a94Sdarrenm bcopy(input, &context->buffer[index], partLen); 138*734b6a94Sdarrenm MD4Transform(context->state, (uchar_t *)context->buffer); 139*734b6a94Sdarrenm 140*734b6a94Sdarrenm for (i = partLen; i + 63 < inputLen; i += 64) { 141*734b6a94Sdarrenm MD4Transform(context->state, (uchar_t *)&input[i]); 142*734b6a94Sdarrenm } 143*734b6a94Sdarrenm 144*734b6a94Sdarrenm index = 0; 145*734b6a94Sdarrenm } else { 146*734b6a94Sdarrenm i = 0; 147*734b6a94Sdarrenm } 148*734b6a94Sdarrenm 149*734b6a94Sdarrenm /* Buffer remaining input */ 150*734b6a94Sdarrenm bcopy(&input[i], &context->buffer[index], inputLen - i); 151*734b6a94Sdarrenm } 152*734b6a94Sdarrenm 153*734b6a94Sdarrenm /* 154*734b6a94Sdarrenm * MD4 finalization. Ends an MD4 message-digest operation, writing the 155*734b6a94Sdarrenm * the message digest and zeroizing the context. 156*734b6a94Sdarrenm */ 157*734b6a94Sdarrenm void 158*734b6a94Sdarrenm MD4Final(void *digest, MD4_CTX *context) 159*734b6a94Sdarrenm { 160*734b6a94Sdarrenm unsigned char bits[8]; 161*734b6a94Sdarrenm unsigned int index, padLen; 162*734b6a94Sdarrenm 163*734b6a94Sdarrenm /* Save number of bits */ 164*734b6a94Sdarrenm Encode(bits, context->count, 8); 165*734b6a94Sdarrenm 166*734b6a94Sdarrenm /* 167*734b6a94Sdarrenm * Pad out to 56 mod 64. 168*734b6a94Sdarrenm */ 169*734b6a94Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3f); 170*734b6a94Sdarrenm padLen = (index < 56) ? (56 - index) : (120 - index); 171*734b6a94Sdarrenm MD4Update(context, PADDING, padLen); 172*734b6a94Sdarrenm 173*734b6a94Sdarrenm /* Append length (before padding) */ 174*734b6a94Sdarrenm MD4Update(context, bits, 8); 175*734b6a94Sdarrenm /* Store state in digest */ 176*734b6a94Sdarrenm Encode(digest, context->state, 16); 177*734b6a94Sdarrenm 178*734b6a94Sdarrenm /* zeroize sensitive information */ 179*734b6a94Sdarrenm bzero(context, sizeof (*context)); 180*734b6a94Sdarrenm } 181*734b6a94Sdarrenm 182*734b6a94Sdarrenm /* 183*734b6a94Sdarrenm * MD4 basic transformation. Transforms state based on block. 184*734b6a94Sdarrenm */ 185*734b6a94Sdarrenm static void 186*734b6a94Sdarrenm MD4Transform(ulong_t state[4], unsigned char block[64]) 187*734b6a94Sdarrenm { 188*734b6a94Sdarrenm ulong_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 189*734b6a94Sdarrenm 190*734b6a94Sdarrenm 191*734b6a94Sdarrenm Decode(x, block, 64); 192*734b6a94Sdarrenm 193*734b6a94Sdarrenm /* Round 1 */ 194*734b6a94Sdarrenm FF(a, b, c, d, x[ 0], S11); /* 1 */ 195*734b6a94Sdarrenm FF(d, a, b, c, x[ 1], S12); /* 2 */ 196*734b6a94Sdarrenm FF(c, d, a, b, x[ 2], S13); /* 3 */ 197*734b6a94Sdarrenm FF(b, c, d, a, x[ 3], S14); /* 4 */ 198*734b6a94Sdarrenm FF(a, b, c, d, x[ 4], S11); /* 5 */ 199*734b6a94Sdarrenm FF(d, a, b, c, x[ 5], S12); /* 6 */ 200*734b6a94Sdarrenm FF(c, d, a, b, x[ 6], S13); /* 7 */ 201*734b6a94Sdarrenm FF(b, c, d, a, x[ 7], S14); /* 8 */ 202*734b6a94Sdarrenm FF(a, b, c, d, x[ 8], S11); /* 9 */ 203*734b6a94Sdarrenm FF(d, a, b, c, x[ 9], S12); /* 10 */ 204*734b6a94Sdarrenm FF(c, d, a, b, x[10], S13); /* 11 */ 205*734b6a94Sdarrenm FF(b, c, d, a, x[11], S14); /* 12 */ 206*734b6a94Sdarrenm FF(a, b, c, d, x[12], S11); /* 13 */ 207*734b6a94Sdarrenm FF(d, a, b, c, x[13], S12); /* 14 */ 208*734b6a94Sdarrenm FF(c, d, a, b, x[14], S13); /* 15 */ 209*734b6a94Sdarrenm FF(b, c, d, a, x[15], S14); /* 16 */ 210*734b6a94Sdarrenm 211*734b6a94Sdarrenm /* Round 2 */ 212*734b6a94Sdarrenm GG(a, b, c, d, x[ 0], S21); /* 17 */ 213*734b6a94Sdarrenm GG(d, a, b, c, x[ 4], S22); /* 18 */ 214*734b6a94Sdarrenm GG(c, d, a, b, x[ 8], S23); /* 19 */ 215*734b6a94Sdarrenm GG(b, c, d, a, x[12], S24); /* 20 */ 216*734b6a94Sdarrenm GG(a, b, c, d, x[ 1], S21); /* 21 */ 217*734b6a94Sdarrenm GG(d, a, b, c, x[ 5], S22); /* 22 */ 218*734b6a94Sdarrenm GG(c, d, a, b, x[ 9], S23); /* 23 */ 219*734b6a94Sdarrenm GG(b, c, d, a, x[13], S24); /* 24 */ 220*734b6a94Sdarrenm GG(a, b, c, d, x[ 2], S21); /* 25 */ 221*734b6a94Sdarrenm GG(d, a, b, c, x[ 6], S22); /* 26 */ 222*734b6a94Sdarrenm GG(c, d, a, b, x[10], S23); /* 27 */ 223*734b6a94Sdarrenm GG(b, c, d, a, x[14], S24); /* 28 */ 224*734b6a94Sdarrenm GG(a, b, c, d, x[ 3], S21); /* 29 */ 225*734b6a94Sdarrenm GG(d, a, b, c, x[ 7], S22); /* 30 */ 226*734b6a94Sdarrenm GG(c, d, a, b, x[11], S23); /* 31 */ 227*734b6a94Sdarrenm GG(b, c, d, a, x[15], S24); /* 32 */ 228*734b6a94Sdarrenm 229*734b6a94Sdarrenm 230*734b6a94Sdarrenm /* Round 3 */ 231*734b6a94Sdarrenm HH(a, b, c, d, x[ 0], S31); /* 33 */ 232*734b6a94Sdarrenm HH(d, a, b, c, x[ 8], S32); /* 34 */ 233*734b6a94Sdarrenm HH(c, d, a, b, x[ 4], S33); /* 35 */ 234*734b6a94Sdarrenm HH(b, c, d, a, x[12], S34); /* 36 */ 235*734b6a94Sdarrenm HH(a, b, c, d, x[ 2], S31); /* 37 */ 236*734b6a94Sdarrenm HH(d, a, b, c, x[10], S32); /* 38 */ 237*734b6a94Sdarrenm HH(c, d, a, b, x[ 6], S33); /* 39 */ 238*734b6a94Sdarrenm HH(b, c, d, a, x[14], S34); /* 40 */ 239*734b6a94Sdarrenm HH(a, b, c, d, x[ 1], S31); /* 41 */ 240*734b6a94Sdarrenm HH(d, a, b, c, x[ 9], S32); /* 42 */ 241*734b6a94Sdarrenm HH(c, d, a, b, x[ 5], S33); /* 43 */ 242*734b6a94Sdarrenm HH(b, c, d, a, x[13], S34); /* 44 */ 243*734b6a94Sdarrenm HH(a, b, c, d, x[ 3], S31); /* 45 */ 244*734b6a94Sdarrenm HH(d, a, b, c, x[11], S32); /* 46 */ 245*734b6a94Sdarrenm HH(c, d, a, b, x[ 7], S33); /* 47 */ 246*734b6a94Sdarrenm HH(b, c, d, a, x[15], S34); /* 48 */ 247*734b6a94Sdarrenm 248*734b6a94Sdarrenm state[0] += a; 249*734b6a94Sdarrenm state[1] += b; 250*734b6a94Sdarrenm state[2] += c; 251*734b6a94Sdarrenm state[3] += d; 252*734b6a94Sdarrenm 253*734b6a94Sdarrenm /* zeroize sensitive information */ 254*734b6a94Sdarrenm bzero(x, sizeof (*x)); 255*734b6a94Sdarrenm } 256*734b6a94Sdarrenm 257*734b6a94Sdarrenm /* 258*734b6a94Sdarrenm * Encodes input (ulong_t) into output (unsigned char). Assumes len is 259*734b6a94Sdarrenm * a multiple of 4. 260*734b6a94Sdarrenm */ 261*734b6a94Sdarrenm static void 262*734b6a94Sdarrenm Encode(output, input, len) 263*734b6a94Sdarrenm unsigned char *output; 264*734b6a94Sdarrenm ulong_t *input; 265*734b6a94Sdarrenm unsigned int len; 266*734b6a94Sdarrenm { 267*734b6a94Sdarrenm unsigned int i, j; 268*734b6a94Sdarrenm 269*734b6a94Sdarrenm for (i = 0, j = 0; j < len; i++, j += 4) { 270*734b6a94Sdarrenm output[j] = (unsigned char)(input[i] & 0xff); 271*734b6a94Sdarrenm output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 272*734b6a94Sdarrenm output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 273*734b6a94Sdarrenm output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 274*734b6a94Sdarrenm } 275*734b6a94Sdarrenm } 276*734b6a94Sdarrenm 277*734b6a94Sdarrenm /* 278*734b6a94Sdarrenm * Decodes input (unsigned char) into output (ulong_t). Assumes len is 279*734b6a94Sdarrenm * a multiple of 4. 280*734b6a94Sdarrenm */ 281*734b6a94Sdarrenm static void 282*734b6a94Sdarrenm Decode(output, input, len) 283*734b6a94Sdarrenm ulong_t *output; 284*734b6a94Sdarrenm unsigned char *input; 285*734b6a94Sdarrenm unsigned int len; 286*734b6a94Sdarrenm { 287*734b6a94Sdarrenm unsigned int i, j; 288*734b6a94Sdarrenm 289*734b6a94Sdarrenm for (i = 0, j = 0; j < len; i++, j += 4) 290*734b6a94Sdarrenm output[i] = ((ulong_t)input[j]) | 291*734b6a94Sdarrenm (((ulong_t)input[j+1]) << 8) | 292*734b6a94Sdarrenm (((ulong_t)input[j+2]) << 16) | 293*734b6a94Sdarrenm (((ulong_t)input[j+3]) << 24); 294*734b6a94Sdarrenm } 295