1681a5bbeSBoris Popov /* MD4C.C - RSA Data Security, Inc., MD4 message-digest algorithm 2681a5bbeSBoris Popov */ 3681a5bbeSBoris Popov 49454b2d8SWarner Losh /*- 5*62cf53fdSPedro F. Giffuni SPDX-License-Identifier: RSA-MD 6*62cf53fdSPedro F. Giffuni 79454b2d8SWarner Losh Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 8681a5bbeSBoris Popov 9681a5bbeSBoris Popov License to copy and use this software is granted provided that it 10681a5bbeSBoris Popov is identified as the "RSA Data Security, Inc. MD4 Message-Digest 11681a5bbeSBoris Popov Algorithm" in all material mentioning or referencing this software 12681a5bbeSBoris Popov or this function. 13681a5bbeSBoris Popov 14681a5bbeSBoris Popov License is also granted to make and use derivative works provided 15681a5bbeSBoris Popov that such works are identified as "derived from the RSA Data 16681a5bbeSBoris Popov Security, Inc. MD4 Message-Digest Algorithm" in all material 17681a5bbeSBoris Popov mentioning or referencing the derived work. 18681a5bbeSBoris Popov 19681a5bbeSBoris Popov RSA Data Security, Inc. makes no representations concerning either 20681a5bbeSBoris Popov the merchantability of this software or the suitability of this 21681a5bbeSBoris Popov software for any particular purpose. It is provided "as is" 22681a5bbeSBoris Popov without express or implied warranty of any kind. 23681a5bbeSBoris Popov 24681a5bbeSBoris Popov These notices must be retained in any copies of any part of this 25681a5bbeSBoris Popov documentation and/or software. 26681a5bbeSBoris Popov */ 27681a5bbeSBoris Popov 28677b542eSDavid E. O'Brien #include <sys/cdefs.h> 29677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 30677b542eSDavid E. O'Brien 31681a5bbeSBoris Popov #include <sys/param.h> 32681a5bbeSBoris Popov #include <sys/systm.h> 33681a5bbeSBoris Popov #include <sys/md4.h> 34681a5bbeSBoris Popov 35681a5bbeSBoris Popov typedef unsigned char *POINTER; 36681a5bbeSBoris Popov typedef u_int16_t UINT2; 37681a5bbeSBoris Popov typedef u_int32_t UINT4; 38681a5bbeSBoris Popov 39681a5bbeSBoris Popov #define PROTO_LIST(list) list 40681a5bbeSBoris Popov 41681a5bbeSBoris Popov /* Constants for MD4Transform routine. 42681a5bbeSBoris Popov */ 43681a5bbeSBoris Popov #define S11 3 44681a5bbeSBoris Popov #define S12 7 45681a5bbeSBoris Popov #define S13 11 46681a5bbeSBoris Popov #define S14 19 47681a5bbeSBoris Popov #define S21 3 48681a5bbeSBoris Popov #define S22 5 49681a5bbeSBoris Popov #define S23 9 50681a5bbeSBoris Popov #define S24 13 51681a5bbeSBoris Popov #define S31 3 52681a5bbeSBoris Popov #define S32 9 53681a5bbeSBoris Popov #define S33 11 54681a5bbeSBoris Popov #define S34 15 55681a5bbeSBoris Popov 56681a5bbeSBoris Popov static void MD4Transform PROTO_LIST ((UINT4 [4], const unsigned char [64])); 57681a5bbeSBoris Popov static void Encode PROTO_LIST 58681a5bbeSBoris Popov ((unsigned char *, UINT4 *, unsigned int)); 59681a5bbeSBoris Popov static void Decode PROTO_LIST 60681a5bbeSBoris Popov ((UINT4 *, const unsigned char *, unsigned int)); 61681a5bbeSBoris Popov 62681a5bbeSBoris Popov static unsigned char PADDING[64] = { 63681a5bbeSBoris Popov 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64681a5bbeSBoris Popov 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 65681a5bbeSBoris Popov 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 66681a5bbeSBoris Popov }; 67681a5bbeSBoris Popov 68681a5bbeSBoris Popov /* F, G and H are basic MD4 functions. 69681a5bbeSBoris Popov */ 70681a5bbeSBoris Popov #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 71681a5bbeSBoris Popov #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 72681a5bbeSBoris Popov #define H(x, y, z) ((x) ^ (y) ^ (z)) 73681a5bbeSBoris Popov 74681a5bbeSBoris Popov /* ROTATE_LEFT rotates x left n bits. 75681a5bbeSBoris Popov */ 76681a5bbeSBoris Popov #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 77681a5bbeSBoris Popov 78681a5bbeSBoris Popov /* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 79681a5bbeSBoris Popov /* Rotation is separate from addition to prevent recomputation */ 80681a5bbeSBoris Popov #define FF(a, b, c, d, x, s) { \ 81681a5bbeSBoris Popov (a) += F ((b), (c), (d)) + (x); \ 82681a5bbeSBoris Popov (a) = ROTATE_LEFT ((a), (s)); \ 83681a5bbeSBoris Popov } 84681a5bbeSBoris Popov #define GG(a, b, c, d, x, s) { \ 85681a5bbeSBoris Popov (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ 86681a5bbeSBoris Popov (a) = ROTATE_LEFT ((a), (s)); \ 87681a5bbeSBoris Popov } 88681a5bbeSBoris Popov #define HH(a, b, c, d, x, s) { \ 89681a5bbeSBoris Popov (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ 90681a5bbeSBoris Popov (a) = ROTATE_LEFT ((a), (s)); \ 91681a5bbeSBoris Popov } 92681a5bbeSBoris Popov 93681a5bbeSBoris Popov /* MD4 initialization. Begins an MD4 operation, writing a new context. 94681a5bbeSBoris Popov */ 9580dc9f88SEd Maste void 9680dc9f88SEd Maste MD4Init(MD4_CTX *context) 97681a5bbeSBoris Popov { 98681a5bbeSBoris Popov context->count[0] = context->count[1] = 0; 99681a5bbeSBoris Popov 100681a5bbeSBoris Popov /* Load magic initialization constants. 101681a5bbeSBoris Popov */ 102681a5bbeSBoris Popov context->state[0] = 0x67452301; 103681a5bbeSBoris Popov context->state[1] = 0xefcdab89; 104681a5bbeSBoris Popov context->state[2] = 0x98badcfe; 105681a5bbeSBoris Popov context->state[3] = 0x10325476; 106681a5bbeSBoris Popov } 107681a5bbeSBoris Popov 108681a5bbeSBoris Popov /* MD4 block update operation. Continues an MD4 message-digest 109681a5bbeSBoris Popov operation, processing another message block, and updating the 110681a5bbeSBoris Popov context. 111681a5bbeSBoris Popov */ 11280dc9f88SEd Maste void 11380dc9f88SEd Maste MD4Update(MD4_CTX *context, const unsigned char *input, 11480dc9f88SEd Maste unsigned int inputLen) 115681a5bbeSBoris Popov { 116681a5bbeSBoris Popov unsigned int i, index, partLen; 117681a5bbeSBoris Popov 118681a5bbeSBoris Popov /* Compute number of bytes mod 64 */ 119681a5bbeSBoris Popov index = (unsigned int)((context->count[0] >> 3) & 0x3F); 120681a5bbeSBoris Popov /* Update number of bits */ 121681a5bbeSBoris Popov if ((context->count[0] += ((UINT4)inputLen << 3)) 122681a5bbeSBoris Popov < ((UINT4)inputLen << 3)) 123681a5bbeSBoris Popov context->count[1]++; 124681a5bbeSBoris Popov context->count[1] += ((UINT4)inputLen >> 29); 125681a5bbeSBoris Popov 126681a5bbeSBoris Popov partLen = 64 - index; 127681a5bbeSBoris Popov /* Transform as many times as possible. 128681a5bbeSBoris Popov */ 129681a5bbeSBoris Popov if (inputLen >= partLen) { 130681a5bbeSBoris Popov bcopy(input, &context->buffer[index], partLen); 131681a5bbeSBoris Popov MD4Transform (context->state, context->buffer); 132681a5bbeSBoris Popov 133681a5bbeSBoris Popov for (i = partLen; i + 63 < inputLen; i += 64) 134681a5bbeSBoris Popov MD4Transform (context->state, &input[i]); 135681a5bbeSBoris Popov 136681a5bbeSBoris Popov index = 0; 137681a5bbeSBoris Popov } 138681a5bbeSBoris Popov else 139681a5bbeSBoris Popov i = 0; 140681a5bbeSBoris Popov 141681a5bbeSBoris Popov /* Buffer remaining input */ 142681a5bbeSBoris Popov bcopy(&input[i], &context->buffer[index], inputLen-i); 143681a5bbeSBoris Popov } 144681a5bbeSBoris Popov 145681a5bbeSBoris Popov /* MD4 padding. */ 14680dc9f88SEd Maste void 14780dc9f88SEd Maste MD4Pad(MD4_CTX *context) 148681a5bbeSBoris Popov { 149681a5bbeSBoris Popov unsigned char bits[8]; 150681a5bbeSBoris Popov unsigned int index, padLen; 151681a5bbeSBoris Popov 152681a5bbeSBoris Popov /* Save number of bits */ 153681a5bbeSBoris Popov Encode (bits, context->count, 8); 154681a5bbeSBoris Popov 155681a5bbeSBoris Popov /* Pad out to 56 mod 64. 156681a5bbeSBoris Popov */ 157681a5bbeSBoris Popov index = (unsigned int)((context->count[0] >> 3) & 0x3f); 158681a5bbeSBoris Popov padLen = (index < 56) ? (56 - index) : (120 - index); 159681a5bbeSBoris Popov MD4Update (context, PADDING, padLen); 160681a5bbeSBoris Popov 161681a5bbeSBoris Popov /* Append length (before padding) */ 162681a5bbeSBoris Popov MD4Update (context, bits, 8); 163681a5bbeSBoris Popov } 164681a5bbeSBoris Popov 165681a5bbeSBoris Popov /* MD4 finalization. Ends an MD4 message-digest operation, writing the 166681a5bbeSBoris Popov the message digest and zeroizing the context. 167681a5bbeSBoris Popov */ 16880dc9f88SEd Maste void 16980dc9f88SEd Maste MD4Final(unsigned char digest[static 16], MD4_CTX *context) 170681a5bbeSBoris Popov { 171681a5bbeSBoris Popov /* Do padding */ 172681a5bbeSBoris Popov MD4Pad (context); 173681a5bbeSBoris Popov 174681a5bbeSBoris Popov /* Store state in digest */ 175681a5bbeSBoris Popov Encode (digest, context->state, 16); 176681a5bbeSBoris Popov 177681a5bbeSBoris Popov /* Zeroize sensitive information. 178681a5bbeSBoris Popov */ 179571ebf76SConrad Meyer bzero(context, sizeof (*context)); 180681a5bbeSBoris Popov } 181681a5bbeSBoris Popov 182681a5bbeSBoris Popov /* MD4 basic transformation. Transforms state based on block. 183681a5bbeSBoris Popov */ 18480dc9f88SEd Maste static void 18580dc9f88SEd Maste MD4Transform(UINT4 state[4], const unsigned char block[64]) 186681a5bbeSBoris Popov { 187681a5bbeSBoris Popov UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 188681a5bbeSBoris Popov 189681a5bbeSBoris Popov Decode (x, block, 64); 190681a5bbeSBoris Popov 191681a5bbeSBoris Popov /* Round 1 */ 192681a5bbeSBoris Popov FF (a, b, c, d, x[ 0], S11); /* 1 */ 193681a5bbeSBoris Popov FF (d, a, b, c, x[ 1], S12); /* 2 */ 194681a5bbeSBoris Popov FF (c, d, a, b, x[ 2], S13); /* 3 */ 195681a5bbeSBoris Popov FF (b, c, d, a, x[ 3], S14); /* 4 */ 196681a5bbeSBoris Popov FF (a, b, c, d, x[ 4], S11); /* 5 */ 197681a5bbeSBoris Popov FF (d, a, b, c, x[ 5], S12); /* 6 */ 198681a5bbeSBoris Popov FF (c, d, a, b, x[ 6], S13); /* 7 */ 199681a5bbeSBoris Popov FF (b, c, d, a, x[ 7], S14); /* 8 */ 200681a5bbeSBoris Popov FF (a, b, c, d, x[ 8], S11); /* 9 */ 201681a5bbeSBoris Popov FF (d, a, b, c, x[ 9], S12); /* 10 */ 202681a5bbeSBoris Popov FF (c, d, a, b, x[10], S13); /* 11 */ 203681a5bbeSBoris Popov FF (b, c, d, a, x[11], S14); /* 12 */ 204681a5bbeSBoris Popov FF (a, b, c, d, x[12], S11); /* 13 */ 205681a5bbeSBoris Popov FF (d, a, b, c, x[13], S12); /* 14 */ 206681a5bbeSBoris Popov FF (c, d, a, b, x[14], S13); /* 15 */ 207681a5bbeSBoris Popov FF (b, c, d, a, x[15], S14); /* 16 */ 208681a5bbeSBoris Popov 209681a5bbeSBoris Popov /* Round 2 */ 210681a5bbeSBoris Popov GG (a, b, c, d, x[ 0], S21); /* 17 */ 211681a5bbeSBoris Popov GG (d, a, b, c, x[ 4], S22); /* 18 */ 212681a5bbeSBoris Popov GG (c, d, a, b, x[ 8], S23); /* 19 */ 213681a5bbeSBoris Popov GG (b, c, d, a, x[12], S24); /* 20 */ 214681a5bbeSBoris Popov GG (a, b, c, d, x[ 1], S21); /* 21 */ 215681a5bbeSBoris Popov GG (d, a, b, c, x[ 5], S22); /* 22 */ 216681a5bbeSBoris Popov GG (c, d, a, b, x[ 9], S23); /* 23 */ 217681a5bbeSBoris Popov GG (b, c, d, a, x[13], S24); /* 24 */ 218681a5bbeSBoris Popov GG (a, b, c, d, x[ 2], S21); /* 25 */ 219681a5bbeSBoris Popov GG (d, a, b, c, x[ 6], S22); /* 26 */ 220681a5bbeSBoris Popov GG (c, d, a, b, x[10], S23); /* 27 */ 221681a5bbeSBoris Popov GG (b, c, d, a, x[14], S24); /* 28 */ 222681a5bbeSBoris Popov GG (a, b, c, d, x[ 3], S21); /* 29 */ 223681a5bbeSBoris Popov GG (d, a, b, c, x[ 7], S22); /* 30 */ 224681a5bbeSBoris Popov GG (c, d, a, b, x[11], S23); /* 31 */ 225681a5bbeSBoris Popov GG (b, c, d, a, x[15], S24); /* 32 */ 226681a5bbeSBoris Popov 227681a5bbeSBoris Popov /* Round 3 */ 228681a5bbeSBoris Popov HH (a, b, c, d, x[ 0], S31); /* 33 */ 229681a5bbeSBoris Popov HH (d, a, b, c, x[ 8], S32); /* 34 */ 230681a5bbeSBoris Popov HH (c, d, a, b, x[ 4], S33); /* 35 */ 231681a5bbeSBoris Popov HH (b, c, d, a, x[12], S34); /* 36 */ 232681a5bbeSBoris Popov HH (a, b, c, d, x[ 2], S31); /* 37 */ 233681a5bbeSBoris Popov HH (d, a, b, c, x[10], S32); /* 38 */ 234681a5bbeSBoris Popov HH (c, d, a, b, x[ 6], S33); /* 39 */ 235681a5bbeSBoris Popov HH (b, c, d, a, x[14], S34); /* 40 */ 236681a5bbeSBoris Popov HH (a, b, c, d, x[ 1], S31); /* 41 */ 237681a5bbeSBoris Popov HH (d, a, b, c, x[ 9], S32); /* 42 */ 238681a5bbeSBoris Popov HH (c, d, a, b, x[ 5], S33); /* 43 */ 239681a5bbeSBoris Popov HH (b, c, d, a, x[13], S34); /* 44 */ 240681a5bbeSBoris Popov HH (a, b, c, d, x[ 3], S31); /* 45 */ 241681a5bbeSBoris Popov HH (d, a, b, c, x[11], S32); /* 46 */ 242681a5bbeSBoris Popov HH (c, d, a, b, x[ 7], S33); /* 47 */ 243681a5bbeSBoris Popov HH (b, c, d, a, x[15], S34); /* 48 */ 244681a5bbeSBoris Popov 245681a5bbeSBoris Popov state[0] += a; 246681a5bbeSBoris Popov state[1] += b; 247681a5bbeSBoris Popov state[2] += c; 248681a5bbeSBoris Popov state[3] += d; 249681a5bbeSBoris Popov 250681a5bbeSBoris Popov /* Zeroize sensitive information. 251681a5bbeSBoris Popov */ 252681a5bbeSBoris Popov bzero((POINTER)x, sizeof (x)); 253681a5bbeSBoris Popov } 254681a5bbeSBoris Popov 255681a5bbeSBoris Popov /* Encodes input (UINT4) into output (unsigned char). Assumes len is 256681a5bbeSBoris Popov a multiple of 4. 257681a5bbeSBoris Popov */ 25880dc9f88SEd Maste static void 25980dc9f88SEd Maste Encode(unsigned char *output, UINT4 *input, unsigned int len) 260681a5bbeSBoris Popov { 261681a5bbeSBoris Popov unsigned int i, j; 262681a5bbeSBoris Popov 263681a5bbeSBoris Popov for (i = 0, j = 0; j < len; i++, j += 4) { 264681a5bbeSBoris Popov output[j] = (unsigned char)(input[i] & 0xff); 265681a5bbeSBoris Popov output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 266681a5bbeSBoris Popov output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 267681a5bbeSBoris Popov output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 268681a5bbeSBoris Popov } 269681a5bbeSBoris Popov } 270681a5bbeSBoris Popov 271681a5bbeSBoris Popov /* Decodes input (unsigned char) into output (UINT4). Assumes len is 272681a5bbeSBoris Popov a multiple of 4. 273681a5bbeSBoris Popov */ 27480dc9f88SEd Maste static void 27580dc9f88SEd Maste Decode(UINT4 *output, const unsigned char *input, unsigned int len) 276681a5bbeSBoris Popov { 277681a5bbeSBoris Popov unsigned int i, j; 278681a5bbeSBoris Popov 279681a5bbeSBoris Popov for (i = 0, j = 0; j < len; i++, j += 4) 280681a5bbeSBoris Popov output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | 281681a5bbeSBoris Popov (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); 282681a5bbeSBoris Popov } 283