11694Sdarrenm /* 2*7421SDaniel.Anderson@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 31694Sdarrenm * Use is subject to license terms. 41694Sdarrenm */ 51694Sdarrenm 61694Sdarrenm /* 71694Sdarrenm * MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm 81694Sdarrenm */ 91694Sdarrenm 101694Sdarrenm /* 111694Sdarrenm * Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 121694Sdarrenm * 131694Sdarrenm * License to copy and use this software is granted provided that it 141694Sdarrenm * is identified as the "RSA Data Security, Inc. MD4 Message-Digest 151694Sdarrenm * Algorithm" in all material mentioning or referencing this software 161694Sdarrenm * or this function. 171694Sdarrenm * 181694Sdarrenm * License is also granted to make and use derivative works provided 191694Sdarrenm * that such works are identified as "derived from the RSA Data 201694Sdarrenm * Security, Inc. MD4 Message-Digest Algorithm" in all material 211694Sdarrenm * mentioning or referencing the derived work. 221694Sdarrenm * 231694Sdarrenm * RSA Data Security, Inc. makes no representations concerning either 241694Sdarrenm * the merchantability of this software or the suitability of this 251694Sdarrenm * software for any particular purpose. It is provided "as is" 261694Sdarrenm * without express or implied warranty of any kind. 271694Sdarrenm * 281694Sdarrenm * These notices must be retained in any copies of any part of this 291694Sdarrenm * documentation and/or software. 301694Sdarrenm */ 311694Sdarrenm 324002Sdarrenm #include <sys/types.h> 334002Sdarrenm #ifdef _KERNEL 344002Sdarrenm #include <sys/sunddi.h> 354002Sdarrenm #else 364002Sdarrenm #include <strings.h> 374002Sdarrenm #endif /* _KERNEL */ 381694Sdarrenm 39*7421SDaniel.Anderson@Sun.COM #if defined(__i386) || defined(__amd64) 40*7421SDaniel.Anderson@Sun.COM #define UNALIGNED_POINTERS_PERMITTED 41*7421SDaniel.Anderson@Sun.COM #endif 42*7421SDaniel.Anderson@Sun.COM 434002Sdarrenm #include <sys/md4.h> 441694Sdarrenm 451694Sdarrenm /* 461694Sdarrenm * Constants for MD4Transform routine. 471694Sdarrenm */ 481694Sdarrenm #define S11 3 491694Sdarrenm #define S12 7 501694Sdarrenm #define S13 11 511694Sdarrenm #define S14 19 521694Sdarrenm #define S21 3 531694Sdarrenm #define S22 5 541694Sdarrenm #define S23 9 551694Sdarrenm #define S24 13 561694Sdarrenm #define S31 3 571694Sdarrenm #define S32 9 581694Sdarrenm #define S33 11 591694Sdarrenm #define S34 15 601694Sdarrenm 614002Sdarrenm static void MD4Transform(uint32_t [4], unsigned char [64]); 624002Sdarrenm static void Encode(unsigned char *, uint32_t *, unsigned int); 634002Sdarrenm static void Decode(uint32_t *, unsigned char *, unsigned int); 641694Sdarrenm 651694Sdarrenm static unsigned char PADDING[64] = { 661694Sdarrenm 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 671694Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 681694Sdarrenm 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 691694Sdarrenm }; 701694Sdarrenm 711694Sdarrenm /* 721694Sdarrenm * F, G and H are basic MD4 functions. 731694Sdarrenm */ 741694Sdarrenm #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 751694Sdarrenm #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 761694Sdarrenm #define H(x, y, z) ((x) ^ (y) ^ (z)) 771694Sdarrenm 781694Sdarrenm /* 791694Sdarrenm * ROTATE_LEFT rotates x left n bits. 801694Sdarrenm */ 811694Sdarrenm #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 821694Sdarrenm 831694Sdarrenm /* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 841694Sdarrenm /* Rotation is separate from addition to prevent recomputation */ 851694Sdarrenm 861694Sdarrenm #define FF(a, b, c, d, x, s) { \ 871694Sdarrenm (a) += F((b), (c), (d)) + (x); \ 881694Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 891694Sdarrenm } 901694Sdarrenm #define GG(a, b, c, d, x, s) { \ 914002Sdarrenm (a) += G((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \ 921694Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 931694Sdarrenm } 941694Sdarrenm #define HH(a, b, c, d, x, s) { \ 954002Sdarrenm (a) += H((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \ 961694Sdarrenm (a) = ROTATE_LEFT((a), (s)); \ 971694Sdarrenm } 981694Sdarrenm 991694Sdarrenm /* 1001694Sdarrenm * MD4 initialization. Begins an MD4 operation, writing a new context. 1011694Sdarrenm */ 1021694Sdarrenm void 1034002Sdarrenm MD4Init(MD4_CTX *context) 1041694Sdarrenm { 1051694Sdarrenm context->count[0] = context->count[1] = 0; 1061694Sdarrenm 1071694Sdarrenm /* 1081694Sdarrenm * Load magic initialization constants. 1091694Sdarrenm */ 1101694Sdarrenm context->state[0] = 0x67452301UL; 1111694Sdarrenm context->state[1] = 0xefcdab89UL; 1121694Sdarrenm context->state[2] = 0x98badcfeUL; 1131694Sdarrenm context->state[3] = 0x10325476UL; 1141694Sdarrenm } 1151694Sdarrenm 1161694Sdarrenm 1171694Sdarrenm /* 1181694Sdarrenm * MD4 block update operation. Continues an MD4 message-digest 1191694Sdarrenm * operation, processing another message block, and updating the 1201694Sdarrenm * context. 1211694Sdarrenm */ 1221694Sdarrenm void 1231694Sdarrenm MD4Update(MD4_CTX *context, const void *_RESTRICT_KYWD inptr, size_t inputLen) 1241694Sdarrenm { 1251694Sdarrenm unsigned int i, index, partLen; 1261694Sdarrenm uchar_t *input = (uchar_t *)inptr; 1271694Sdarrenm 1281694Sdarrenm /* Compute number of bytes mod 64 */ 1291694Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3F); 1301694Sdarrenm /* Update number of bits */ 1314002Sdarrenm if ((context->count[0] += ((uint32_t)inputLen << 3)) 1324002Sdarrenm < ((uint32_t)inputLen << 3)) 1331694Sdarrenm context->count[1]++; 1344002Sdarrenm context->count[1] += ((uint32_t)inputLen >> 29); 1351694Sdarrenm 1361694Sdarrenm partLen = 64 - index; 1371694Sdarrenm 1381694Sdarrenm /* 1391694Sdarrenm * Transform as many times as possible. 1401694Sdarrenm */ 1411694Sdarrenm if (inputLen >= partLen) { 1421694Sdarrenm bcopy(input, &context->buffer[index], partLen); 1431694Sdarrenm MD4Transform(context->state, (uchar_t *)context->buffer); 1441694Sdarrenm 1451694Sdarrenm for (i = partLen; i + 63 < inputLen; i += 64) { 1461694Sdarrenm MD4Transform(context->state, (uchar_t *)&input[i]); 1471694Sdarrenm } 1481694Sdarrenm 1491694Sdarrenm index = 0; 1501694Sdarrenm } else { 1511694Sdarrenm i = 0; 1521694Sdarrenm } 1531694Sdarrenm 1541694Sdarrenm /* Buffer remaining input */ 1551694Sdarrenm bcopy(&input[i], &context->buffer[index], inputLen - i); 1561694Sdarrenm } 1571694Sdarrenm 1581694Sdarrenm /* 1591694Sdarrenm * MD4 finalization. Ends an MD4 message-digest operation, writing the 1601694Sdarrenm * the message digest and zeroizing the context. 1611694Sdarrenm */ 1621694Sdarrenm void 1631694Sdarrenm MD4Final(void *digest, MD4_CTX *context) 1641694Sdarrenm { 1651694Sdarrenm unsigned char bits[8]; 1661694Sdarrenm unsigned int index, padLen; 1671694Sdarrenm 1681694Sdarrenm /* Save number of bits */ 1691694Sdarrenm Encode(bits, context->count, 8); 1701694Sdarrenm 1711694Sdarrenm /* 1721694Sdarrenm * Pad out to 56 mod 64. 1731694Sdarrenm */ 1741694Sdarrenm index = (unsigned int)((context->count[0] >> 3) & 0x3f); 1751694Sdarrenm padLen = (index < 56) ? (56 - index) : (120 - index); 1761694Sdarrenm MD4Update(context, PADDING, padLen); 1771694Sdarrenm 1781694Sdarrenm /* Append length (before padding) */ 1791694Sdarrenm MD4Update(context, bits, 8); 1801694Sdarrenm /* Store state in digest */ 1811694Sdarrenm Encode(digest, context->state, 16); 1821694Sdarrenm 1831694Sdarrenm /* zeroize sensitive information */ 1841694Sdarrenm bzero(context, sizeof (*context)); 1851694Sdarrenm } 1861694Sdarrenm 1871694Sdarrenm /* 1881694Sdarrenm * MD4 basic transformation. Transforms state based on block. 1891694Sdarrenm */ 1901694Sdarrenm static void 1914002Sdarrenm MD4Transform(uint32_t state[4], unsigned char block[64]) 1921694Sdarrenm { 1934002Sdarrenm uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 1941694Sdarrenm 1951694Sdarrenm 1961694Sdarrenm Decode(x, block, 64); 1971694Sdarrenm 1981694Sdarrenm /* Round 1 */ 1991694Sdarrenm FF(a, b, c, d, x[ 0], S11); /* 1 */ 2001694Sdarrenm FF(d, a, b, c, x[ 1], S12); /* 2 */ 2011694Sdarrenm FF(c, d, a, b, x[ 2], S13); /* 3 */ 2021694Sdarrenm FF(b, c, d, a, x[ 3], S14); /* 4 */ 2031694Sdarrenm FF(a, b, c, d, x[ 4], S11); /* 5 */ 2041694Sdarrenm FF(d, a, b, c, x[ 5], S12); /* 6 */ 2051694Sdarrenm FF(c, d, a, b, x[ 6], S13); /* 7 */ 2061694Sdarrenm FF(b, c, d, a, x[ 7], S14); /* 8 */ 2071694Sdarrenm FF(a, b, c, d, x[ 8], S11); /* 9 */ 2081694Sdarrenm FF(d, a, b, c, x[ 9], S12); /* 10 */ 2091694Sdarrenm FF(c, d, a, b, x[10], S13); /* 11 */ 2101694Sdarrenm FF(b, c, d, a, x[11], S14); /* 12 */ 2111694Sdarrenm FF(a, b, c, d, x[12], S11); /* 13 */ 2121694Sdarrenm FF(d, a, b, c, x[13], S12); /* 14 */ 2131694Sdarrenm FF(c, d, a, b, x[14], S13); /* 15 */ 2141694Sdarrenm FF(b, c, d, a, x[15], S14); /* 16 */ 2151694Sdarrenm 2161694Sdarrenm /* Round 2 */ 2171694Sdarrenm GG(a, b, c, d, x[ 0], S21); /* 17 */ 2181694Sdarrenm GG(d, a, b, c, x[ 4], S22); /* 18 */ 2191694Sdarrenm GG(c, d, a, b, x[ 8], S23); /* 19 */ 2201694Sdarrenm GG(b, c, d, a, x[12], S24); /* 20 */ 2211694Sdarrenm GG(a, b, c, d, x[ 1], S21); /* 21 */ 2221694Sdarrenm GG(d, a, b, c, x[ 5], S22); /* 22 */ 2231694Sdarrenm GG(c, d, a, b, x[ 9], S23); /* 23 */ 2241694Sdarrenm GG(b, c, d, a, x[13], S24); /* 24 */ 2251694Sdarrenm GG(a, b, c, d, x[ 2], S21); /* 25 */ 2261694Sdarrenm GG(d, a, b, c, x[ 6], S22); /* 26 */ 2271694Sdarrenm GG(c, d, a, b, x[10], S23); /* 27 */ 2281694Sdarrenm GG(b, c, d, a, x[14], S24); /* 28 */ 2291694Sdarrenm GG(a, b, c, d, x[ 3], S21); /* 29 */ 2301694Sdarrenm GG(d, a, b, c, x[ 7], S22); /* 30 */ 2311694Sdarrenm GG(c, d, a, b, x[11], S23); /* 31 */ 2321694Sdarrenm GG(b, c, d, a, x[15], S24); /* 32 */ 2331694Sdarrenm 2341694Sdarrenm 2351694Sdarrenm /* Round 3 */ 2361694Sdarrenm HH(a, b, c, d, x[ 0], S31); /* 33 */ 2371694Sdarrenm HH(d, a, b, c, x[ 8], S32); /* 34 */ 2381694Sdarrenm HH(c, d, a, b, x[ 4], S33); /* 35 */ 2391694Sdarrenm HH(b, c, d, a, x[12], S34); /* 36 */ 2401694Sdarrenm HH(a, b, c, d, x[ 2], S31); /* 37 */ 2411694Sdarrenm HH(d, a, b, c, x[10], S32); /* 38 */ 2421694Sdarrenm HH(c, d, a, b, x[ 6], S33); /* 39 */ 2431694Sdarrenm HH(b, c, d, a, x[14], S34); /* 40 */ 2441694Sdarrenm HH(a, b, c, d, x[ 1], S31); /* 41 */ 2451694Sdarrenm HH(d, a, b, c, x[ 9], S32); /* 42 */ 2461694Sdarrenm HH(c, d, a, b, x[ 5], S33); /* 43 */ 2471694Sdarrenm HH(b, c, d, a, x[13], S34); /* 44 */ 2481694Sdarrenm HH(a, b, c, d, x[ 3], S31); /* 45 */ 2491694Sdarrenm HH(d, a, b, c, x[11], S32); /* 46 */ 2501694Sdarrenm HH(c, d, a, b, x[ 7], S33); /* 47 */ 2511694Sdarrenm HH(b, c, d, a, x[15], S34); /* 48 */ 2521694Sdarrenm 2531694Sdarrenm state[0] += a; 2541694Sdarrenm state[1] += b; 2551694Sdarrenm state[2] += c; 2561694Sdarrenm state[3] += d; 2571694Sdarrenm 2581694Sdarrenm /* zeroize sensitive information */ 2591694Sdarrenm bzero(x, sizeof (*x)); 2601694Sdarrenm } 2611694Sdarrenm 2621694Sdarrenm /* 2634002Sdarrenm * Encodes input (uint32_t) into output (unsigned char). Assumes len is 2641694Sdarrenm * a multiple of 4. 2651694Sdarrenm */ 2661694Sdarrenm static void 267*7421SDaniel.Anderson@Sun.COM Encode(unsigned char *output, uint32_t *input, unsigned int len) 2681694Sdarrenm { 2691694Sdarrenm unsigned int i, j; 2701694Sdarrenm 2711694Sdarrenm for (i = 0, j = 0; j < len; i++, j += 4) { 272*7421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED) 273*7421SDaniel.Anderson@Sun.COM *(uint32_t *)&output[j] = input[i]; 274*7421SDaniel.Anderson@Sun.COM #else 275*7421SDaniel.Anderson@Sun.COM /* endian-independent code */ 2761694Sdarrenm output[j] = (unsigned char)(input[i] & 0xff); 2771694Sdarrenm output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 2781694Sdarrenm output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 2791694Sdarrenm output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 280*7421SDaniel.Anderson@Sun.COM #endif /* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */ 2811694Sdarrenm } 2821694Sdarrenm } 2831694Sdarrenm 2841694Sdarrenm /* 2854002Sdarrenm * Decodes input (unsigned char) into output (uint32_t). Assumes len is 2861694Sdarrenm * a multiple of 4. 2871694Sdarrenm */ 2881694Sdarrenm static void 289*7421SDaniel.Anderson@Sun.COM Decode(uint32_t *output, unsigned char *input, unsigned int len) 2901694Sdarrenm { 2911694Sdarrenm unsigned int i, j; 2921694Sdarrenm 293*7421SDaniel.Anderson@Sun.COM for (i = 0, j = 0; j < len; i++, j += 4) { 294*7421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED) 295*7421SDaniel.Anderson@Sun.COM output[i] = *(uint32_t *)&input[j]; 296*7421SDaniel.Anderson@Sun.COM #else 297*7421SDaniel.Anderson@Sun.COM /* endian-independent code */ 2984002Sdarrenm output[i] = ((uint32_t)input[j]) | 299*7421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+1]) << 8) | 300*7421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+2]) << 16) | 301*7421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+3]) << 24); 302*7421SDaniel.Anderson@Sun.COM #endif /* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */ 303*7421SDaniel.Anderson@Sun.COM } 304*7421SDaniel.Anderson@Sun.COM 3051694Sdarrenm } 306