1734b6a94Sdarrenm /* 2*5151fb12Sdarrenm * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3734b6a94Sdarrenm * Use is subject to license terms. 4734b6a94Sdarrenm */ 5734b6a94Sdarrenm 6734b6a94Sdarrenm #pragma ident "%Z%%M% %I% %E% SMI" 7734b6a94Sdarrenm 8734b6a94Sdarrenm /* 9734b6a94Sdarrenm * MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm 10734b6a94Sdarrenm */ 11734b6a94Sdarrenm 12734b6a94Sdarrenm /* 13734b6a94Sdarrenm * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 14734b6a94Sdarrenm * 15734b6a94Sdarrenm * License to copy and use this software is granted provided that it 16734b6a94Sdarrenm * is identified as the "RSA Data Security, Inc. MD4 Message-Digest 17734b6a94Sdarrenm * Algorithm" in all material mentioning or referencing this software 18734b6a94Sdarrenm * or this function. 19734b6a94Sdarrenm * 20734b6a94Sdarrenm * License is also granted to make and use derivative works provided 21734b6a94Sdarrenm * that such works are identified as "derived from the RSA Data 22734b6a94Sdarrenm * Security, Inc. MD4 Message-Digest Algorithm" in all material 23734b6a94Sdarrenm * mentioning or referencing the derived work. 24734b6a94Sdarrenm * 25734b6a94Sdarrenm * RSA Data Security, Inc. makes no representations concerning either 26734b6a94Sdarrenm * the merchantability of this software or the suitability of this 27734b6a94Sdarrenm * software for any particular purpose. It is provided "as is" 28734b6a94Sdarrenm * without express or implied warranty of any kind. 29734b6a94Sdarrenm * 30734b6a94Sdarrenm * These notices must be retained in any copies of any part of this 31734b6a94Sdarrenm * documentation and/or software. 32734b6a94Sdarrenm */ 33734b6a94Sdarrenm 34734b6a94Sdarrenm #include <sys/types.h> 35*5151fb12Sdarrenm #ifdef _KERNEL 36*5151fb12Sdarrenm #include <sys/sunddi.h> 37*5151fb12Sdarrenm #else 38*5151fb12Sdarrenm #include <strings.h> 39*5151fb12Sdarrenm #endif /* _KERNEL */ 40734b6a94Sdarrenm 41*5151fb12Sdarrenm #include <sys/md4.h> 42734b6a94Sdarrenm 43734b6a94Sdarrenm /* 44734b6a94Sdarrenm * Constants for MD4Transform routine. 45734b6a94Sdarrenm */ 46734b6a94Sdarrenm #define S11 3 47734b6a94Sdarrenm #define S12 7 48734b6a94Sdarrenm #define S13 11 49734b6a94Sdarrenm #define S14 19 50734b6a94Sdarrenm #define S21 3 51734b6a94Sdarrenm #define S22 5 52734b6a94Sdarrenm #define S23 9 53734b6a94Sdarrenm #define S24 13 54734b6a94Sdarrenm #define S31 3 55734b6a94Sdarrenm #define S32 9 56734b6a94Sdarrenm #define S33 11 57734b6a94Sdarrenm #define S34 15 58734b6a94Sdarrenm 59*5151fb12Sdarrenm static void MD4Transform(uint32_t [4], unsigned char [64]); 60*5151fb12Sdarrenm static void Encode(unsigned char *, uint32_t *, unsigned int); 61*5151fb12Sdarrenm static void Decode(uint32_t *, unsigned char *, unsigned int); 62734b6a94Sdarrenm 63734b6a94Sdarrenm static unsigned char PADDING[64] = { 64734b6a94Sdarrenm 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65734b6a94Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 66734b6a94Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 67734b6a94Sdarrenm }; 68734b6a94Sdarrenm 69734b6a94Sdarrenm /* 70734b6a94Sdarrenm * F, G and H are basic MD4 functions. 71734b6a94Sdarrenm */ 72734b6a94Sdarrenm #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 73734b6a94Sdarrenm #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 74734b6a94Sdarrenm #define H(x, y, z) ((x) ^ (y) ^ (z)) 75734b6a94Sdarrenm 76734b6a94Sdarrenm /* 77734b6a94Sdarrenm * ROTATE_LEFT rotates x left n bits. 78734b6a94Sdarrenm */ 79734b6a94Sdarrenm #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 80734b6a94Sdarrenm 81734b6a94Sdarrenm /* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 82734b6a94Sdarrenm /* Rotation is separate from addition to prevent recomputation */ 83734b6a94Sdarrenm 84734b6a94Sdarrenm #define FF(a, b, c, d, x, s) { \ 85734b6a94Sdarrenm (a) += F((b), (c), (d)) + (x); \ 86734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 87734b6a94Sdarrenm } 88734b6a94Sdarrenm #define GG(a, b, c, d, x, s) { \ 89*5151fb12Sdarrenm (a) += G((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \ 90734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 91734b6a94Sdarrenm } 92734b6a94Sdarrenm #define HH(a, b, c, d, x, s) { \ 93*5151fb12Sdarrenm (a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \ 94734b6a94Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 95734b6a94Sdarrenm } 96734b6a94Sdarrenm 97734b6a94Sdarrenm /* 98734b6a94Sdarrenm * MD4 initialization. Begins an MD4 operation, writing a new context. 99734b6a94Sdarrenm */ 100734b6a94Sdarrenm void 101*5151fb12Sdarrenm MD4Init(MD4_CTX *context) 102734b6a94Sdarrenm { 103734b6a94Sdarrenm context->count[0] = context->count[1] = 0; 104734b6a94Sdarrenm 105734b6a94Sdarrenm /* 106734b6a94Sdarrenm * Load magic initialization constants. 107734b6a94Sdarrenm */ 108734b6a94Sdarrenm context->state[0] = 0x67452301UL; 109734b6a94Sdarrenm context->state[1] = 0xefcdab89UL; 110734b6a94Sdarrenm context->state[2] = 0x98badcfeUL; 111734b6a94Sdarrenm context->state[3] = 0x10325476UL; 112734b6a94Sdarrenm } 113734b6a94Sdarrenm 114734b6a94Sdarrenm 115734b6a94Sdarrenm /* 116734b6a94Sdarrenm * MD4 block update operation. Continues an MD4 message-digest 117734b6a94Sdarrenm * operation, processing another message block, and updating the 118734b6a94Sdarrenm * context. 119734b6a94Sdarrenm */ 120734b6a94Sdarrenm void 121734b6a94Sdarrenm MD4Update(MD4_CTX *context, const void *_RESTRICT_KYWD inptr, size_t inputLen) 122734b6a94Sdarrenm { 123734b6a94Sdarrenm unsigned int i, index, partLen; 124734b6a94Sdarrenm uchar_t *input = (uchar_t *)inptr; 125734b6a94Sdarrenm 126734b6a94Sdarrenm /* Compute number of bytes mod 64 */ 127734b6a94Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3F); 128734b6a94Sdarrenm /* Update number of bits */ 129*5151fb12Sdarrenm if ((context->count[0] += ((uint32_t)inputLen << 3)) 130*5151fb12Sdarrenm < ((uint32_t)inputLen << 3)) 131734b6a94Sdarrenm context->count[1]++; 132*5151fb12Sdarrenm context->count[1] += ((uint32_t)inputLen >> 29); 133734b6a94Sdarrenm 134734b6a94Sdarrenm partLen = 64 - index; 135734b6a94Sdarrenm 136734b6a94Sdarrenm /* 137734b6a94Sdarrenm * Transform as many times as possible. 138734b6a94Sdarrenm */ 139734b6a94Sdarrenm if (inputLen >= partLen) { 140734b6a94Sdarrenm bcopy(input, &context->buffer[index], partLen); 141734b6a94Sdarrenm MD4Transform(context->state, (uchar_t *)context->buffer); 142734b6a94Sdarrenm 143734b6a94Sdarrenm for (i = partLen; i + 63 < inputLen; i += 64) { 144734b6a94Sdarrenm MD4Transform(context->state, (uchar_t *)&input[i]); 145734b6a94Sdarrenm } 146734b6a94Sdarrenm 147734b6a94Sdarrenm index = 0; 148734b6a94Sdarrenm } else { 149734b6a94Sdarrenm i = 0; 150734b6a94Sdarrenm } 151734b6a94Sdarrenm 152734b6a94Sdarrenm /* Buffer remaining input */ 153734b6a94Sdarrenm bcopy(&input[i], &context->buffer[index], inputLen - i); 154734b6a94Sdarrenm } 155734b6a94Sdarrenm 156734b6a94Sdarrenm /* 157734b6a94Sdarrenm * MD4 finalization. Ends an MD4 message-digest operation, writing the 158734b6a94Sdarrenm * the message digest and zeroizing the context. 159734b6a94Sdarrenm */ 160734b6a94Sdarrenm void 161734b6a94Sdarrenm MD4Final(void *digest, MD4_CTX *context) 162734b6a94Sdarrenm { 163734b6a94Sdarrenm unsigned char bits[8]; 164734b6a94Sdarrenm unsigned int index, padLen; 165734b6a94Sdarrenm 166734b6a94Sdarrenm /* Save number of bits */ 167734b6a94Sdarrenm Encode(bits, context->count, 8); 168734b6a94Sdarrenm 169734b6a94Sdarrenm /* 170734b6a94Sdarrenm * Pad out to 56 mod 64. 171734b6a94Sdarrenm */ 172734b6a94Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3f); 173734b6a94Sdarrenm padLen = (index < 56) ? (56 - index) : (120 - index); 174734b6a94Sdarrenm MD4Update(context, PADDING, padLen); 175734b6a94Sdarrenm 176734b6a94Sdarrenm /* Append length (before padding) */ 177734b6a94Sdarrenm MD4Update(context, bits, 8); 178734b6a94Sdarrenm /* Store state in digest */ 179734b6a94Sdarrenm Encode(digest, context->state, 16); 180734b6a94Sdarrenm 181734b6a94Sdarrenm /* zeroize sensitive information */ 182734b6a94Sdarrenm bzero(context, sizeof (*context)); 183734b6a94Sdarrenm } 184734b6a94Sdarrenm 185734b6a94Sdarrenm /* 186734b6a94Sdarrenm * MD4 basic transformation. Transforms state based on block. 187734b6a94Sdarrenm */ 188734b6a94Sdarrenm static void 189*5151fb12Sdarrenm MD4Transform(uint32_t state[4], unsigned char block[64]) 190734b6a94Sdarrenm { 191*5151fb12Sdarrenm uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 192734b6a94Sdarrenm 193734b6a94Sdarrenm 194734b6a94Sdarrenm Decode(x, block, 64); 195734b6a94Sdarrenm 196734b6a94Sdarrenm /* Round 1 */ 197734b6a94Sdarrenm FF(a, b, c, d, x[ 0], S11); /* 1 */ 198734b6a94Sdarrenm FF(d, a, b, c, x[ 1], S12); /* 2 */ 199734b6a94Sdarrenm FF(c, d, a, b, x[ 2], S13); /* 3 */ 200734b6a94Sdarrenm FF(b, c, d, a, x[ 3], S14); /* 4 */ 201734b6a94Sdarrenm FF(a, b, c, d, x[ 4], S11); /* 5 */ 202734b6a94Sdarrenm FF(d, a, b, c, x[ 5], S12); /* 6 */ 203734b6a94Sdarrenm FF(c, d, a, b, x[ 6], S13); /* 7 */ 204734b6a94Sdarrenm FF(b, c, d, a, x[ 7], S14); /* 8 */ 205734b6a94Sdarrenm FF(a, b, c, d, x[ 8], S11); /* 9 */ 206734b6a94Sdarrenm FF(d, a, b, c, x[ 9], S12); /* 10 */ 207734b6a94Sdarrenm FF(c, d, a, b, x[10], S13); /* 11 */ 208734b6a94Sdarrenm FF(b, c, d, a, x[11], S14); /* 12 */ 209734b6a94Sdarrenm FF(a, b, c, d, x[12], S11); /* 13 */ 210734b6a94Sdarrenm FF(d, a, b, c, x[13], S12); /* 14 */ 211734b6a94Sdarrenm FF(c, d, a, b, x[14], S13); /* 15 */ 212734b6a94Sdarrenm FF(b, c, d, a, x[15], S14); /* 16 */ 213734b6a94Sdarrenm 214734b6a94Sdarrenm /* Round 2 */ 215734b6a94Sdarrenm GG(a, b, c, d, x[ 0], S21); /* 17 */ 216734b6a94Sdarrenm GG(d, a, b, c, x[ 4], S22); /* 18 */ 217734b6a94Sdarrenm GG(c, d, a, b, x[ 8], S23); /* 19 */ 218734b6a94Sdarrenm GG(b, c, d, a, x[12], S24); /* 20 */ 219734b6a94Sdarrenm GG(a, b, c, d, x[ 1], S21); /* 21 */ 220734b6a94Sdarrenm GG(d, a, b, c, x[ 5], S22); /* 22 */ 221734b6a94Sdarrenm GG(c, d, a, b, x[ 9], S23); /* 23 */ 222734b6a94Sdarrenm GG(b, c, d, a, x[13], S24); /* 24 */ 223734b6a94Sdarrenm GG(a, b, c, d, x[ 2], S21); /* 25 */ 224734b6a94Sdarrenm GG(d, a, b, c, x[ 6], S22); /* 26 */ 225734b6a94Sdarrenm GG(c, d, a, b, x[10], S23); /* 27 */ 226734b6a94Sdarrenm GG(b, c, d, a, x[14], S24); /* 28 */ 227734b6a94Sdarrenm GG(a, b, c, d, x[ 3], S21); /* 29 */ 228734b6a94Sdarrenm GG(d, a, b, c, x[ 7], S22); /* 30 */ 229734b6a94Sdarrenm GG(c, d, a, b, x[11], S23); /* 31 */ 230734b6a94Sdarrenm GG(b, c, d, a, x[15], S24); /* 32 */ 231734b6a94Sdarrenm 232734b6a94Sdarrenm 233734b6a94Sdarrenm /* Round 3 */ 234734b6a94Sdarrenm HH(a, b, c, d, x[ 0], S31); /* 33 */ 235734b6a94Sdarrenm HH(d, a, b, c, x[ 8], S32); /* 34 */ 236734b6a94Sdarrenm HH(c, d, a, b, x[ 4], S33); /* 35 */ 237734b6a94Sdarrenm HH(b, c, d, a, x[12], S34); /* 36 */ 238734b6a94Sdarrenm HH(a, b, c, d, x[ 2], S31); /* 37 */ 239734b6a94Sdarrenm HH(d, a, b, c, x[10], S32); /* 38 */ 240734b6a94Sdarrenm HH(c, d, a, b, x[ 6], S33); /* 39 */ 241734b6a94Sdarrenm HH(b, c, d, a, x[14], S34); /* 40 */ 242734b6a94Sdarrenm HH(a, b, c, d, x[ 1], S31); /* 41 */ 243734b6a94Sdarrenm HH(d, a, b, c, x[ 9], S32); /* 42 */ 244734b6a94Sdarrenm HH(c, d, a, b, x[ 5], S33); /* 43 */ 245734b6a94Sdarrenm HH(b, c, d, a, x[13], S34); /* 44 */ 246734b6a94Sdarrenm HH(a, b, c, d, x[ 3], S31); /* 45 */ 247734b6a94Sdarrenm HH(d, a, b, c, x[11], S32); /* 46 */ 248734b6a94Sdarrenm HH(c, d, a, b, x[ 7], S33); /* 47 */ 249734b6a94Sdarrenm HH(b, c, d, a, x[15], S34); /* 48 */ 250734b6a94Sdarrenm 251734b6a94Sdarrenm state[0] += a; 252734b6a94Sdarrenm state[1] += b; 253734b6a94Sdarrenm state[2] += c; 254734b6a94Sdarrenm state[3] += d; 255734b6a94Sdarrenm 256734b6a94Sdarrenm /* zeroize sensitive information */ 257734b6a94Sdarrenm bzero(x, sizeof (*x)); 258734b6a94Sdarrenm } 259734b6a94Sdarrenm 260734b6a94Sdarrenm /* 261*5151fb12Sdarrenm * Encodes input (uint32_t) into output (unsigned char). Assumes len is 262734b6a94Sdarrenm * a multiple of 4. 263734b6a94Sdarrenm */ 264734b6a94Sdarrenm static void 265734b6a94Sdarrenm Encode(output, input, len) 266734b6a94Sdarrenm unsigned char *output; 267*5151fb12Sdarrenm uint32_t *input; 268734b6a94Sdarrenm unsigned int len; 269734b6a94Sdarrenm { 270734b6a94Sdarrenm unsigned int i, j; 271734b6a94Sdarrenm 272734b6a94Sdarrenm for (i = 0, j = 0; j < len; i++, j += 4) { 273734b6a94Sdarrenm output[j] = (unsigned char)(input[i] & 0xff); 274734b6a94Sdarrenm output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 275734b6a94Sdarrenm output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 276734b6a94Sdarrenm output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 277734b6a94Sdarrenm } 278734b6a94Sdarrenm } 279734b6a94Sdarrenm 280734b6a94Sdarrenm /* 281*5151fb12Sdarrenm * Decodes input (unsigned char) into output (uint32_t). Assumes len is 282734b6a94Sdarrenm * a multiple of 4. 283734b6a94Sdarrenm */ 284734b6a94Sdarrenm static void 285734b6a94Sdarrenm Decode(output, input, len) 286*5151fb12Sdarrenm uint32_t *output; 287734b6a94Sdarrenm unsigned char *input; 288734b6a94Sdarrenm unsigned int len; 289734b6a94Sdarrenm { 290734b6a94Sdarrenm unsigned int i, j; 291734b6a94Sdarrenm 292734b6a94Sdarrenm for (i = 0, j = 0; j < len; i++, j += 4) 293*5151fb12Sdarrenm output[i] = ((uint32_t)input[j]) | 294*5151fb12Sdarrenm (((uint32_t)input[j+1]) << 8) | 295*5151fb12Sdarrenm (((uint32_t)input[j+2]) << 16) | 296*5151fb12Sdarrenm (((uint32_t)input[j+3]) << 24); 297734b6a94Sdarrenm } 298