1145519Sdarrenr/* $FreeBSD$ */ 2145510Sdarrenr 3145510Sdarrenr 4145510Sdarrenr 5145510Sdarrenr/* 6145510Sdarrenr *********************************************************************** 7145510Sdarrenr ** md5.c -- the source code for MD5 routines ** 8145510Sdarrenr ** RSA Data Security, Inc. MD5 Message-Digest Algorithm ** 9145510Sdarrenr ** Created: 2/17/90 RLR ** 10145510Sdarrenr ** Revised: 1/91 SRD,AJ,BSK,JT Reference C ver., 7/10 constant corr. ** 11145510Sdarrenr *********************************************************************** 12145510Sdarrenr */ 13145510Sdarrenr 14145510Sdarrenr/* 15145510Sdarrenr *********************************************************************** 16145510Sdarrenr ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** 17145510Sdarrenr ** ** 18145510Sdarrenr ** License to copy and use this software is granted provided that ** 19145510Sdarrenr ** it is identified as the "RSA Data Security, Inc. MD5 Message- ** 20145510Sdarrenr ** Digest Algorithm" in all material mentioning or referencing this ** 21145510Sdarrenr ** software or this function. ** 22145510Sdarrenr ** ** 23145510Sdarrenr ** License is also granted to make and use derivative works ** 24145510Sdarrenr ** provided that such works are identified as "derived from the RSA ** 25145510Sdarrenr ** Data Security, Inc. MD5 Message-Digest Algorithm" in all ** 26145510Sdarrenr ** material mentioning or referencing the derived work. ** 27145510Sdarrenr ** ** 28145510Sdarrenr ** RSA Data Security, Inc. makes no representations concerning ** 29145510Sdarrenr ** either the merchantability of this software or the suitability ** 30145510Sdarrenr ** of this software for any particular purpose. It is provided "as ** 31145510Sdarrenr ** is" without express or implied warranty of any kind. ** 32145510Sdarrenr ** ** 33145510Sdarrenr ** These notices must be retained in any copies of any part of this ** 34145510Sdarrenr ** documentation and/or software. ** 35145510Sdarrenr *********************************************************************** 36145510Sdarrenr */ 37145510Sdarrenr 38255332Scy#if defined(linux) && defined(_KERNEL) 39255332Scyextern void *memcpy(void *, const void *, unsigned long); 40255332Scy# define bcopy(a,b,c) memcpy(b,a,c) 41145510Sdarrenr#else 42255332Scy# if defined(_KERNEL) && !defined(__sgi) 43255332Scy# include <sys/systm.h> 44255332Scy# else 45255332Scy# include <string.h> 46255332Scy# endif 47145510Sdarrenr#endif 48145510Sdarrenr 49145510Sdarrenr#include "md5.h" 50145510Sdarrenr 51145510Sdarrenr/* 52145510Sdarrenr *********************************************************************** 53145510Sdarrenr ** Message-digest routines: ** 54145510Sdarrenr ** To form the message digest for a message M ** 55145510Sdarrenr ** (1) Initialize a context buffer mdContext using MD5Init ** 56145510Sdarrenr ** (2) Call MD5Update on mdContext and M ** 57145510Sdarrenr ** (3) Call MD5Final on mdContext ** 58145510Sdarrenr ** The message digest is now in mdContext->digest[0...15] ** 59145510Sdarrenr *********************************************************************** 60145510Sdarrenr */ 61145510Sdarrenr 62145510Sdarrenr/* forward declaration */ 63145510Sdarrenrstatic void Transform __P((UINT4 *, UINT4 *)); 64145510Sdarrenr 65145510Sdarrenrstatic unsigned char PADDING[64] = { 66145510Sdarrenr 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 67145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 68145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 69145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 70145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73145510Sdarrenr 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 74145510Sdarrenr}; 75145510Sdarrenr 76145510Sdarrenr/* F, G, H and I are basic MD5 functions */ 77145510Sdarrenr#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) 78145510Sdarrenr#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) 79145510Sdarrenr#define H(x, y, z) ((x) ^ (y) ^ (z)) 80145510Sdarrenr#define I(x, y, z) ((y) ^ ((x) | (~z))) 81145510Sdarrenr 82145510Sdarrenr/* ROTATE_LEFT rotates x left n bits */ 83145510Sdarrenr#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) 84145510Sdarrenr 85145510Sdarrenr/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ 86145510Sdarrenr/* Rotation is separate from addition to prevent recomputation */ 87145510Sdarrenr#define FF(a, b, c, d, x, s, ac) \ 88145510Sdarrenr {(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \ 89145510Sdarrenr (a) = ROTATE_LEFT ((a), (s)); \ 90145510Sdarrenr (a) += (b); \ 91145510Sdarrenr } 92145510Sdarrenr#define GG(a, b, c, d, x, s, ac) \ 93145510Sdarrenr {(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \ 94145510Sdarrenr (a) = ROTATE_LEFT ((a), (s)); \ 95145510Sdarrenr (a) += (b); \ 96145510Sdarrenr } 97145510Sdarrenr#define HH(a, b, c, d, x, s, ac) \ 98145510Sdarrenr {(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \ 99145510Sdarrenr (a) = ROTATE_LEFT ((a), (s)); \ 100145510Sdarrenr (a) += (b); \ 101145510Sdarrenr } 102145510Sdarrenr#define II(a, b, c, d, x, s, ac) \ 103145510Sdarrenr {(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \ 104145510Sdarrenr (a) = ROTATE_LEFT ((a), (s)); \ 105145510Sdarrenr (a) += (b); \ 106145510Sdarrenr } 107145510Sdarrenr 108145510Sdarrenr#ifdef __STDC__ 109145510Sdarrenr#define UL(x) x##U 110145510Sdarrenr#else 111145510Sdarrenr#define UL(x) x 112145510Sdarrenr#endif 113145510Sdarrenr 114145510Sdarrenr/* The routine MD5Init initializes the message-digest context 115145510Sdarrenr mdContext. All fields are set to zero. 116145510Sdarrenr */ 117145510Sdarrenrvoid MD5Init (mdContext) 118145510SdarrenrMD5_CTX *mdContext; 119145510Sdarrenr{ 120145510Sdarrenr mdContext->i[0] = mdContext->i[1] = (UINT4)0; 121145510Sdarrenr 122145510Sdarrenr /* Load magic initialization constants. 123145510Sdarrenr */ 124145510Sdarrenr mdContext->buf[0] = (UINT4)0x67452301; 125145510Sdarrenr mdContext->buf[1] = (UINT4)0xefcdab89; 126145510Sdarrenr mdContext->buf[2] = (UINT4)0x98badcfe; 127145510Sdarrenr mdContext->buf[3] = (UINT4)0x10325476; 128145510Sdarrenr} 129145510Sdarrenr 130145510Sdarrenr/* The routine MD5Update updates the message-digest context to 131145510Sdarrenr account for the presence of each of the characters inBuf[0..inLen-1] 132145510Sdarrenr in the message whose digest is being computed. 133145510Sdarrenr */ 134145510Sdarrenrvoid MD5Update (mdContext, inBuf, inLen) 135145510SdarrenrMD5_CTX *mdContext; 136145510Sdarrenrunsigned char *inBuf; 137145510Sdarrenrunsigned int inLen; 138145510Sdarrenr{ 139145510Sdarrenr UINT4 in[16]; 140145510Sdarrenr int mdi; 141145510Sdarrenr unsigned int i, ii; 142145510Sdarrenr 143145510Sdarrenr /* compute number of bytes mod 64 */ 144145510Sdarrenr mdi = (int)((mdContext->i[0] >> 3) & 0x3F); 145145510Sdarrenr 146145510Sdarrenr /* update number of bits */ 147145510Sdarrenr if ((mdContext->i[0] + ((UINT4)inLen << 3)) < mdContext->i[0]) 148145510Sdarrenr mdContext->i[1]++; 149145510Sdarrenr mdContext->i[0] += ((UINT4)inLen << 3); 150145510Sdarrenr mdContext->i[1] += ((UINT4)inLen >> 29); 151145510Sdarrenr 152145510Sdarrenr while (inLen--) { 153145510Sdarrenr /* add new character to buffer, increment mdi */ 154145510Sdarrenr mdContext->in[mdi++] = *inBuf++; 155145510Sdarrenr 156145510Sdarrenr /* transform if necessary */ 157145510Sdarrenr if (mdi == 0x40) { 158145510Sdarrenr for (i = 0, ii = 0; i < 16; i++, ii += 4) 159145510Sdarrenr in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | 160145510Sdarrenr (((UINT4)mdContext->in[ii+2]) << 16) | 161145510Sdarrenr (((UINT4)mdContext->in[ii+1]) << 8) | 162145510Sdarrenr ((UINT4)mdContext->in[ii]); 163145510Sdarrenr Transform (mdContext->buf, in); 164145510Sdarrenr mdi = 0; 165145510Sdarrenr } 166145510Sdarrenr } 167145510Sdarrenr} 168145510Sdarrenr 169145510Sdarrenr/* The routine MD5Final terminates the message-digest computation and 170145510Sdarrenr ends with the desired message digest in mdContext->digest[0...15]. 171145510Sdarrenr */ 172145510Sdarrenrvoid MD5Final (hash, mdContext) 173145510Sdarrenrunsigned char hash[]; 174145510SdarrenrMD5_CTX *mdContext; 175145510Sdarrenr{ 176145510Sdarrenr UINT4 in[16]; 177145510Sdarrenr int mdi; 178145510Sdarrenr unsigned int i, ii; 179145510Sdarrenr unsigned int padLen; 180145510Sdarrenr 181145510Sdarrenr /* save number of bits */ 182145510Sdarrenr in[14] = mdContext->i[0]; 183145510Sdarrenr in[15] = mdContext->i[1]; 184145510Sdarrenr 185145510Sdarrenr /* compute number of bytes mod 64 */ 186145510Sdarrenr mdi = (int)((mdContext->i[0] >> 3) & 0x3F); 187145510Sdarrenr 188145510Sdarrenr /* pad out to 56 mod 64 */ 189145510Sdarrenr padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); 190145510Sdarrenr MD5Update (mdContext, PADDING, padLen); 191145510Sdarrenr 192145510Sdarrenr /* append length in bits and transform */ 193145510Sdarrenr for (i = 0, ii = 0; i < 14; i++, ii += 4) 194145510Sdarrenr in[i] = (((UINT4)mdContext->in[ii+3]) << 24) | 195145510Sdarrenr (((UINT4)mdContext->in[ii+2]) << 16) | 196145510Sdarrenr (((UINT4)mdContext->in[ii+1]) << 8) | 197145510Sdarrenr ((UINT4)mdContext->in[ii]); 198145510Sdarrenr Transform (mdContext->buf, in); 199145510Sdarrenr 200145510Sdarrenr /* store buffer in digest */ 201145510Sdarrenr for (i = 0, ii = 0; i < 4; i++, ii += 4) { 202145510Sdarrenr mdContext->digest[ii] = (unsigned char)(mdContext->buf[i] & 0xFF); 203145510Sdarrenr mdContext->digest[ii+1] = 204145510Sdarrenr (unsigned char)((mdContext->buf[i] >> 8) & 0xFF); 205145510Sdarrenr mdContext->digest[ii+2] = 206145510Sdarrenr (unsigned char)((mdContext->buf[i] >> 16) & 0xFF); 207145510Sdarrenr mdContext->digest[ii+3] = 208145510Sdarrenr (unsigned char)((mdContext->buf[i] >> 24) & 0xFF); 209145510Sdarrenr } 210145510Sdarrenr bcopy((char *)mdContext->digest, (char *)hash, 16); 211145510Sdarrenr} 212145510Sdarrenr 213145510Sdarrenr/* Basic MD5 step. Transforms buf based on in. 214145510Sdarrenr */ 215145510Sdarrenrstatic void Transform (buf, in) 216145510SdarrenrUINT4 *buf; 217145510SdarrenrUINT4 *in; 218145510Sdarrenr{ 219145510Sdarrenr UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; 220145510Sdarrenr 221145510Sdarrenr /* Round 1 */ 222145510Sdarrenr#define S11 7 223145510Sdarrenr#define S12 12 224145510Sdarrenr#define S13 17 225145510Sdarrenr#define S14 22 226145510Sdarrenr FF ( a, b, c, d, in[ 0], S11, UL(3614090360)); /* 1 */ 227145510Sdarrenr FF ( d, a, b, c, in[ 1], S12, UL(3905402710)); /* 2 */ 228145510Sdarrenr FF ( c, d, a, b, in[ 2], S13, UL( 606105819)); /* 3 */ 229145510Sdarrenr FF ( b, c, d, a, in[ 3], S14, UL(3250441966)); /* 4 */ 230145510Sdarrenr FF ( a, b, c, d, in[ 4], S11, UL(4118548399)); /* 5 */ 231145510Sdarrenr FF ( d, a, b, c, in[ 5], S12, UL(1200080426)); /* 6 */ 232145510Sdarrenr FF ( c, d, a, b, in[ 6], S13, UL(2821735955)); /* 7 */ 233145510Sdarrenr FF ( b, c, d, a, in[ 7], S14, UL(4249261313)); /* 8 */ 234145510Sdarrenr FF ( a, b, c, d, in[ 8], S11, UL(1770035416)); /* 9 */ 235145510Sdarrenr FF ( d, a, b, c, in[ 9], S12, UL(2336552879)); /* 10 */ 236145510Sdarrenr FF ( c, d, a, b, in[10], S13, UL(4294925233)); /* 11 */ 237145510Sdarrenr FF ( b, c, d, a, in[11], S14, UL(2304563134)); /* 12 */ 238145510Sdarrenr FF ( a, b, c, d, in[12], S11, UL(1804603682)); /* 13 */ 239145510Sdarrenr FF ( d, a, b, c, in[13], S12, UL(4254626195)); /* 14 */ 240145510Sdarrenr FF ( c, d, a, b, in[14], S13, UL(2792965006)); /* 15 */ 241145510Sdarrenr FF ( b, c, d, a, in[15], S14, UL(1236535329)); /* 16 */ 242145510Sdarrenr 243145510Sdarrenr /* Round 2 */ 244145510Sdarrenr#define S21 5 245145510Sdarrenr#define S22 9 246145510Sdarrenr#define S23 14 247145510Sdarrenr#define S24 20 248145510Sdarrenr GG ( a, b, c, d, in[ 1], S21, UL(4129170786)); /* 17 */ 249145510Sdarrenr GG ( d, a, b, c, in[ 6], S22, UL(3225465664)); /* 18 */ 250145510Sdarrenr GG ( c, d, a, b, in[11], S23, UL( 643717713)); /* 19 */ 251145510Sdarrenr GG ( b, c, d, a, in[ 0], S24, UL(3921069994)); /* 20 */ 252145510Sdarrenr GG ( a, b, c, d, in[ 5], S21, UL(3593408605)); /* 21 */ 253145510Sdarrenr GG ( d, a, b, c, in[10], S22, UL( 38016083)); /* 22 */ 254145510Sdarrenr GG ( c, d, a, b, in[15], S23, UL(3634488961)); /* 23 */ 255145510Sdarrenr GG ( b, c, d, a, in[ 4], S24, UL(3889429448)); /* 24 */ 256145510Sdarrenr GG ( a, b, c, d, in[ 9], S21, UL( 568446438)); /* 25 */ 257145510Sdarrenr GG ( d, a, b, c, in[14], S22, UL(3275163606)); /* 26 */ 258145510Sdarrenr GG ( c, d, a, b, in[ 3], S23, UL(4107603335)); /* 27 */ 259145510Sdarrenr GG ( b, c, d, a, in[ 8], S24, UL(1163531501)); /* 28 */ 260145510Sdarrenr GG ( a, b, c, d, in[13], S21, UL(2850285829)); /* 29 */ 261145510Sdarrenr GG ( d, a, b, c, in[ 2], S22, UL(4243563512)); /* 30 */ 262145510Sdarrenr GG ( c, d, a, b, in[ 7], S23, UL(1735328473)); /* 31 */ 263145510Sdarrenr GG ( b, c, d, a, in[12], S24, UL(2368359562)); /* 32 */ 264145510Sdarrenr 265145510Sdarrenr /* Round 3 */ 266145510Sdarrenr#define S31 4 267145510Sdarrenr#define S32 11 268145510Sdarrenr#define S33 16 269145510Sdarrenr#define S34 23 270145510Sdarrenr HH ( a, b, c, d, in[ 5], S31, UL(4294588738)); /* 33 */ 271145510Sdarrenr HH ( d, a, b, c, in[ 8], S32, UL(2272392833)); /* 34 */ 272145510Sdarrenr HH ( c, d, a, b, in[11], S33, UL(1839030562)); /* 35 */ 273145510Sdarrenr HH ( b, c, d, a, in[14], S34, UL(4259657740)); /* 36 */ 274145510Sdarrenr HH ( a, b, c, d, in[ 1], S31, UL(2763975236)); /* 37 */ 275145510Sdarrenr HH ( d, a, b, c, in[ 4], S32, UL(1272893353)); /* 38 */ 276145510Sdarrenr HH ( c, d, a, b, in[ 7], S33, UL(4139469664)); /* 39 */ 277145510Sdarrenr HH ( b, c, d, a, in[10], S34, UL(3200236656)); /* 40 */ 278145510Sdarrenr HH ( a, b, c, d, in[13], S31, UL( 681279174)); /* 41 */ 279145510Sdarrenr HH ( d, a, b, c, in[ 0], S32, UL(3936430074)); /* 42 */ 280145510Sdarrenr HH ( c, d, a, b, in[ 3], S33, UL(3572445317)); /* 43 */ 281145510Sdarrenr HH ( b, c, d, a, in[ 6], S34, UL( 76029189)); /* 44 */ 282145510Sdarrenr HH ( a, b, c, d, in[ 9], S31, UL(3654602809)); /* 45 */ 283145510Sdarrenr HH ( d, a, b, c, in[12], S32, UL(3873151461)); /* 46 */ 284145510Sdarrenr HH ( c, d, a, b, in[15], S33, UL( 530742520)); /* 47 */ 285145510Sdarrenr HH ( b, c, d, a, in[ 2], S34, UL(3299628645)); /* 48 */ 286145510Sdarrenr 287145510Sdarrenr /* Round 4 */ 288145510Sdarrenr#define S41 6 289145510Sdarrenr#define S42 10 290145510Sdarrenr#define S43 15 291145510Sdarrenr#define S44 21 292145510Sdarrenr II ( a, b, c, d, in[ 0], S41, UL(4096336452)); /* 49 */ 293145510Sdarrenr II ( d, a, b, c, in[ 7], S42, UL(1126891415)); /* 50 */ 294145510Sdarrenr II ( c, d, a, b, in[14], S43, UL(2878612391)); /* 51 */ 295145510Sdarrenr II ( b, c, d, a, in[ 5], S44, UL(4237533241)); /* 52 */ 296145510Sdarrenr II ( a, b, c, d, in[12], S41, UL(1700485571)); /* 53 */ 297145510Sdarrenr II ( d, a, b, c, in[ 3], S42, UL(2399980690)); /* 54 */ 298145510Sdarrenr II ( c, d, a, b, in[10], S43, UL(4293915773)); /* 55 */ 299145510Sdarrenr II ( b, c, d, a, in[ 1], S44, UL(2240044497)); /* 56 */ 300145510Sdarrenr II ( a, b, c, d, in[ 8], S41, UL(1873313359)); /* 57 */ 301145510Sdarrenr II ( d, a, b, c, in[15], S42, UL(4264355552)); /* 58 */ 302145510Sdarrenr II ( c, d, a, b, in[ 6], S43, UL(2734768916)); /* 59 */ 303145510Sdarrenr II ( b, c, d, a, in[13], S44, UL(1309151649)); /* 60 */ 304145510Sdarrenr II ( a, b, c, d, in[ 4], S41, UL(4149444226)); /* 61 */ 305145510Sdarrenr II ( d, a, b, c, in[11], S42, UL(3174756917)); /* 62 */ 306145510Sdarrenr II ( c, d, a, b, in[ 2], S43, UL( 718787259)); /* 63 */ 307145510Sdarrenr II ( b, c, d, a, in[ 9], S44, UL(3951481745)); /* 64 */ 308145510Sdarrenr 309145510Sdarrenr buf[0] += a; 310145510Sdarrenr buf[1] += b; 311145510Sdarrenr buf[2] += c; 312145510Sdarrenr buf[3] += d; 313145510Sdarrenr} 314145510Sdarrenr 315145510Sdarrenr/* 316145510Sdarrenr *********************************************************************** 317145510Sdarrenr ** End of md5.c ** 318145510Sdarrenr ******************************** (cut) ******************************** 319145510Sdarrenr */ 320