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