11694Sdarrenm /*
27421SDaniel.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
397421SDaniel.Anderson@Sun.COM #if defined(__i386) || defined(__amd64)
407421SDaniel.Anderson@Sun.COM #define UNALIGNED_POINTERS_PERMITTED
417421SDaniel.Anderson@Sun.COM #endif
427421SDaniel.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
MD4Init(MD4_CTX * context)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
MD4Update(MD4_CTX * context,const void * _RESTRICT_KYWD inptr,size_t inputLen)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
MD4Final(void * digest,MD4_CTX * context)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
MD4Transform(uint32_t state[4],unsigned char block[64])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
Encode(unsigned char * output,uint32_t * input,unsigned int len)2677421SDaniel.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) {
2727421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
273*7434SDaniel.Anderson@Sun.COM *(uint32_t *)(void *)&output[j] = input[i];
2747421SDaniel.Anderson@Sun.COM #else
2757421SDaniel.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);
2807421SDaniel.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
Decode(uint32_t * output,unsigned char * input,unsigned int len)2897421SDaniel.Anderson@Sun.COM Decode(uint32_t *output, unsigned char *input, unsigned int len)
2901694Sdarrenm {
2911694Sdarrenm unsigned int i, j;
2921694Sdarrenm
2937421SDaniel.Anderson@Sun.COM for (i = 0, j = 0; j < len; i++, j += 4) {
2947421SDaniel.Anderson@Sun.COM #if defined(_LITTLE_ENDIAN) && defined(UNALIGNED_POINTERS_PERMITTED)
295*7434SDaniel.Anderson@Sun.COM output[i] = *(uint32_t *)(void *)&input[j];
2967421SDaniel.Anderson@Sun.COM #else
2977421SDaniel.Anderson@Sun.COM /* endian-independent code */
2984002Sdarrenm output[i] = ((uint32_t)input[j]) |
2997421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+1]) << 8) |
3007421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+2]) << 16) |
3017421SDaniel.Anderson@Sun.COM (((uint32_t)input[j+3]) << 24);
3027421SDaniel.Anderson@Sun.COM #endif /* _LITTLE_ENDIAN && UNALIGNED_POINTERS_PERMITTED */
3037421SDaniel.Anderson@Sun.COM }
3047421SDaniel.Anderson@Sun.COM
3051694Sdarrenm }
306