1/*- 2 Copyright (C) 1990-2, RSA Data Security, Inc. All rights reserved. 3 4 License to copy and use this software is granted provided that it 5 is identified as the "RSA Data Security, Inc. MD4 Message-Digest 6 Algorithm" in all material mentioning or referencing this software 7 or this function. 8 9 License is also granted to make and use derivative works provided 10 that such works are identified as "derived from the RSA Data 11 Security, Inc. MD4 Message-Digest Algorithm" in all material 12 mentioning or referencing the derived work. 13 14 RSA Data Security, Inc. makes no representations concerning either 15 the merchantability of this software or the suitability of this 16 software for any particular purpose. It is provided "as is" 17 without express or implied warranty of any kind. 18 19 These notices must be retained in any copies of any part of this 20 documentation and/or software. 21 */ 22 23#include "setup.h" 24 25/* NSS crypto library does not provide the MD4 hash algorithm, so that we have 26 * a local implementation of it */ 27#ifdef USE_NSS 28 29#include "curl_md4.h" 30 31typedef unsigned int UINT4; 32 33typedef struct MD4Context { 34 UINT4 state[4]; /* state (ABCD) */ 35 UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ 36 unsigned char buffer[64]; /* input buffer */ 37} MD4_CTX; 38 39/* Constants for MD4Transform routine. 40 */ 41#define S11 3 42#define S12 7 43#define S13 11 44#define S14 19 45#define S21 3 46#define S22 5 47#define S23 9 48#define S24 13 49#define S31 3 50#define S32 9 51#define S33 11 52#define S34 15 53 54static void MD4Transform(UINT4 [4], const unsigned char [64]); 55static void Encode(unsigned char *, UINT4 *, unsigned int); 56static void Decode(UINT4 *, const unsigned char *, unsigned int); 57 58static unsigned char PADDING[64] = { 59 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 61 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 62}; 63 64/* F, G and H are basic MD4 functions. 65 */ 66#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 67#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 68#define H(x, y, z) ((x) ^ (y) ^ (z)) 69 70/* ROTATE_LEFT rotates x left n bits. 71 */ 72#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 73 74/* FF, GG and HH are transformations for rounds 1, 2 and 3 */ 75/* Rotation is separate from addition to prevent recomputation */ 76#define FF(a, b, c, d, x, s) { \ 77 (a) += F ((b), (c), (d)) + (x); \ 78 (a) = ROTATE_LEFT ((a), (s)); \ 79 } 80#define GG(a, b, c, d, x, s) { \ 81 (a) += G ((b), (c), (d)) + (x) + (UINT4)0x5a827999; \ 82 (a) = ROTATE_LEFT ((a), (s)); \ 83 } 84#define HH(a, b, c, d, x, s) { \ 85 (a) += H ((b), (c), (d)) + (x) + (UINT4)0x6ed9eba1; \ 86 (a) = ROTATE_LEFT ((a), (s)); \ 87 } 88 89/* MD4 initialization. Begins an MD4 operation, writing a new context. 90 */ 91static void MD4Init(MD4_CTX *context) 92{ 93 context->count[0] = context->count[1] = 0; 94 95 /* Load magic initialization constants. 96 */ 97 context->state[0] = 0x67452301; 98 context->state[1] = 0xefcdab89; 99 context->state[2] = 0x98badcfe; 100 context->state[3] = 0x10325476; 101} 102 103/* MD4 block update operation. Continues an MD4 message-digest 104 operation, processing another message block, and updating the 105 context. 106 */ 107static void MD4Update(MD4_CTX *context, const unsigned char *input, 108 unsigned int inputLen) 109{ 110 unsigned int i, bufindex, partLen; 111 112 /* Compute number of bytes mod 64 */ 113 bufindex = (unsigned int)((context->count[0] >> 3) & 0x3F); 114 /* Update number of bits */ 115 if((context->count[0] += ((UINT4)inputLen << 3)) 116 < ((UINT4)inputLen << 3)) 117 context->count[1]++; 118 context->count[1] += ((UINT4)inputLen >> 29); 119 120 partLen = 64 - bufindex; 121 /* Transform as many times as possible. 122 */ 123 if(inputLen >= partLen) { 124 memcpy(&context->buffer[bufindex], input, partLen); 125 MD4Transform (context->state, context->buffer); 126 127 for(i = partLen; i + 63 < inputLen; i += 64) 128 MD4Transform (context->state, &input[i]); 129 130 bufindex = 0; 131 } 132 else 133 i = 0; 134 135 /* Buffer remaining input */ 136 memcpy(&context->buffer[bufindex], &input[i], inputLen-i); 137} 138 139/* MD4 padding. */ 140static void MD4Pad(MD4_CTX *context) 141{ 142 unsigned char bits[8]; 143 unsigned int bufindex, padLen; 144 145 /* Save number of bits */ 146 Encode (bits, context->count, 8); 147 148 /* Pad out to 56 mod 64. 149 */ 150 bufindex = (unsigned int)((context->count[0] >> 3) & 0x3f); 151 padLen = (bufindex < 56) ? (56 - bufindex) : (120 - bufindex); 152 MD4Update (context, PADDING, padLen); 153 154 /* Append length (before padding) */ 155 MD4Update (context, bits, 8); 156} 157 158/* MD4 finalization. Ends an MD4 message-digest operation, writing the 159 the message digest and zeroizing the context. 160 */ 161static void MD4Final (unsigned char digest[16], MD4_CTX *context) 162{ 163 /* Do padding */ 164 MD4Pad (context); 165 166 /* Store state in digest */ 167 Encode (digest, context->state, 16); 168 169 /* Zeroize sensitive information. 170 */ 171 memset(context, 0, sizeof(*context)); 172} 173 174/* MD4 basic transformation. Transforms state based on block. 175 */ 176static void MD4Transform (UINT4 state[4], const unsigned char block[64]) 177{ 178 UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 179 180 Decode (x, block, 64); 181 182 /* Round 1 */ 183 FF (a, b, c, d, x[ 0], S11); /* 1 */ 184 FF (d, a, b, c, x[ 1], S12); /* 2 */ 185 FF (c, d, a, b, x[ 2], S13); /* 3 */ 186 FF (b, c, d, a, x[ 3], S14); /* 4 */ 187 FF (a, b, c, d, x[ 4], S11); /* 5 */ 188 FF (d, a, b, c, x[ 5], S12); /* 6 */ 189 FF (c, d, a, b, x[ 6], S13); /* 7 */ 190 FF (b, c, d, a, x[ 7], S14); /* 8 */ 191 FF (a, b, c, d, x[ 8], S11); /* 9 */ 192 FF (d, a, b, c, x[ 9], S12); /* 10 */ 193 FF (c, d, a, b, x[10], S13); /* 11 */ 194 FF (b, c, d, a, x[11], S14); /* 12 */ 195 FF (a, b, c, d, x[12], S11); /* 13 */ 196 FF (d, a, b, c, x[13], S12); /* 14 */ 197 FF (c, d, a, b, x[14], S13); /* 15 */ 198 FF (b, c, d, a, x[15], S14); /* 16 */ 199 200 /* Round 2 */ 201 GG (a, b, c, d, x[ 0], S21); /* 17 */ 202 GG (d, a, b, c, x[ 4], S22); /* 18 */ 203 GG (c, d, a, b, x[ 8], S23); /* 19 */ 204 GG (b, c, d, a, x[12], S24); /* 20 */ 205 GG (a, b, c, d, x[ 1], S21); /* 21 */ 206 GG (d, a, b, c, x[ 5], S22); /* 22 */ 207 GG (c, d, a, b, x[ 9], S23); /* 23 */ 208 GG (b, c, d, a, x[13], S24); /* 24 */ 209 GG (a, b, c, d, x[ 2], S21); /* 25 */ 210 GG (d, a, b, c, x[ 6], S22); /* 26 */ 211 GG (c, d, a, b, x[10], S23); /* 27 */ 212 GG (b, c, d, a, x[14], S24); /* 28 */ 213 GG (a, b, c, d, x[ 3], S21); /* 29 */ 214 GG (d, a, b, c, x[ 7], S22); /* 30 */ 215 GG (c, d, a, b, x[11], S23); /* 31 */ 216 GG (b, c, d, a, x[15], S24); /* 32 */ 217 218 /* Round 3 */ 219 HH (a, b, c, d, x[ 0], S31); /* 33 */ 220 HH (d, a, b, c, x[ 8], S32); /* 34 */ 221 HH (c, d, a, b, x[ 4], S33); /* 35 */ 222 HH (b, c, d, a, x[12], S34); /* 36 */ 223 HH (a, b, c, d, x[ 2], S31); /* 37 */ 224 HH (d, a, b, c, x[10], S32); /* 38 */ 225 HH (c, d, a, b, x[ 6], S33); /* 39 */ 226 HH (b, c, d, a, x[14], S34); /* 40 */ 227 HH (a, b, c, d, x[ 1], S31); /* 41 */ 228 HH (d, a, b, c, x[ 9], S32); /* 42 */ 229 HH (c, d, a, b, x[ 5], S33); /* 43 */ 230 HH (b, c, d, a, x[13], S34); /* 44 */ 231 HH (a, b, c, d, x[ 3], S31); /* 45 */ 232 HH (d, a, b, c, x[11], S32); /* 46 */ 233 HH (c, d, a, b, x[ 7], S33); /* 47 */ 234 HH (b, c, d, a, x[15], S34); /* 48 */ 235 236 state[0] += a; 237 state[1] += b; 238 state[2] += c; 239 state[3] += d; 240 241 /* Zeroize sensitive information. 242 */ 243 memset(x, 0, sizeof(x)); 244} 245 246/* Encodes input (UINT4) into output (unsigned char). Assumes len is 247 a multiple of 4. 248 */ 249static void Encode(unsigned char *output, UINT4 *input, unsigned int len) 250{ 251 unsigned int i, j; 252 253 for(i = 0, j = 0; j < len; i++, j += 4) { 254 output[j] = (unsigned char)(input[i] & 0xff); 255 output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); 256 output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); 257 output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); 258 } 259} 260 261/* Decodes input (unsigned char) into output (UINT4). Assumes len is 262 a multiple of 4. 263 */ 264static void Decode (UINT4 *output, const unsigned char *input, 265 unsigned int len) 266{ 267 unsigned int i, j; 268 269 for(i = 0, j = 0; j < len; i++, j += 4) 270 output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) | 271 (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24); 272} 273 274void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len) 275{ 276 MD4_CTX ctx; 277 MD4Init(&ctx); 278 MD4Update(&ctx, input, (unsigned int)len); 279 MD4Final(output, &ctx); 280} 281#endif /* USE_NSS */ 282