src/3rdparty/md4/md4.cpp
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /*
       
     2  * MD4 (RFC-1320) message digest.
       
     3  * Modified from MD5 code by Andrey Panin <pazke@donpac.ru>
       
     4  *
       
     5  * Written by Solar Designer <solar@openwall.com> in 2001, and placed in
       
     6  * the public domain.  There's absolutely no warranty.
       
     7  *
       
     8  * This differs from Colin Plumb's older public domain implementation in
       
     9  * that no 32-bit integer data type is required, there's no compile-time
       
    10  * endianness configuration, and the function prototypes match OpenSSL's.
       
    11  * The primary goals are portability and ease of use.
       
    12  *
       
    13  * This implementation is meant to be fast, but not as fast as possible.
       
    14  * Some known optimizations are not included to reduce source code size
       
    15  * and avoid compile-time configuration.
       
    16  */
       
    17 
       
    18 #include "md4.h"
       
    19 
       
    20 #include <string.h>
       
    21 
       
    22 QT_BEGIN_NAMESPACE
       
    23 
       
    24 /*
       
    25  * The basic MD4 functions.
       
    26  */
       
    27 #define F(x, y, z)	((z) ^ ((x) & ((y) ^ (z))))
       
    28 #define G(x, y, z)	(((x) & (y)) | ((x) & (z)) | ((y) & (z)))
       
    29 #define H(x, y, z)	((x) ^ (y) ^ (z))
       
    30 
       
    31 /*
       
    32  * The MD4 transformation for all four rounds.
       
    33  */
       
    34 #define STEP(f, a, b, c, d, x, s) \
       
    35 	(a) += f((b), (c), (d)) + (x);	 \
       
    36 	(a) = ((a) << (s)) | ((a) >> (32 - (s)))
       
    37 
       
    38 
       
    39 /*
       
    40  * SET reads 4 input bytes in little-endian byte order and stores them
       
    41  * in a properly aligned word in host byte order.
       
    42  *
       
    43  * The check for little-endian architectures which tolerate unaligned
       
    44  * memory accesses is just an optimization.  Nothing will break if it
       
    45  * doesn't work.
       
    46  */
       
    47 #if defined(__i386__) || defined(__x86_64__)
       
    48 #define SET(n) \
       
    49 	(*(const quint32 *)&ptr[(n) * 4])
       
    50 #define GET(n) \
       
    51 	SET(n)
       
    52 #else
       
    53 #define SET(n) \
       
    54 	(ctx->block[(n)] = \
       
    55 	(quint32)ptr[(n) * 4] | \
       
    56 	((quint32)ptr[(n) * 4 + 1] << 8) | \
       
    57 	((quint32)ptr[(n) * 4 + 2] << 16) | \
       
    58 	((quint32)ptr[(n) * 4 + 3] << 24))
       
    59 #define GET(n) \
       
    60 	(ctx->block[(n)])
       
    61 #endif
       
    62 
       
    63 /*
       
    64  * This processes one or more 64-byte data blocks, but does NOT update
       
    65  * the bit counters.  There're no alignment requirements.
       
    66  */
       
    67 static const unsigned char *body(struct md4_context *ctx, const unsigned char *data, size_t size)
       
    68 {
       
    69 	const unsigned char *ptr;
       
    70 	quint32 a, b, c, d;
       
    71 	quint32 saved_a, saved_b, saved_c, saved_d;
       
    72 
       
    73 	ptr = data;
       
    74 
       
    75 	a = ctx->a;
       
    76 	b = ctx->b;
       
    77 	c = ctx->c;
       
    78 	d = ctx->d;
       
    79 
       
    80 	do {
       
    81 		saved_a = a;
       
    82 		saved_b = b;
       
    83 		saved_c = c;
       
    84 		saved_d = d;
       
    85 
       
    86 /* Round 1 */
       
    87 		STEP(F, a, b, c, d, SET( 0),  3);
       
    88 		STEP(F, d, a, b, c, SET( 1),  7);
       
    89 		STEP(F, c, d, a, b, SET( 2), 11);
       
    90 		STEP(F, b, c, d, a, SET( 3), 19);
       
    91 
       
    92 		STEP(F, a, b, c, d, SET( 4),  3);
       
    93 		STEP(F, d, a, b, c, SET( 5),  7);
       
    94 		STEP(F, c, d, a, b, SET( 6), 11);
       
    95 		STEP(F, b, c, d, a, SET( 7), 19);
       
    96 
       
    97 		STEP(F, a, b, c, d, SET( 8),  3);
       
    98 		STEP(F, d, a, b, c, SET( 9),  7);
       
    99 		STEP(F, c, d, a, b, SET(10), 11);
       
   100 		STEP(F, b, c, d, a, SET(11), 19);
       
   101 
       
   102 		STEP(F, a, b, c, d, SET(12),  3);
       
   103 		STEP(F, d, a, b, c, SET(13),  7);
       
   104 		STEP(F, c, d, a, b, SET(14), 11);
       
   105 		STEP(F, b, c, d, a, SET(15), 19);
       
   106 /* Round 2 */
       
   107 		STEP(G, a, b, c, d, GET( 0) + 0x5A827999,  3);
       
   108 		STEP(G, d, a, b, c, GET( 4) + 0x5A827999,  5);
       
   109 		STEP(G, c, d, a, b, GET( 8) + 0x5A827999,  9);
       
   110 		STEP(G, b, c, d, a, GET(12) + 0x5A827999, 13);
       
   111 
       
   112 		STEP(G, a, b, c, d, GET( 1) + 0x5A827999,  3);
       
   113 		STEP(G, d, a, b, c, GET( 5) + 0x5A827999,  5);
       
   114 		STEP(G, c, d, a, b, GET( 9) + 0x5A827999,  9);
       
   115 		STEP(G, b, c, d, a, GET(13) + 0x5A827999, 13);
       
   116 
       
   117 		STEP(G, a, b, c, d, GET( 2) + 0x5A827999,  3);
       
   118 		STEP(G, d, a, b, c, GET( 6) + 0x5A827999,  5);
       
   119 		STEP(G, c, d, a, b, GET(10) + 0x5A827999,  9);
       
   120 		STEP(G, b, c, d, a, GET(14) + 0x5A827999, 13);
       
   121 
       
   122 		STEP(G, a, b, c, d, GET( 3) + 0x5A827999,  3);
       
   123 		STEP(G, d, a, b, c, GET( 7) + 0x5A827999,  5);
       
   124 		STEP(G, c, d, a, b, GET(11) + 0x5A827999,  9);
       
   125 		STEP(G, b, c, d, a, GET(15) + 0x5A827999, 13);
       
   126 /* Round 3 */
       
   127 		STEP(H, a, b, c, d, GET( 0) + 0x6ED9EBA1,  3);
       
   128 		STEP(H, d, a, b, c, GET( 8) + 0x6ED9EBA1,  9);
       
   129 		STEP(H, c, d, a, b, GET( 4) + 0x6ED9EBA1, 11);
       
   130 		STEP(H, b, c, d, a, GET(12) + 0x6ED9EBA1, 15);
       
   131 
       
   132 		STEP(H, a, b, c, d, GET( 2) + 0x6ED9EBA1,  3);
       
   133 		STEP(H, d, a, b, c, GET(10) + 0x6ED9EBA1,  9);
       
   134 		STEP(H, c, d, a, b, GET( 6) + 0x6ED9EBA1, 11);
       
   135 		STEP(H, b, c, d, a, GET(14) + 0x6ED9EBA1, 15);
       
   136 
       
   137 		STEP(H, a, b, c, d, GET( 1) + 0x6ED9EBA1,  3);
       
   138 		STEP(H, d, a, b, c, GET( 9) + 0x6ED9EBA1,  9);
       
   139 		STEP(H, c, d, a, b, GET( 5) + 0x6ED9EBA1, 11);
       
   140 		STEP(H, b, c, d, a, GET(13) + 0x6ED9EBA1, 15);
       
   141 
       
   142 		STEP(H, a, b, c, d, GET( 3) + 0x6ED9EBA1,  3);
       
   143 		STEP(H, d, a, b, c, GET(11) + 0x6ED9EBA1,  9);
       
   144 		STEP(H, c, d, a, b, GET( 7) + 0x6ED9EBA1, 11);
       
   145 		STEP(H, b, c, d, a, GET(15) + 0x6ED9EBA1, 15);
       
   146 
       
   147 		a += saved_a;
       
   148 		b += saved_b;
       
   149 		c += saved_c;
       
   150 		d += saved_d;
       
   151 
       
   152 		ptr += 64;
       
   153 	} while (size -= 64);
       
   154 
       
   155 	ctx->a = a;
       
   156 	ctx->b = b;
       
   157 	ctx->c = c;
       
   158 	ctx->d = d;
       
   159 
       
   160 	return ptr;
       
   161 }
       
   162 
       
   163 static void md4_init(struct md4_context *ctx)
       
   164 {
       
   165 	ctx->a = 0x67452301;
       
   166 	ctx->b = 0xefcdab89;
       
   167 	ctx->c = 0x98badcfe;
       
   168 	ctx->d = 0x10325476;
       
   169 
       
   170 	ctx->lo = 0;
       
   171 	ctx->hi = 0;
       
   172 }
       
   173 
       
   174 static void md4_update(struct md4_context *ctx, const unsigned char *data, size_t size)
       
   175 {
       
   176 	/* @UNSAFE */
       
   177 	quint32 saved_lo;
       
   178 	unsigned long used, free;
       
   179 
       
   180 	saved_lo = ctx->lo;
       
   181 	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
       
   182 		ctx->hi++;
       
   183 	ctx->hi += size >> 29;
       
   184 
       
   185 	used = saved_lo & 0x3f;
       
   186 
       
   187 	if (used) {
       
   188 		free = 64 - used;
       
   189 
       
   190 		if (size < free) {
       
   191 			memcpy(&ctx->buffer[used], data, size);
       
   192 			return;
       
   193 		}
       
   194 
       
   195 		memcpy(&ctx->buffer[used], data, free);
       
   196 		data = (const unsigned char *) data + free;
       
   197 		size -= free;
       
   198 		body(ctx, ctx->buffer, 64);
       
   199 	}
       
   200 
       
   201 	if (size >= 64) {
       
   202 		data = body(ctx, data, size & ~(unsigned long)0x3f);
       
   203 		size &= 0x3f;
       
   204 	}
       
   205 
       
   206 	memcpy(ctx->buffer, data, size);
       
   207 }
       
   208 
       
   209 static void md4_final(struct md4_context *ctx, unsigned char result[MD4_RESULTLEN])
       
   210 {
       
   211 	/* @UNSAFE */
       
   212 	unsigned long used, free;
       
   213 
       
   214 	used = ctx->lo & 0x3f;
       
   215 
       
   216 	ctx->buffer[used++] = 0x80;
       
   217 
       
   218 	free = 64 - used;
       
   219 
       
   220 	if (free < 8) {
       
   221 		memset(&ctx->buffer[used], 0, free);
       
   222 		body(ctx, ctx->buffer, 64);
       
   223 		used = 0;
       
   224 		free = 64;
       
   225 	}
       
   226 
       
   227 	memset(&ctx->buffer[used], 0, free - 8);
       
   228 
       
   229 	ctx->lo <<= 3;
       
   230 	ctx->buffer[56] = ctx->lo;
       
   231 	ctx->buffer[57] = ctx->lo >> 8;
       
   232 	ctx->buffer[58] = ctx->lo >> 16;
       
   233 	ctx->buffer[59] = ctx->lo >> 24;
       
   234 	ctx->buffer[60] = ctx->hi;
       
   235 	ctx->buffer[61] = ctx->hi >> 8;
       
   236 	ctx->buffer[62] = ctx->hi >> 16;
       
   237 	ctx->buffer[63] = ctx->hi >> 24;
       
   238 
       
   239 	body(ctx, ctx->buffer, 64);
       
   240 
       
   241 	result[0] = ctx->a;
       
   242 	result[1] = ctx->a >> 8;
       
   243 	result[2] = ctx->a >> 16;
       
   244 	result[3] = ctx->a >> 24;
       
   245 	result[4] = ctx->b;
       
   246 	result[5] = ctx->b >> 8;
       
   247 	result[6] = ctx->b >> 16;
       
   248 	result[7] = ctx->b >> 24;
       
   249 	result[8] = ctx->c;
       
   250 	result[9] = ctx->c >> 8;
       
   251 	result[10] = ctx->c >> 16;
       
   252 	result[11] = ctx->c >> 24;
       
   253 	result[12] = ctx->d;
       
   254 	result[13] = ctx->d >> 8;
       
   255 	result[14] = ctx->d >> 16;
       
   256 	result[15] = ctx->d >> 24;
       
   257 
       
   258 	memset(ctx, 0, sizeof(*ctx));
       
   259 }
       
   260 
       
   261 #undef F
       
   262 #undef G
       
   263 #undef H
       
   264 
       
   265 QT_END_NAMESPACE