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