1139749Simp/* $NetBSD$ */ 250702Swpaul 350702Swpaul/* crypto/md/md5_dgst.c */ 450702Swpaul/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com) 550702Swpaul * All rights reserved. 650702Swpaul * 750702Swpaul * This package is an SSL implementation written 850702Swpaul * by Eric Young (eay@cryptsoft.com). 950702Swpaul * The implementation was written so as to conform with Netscapes SSL. 1050702Swpaul * 1150702Swpaul * This library is free for commercial and non-commercial use as long as 1250702Swpaul * the following conditions are aheared to. The following conditions 1350702Swpaul * apply to all code found in this distribution, be it the RC4, RSA, 1450702Swpaul * lhash, DES, etc., code; not just the SSL code. The SSL documentation 1550702Swpaul * included with this distribution is covered by the same copyright terms 1650702Swpaul * except that the holder is Tim Hudson (tjh@cryptsoft.com). 1750702Swpaul * 1850702Swpaul * Copyright remains Eric Young's, and as such any Copyright notices in 1950702Swpaul * the code are not to be removed. 2050702Swpaul * If this package is used in a product, Eric Young should be given attribution 2150702Swpaul * as the author of the parts of the library used. 2250702Swpaul * This can be in the form of a textual message at program startup or 2350702Swpaul * in documentation (online or textual) provided with the package. 2450702Swpaul * 2550702Swpaul * Redistribution and use in source and binary forms, with or without 2650702Swpaul * modification, are permitted provided that the following conditions 2750702Swpaul * are met: 2850702Swpaul * 1. Redistributions of source code must retain the copyright 2950702Swpaul * notice, this list of conditions and the following disclaimer. 3050702Swpaul * 2. Redistributions in binary form must reproduce the above copyright 3150702Swpaul * notice, this list of conditions and the following disclaimer in the 3250702Swpaul * documentation and/or other materials provided with the distribution. 33119418Sobrien * 3. All advertising materials mentioning features or use of this software 34119418Sobrien * must display the following acknowledgement: 35119418Sobrien * "This product includes cryptographic software written by 3650702Swpaul * Eric Young (eay@cryptsoft.com)" 3750702Swpaul * The word 'cryptographic' can be left out if the rouines from the library 3850702Swpaul * being used are not cryptographic related :-). 3950702Swpaul * 4. If you include any Windows specific code (or a derivative thereof) from 4050702Swpaul * the apps directory (application code) you must include an acknowledgement: 4150702Swpaul * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 4250702Swpaul * 43129876Sphk * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 4450702Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4550702Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4650702Swpaul * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4750702Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4894149Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4950702Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 5050702Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 5150702Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5250702Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53109514Sobrien * SUCH DAMAGE. 5450702Swpaul * 5594149Swpaul * The licence and distribution terms for any publically available version or 5694149Swpaul * derivative of this code cannot be changed. i.e. this code cannot simply be 5794149Swpaul * copied and put under another distribution licence 5850702Swpaul * [including the GNU Public Licence.] 5950702Swpaul */ 60105135Salfred 61105135Salfred#ifdef USE_MD5 /*%< Added by ogud@tis.com 1998/1/26 */ 6250702Swpaul#include <port_before.h> 6350702Swpaul#ifndef HAVE_MD5 6450702Swpaul#include <stdio.h> 6550702Swpaul#include "md5_locl.h" 6650702Swpaul#include <port_after.h> 6795722Sphk 6850702Swpaulconst char *MD5_version="MD5 part of SSLeay 0.8.1 19-Jul-1997"; 69227908Smarius 7050702Swpaul/*! \file 7150702Swpaul * \brief 7250702Swpaul * Implemented from RFC1321 The MD5 Message-Digest Algorithm 7350702Swpaul */ 7450702Swpaul 7550702Swpaul#define INIT_DATA_A (unsigned long)0x67452301L 7650702Swpaul#define INIT_DATA_B (unsigned long)0xefcdab89L 77221407Smarius#define INIT_DATA_C (unsigned long)0x98badcfeL 7850702Swpaul#define INIT_DATA_D (unsigned long)0x10325476L 7950702Swpaul 8050702Swpaul#ifndef NOPROTO 8150702Swpaulstatic void md5_block(MD5_CTX *c, unsigned long *p); 8292739Salfred#else 8394149Swpaulstatic void md5_block(); 8450702Swpaul#endif 85165991Smarius 86165991Smariusvoid MD5_Init(c) 87165991SmariusMD5_CTX *c; 88165991Smarius { 89165991Smarius c->A=INIT_DATA_A; 90165991Smarius c->B=INIT_DATA_B; 91165991Smarius c->C=INIT_DATA_C; 92165991Smarius c->D=INIT_DATA_D; 93165991Smarius c->Nl=0; 94164827Smarius c->Nh=0; 95221407Smarius c->num=0; 96221407Smarius } 97221407Smarius 98164827Smariusvoid MD5_Update(c, data, len) 99164827SmariusMD5_CTX *c; 100164827Smariusregister const unsigned char *data; 101221407Smariusunsigned long len; 102221407Smarius { 103221407Smarius register ULONG *p; 104221407Smarius int sw,sc; 105221407Smarius ULONG l; 106221407Smarius 107105135Salfred if (len == 0U) return; 108150763Simp 10950702Swpaul l=(c->Nl+(len<<3))&0xffffffffL; 110164827Smarius /* 95-05-24 eay Fixed a bug with the overflow handling, thanks to 111164827Smarius * Wei Dai <weidai@eskimo.com> for pointing it out. */ 11250702Swpaul if (l < c->Nl) /*%< overflow */ 113164827Smarius c->Nh++; 114164827Smarius c->Nh+=(len>>29); 115164827Smarius c->Nl=l; 11650702Swpaul 117164827Smarius if (c->num != 0) 118166164Smarius { 119165991Smarius p=c->data; 120165991Smarius sw=c->num>>2; 12150702Swpaul sc=c->num&0x03; 12250702Swpaul 123105135Salfred if ((c->num+len) >= (size_t)MD5_CBLOCK) 124150763Simp { 12550702Swpaul l= p[sw]; 12650702Swpaul p_c2l(data,l,sc); 127213364Smarius p[sw++]=l; 128213364Smarius for (; sw<MD5_LBLOCK; sw++) 129213364Smarius { 130221407Smarius c2l(data,l); 131221407Smarius p[sw]=l; 132164711Smarius } 13350702Swpaul len-=(MD5_CBLOCK-c->num); 13450702Swpaul 13584145Sjlemon md5_block(c,p); 136150763Simp c->num=0; 13750702Swpaul /* drop through and do the rest */ 13850702Swpaul } 13950702Swpaul else 14050702Swpaul { 14150702Swpaul int ew,ec; 14250702Swpaul 14350702Swpaul c->num+=(int)len; 14450702Swpaul if ((sc+len) < 4U) /*%< ugly, add char's to a word */ 14550702Swpaul { 14650702Swpaul l= p[sw]; 14750702Swpaul p_c2l_p(data,l,sc,len); 14850702Swpaul p[sw]=l; 14950702Swpaul } 150164711Smarius else 15150702Swpaul { 15250702Swpaul ew=(c->num>>2); 15350702Swpaul ec=(c->num&0x03); 15450702Swpaul l= p[sw]; 15550702Swpaul p_c2l(data,l,sc); 15650702Swpaul p[sw++]=l; 15750702Swpaul for (; sw < ew; sw++) 15850702Swpaul { c2l(data,l); p[sw]=l; } 15950702Swpaul if (ec) 16050702Swpaul { 16150702Swpaul c2l_p(data,l,ec); 16250702Swpaul p[sw]=l; 16350702Swpaul } 16450702Swpaul } 16550702Swpaul return; 16650702Swpaul } 16750702Swpaul } 168221407Smarius /* we now can process the input data in blocks of MD5_CBLOCK 16950702Swpaul * chars and save the leftovers to c->data. */ 17050702Swpaul p=c->data; 17184145Sjlemon while (len >= (size_t)MD5_CBLOCK) 17250702Swpaul { 17350702Swpaul#if defined(L_ENDIAN) || defined(B_ENDIAN) 17494149Swpaul memcpy(p,data,MD5_CBLOCK); 175104094Sphk data+=MD5_CBLOCK; 176150763Simp#ifdef B_ENDIAN 17794149Swpaul for (sw=(MD5_LBLOCK/4); sw; sw--) 17894149Swpaul { 179164711Smarius Endian_Reverse32(p[0]); 18094149Swpaul Endian_Reverse32(p[1]); 18194149Swpaul Endian_Reverse32(p[2]); 18294149Swpaul Endian_Reverse32(p[3]); 18394149Swpaul p+=4; 18494149Swpaul } 18594149Swpaul#endif 18694149Swpaul#else 18794149Swpaul for (sw=(MD5_LBLOCK/4); sw; sw--) 18894149Swpaul { 18994149Swpaul c2l(data,l); *(p++)=l; 19094149Swpaul c2l(data,l); *(p++)=l; 19194149Swpaul c2l(data,l); *(p++)=l; 19294149Swpaul c2l(data,l); *(p++)=l; 19394149Swpaul } 19494149Swpaul#endif 19594149Swpaul p=c->data; 19694149Swpaul md5_block(c,p); 19794149Swpaul len-=MD5_CBLOCK; 19894149Swpaul } 19994149Swpaul sc=(int)len; 20094149Swpaul c->num=sc; 20194149Swpaul if (sc) 20294149Swpaul { 20394149Swpaul sw=sc>>2; /*%< words to copy */ 20494149Swpaul#ifdef L_ENDIAN 20594149Swpaul p[sw]=0; 20694149Swpaul memcpy(p,data,sc); 20794149Swpaul#else 20894149Swpaul sc&=0x03; 20994149Swpaul for ( ; sw; sw--) 21094149Swpaul { c2l(data,l); *(p++)=l; } 21194149Swpaul c2l_p(data,l,sc); 21294149Swpaul *p=l; 213173665Syongari#endif 214173665Syongari } 215173665Syongari } 216213384Smarius 21794149Swpaulstatic void md5_block(c, X) 218213384SmariusMD5_CTX *c; 21994149Swpaulregister ULONG *X; 22094149Swpaul { 22194149Swpaul register ULONG A,B,C,D; 222213384Smarius 22394149Swpaul A=c->A; 224164711Smarius B=c->B; 225221407Smarius C=c->C; 226221407Smarius D=c->D; 227221407Smarius 22894149Swpaul /* Round 0 */ 22994149Swpaul R0(A,B,C,D,X[ 0], 7,0xd76aa478L); 23094149Swpaul R0(D,A,B,C,X[ 1],12,0xe8c7b756L); 23194149Swpaul R0(C,D,A,B,X[ 2],17,0x242070dbL); 23294149Swpaul R0(B,C,D,A,X[ 3],22,0xc1bdceeeL); 233164711Smarius R0(A,B,C,D,X[ 4], 7,0xf57c0fafL); 23494149Swpaul R0(D,A,B,C,X[ 5],12,0x4787c62aL); 23594149Swpaul R0(C,D,A,B,X[ 6],17,0xa8304613L); 23694149Swpaul R0(B,C,D,A,X[ 7],22,0xfd469501L); 23794149Swpaul R0(A,B,C,D,X[ 8], 7,0x698098d8L); 23894149Swpaul R0(D,A,B,C,X[ 9],12,0x8b44f7afL); 23994149Swpaul R0(C,D,A,B,X[10],17,0xffff5bb1L); 24094149Swpaul R0(B,C,D,A,X[11],22,0x895cd7beL); 24194149Swpaul R0(A,B,C,D,X[12], 7,0x6b901122L); 24294149Swpaul R0(D,A,B,C,X[13],12,0xfd987193L); 24394149Swpaul R0(C,D,A,B,X[14],17,0xa679438eL); 24494149Swpaul R0(B,C,D,A,X[15],22,0x49b40821L); 24594149Swpaul /* Round 1 */ 24694149Swpaul R1(A,B,C,D,X[ 1], 5,0xf61e2562L); 24794149Swpaul R1(D,A,B,C,X[ 6], 9,0xc040b340L); 248221407Smarius R1(C,D,A,B,X[11],14,0x265e5a51L); 249221407Smarius R1(B,C,D,A,X[ 0],20,0xe9b6c7aaL); 250221407Smarius R1(A,B,C,D,X[ 5], 5,0xd62f105dL); 251221407Smarius R1(D,A,B,C,X[10], 9,0x02441453L); 25294149Swpaul R1(C,D,A,B,X[15],14,0xd8a1e681L); 25394149Swpaul R1(B,C,D,A,X[ 4],20,0xe7d3fbc8L); 25494149Swpaul R1(A,B,C,D,X[ 9], 5,0x21e1cde6L); 25594149Swpaul R1(D,A,B,C,X[14], 9,0xc33707d6L); 25694149Swpaul R1(C,D,A,B,X[ 3],14,0xf4d50d87L); 257221407Smarius R1(B,C,D,A,X[ 8],20,0x455a14edL); 25894149Swpaul R1(A,B,C,D,X[13], 5,0xa9e3e905L); 25994149Swpaul R1(D,A,B,C,X[ 2], 9,0xfcefa3f8L); 26094149Swpaul R1(C,D,A,B,X[ 7],14,0x676f02d9L); 26194149Swpaul R1(B,C,D,A,X[12],20,0x8d2a4c8aL); 26294149Swpaul /* Round 2 */ 26394149Swpaul R2(A,B,C,D,X[ 5], 4,0xfffa3942L); 26494149Swpaul R2(D,A,B,C,X[ 8],11,0x8771f681L); 26594149Swpaul R2(C,D,A,B,X[11],16,0x6d9d6122L); 26694149Swpaul R2(B,C,D,A,X[14],23,0xfde5380cL); 26794149Swpaul R2(A,B,C,D,X[ 1], 4,0xa4beea44L); 26894149Swpaul R2(D,A,B,C,X[ 4],11,0x4bdecfa9L); 269213384Smarius R2(C,D,A,B,X[ 7],16,0xf6bb4b60L); 27094149Swpaul R2(B,C,D,A,X[10],23,0xbebfbc70L); 271164711Smarius R2(A,B,C,D,X[13], 4,0x289b7ec6L); 27294149Swpaul R2(D,A,B,C,X[ 0],11,0xeaa127faL); 273 R2(C,D,A,B,X[ 3],16,0xd4ef3085L); 274 R2(B,C,D,A,X[ 6],23,0x04881d05L); 275 R2(A,B,C,D,X[ 9], 4,0xd9d4d039L); 276 R2(D,A,B,C,X[12],11,0xe6db99e5L); 277 R2(C,D,A,B,X[15],16,0x1fa27cf8L); 278 R2(B,C,D,A,X[ 2],23,0xc4ac5665L); 279 /* Round 3 */ 280 R3(A,B,C,D,X[ 0], 6,0xf4292244L); 281 R3(D,A,B,C,X[ 7],10,0x432aff97L); 282 R3(C,D,A,B,X[14],15,0xab9423a7L); 283 R3(B,C,D,A,X[ 5],21,0xfc93a039L); 284 R3(A,B,C,D,X[12], 6,0x655b59c3L); 285 R3(D,A,B,C,X[ 3],10,0x8f0ccc92L); 286 R3(C,D,A,B,X[10],15,0xffeff47dL); 287 R3(B,C,D,A,X[ 1],21,0x85845dd1L); 288 R3(A,B,C,D,X[ 8], 6,0x6fa87e4fL); 289 R3(D,A,B,C,X[15],10,0xfe2ce6e0L); 290 R3(C,D,A,B,X[ 6],15,0xa3014314L); 291 R3(B,C,D,A,X[13],21,0x4e0811a1L); 292 R3(A,B,C,D,X[ 4], 6,0xf7537e82L); 293 R3(D,A,B,C,X[11],10,0xbd3af235L); 294 R3(C,D,A,B,X[ 2],15,0x2ad7d2bbL); 295 R3(B,C,D,A,X[ 9],21,0xeb86d391L); 296 297 c->A+=A&0xffffffffL; 298 c->B+=B&0xffffffffL; 299 c->C+=C&0xffffffffL; 300 c->D+=D&0xffffffffL; 301 } 302 303void MD5_Final(md, c) 304unsigned char *md; 305MD5_CTX *c; 306 { 307 register int i,j; 308 register ULONG l; 309 register ULONG *p; 310 static unsigned char end[4]={0x80,0x00,0x00,0x00}; 311 unsigned char *cp=end; 312 313 /* c->num should definitly have room for at least one more byte. */ 314 p=c->data; 315 j=c->num; 316 i=j>>2; 317 318 /* purify often complains about the following line as an 319 * Uninitialized Memory Read. While this can be true, the 320 * following p_c2l macro will reset l when that case is true. 321 * This is because j&0x03 contains the number of 'valid' bytes 322 * already in p[i]. If and only if j&0x03 == 0, the UMR will 323 * occur but this is also the only time p_c2l will do 324 * l= *(cp++) instead of l|= *(cp++) 325 * Many thanks to Alex Tang <altitude@cic.net> for pickup this 326 * 'potential bug' */ 327#ifdef PURIFY 328 if ((j&0x03) == 0) p[i]=0; 329#endif 330 l=p[i]; 331 p_c2l(cp,l,j&0x03); 332 p[i]=l; 333 i++; 334 /* i is the next 'undefined word' */ 335 if (c->num >= MD5_LAST_BLOCK) 336 { 337 for (; i<MD5_LBLOCK; i++) 338 p[i]=0; 339 md5_block(c,p); 340 i=0; 341 } 342 for (; i<(MD5_LBLOCK-2); i++) 343 p[i]=0; 344 p[MD5_LBLOCK-2]=c->Nl; 345 p[MD5_LBLOCK-1]=c->Nh; 346 md5_block(c,p); 347 cp=md; 348 l=c->A; l2c(l,cp); 349 l=c->B; l2c(l,cp); 350 l=c->C; l2c(l,cp); 351 l=c->D; l2c(l,cp); 352 353 /* clear stuff, md5_block may be leaving some stuff on the stack 354 * but I'm not worried :-) */ 355 c->num=0; 356/* memset((char *)&c,0,sizeof(c));*/ 357 } 358 359#ifdef undef 360int printit(l) 361unsigned long *l; 362 { 363 int i,ii; 364 365 for (i=0; i<2; i++) 366 { 367 for (ii=0; ii<8; ii++) 368 { 369 fprintf(stderr,"%08lx ",l[i*8+ii]); 370 } 371 fprintf(stderr,"\n"); 372 } 373 } 374#endif 375#endif /* HAVE_MD5 */ 376#endif /* USE_MD5 */ 377