Return to md4_hasher.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / md4 |
1.1 misho 1: /* 2: * Copyright (C) 2005-2006 Martin Willi 3: * Copyright (C) 2005 Jan Hutter 4: * HSR Hochschule fuer Technik Rapperswil 5: * Copyright (C) 1990-1992, RSA Data Security, Inc. Created 1990. 6: * All rights reserved. 7: * 8: * Derived from the RSA Data Security, Inc. MD4 Message-Digest Algorithm. 9: * Ported to fulfill hasher_t interface. 10: * 11: * This program is free software; you can redistribute it and/or modify it 12: * under the terms of the GNU General Public License as published by the 13: * Free Software Foundation; either version 2 of the License, or (at your 14: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 15: * 16: * This program is distributed in the hope that it will be useful, but 17: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 18: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 19: * for more details. 20: */ 21: 22: #include <string.h> 23: 24: #include "md4_hasher.h" 25: 26: /* 27: * Constants for MD4Transform routine. 28: */ 29: #define S11 3 30: #define S12 7 31: #define S13 11 32: #define S14 19 33: #define S21 3 34: #define S22 5 35: #define S23 9 36: #define S24 13 37: #define S31 3 38: #define S32 9 39: #define S33 11 40: #define S34 15 41: 42: static uint8_t PADDING[64] = { 43: 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 46: }; 47: 48: /* 49: * F, G, H and I are basic MD4 functions. 50: */ 51: #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 52: #define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) 53: #define H(x, y, z) ((x) ^ (y) ^ (z)) 54: 55: /* 56: * ROTATE_LEFT rotates x left n bits. 57: */ 58: #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 59: 60: /* FF, GG and HH are transformations for rounds 1, 2 and 3 61: * Rotation is separate from addition to prevent recomputation 62: */ 63: #define FF(a, b, c, d, x, s) { \ 64: (a) += F ((b), (c), (d)) + (x); \ 65: (a) = ROTATE_LEFT ((a), (s)); \ 66: } 67: #define GG(a, b, c, d, x, s) { \ 68: (a) += G ((b), (c), (d)) + (x) + (uint32_t)0x5a827999; \ 69: (a) = ROTATE_LEFT ((a), (s)); \ 70: } 71: #define HH(a, b, c, d, x, s) { \ 72: (a) += H ((b), (c), (d)) + (x) + (uint32_t)0x6ed9eba1; \ 73: (a) = ROTATE_LEFT ((a), (s)); \ 74: } 75: 76: typedef struct private_md4_hasher_t private_md4_hasher_t; 77: 78: /** 79: * Private data structure with hashing context. 80: */ 81: struct private_md4_hasher_t { 82: /** 83: * Public interface for this hasher. 84: */ 85: md4_hasher_t public; 86: 87: /* 88: * State of the hasher. 89: */ 90: uint32_t state[4]; 91: uint32_t count[2]; 92: uint8_t buffer[64]; 93: }; 94: 95: #if BYTE_ORDER != LITTLE_ENDIAN 96: 97: /* Encodes input (uint32_t) into output (uint8_t). Assumes len is 98: * a multiple of 4. 99: */ 100: static void Encode (uint8_t *output, uint32_t *input, size_t len) 101: { 102: size_t i, j; 103: 104: for (i = 0, j = 0; j < len; i++, j += 4) 105: { 106: output[j] = (uint8_t)(input[i] & 0xff); 107: output[j+1] = (uint8_t)((input[i] >> 8) & 0xff); 108: output[j+2] = (uint8_t)((input[i] >> 16) & 0xff); 109: output[j+3] = (uint8_t)((input[i] >> 24) & 0xff); 110: } 111: } 112: 113: /* Decodes input (uint8_t) into output (uint32_t). Assumes len is 114: * a multiple of 4. 115: */ 116: static void Decode(uint32_t *output, uint8_t *input, size_t len) 117: { 118: size_t i, j; 119: 120: for (i = 0, j = 0; j < len; i++, j += 4) 121: { 122: output[i] = ((uint32_t)input[j]) | (((uint32_t)input[j+1]) << 8) | 123: (((uint32_t)input[j+2]) << 16) | (((uint32_t)input[j+3]) << 24); 124: } 125: } 126: 127: #elif BYTE_ORDER == LITTLE_ENDIAN 128: #define Encode memcpy 129: #define Decode memcpy 130: #endif 131: 132: /* 133: * MD4 basic transformation. Transforms state based on block. 134: */ 135: static void MD4Transform(uint32_t state[4], uint8_t block[64]) 136: { 137: uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 138: 139: Decode(x, block, 64); 140: 141: /* Round 1 */ 142: FF (a, b, c, d, x[ 0], S11); /* 1 */ 143: FF (d, a, b, c, x[ 1], S12); /* 2 */ 144: FF (c, d, a, b, x[ 2], S13); /* 3 */ 145: FF (b, c, d, a, x[ 3], S14); /* 4 */ 146: FF (a, b, c, d, x[ 4], S11); /* 5 */ 147: FF (d, a, b, c, x[ 5], S12); /* 6 */ 148: FF (c, d, a, b, x[ 6], S13); /* 7 */ 149: FF (b, c, d, a, x[ 7], S14); /* 8 */ 150: FF (a, b, c, d, x[ 8], S11); /* 9 */ 151: FF (d, a, b, c, x[ 9], S12); /* 10 */ 152: FF (c, d, a, b, x[10], S13); /* 11 */ 153: FF (b, c, d, a, x[11], S14); /* 12 */ 154: FF (a, b, c, d, x[12], S11); /* 13 */ 155: FF (d, a, b, c, x[13], S12); /* 14 */ 156: FF (c, d, a, b, x[14], S13); /* 15 */ 157: FF (b, c, d, a, x[15], S14); /* 16 */ 158: 159: /* Round 2 */ 160: GG (a, b, c, d, x[ 0], S21); /* 17 */ 161: GG (d, a, b, c, x[ 4], S22); /* 18 */ 162: GG (c, d, a, b, x[ 8], S23); /* 19 */ 163: GG (b, c, d, a, x[12], S24); /* 20 */ 164: GG (a, b, c, d, x[ 1], S21); /* 21 */ 165: GG (d, a, b, c, x[ 5], S22); /* 22 */ 166: GG (c, d, a, b, x[ 9], S23); /* 23 */ 167: GG (b, c, d, a, x[13], S24); /* 24 */ 168: GG (a, b, c, d, x[ 2], S21); /* 25 */ 169: GG (d, a, b, c, x[ 6], S22); /* 26 */ 170: GG (c, d, a, b, x[10], S23); /* 27 */ 171: GG (b, c, d, a, x[14], S24); /* 28 */ 172: GG (a, b, c, d, x[ 3], S21); /* 29 */ 173: GG (d, a, b, c, x[ 7], S22); /* 30 */ 174: GG (c, d, a, b, x[11], S23); /* 31 */ 175: GG (b, c, d, a, x[15], S24); /* 32 */ 176: 177: /* Round 3 */ 178: HH (a, b, c, d, x[ 0], S31); /* 33 */ 179: HH (d, a, b, c, x[ 8], S32); /* 34 */ 180: HH (c, d, a, b, x[ 4], S33); /* 35 */ 181: HH (b, c, d, a, x[12], S34); /* 36 */ 182: HH (a, b, c, d, x[ 2], S31); /* 37 */ 183: HH (d, a, b, c, x[10], S32); /* 38 */ 184: HH (c, d, a, b, x[ 6], S33); /* 39 */ 185: HH (b, c, d, a, x[14], S34); /* 40 */ 186: HH (a, b, c, d, x[ 1], S31); /* 41 */ 187: HH (d, a, b, c, x[ 9], S32); /* 42 */ 188: HH (c, d, a, b, x[ 5], S33); /* 43 */ 189: HH (b, c, d, a, x[13], S34); /* 44 */ 190: HH (a, b, c, d, x[ 3], S31); /* 45 */ 191: HH (d, a, b, c, x[11], S32); /* 46 */ 192: HH (c, d, a, b, x[ 7], S33); /* 47 */ 193: HH (b, c, d, a, x[15], S34); /* 48 */ 194: 195: state[0] += a; 196: state[1] += b; 197: state[2] += c; 198: state[3] += d; 199: } 200: 201: /* MD4 block update operation. Continues an MD4 message-digest 202: * operation, processing another message block, and updating the 203: * context. 204: */ 205: static void MD4Update(private_md4_hasher_t *this, uint8_t *input, size_t inputLen) 206: { 207: uint32_t i; 208: size_t index, partLen; 209: 210: /* Compute number of bytes mod 64 */ 211: index = (uint8_t)((this->count[0] >> 3) & 0x3F); 212: 213: /* Update number of bits */ 214: if ((this->count[0] += (inputLen << 3)) < (inputLen << 3)) 215: { 216: this->count[1]++; 217: } 218: this->count[1] += (inputLen >> 29); 219: 220: partLen = 64 - index; 221: 222: /* Transform as many times as possible. */ 223: if (inputLen >= partLen) 224: { 225: memcpy(&this->buffer[index], input, partLen); 226: MD4Transform (this->state, this->buffer); 227: 228: for (i = partLen; i + 63 < inputLen; i += 64) 229: { 230: MD4Transform (this->state, &input[i]); 231: } 232: index = 0; 233: } 234: else 235: { 236: i = 0; 237: } 238: 239: /* Buffer remaining input */ 240: memcpy(&this->buffer[index], &input[i], inputLen-i); 241: } 242: 243: /* MD4 finalization. Ends an MD4 message-digest operation, writing the 244: * the message digest and zeroizing the context. 245: */ 246: static void MD4Final (private_md4_hasher_t *this, uint8_t digest[16]) 247: { 248: uint8_t bits[8]; 249: size_t index, padLen; 250: 251: /* Save number of bits */ 252: Encode (bits, this->count, 8); 253: 254: /* Pad out to 56 mod 64. */ 255: index = (size_t)((this->count[0] >> 3) & 0x3f); 256: padLen = (index < 56) ? (56 - index) : (120 - index); 257: MD4Update (this, PADDING, padLen); 258: 259: /* Append length (before padding) */ 260: MD4Update (this, bits, 8); 261: 262: if (digest != NULL) /* Bill Simpson's padding */ 263: { 264: /* store state in digest */ 265: Encode (digest, this->state, 16); 266: } 267: } 268: 269: METHOD(hasher_t, reset, bool, 270: private_md4_hasher_t *this) 271: { 272: this->state[0] = 0x67452301; 273: this->state[1] = 0xefcdab89; 274: this->state[2] = 0x98badcfe; 275: this->state[3] = 0x10325476; 276: this->count[0] = 0; 277: this->count[1] = 0; 278: 279: return TRUE; 280: } 281: 282: METHOD(hasher_t, get_hash, bool, 283: private_md4_hasher_t *this, chunk_t chunk, uint8_t *buffer) 284: { 285: MD4Update(this, chunk.ptr, chunk.len); 286: if (buffer != NULL) 287: { 288: MD4Final(this, buffer); 289: reset(this); 290: } 291: return TRUE; 292: } 293: 294: METHOD(hasher_t, allocate_hash, bool, 295: private_md4_hasher_t *this, chunk_t chunk, chunk_t *hash) 296: { 297: chunk_t allocated_hash; 298: 299: MD4Update(this, chunk.ptr, chunk.len); 300: if (hash != NULL) 301: { 302: allocated_hash.ptr = malloc(HASH_SIZE_MD4); 303: allocated_hash.len = HASH_SIZE_MD4; 304: 305: MD4Final(this, allocated_hash.ptr); 306: reset(this); 307: 308: *hash = allocated_hash; 309: } 310: return TRUE; 311: } 312: 313: METHOD(hasher_t, get_hash_size, size_t, 314: private_md4_hasher_t *this) 315: { 316: return HASH_SIZE_MD4; 317: } 318: 319: METHOD(hasher_t, destroy, void, 320: private_md4_hasher_t *this) 321: { 322: free(this); 323: } 324: 325: /* 326: * Described in header. 327: */ 328: md4_hasher_t *md4_hasher_create(hash_algorithm_t algo) 329: { 330: private_md4_hasher_t *this; 331: 332: if (algo != HASH_MD4) 333: { 334: return NULL; 335: } 336: 337: INIT(this, 338: .public = { 339: .hasher_interface = { 340: .get_hash = _get_hash, 341: .allocate_hash = _allocate_hash, 342: .get_hash_size = _get_hash_size, 343: .reset = _reset, 344: .destroy = _destroy, 345: }, 346: }, 347: ); 348: 349: /* initialize */ 350: reset(this); 351: 352: return &(this->public); 353: }