122347Spst/* md4c.c: "RSA Data Security, Inc. MD4 Message-Digest Algorithm" 222347Spst 329964Sache%%% portions-copyright-cmetz-96 492906SmarkmPortions of this software are Copyright 1996-1999 by Craig Metz, All Rights 522347SpstReserved. The Inner Net License Version 2 applies to these portions of 622347Spstthe software. 722347SpstYou should have received a copy of the license with this software. If 822347Spstyou didn't get a copy, you may request one from <license@inner.net>. 922347Spst 1022347SpstPortions of this software are Copyright 1995 by Randall Atkinson and Dan 1122347SpstMcDonald, All Rights Reserved. All Rights under this copyright are assigned 1222347Spstto the U.S. Naval Research Laboratory (NRL). The NRL Copyright Notice and 1322347SpstLicense Agreement applies to this software. 1422347Spst 1522347Spst History: 1622347Spst 1722347Spst Modified by cmetz for OPIE 2.2. Use FUNCTION declaration et al. 1822347Spst Use the real memcpy() and memset(). Use unified context 1922347Spst structure. 2022347Spst Modified at NRL for OPIE 2.0. 2122347Spst Originally from RSADSI reference code. 2222347Spst*/ 2322347Spst/* Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 2422347Spst 2522347Spst License to copy and use this software is granted provided that it 2622347Spst is identified as the "RSA Data Security, Inc. MD4 Message-Digest 2722347Spst Algorithm" in all material mentioning or referencing this software 2822347Spst or this function. 2922347Spst 3022347Spst License is also granted to make and use derivative works provided 3122347Spst that such works are identified as "derived from the RSA Data 3222347Spst Security, Inc. MD4 Message-Digest Algorithm" in all material 3322347Spst mentioning or referencing the derived work. 3422347Spst 3522347Spst RSA Data Security, Inc. makes no representations concerning either 3622347Spst the merchantability of this software or the suitability of this 3722347Spst software for any particular purpose. It is provided "as is" 3822347Spst without express or implied warranty of any kind. 3922347Spst 4022347Spst These notices must be retained in any copies of any part of this 4122347Spst documentation and/or software. 4222347Spst */ 4322347Spst 4422347Spst#include "opie_cfg.h" 4522347Spst#include "opie.h" 4622347Spst 4722347Spst/* Constants for MD4Transform routine. 4822347Spst */ 4922347Spst#define S11 3 5022347Spst#define S12 7 5122347Spst#define S13 11 5222347Spst#define S14 19 5322347Spst#define S21 3 5422347Spst#define S22 5 5522347Spst#define S23 9 5622347Spst#define S24 13 5722347Spst#define S31 3 5822347Spst#define S32 9 5922347Spst#define S33 11 6022347Spst#define S34 15 6122347Spst 6222347Spststatic VOIDRET MD4Transform __P((UINT4[4], unsigned char[64])); 6322347Spststatic VOIDRET Encode __P((unsigned char *, UINT4 *, unsigned int)); 6422347Spststatic VOIDRET Decode __P((UINT4 *, unsigned char *, unsigned int)); 6522347Spst 6622347Spststatic unsigned char PADDING[64] = 6722347Spst{ 6822347Spst 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6922347Spst 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7022347Spst 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 7122347Spst}; 7222347Spst 7322347Spst/* F, G and H are basic MD4 functions. 7422347Spst */ 7522347Spst#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 7622347Spst#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 7722347Spst#define H(x, y, z) ((x) ^ (y) ^ (z)) 7822347Spst 7922347Spst/* ROTATE_LEFT rotates x left n bits. 8022347Spst */ 8122347Spst#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 8222347Spst 8322347Spst/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 8422347Spst/* Rotation is separate from addition to prevent recomputation */ 8522347Spst 8622347Spst#define FF(a, b, c, d, x, s) { \ 8722347Spst (a) += F ((b), (c), (d)) + (x); \ 8822347Spst (a) = ROTATE_LEFT ((a), (s)); \ 8922347Spst } 9022347Spst#define GG(a, b, c, d, x, s) { \ 9122347Spst (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ 9222347Spst (a) = ROTATE_LEFT ((a), (s)); \ 9322347Spst } 9422347Spst#define HH(a, b, c, d, x, s) { \ 9522347Spst (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ 9622347Spst (a) = ROTATE_LEFT ((a), (s)); \ 9722347Spst } 9822347Spst 9922347Spst/* MD4 initialization. Begins an MD4 operation, writing a new context. 10022347Spst */ 10122347SpstVOIDRET opiemd4init FUNCTION((context), struct opiemdx_ctx *context) 10222347Spst{ 10322347Spst context->count[0] = context->count[1] = 0; 10422347Spst 10522347Spst /* Load magic initialization constants. */ 10622347Spst context->state[0] = 0x67452301; 10722347Spst context->state[1] = 0xefcdab89; 10822347Spst context->state[2] = 0x98badcfe; 10922347Spst context->state[3] = 0x10325476; 11022347Spst} 11122347Spst 11222347Spst/* MD4 block update operation. Continues an MD4 message-digest 11322347Spst operation, processing another message block, and updating the 11422347Spst context. 11522347Spst */ 11622347SpstVOIDRET opiemd4update FUNCTION((context, input, inputLen), struct opiemdx_ctx *context AND unsigned char *input AND unsigned int inputLen) 11722347Spst{ 11822347Spst unsigned int i, index, partLen; 11922347Spst 12022347Spst /* Compute number of bytes mod 64 */ 12122347Spst index = (unsigned int) ((context->count[0] >> 3) & 0x3F); 12222347Spst /* Update number of bits */ 12322347Spst if ((context->count[0] += ((UINT4) inputLen << 3)) 12422347Spst < ((UINT4) inputLen << 3)) 12522347Spst context->count[1]++; 12622347Spst context->count[1] += ((UINT4) inputLen >> 29); 12722347Spst 12822347Spst partLen = 64 - index; 12922347Spst 13022347Spst /* Transform as many times as possible. */ 13122347Spst if (inputLen >= partLen) { 13222347Spst memcpy((POINTER) & context->buffer[index], (POINTER) input, partLen); 13322347Spst MD4Transform(context->state, context->buffer); 13422347Spst 13522347Spst for (i = partLen; i + 63 < inputLen; i += 64) 13622347Spst MD4Transform(context->state, &input[i]); 13722347Spst 13822347Spst index = 0; 13922347Spst } else 14022347Spst i = 0; 14122347Spst 14222347Spst /* Buffer remaining input */ 14322347Spst memcpy((POINTER) & context->buffer[index], (POINTER) & input[i], inputLen - i); 14422347Spst} 14522347Spst 14622347Spst/* MD4 finalization. Ends an MD4 message-digest operation, writing the 14722347Spst the message digest and zeroizing the context. 14822347Spst */ 14922347SpstVOIDRET opiemd4final FUNCTION((digest, context), unsigned char *digest AND struct opiemdx_ctx *context) 15022347Spst{ 15122347Spst unsigned char bits[8]; 15222347Spst unsigned int index, padLen; 15322347Spst 15422347Spst /* Save number of bits */ 15522347Spst Encode(bits, context->count, 8); 15622347Spst 15722347Spst /* Pad out to 56 mod 64. */ 15822347Spst index = (unsigned int) ((context->count[0] >> 3) & 0x3f); 15922347Spst padLen = (index < 56) ? (56 - index) : (120 - index); 16022347Spst opiemd4update(context, PADDING, padLen); 16122347Spst 16222347Spst /* Append length (before padding) */ 16322347Spst opiemd4update(context, bits, 8); 16422347Spst /* Store state in digest */ 16522347Spst Encode(digest, context->state, 16); 16622347Spst 16722347Spst /* Zeroize sensitive information. */ 16822347Spst memset((POINTER) context, 0, sizeof(*context)); 16922347Spst} 17022347Spst 17122347Spst/* MD4 basic transformation. Transforms state based on block. 17222347Spst */ 17322347Spststatic VOIDRET MD4Transform FUNCTION((state, block), UINT4 state[4] AND unsigned char block[64]) 17422347Spst{ 17522347Spst UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 17622347Spst 17722347Spst Decode(x, block, 64); 17822347Spst 17922347Spst /* Round 1 */ 18022347Spst FF(a, b, c, d, x[0], S11); /* 1 */ 18122347Spst FF(d, a, b, c, x[1], S12); /* 2 */ 18222347Spst FF(c, d, a, b, x[2], S13); /* 3 */ 18322347Spst FF(b, c, d, a, x[3], S14); /* 4 */ 18422347Spst FF(a, b, c, d, x[4], S11); /* 5 */ 18522347Spst FF(d, a, b, c, x[5], S12); /* 6 */ 18622347Spst FF(c, d, a, b, x[6], S13); /* 7 */ 18722347Spst FF(b, c, d, a, x[7], S14); /* 8 */ 18822347Spst FF(a, b, c, d, x[8], S11); /* 9 */ 18922347Spst FF(d, a, b, c, x[9], S12); /* 10 */ 19022347Spst FF(c, d, a, b, x[10], S13); /* 11 */ 19122347Spst FF(b, c, d, a, x[11], S14); /* 12 */ 19222347Spst FF(a, b, c, d, x[12], S11); /* 13 */ 19322347Spst FF(d, a, b, c, x[13], S12); /* 14 */ 19422347Spst FF(c, d, a, b, x[14], S13); /* 15 */ 19522347Spst FF(b, c, d, a, x[15], S14); /* 16 */ 19622347Spst 19722347Spst /* Round 2 */ 19822347Spst GG(a, b, c, d, x[0], S21); /* 17 */ 19922347Spst GG(d, a, b, c, x[4], S22); /* 18 */ 20022347Spst GG(c, d, a, b, x[8], S23); /* 19 */ 20122347Spst GG(b, c, d, a, x[12], S24); /* 20 */ 20222347Spst GG(a, b, c, d, x[1], S21); /* 21 */ 20322347Spst GG(d, a, b, c, x[5], S22); /* 22 */ 20422347Spst GG(c, d, a, b, x[9], S23); /* 23 */ 20522347Spst GG(b, c, d, a, x[13], S24); /* 24 */ 20622347Spst GG(a, b, c, d, x[2], S21); /* 25 */ 20722347Spst GG(d, a, b, c, x[6], S22); /* 26 */ 20822347Spst GG(c, d, a, b, x[10], S23); /* 27 */ 20922347Spst GG(b, c, d, a, x[14], S24); /* 28 */ 21022347Spst GG(a, b, c, d, x[3], S21); /* 29 */ 21122347Spst GG(d, a, b, c, x[7], S22); /* 30 */ 21222347Spst GG(c, d, a, b, x[11], S23); /* 31 */ 21322347Spst GG(b, c, d, a, x[15], S24); /* 32 */ 21422347Spst 21522347Spst /* Round 3 */ 21622347Spst HH(a, b, c, d, x[0], S31); /* 33 */ 21722347Spst HH(d, a, b, c, x[8], S32); /* 34 */ 21822347Spst HH(c, d, a, b, x[4], S33); /* 35 */ 21922347Spst HH(b, c, d, a, x[12], S34); /* 36 */ 22022347Spst HH(a, b, c, d, x[2], S31); /* 37 */ 22122347Spst HH(d, a, b, c, x[10], S32); /* 38 */ 22222347Spst HH(c, d, a, b, x[6], S33); /* 39 */ 22322347Spst HH(b, c, d, a, x[14], S34); /* 40 */ 22422347Spst HH(a, b, c, d, x[1], S31); /* 41 */ 22522347Spst HH(d, a, b, c, x[9], S32); /* 42 */ 22622347Spst HH(c, d, a, b, x[5], S33); /* 43 */ 22722347Spst HH(b, c, d, a, x[13], S34); /* 44 */ 22822347Spst HH(a, b, c, d, x[3], S31); /* 45 */ 22922347Spst HH(d, a, b, c, x[11], S32); /* 46 */ 23022347Spst HH(c, d, a, b, x[7], S33); /* 47 */ 23122347Spst HH(b, c, d, a, x[15], S34); /* 48 */ 23222347Spst 23322347Spst state[0] += a; 23422347Spst state[1] += b; 23522347Spst state[2] += c; 23622347Spst state[3] += d; 23722347Spst 23822347Spst /* Zeroize sensitive information. */ 23922347Spst memset((POINTER) x, 0, sizeof(x)); 24022347Spst} 24122347Spst 24222347Spst/* Encodes input (UINT4) into output (unsigned char). Assumes len is 24322347Spst a multiple of 4. 24422347Spst */ 24522347Spststatic VOIDRET Encode FUNCTION((output, input, len), unsigned char *output AND UINT4 *input AND unsigned int len) 24622347Spst{ 24722347Spst unsigned int i, j; 24822347Spst 24922347Spst for (i = 0, j = 0; j < len; i++, j += 4) { 25022347Spst output[j] = (unsigned char) (input[i] & 0xff); 25122347Spst output[j + 1] = (unsigned char) ((input[i] >> 8) & 0xff); 25222347Spst output[j + 2] = (unsigned char) ((input[i] >> 16) & 0xff); 25322347Spst output[j + 3] = (unsigned char) ((input[i] >> 24) & 0xff); 25422347Spst } 25522347Spst} 25622347Spst 25722347Spst/* Decodes input (unsigned char) into output (UINT4). Assumes len is 25822347Spst a multiple of 4. 25922347Spst */ 26022347Spststatic VOIDRET Decode FUNCTION((output, input, len), UINT4 *output AND unsigned char *input AND unsigned int len) 26122347Spst{ 26222347Spst unsigned int i, j; 26322347Spst 26422347Spst for (i = 0, j = 0; j < len; i++, j += 4) 26522347Spst output[i] = ((UINT4) input[j]) | (((UINT4) input[j + 1]) << 8) | 26622347Spst (((UINT4) input[j + 2]) << 16) | (((UINT4) input[j + 3]) << 24); 26722347Spst} 268