11802Sphk/* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm 21802Sphk */ 31802Sphk 484211Sdillon#include <sys/cdefs.h> 584211Sdillon__FBSDID("$FreeBSD$"); 684211Sdillon 71802Sphk/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 81802Sphk 91802Sphk License to copy and use this software is granted provided that it 101802Sphk is identified as the "RSA Data Security, Inc. MD4 Message-Digest 111802Sphk Algorithm" in all material mentioning or referencing this software 121802Sphk or this function. 131802Sphk 141802Sphk License is also granted to make and use derivative works provided 151802Sphk that such works are identified as "derived from the RSA Data 161802Sphk Security, Inc. MD4 Message-Digest Algorithm" in all material 171802Sphk mentioning or referencing the derived work. 181802Sphk 191802Sphk RSA Data Security, Inc. makes no representations concerning either 201802Sphk the merchantability of this software or the suitability of this 211802Sphk software for any particular purpose. It is provided "as is" 221802Sphk without express or implied warranty of any kind. 231802Sphk 241802Sphk These notices must be retained in any copies of any part of this 251802Sphk documentation and/or software. 261802Sphk */ 271802Sphk 2819099Sphk#include <sys/types.h> 2919099Sphk#include <string.h> 301802Sphk#include "md4.h" 311802Sphk 321802Sphktypedef unsigned char *POINTER; 33115872Smarkmtypedef const unsigned char *CONST_POINTER; 3419099Sphktypedef u_int16_t UINT2; 3519099Sphktypedef u_int32_t UINT4; 361802Sphk 371802Sphk#define PROTO_LIST(list) list 381802Sphk 391802Sphk/* Constants for MD4Transform routine. 401802Sphk */ 411802Sphk#define S11 3 421802Sphk#define S12 7 431802Sphk#define S13 11 441802Sphk#define S14 19 451802Sphk#define S21 3 461802Sphk#define S22 5 471802Sphk#define S23 9 481802Sphk#define S24 13 491802Sphk#define S31 3 501802Sphk#define S32 9 511802Sphk#define S33 11 521802Sphk#define S34 15 531802Sphk 544245Sphkstatic void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64])); 551802Sphkstatic void Encode PROTO_LIST 561802Sphk ((unsigned char *, UINT4 *, unsigned int)); 571802Sphkstatic void Decode PROTO_LIST 584245Sphk ((UINT4 *, const unsigned char *, unsigned int)); 591802Sphk 601802Sphkstatic unsigned char PADDING[64] = { 611802Sphk 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 621802Sphk 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 631802Sphk 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 641802Sphk}; 651802Sphk 661802Sphk/* F, G and H are basic MD4 functions. 671802Sphk */ 681802Sphk#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 691802Sphk#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 701802Sphk#define H(x, y, z) ((x) ^ (y) ^ (z)) 711802Sphk 721802Sphk/* ROTATE_LEFT rotates x left n bits. 731802Sphk */ 741802Sphk#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 751802Sphk 761802Sphk/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 771802Sphk/* Rotation is separate from addition to prevent recomputation */ 781802Sphk#define FF(a, b, c, d, x, s) { \ 791802Sphk (a) += F ((b), (c), (d)) + (x); \ 801802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 811802Sphk } 821802Sphk#define GG(a, b, c, d, x, s) { \ 831802Sphk (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ 841802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 851802Sphk } 861802Sphk#define HH(a, b, c, d, x, s) { \ 871802Sphk (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ 881802Sphk (a) = ROTATE_LEFT ((a), (s)); \ 891802Sphk } 901802Sphk 911802Sphk/* MD4 initialization. Begins an MD4 operation, writing a new context. 921802Sphk */ 931802Sphkvoid MD4Init (context) 941802SphkMD4_CTX *context; /* context */ 951802Sphk{ 961802Sphk context->count[0] = context->count[1] = 0; 971802Sphk 981802Sphk /* Load magic initialization constants. 991802Sphk */ 1001802Sphk context->state[0] = 0x67452301; 1011802Sphk context->state[1] = 0xefcdab89; 1021802Sphk context->state[2] = 0x98badcfe; 1031802Sphk context->state[3] = 0x10325476; 1041802Sphk} 1051802Sphk 1061802Sphk/* MD4 block update operation. Continues an MD4 message-digest 1071802Sphk operation, processing another message block, and updating the 1081802Sphk context. 1091802Sphk */ 110154479Sphkvoid MD4Update (context, in, inputLen) 1111802SphkMD4_CTX *context; /* context */ 112154479Sphkconst void *in; /* input block */ 1131802Sphkunsigned int inputLen; /* length of input block */ 1141802Sphk{ 115115872Smarkm unsigned int i, idx, partLen; 116154479Sphk const unsigned char *input = in; 1171802Sphk 1181802Sphk /* Compute number of bytes mod 64 */ 119115872Smarkm idx = (unsigned int)((context->count[0] >> 3) & 0x3F); 1201802Sphk /* Update number of bits */ 1211802Sphk if ((context->count[0] += ((UINT4)inputLen << 3)) 1221802Sphk < ((UINT4)inputLen << 3)) 1231802Sphk context->count[1]++; 1241802Sphk context->count[1] += ((UINT4)inputLen >> 29); 1251802Sphk 126115872Smarkm partLen = 64 - idx; 1271802Sphk /* Transform as many times as possible. 1281802Sphk */ 1291802Sphk if (inputLen >= partLen) { 1301802Sphk memcpy 131115872Smarkm ((POINTER)&context->buffer[idx], (CONST_POINTER)input, partLen); 1321802Sphk MD4Transform (context->state, context->buffer); 1331802Sphk 1341802Sphk for (i = partLen; i + 63 < inputLen; i += 64) 1351802Sphk MD4Transform (context->state, &input[i]); 1361802Sphk 137115872Smarkm idx = 0; 1381802Sphk } 1391802Sphk else 1401802Sphk i = 0; 1411802Sphk 1421802Sphk /* Buffer remaining input */ 1431802Sphk memcpy 144115872Smarkm ((POINTER)&context->buffer[idx], (CONST_POINTER)&input[i], 1451802Sphk inputLen-i); 1461802Sphk} 1471802Sphk 14834909Sphk/* MD4 padding. */ 14934909Sphkvoid MD4Pad (context) 1501802SphkMD4_CTX *context; /* context */ 1511802Sphk{ 1521802Sphk unsigned char bits[8]; 153115872Smarkm unsigned int idx, padLen; 1541802Sphk 1551802Sphk /* Save number of bits */ 1561802Sphk Encode (bits, context->count, 8); 1571802Sphk 1581802Sphk /* Pad out to 56 mod 64. 1591802Sphk */ 160115872Smarkm idx = (unsigned int)((context->count[0] >> 3) & 0x3f); 161115872Smarkm padLen = (idx < 56) ? (56 - idx) : (120 - idx); 1621802Sphk MD4Update (context, PADDING, padLen); 1631802Sphk 1641802Sphk /* Append length (before padding) */ 1651802Sphk MD4Update (context, bits, 8); 16634909Sphk} 16734909Sphk 16834909Sphk/* MD4 finalization. Ends an MD4 message-digest operation, writing the 16934909Sphk the message digest and zeroizing the context. 17034909Sphk */ 17134909Sphkvoid MD4Final (digest, context) 17234909Sphkunsigned char digest[16]; /* message digest */ 17334909SphkMD4_CTX *context; /* context */ 17434909Sphk{ 17534909Sphk /* Do padding */ 17634909Sphk MD4Pad (context); 17734909Sphk 1781802Sphk /* Store state in digest */ 1791802Sphk Encode (digest, context->state, 16); 1801802Sphk 1811802Sphk /* Zeroize sensitive information. 1821802Sphk */ 1831802Sphk memset ((POINTER)context, 0, sizeof (*context)); 1841802Sphk} 1851802Sphk 1861802Sphk/* MD4 basic transformation. Transforms state based on block. 1871802Sphk */ 1881802Sphkstatic void MD4Transform (state, block) 1891802SphkUINT4 state[4]; 1904245Sphkconst unsigned char block[64]; 1911802Sphk{ 1921802Sphk UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 1931802Sphk 1941802Sphk Decode (x, block, 64); 1951802Sphk 1961802Sphk /* Round 1 */ 1971802Sphk FF (a, b, c, d, x[ 0], S11); /* 1 */ 1981802Sphk FF (d, a, b, c, x[ 1], S12); /* 2 */ 1991802Sphk FF (c, d, a, b, x[ 2], S13); /* 3 */ 2001802Sphk FF (b, c, d, a, x[ 3], S14); /* 4 */ 2011802Sphk FF (a, b, c, d, x[ 4], S11); /* 5 */ 2021802Sphk FF (d, a, b, c, x[ 5], S12); /* 6 */ 2031802Sphk FF (c, d, a, b, x[ 6], S13); /* 7 */ 2041802Sphk FF (b, c, d, a, x[ 7], S14); /* 8 */ 2051802Sphk FF (a, b, c, d, x[ 8], S11); /* 9 */ 2061802Sphk FF (d, a, b, c, x[ 9], S12); /* 10 */ 2071802Sphk FF (c, d, a, b, x[10], S13); /* 11 */ 2081802Sphk FF (b, c, d, a, x[11], S14); /* 12 */ 2091802Sphk FF (a, b, c, d, x[12], S11); /* 13 */ 2101802Sphk FF (d, a, b, c, x[13], S12); /* 14 */ 2111802Sphk FF (c, d, a, b, x[14], S13); /* 15 */ 2121802Sphk FF (b, c, d, a, x[15], S14); /* 16 */ 2131802Sphk 2141802Sphk /* Round 2 */ 2151802Sphk GG (a, b, c, d, x[ 0], S21); /* 17 */ 2161802Sphk GG (d, a, b, c, x[ 4], S22); /* 18 */ 2171802Sphk GG (c, d, a, b, x[ 8], S23); /* 19 */ 2181802Sphk GG (b, c, d, a, x[12], S24); /* 20 */ 2191802Sphk GG (a, b, c, d, x[ 1], S21); /* 21 */ 2201802Sphk GG (d, a, b, c, x[ 5], S22); /* 22 */ 2211802Sphk GG (c, d, a, b, x[ 9], S23); /* 23 */ 2221802Sphk GG (b, c, d, a, x[13], S24); /* 24 */ 2231802Sphk GG (a, b, c, d, x[ 2], S21); /* 25 */ 2241802Sphk GG (d, a, b, c, x[ 6], S22); /* 26 */ 2251802Sphk GG (c, d, a, b, x[10], S23); /* 27 */ 2261802Sphk GG (b, c, d, a, x[14], S24); /* 28 */ 2271802Sphk GG (a, b, c, d, x[ 3], S21); /* 29 */ 2281802Sphk GG (d, a, b, c, x[ 7], S22); /* 30 */ 2291802Sphk GG (c, d, a, b, x[11], S23); /* 31 */ 2301802Sphk GG (b, c, d, a, x[15], S24); /* 32 */ 2311802Sphk 2321802Sphk /* Round 3 */ 2331802Sphk HH (a, b, c, d, x[ 0], S31); /* 33 */ 2341802Sphk HH (d, a, b, c, x[ 8], S32); /* 34 */ 2351802Sphk HH (c, d, a, b, x[ 4], S33); /* 35 */ 2361802Sphk HH (b, c, d, a, x[12], S34); /* 36 */ 2371802Sphk HH (a, b, c, d, x[ 2], S31); /* 37 */ 2381802Sphk HH (d, a, b, c, x[10], S32); /* 38 */ 2391802Sphk HH (c, d, a, b, x[ 6], S33); /* 39 */ 2401802Sphk HH (b, c, d, a, x[14], S34); /* 40 */ 2411802Sphk HH (a, b, c, d, x[ 1], S31); /* 41 */ 2421802Sphk HH (d, a, b, c, x[ 9], S32); /* 42 */ 2431802Sphk HH (c, d, a, b, x[ 5], S33); /* 43 */ 2441802Sphk HH (b, c, d, a, x[13], S34); /* 44 */ 2451802Sphk HH (a, b, c, d, x[ 3], S31); /* 45 */ 2461802Sphk HH (d, a, b, c, x[11], S32); /* 46 */ 2471802Sphk HH (c, d, a, b, x[ 7], S33); /* 47 */ 2481802Sphk HH (b, c, d, a, x[15], S34); /* 48 */ 2491802Sphk 2501802Sphk state[0] += a; 2511802Sphk state[1] += b; 2521802Sphk state[2] += c; 2531802Sphk state[3] += d; 2541802Sphk 2551802Sphk /* Zeroize sensitive information. 2561802Sphk */ 2571802Sphk memset ((POINTER)x, 0, sizeof (x)); 2581802Sphk} 2591802Sphk 2601802Sphk/* Encodes input (UINT4) into output (unsigned char). Assumes len is 2611802Sphk a multiple of 4. 2621802Sphk */ 2631802Sphkstatic void Encode (output, input, len) 2641802Sphkunsigned char *output; 2651802SphkUINT4 *input; 2661802Sphkunsigned int len; 2671802Sphk{ 2681802Sphk unsigned int i, j; 2691802Sphk 2701802Sphk for (i = 0, j = 0; j < len; i++, j += 4) { 2711802Sphk output[j] = (unsigned char)(input[i] & 0xff); 2721802Sphk output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 2731802Sphk output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 2741802Sphk output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 2751802Sphk } 2761802Sphk} 2771802Sphk 2781802Sphk/* Decodes input (unsigned char) into output (UINT4). Assumes len is 2791802Sphk a multiple of 4. 2801802Sphk */ 2811802Sphkstatic void Decode (output, input, len) 2821802Sphk 2831802SphkUINT4 *output; 2844245Sphkconst unsigned char *input; 2851802Sphkunsigned int len; 2861802Sphk{ 2871802Sphk unsigned int i, j; 2881802Sphk 2891802Sphk for (i = 0, j = 0; j < len; i++, j += 4) 2901802Sphk output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | 2911802Sphk (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); 2921802Sphk} 293