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