1193240Ssam/* $OpenBSD: md5.c,v 1.9 2014/01/08 06:14:57 tedu Exp $ */ 2193240Ssam 3193240Ssam/* 4193240Ssam * This code implements the MD5 message-digest algorithm. 5193240Ssam * The algorithm is due to Ron Rivest. This code was 6193240Ssam * written by Colin Plumb in 1993, no copyright is claimed. 7193240Ssam * This code is in the public domain; do with it what you wish. 8193240Ssam * 9193240Ssam * Equivalent code is available from RSA Data Security, Inc. 10193240Ssam * This code has been tested against that, and is equivalent, 11193240Ssam * except that you don't need to include two pages of legalese 12193240Ssam * with every copy. 13193240Ssam * 14193240Ssam * To compute the message digest of a chunk of bytes, declare an 15193240Ssam * MD5Context structure, pass it to MD5Init, call MD5Update as 16193240Ssam * needed on buffers full of bytes, and then call MD5Final, which 17193240Ssam * will fill a supplied 16-byte array with the digest. 18193240Ssam */ 19193240Ssam 20193240Ssam#include "includes.h" 21193240Ssam 22193240Ssam#ifndef WITH_OPENSSL 23193240Ssam 24193240Ssam#include <sys/types.h> 25193240Ssam#include <string.h> 26193240Ssam#include "md5.h" 27193240Ssam 28193240Ssam#define PUT_64BIT_LE(cp, value) do { \ 29193240Ssam (cp)[7] = (value) >> 56; \ 30193240Ssam (cp)[6] = (value) >> 48; \ 31193240Ssam (cp)[5] = (value) >> 40; \ 32193240Ssam (cp)[4] = (value) >> 32; \ 33193240Ssam (cp)[3] = (value) >> 24; \ 34193240Ssam (cp)[2] = (value) >> 16; \ 35193240Ssam (cp)[1] = (value) >> 8; \ 36193240Ssam (cp)[0] = (value); } while (0) 37193240Ssam 38193240Ssam#define PUT_32BIT_LE(cp, value) do { \ 39193240Ssam (cp)[3] = (value) >> 24; \ 40193240Ssam (cp)[2] = (value) >> 16; \ 41193240Ssam (cp)[1] = (value) >> 8; \ 42193240Ssam (cp)[0] = (value); } while (0) 43193240Ssam 44193240Ssamstatic u_int8_t PADDING[MD5_BLOCK_LENGTH] = { 45193240Ssam 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 46193240Ssam 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 47193240Ssam 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 48193240Ssam}; 49193240Ssam 50193240Ssam/* 51193240Ssam * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious 52193240Ssam * initialization constants. 53193240Ssam */ 54193240Ssamvoid 55193240SsamMD5Init(MD5_CTX *ctx) 56193240Ssam{ 57193240Ssam ctx->count = 0; 58193240Ssam ctx->state[0] = 0x67452301; 59193240Ssam ctx->state[1] = 0xefcdab89; 60193240Ssam ctx->state[2] = 0x98badcfe; 61193240Ssam ctx->state[3] = 0x10325476; 62193240Ssam} 63193240Ssam 64193240Ssam/* 65193240Ssam * Update context to reflect the concatenation of another buffer full 66193240Ssam * of bytes. 67193240Ssam */ 68193240Ssamvoid 69193240SsamMD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len) 70193240Ssam{ 71193240Ssam size_t have, need; 72193240Ssam 73193240Ssam /* Check how many bytes we already have and how many more we need. */ 74193240Ssam have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); 75193240Ssam need = MD5_BLOCK_LENGTH - have; 76193240Ssam 77193240Ssam /* Update bitcount */ 78193240Ssam ctx->count += (u_int64_t)len << 3; 79193240Ssam 80193240Ssam if (len >= need) { 81193240Ssam if (have != 0) { 82193240Ssam memcpy(ctx->buffer + have, input, need); 83193240Ssam MD5Transform(ctx->state, ctx->buffer); 84193240Ssam input += need; 85193240Ssam len -= need; 86193240Ssam have = 0; 87193240Ssam } 88193240Ssam 89193240Ssam /* Process data in MD5_BLOCK_LENGTH-byte chunks. */ 90193240Ssam while (len >= MD5_BLOCK_LENGTH) { 91193240Ssam MD5Transform(ctx->state, input); 92193240Ssam input += MD5_BLOCK_LENGTH; 93193240Ssam len -= MD5_BLOCK_LENGTH; 94193240Ssam } 95193240Ssam } 96193240Ssam 97193240Ssam /* Handle any remaining bytes of data. */ 98193240Ssam if (len != 0) 99193240Ssam memcpy(ctx->buffer + have, input, len); 100193240Ssam} 101193240Ssam 102193240Ssam/* 103193240Ssam * Pad pad to 64-byte boundary with the bit pattern 104193240Ssam * 1 0* (64-bit count of bits processed, MSB-first) 105193240Ssam */ 106193240Ssamvoid 107193240SsamMD5Pad(MD5_CTX *ctx) 108193240Ssam{ 109193240Ssam u_int8_t count[8]; 110193240Ssam size_t padlen; 111193240Ssam 112193240Ssam /* Convert count to 8 bytes in little endian order. */ 113193240Ssam PUT_64BIT_LE(count, ctx->count); 114193240Ssam 115193240Ssam /* Pad out to 56 mod 64. */ 116193240Ssam padlen = MD5_BLOCK_LENGTH - 117193240Ssam ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1)); 118195171Ssam if (padlen < 1 + 8) 119193240Ssam padlen += MD5_BLOCK_LENGTH; 120193240Ssam MD5Update(ctx, PADDING, padlen - 8); /* padlen - 8 <= 64 */ 121193240Ssam MD5Update(ctx, count, 8); 122193240Ssam} 123193240Ssam 124193240Ssam/* 125193240Ssam * Final wrapup--call MD5Pad, fill in digest and zero out ctx. 126193240Ssam */ 127193240Ssamvoid 128193240SsamMD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx) 129193240Ssam{ 130193240Ssam int i; 131193240Ssam 132193240Ssam MD5Pad(ctx); 133193240Ssam for (i = 0; i < 4; i++) 134193240Ssam PUT_32BIT_LE(digest + i * 4, ctx->state[i]); 135193240Ssam memset(ctx, 0, sizeof(*ctx)); 136193240Ssam} 137193240Ssam 138193240Ssam 139193240Ssam/* The four core functions - F1 is optimized somewhat */ 140193240Ssam 141193240Ssam/* #define F1(x, y, z) (x & y | ~x & z) */ 142193240Ssam#define F1(x, y, z) (z ^ (x & (y ^ z))) 143193240Ssam#define F2(x, y, z) F1(z, x, y) 144193240Ssam#define F3(x, y, z) (x ^ y ^ z) 145193240Ssam#define F4(x, y, z) (y ^ (x | ~z)) 146193240Ssam 147193240Ssam/* This is the central step in the MD5 algorithm. */ 148193240Ssam#define MD5STEP(f, w, x, y, z, data, s) \ 149193240Ssam ( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x ) 150193240Ssam 151193240Ssam/* 152193240Ssam * The core of the MD5 algorithm, this alters an existing MD5 hash to 153193240Ssam * reflect the addition of 16 longwords of new data. MD5Update blocks 154193240Ssam * the data and converts bytes into longwords for this routine. 155193240Ssam */ 156193240Ssamvoid 157193240SsamMD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH]) 158193240Ssam{ 159193240Ssam u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4]; 160193240Ssam 161193240Ssam#if BYTE_ORDER == LITTLE_ENDIAN 162193240Ssam memcpy(in, block, sizeof(in)); 163193240Ssam#else 164193240Ssam for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) { 165193240Ssam in[a] = (u_int32_t)( 166193240Ssam (u_int32_t)(block[a * 4 + 0]) | 167193240Ssam (u_int32_t)(block[a * 4 + 1]) << 8 | 168193240Ssam (u_int32_t)(block[a * 4 + 2]) << 16 | 169193240Ssam (u_int32_t)(block[a * 4 + 3]) << 24); 170193240Ssam } 171193240Ssam#endif 172193240Ssam 173193240Ssam a = state[0]; 174193240Ssam b = state[1]; 175193240Ssam c = state[2]; 176193240Ssam d = state[3]; 177193240Ssam 178193240Ssam MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478, 7); 179193240Ssam MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12); 180193240Ssam MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17); 181193240Ssam MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22); 182193240Ssam MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf, 7); 183193240Ssam MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12); 184193240Ssam MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17); 185193240Ssam MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22); 186193240Ssam MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8, 7); 187193240Ssam MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12); 188193240Ssam MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 189193240Ssam MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 190193240Ssam MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 191193240Ssam MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 192193240Ssam MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 193248085Smarius MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 194248085Smarius 195193240Ssam MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562, 5); 196193240Ssam MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340, 9); 197193240Ssam MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 198193240Ssam MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20); 199193240Ssam MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d, 5); 200193240Ssam MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 201193240Ssam MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 202193240Ssam MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20); 203193240Ssam MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6, 5); 204193240Ssam MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 205193240Ssam MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14); 206193240Ssam MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20); 207193240Ssam MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 208193240Ssam MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8, 9); 209193240Ssam MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14); 210193240Ssam MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 211193240Ssam 212193240Ssam MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942, 4); 213193240Ssam MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11); 214193240Ssam MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 215193240Ssam MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 216193240Ssam MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44, 4); 217193240Ssam MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11); 218193240Ssam MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16); 219193240Ssam MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 220193240Ssam MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 221193240Ssam MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11); 222193240Ssam MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16); 223193240Ssam MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23); 224193240Ssam MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039, 4); 225193240Ssam MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 226193240Ssam MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 227193240Ssam MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23); 228193240Ssam 229193240Ssam MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244, 6); 230193240Ssam MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10); 231193240Ssam MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 232193240Ssam MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21); 233193240Ssam MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 234193240Ssam MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10); 235193240Ssam MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 236193240Ssam MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21); 237193240Ssam MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f, 6); 238193240Ssam MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 239193240Ssam MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15); 240193240Ssam MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 241193240Ssam MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82, 6); 242193240Ssam MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 243193240Ssam MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15); 244193240Ssam MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21); 245193240Ssam 246193240Ssam state[0] += a; 247193240Ssam state[1] += b; 248193240Ssam state[2] += c; 249193240Ssam state[3] += d; 250193240Ssam} 251193240Ssam#endif /* !WITH_OPENSSL */ 252193240Ssam