sha1dgst.c

Go to the documentation of this file.
00001 /* crypto/sha/sha1dgst.c */
00002 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
00003  * All rights reserved.
00004  *
00005  * This package is an SSL implementation written
00006  * by Eric Young (eay@cryptsoft.com).
00007  * The implementation was written so as to conform with Netscapes SSL.
00008  * 
00009  * This library is free for commercial and non-commercial use as long as
00010  * the following conditions are aheared to.  The following conditions
00011  * apply to all code found in this distribution, be it the RC4, RSA,
00012  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
00013  * included with this distribution is covered by the same copyright terms
00014  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
00015  * 
00016  * Copyright remains Eric Young's, and as such any Copyright notices in
00017  * the code are not to be removed.
00018  * If this package is used in a product, Eric Young should be given attribution
00019  * as the author of the parts of the library used.
00020  * This can be in the form of a textual message at program startup or
00021  * in documentation (online or textual) provided with the package.
00022  * 
00023  * Redistribution and use in source and binary forms, with or without
00024  * modification, are permitted provided that the following conditions
00025  * are met:
00026  * 1. Redistributions of source code must retain the copyright
00027  *    notice, this list of conditions and the following disclaimer.
00028  * 2. Redistributions in binary form must reproduce the above copyright
00029  *    notice, this list of conditions and the following disclaimer in the
00030  *    documentation and/or other materials provided with the distribution.
00031  * 3. All advertising materials mentioning features or use of this software
00032  *    must display the following acknowledgement:
00033  *    "This product includes cryptographic software written by
00034  *     Eric Young (eay@cryptsoft.com)"
00035  *    The word 'cryptographic' can be left out if the rouines from the library
00036  *    being used are not cryptographic related :-).
00037  * 4. If you include any Windows specific code (or a derivative thereof) from 
00038  *    the apps directory (application code) you must include an acknowledgement:
00039  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
00040  * 
00041  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
00042  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00043  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00044  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
00045  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00046  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00047  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00048  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00049  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00050  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00051  * SUCH DAMAGE.
00052  * 
00053  * The licence and distribution terms for any publically available version or
00054  * derivative of this code cannot be changed.  i.e. this code cannot simply be
00055  * copied and put under another distribution licence
00056  * [including the GNU Public Licence.]
00057  */
00058 
00059 #include <stdio.h>
00060 #include <string.h>
00061 #undef  SHA_0
00062 #define SHA_1
00063 #include "sha.h"
00064 #include "sha_locl.h"
00065 
00066 char *SHA1_version="SHA1 part of OpenSSL 0.9.1c 23-Dec-1998";
00067 
00068 /* Implemented from SHA-1 document - The Secure Hash Algorithm
00069  */
00070 
00071 #define INIT_DATA_h0 (unsigned long)0x67452301L
00072 #define INIT_DATA_h1 (unsigned long)0xefcdab89L
00073 #define INIT_DATA_h2 (unsigned long)0x98badcfeL
00074 #define INIT_DATA_h3 (unsigned long)0x10325476L
00075 #define INIT_DATA_h4 (unsigned long)0xc3d2e1f0L
00076 
00077 #define K_00_19 0x5a827999L
00078 #define K_20_39 0x6ed9eba1L
00079 #define K_40_59 0x8f1bbcdcL
00080 #define K_60_79 0xca62c1d6L
00081 
00082 #ifndef NOPROTO
00083 #  ifdef SHA1_ASM
00084      void sha1_block_x86(SHA_CTX *c, register unsigned long *p, int num);
00085 #    define sha1_block sha1_block_x86
00086 #  else
00087      void sha1_block(SHA_CTX *c, register unsigned long *p, int num);
00088 #  endif
00089 #else
00090 #  ifdef SHA1_ASM
00091      void sha1_block_x86();
00092 #    define sha1_block sha1_block_x86
00093 #  else
00094      void sha1_block();
00095 #  endif
00096 #endif
00097 
00098 
00099 #if defined(L_ENDIAN) && defined(SHA1_ASM)
00100 #  define   M_c2nl      c2l
00101 #  define   M_p_c2nl    p_c2l
00102 #  define   M_c2nl_p    c2l_p
00103 #  define   M_p_c2nl_p  p_c2l_p
00104 #  define   M_nl2c      l2c
00105 #else
00106 #  define   M_c2nl      c2nl
00107 #  define   M_p_c2nl    p_c2nl
00108 #  define   M_c2nl_p    c2nl_p
00109 #  define   M_p_c2nl_p  p_c2nl_p
00110 #  define   M_nl2c      nl2c
00111 #endif
00112 
00113 void SHA1_Init(c)
00114 SHA_CTX *c;
00115     {
00116     c->h0=INIT_DATA_h0;
00117     c->h1=INIT_DATA_h1;
00118     c->h2=INIT_DATA_h2;
00119     c->h3=INIT_DATA_h3;
00120     c->h4=INIT_DATA_h4;
00121     c->Nl=0;
00122     c->Nh=0;
00123     c->num=0;
00124     }
00125 
00126 void SHA1_Update(c, data, len)
00127 SHA_CTX *c;
00128 register unsigned char *data;
00129 unsigned long len;
00130     {
00131     register ULONG *p;
00132     int ew,ec,sw,sc;
00133     ULONG l;
00134 
00135     if (len == 0) return;
00136 
00137     l=(c->Nl+(len<<3))&0xffffffffL;
00138     if (l < c->Nl) /* overflow */
00139         c->Nh++;
00140     c->Nh+=(len>>29);
00141     c->Nl=l;
00142 
00143     if (c->num != 0)
00144         {
00145         p=c->data;
00146         sw=c->num>>2;
00147         sc=c->num&0x03;
00148 
00149         if ((c->num+len) >= SHA_CBLOCK)
00150             {
00151             l= p[sw];
00152             M_p_c2nl(data,l,sc);
00153             p[sw++]=l;
00154             for (; sw<SHA_LBLOCK; sw++)
00155                 {
00156                 M_c2nl(data,l);
00157                 p[sw]=l;
00158                 }
00159             len-=(SHA_CBLOCK-c->num);
00160 
00161             sha1_block(c,p,64);
00162             c->num=0;
00163             /* drop through and do the rest */
00164             }
00165         else
00166             {
00167             c->num+=(int)len;
00168             if ((sc+len) < 4) /* ugly, add char's to a word */
00169                 {
00170                 l= p[sw];
00171                 M_p_c2nl_p(data,l,sc,len);
00172                 p[sw]=l;
00173                 }
00174             else
00175                 {
00176                 ew=(c->num>>2);
00177                 ec=(c->num&0x03);
00178                 l= p[sw];
00179                 M_p_c2nl(data,l,sc);
00180                 p[sw++]=l;
00181                 for (; sw < ew; sw++)
00182                     { M_c2nl(data,l); p[sw]=l; }
00183                 if (ec)
00184                     {
00185                     M_c2nl_p(data,l,ec);
00186                     p[sw]=l;
00187                     }
00188                 }
00189             return;
00190             }
00191         }
00192     /* We can only do the following code for assember, the reason
00193      * being that the sha1_block 'C' version changes the values
00194      * in the 'data' array.  The assember code avoids this and
00195      * copies it to a local array.  I should be able to do this for
00196      * the C version as well....
00197      */
00198 #if 1
00199 #if defined(B_ENDIAN) || defined(SHA1_ASM)
00200     if ((((unsigned long)data)%sizeof(ULONG)) == 0)
00201         {
00202         sw=len/SHA_CBLOCK;
00203         if (sw)
00204             {
00205             sw*=SHA_CBLOCK;
00206             sha1_block(c,(ULONG *)data,sw);
00207             data+=sw;
00208             len-=sw;
00209             }
00210         }
00211 #endif
00212 #endif
00213     /* we now can process the input data in blocks of SHA_CBLOCK
00214      * chars and save the leftovers to c->data. */
00215     p=c->data;
00216     while (len >= SHA_CBLOCK)
00217         {
00218 #if defined(B_ENDIAN) || defined(L_ENDIAN)
00219         if (p != (unsigned long *)data)
00220             memcpy(p,data,SHA_CBLOCK);
00221         data+=SHA_CBLOCK;
00222 #  ifdef L_ENDIAN
00223 #    ifndef SHA1_ASM /* Will not happen */
00224         for (sw=(SHA_LBLOCK/4); sw; sw--)
00225             {
00226             Endian_Reverse32(p[0]);
00227             Endian_Reverse32(p[1]);
00228             Endian_Reverse32(p[2]);
00229             Endian_Reverse32(p[3]);
00230             p+=4;
00231             }
00232         p=c->data;
00233 #    endif
00234 #  endif
00235 #else
00236         for (sw=(SHA_BLOCK/4); sw; sw--)
00237             {
00238             M_c2nl(data,l); *(p++)=l;
00239             M_c2nl(data,l); *(p++)=l;
00240             M_c2nl(data,l); *(p++)=l;
00241             M_c2nl(data,l); *(p++)=l;
00242             }
00243         p=c->data;
00244 #endif
00245         sha1_block(c,p,64);
00246         len-=SHA_CBLOCK;
00247         }
00248     ec=(int)len;
00249     c->num=ec;
00250     ew=(ec>>2);
00251     ec&=0x03;
00252 
00253     for (sw=0; sw < ew; sw++)
00254         { M_c2nl(data,l); p[sw]=l; }
00255     M_c2nl_p(data,l,ec);
00256     p[sw]=l;
00257     }
00258 
00259 void SHA1_Transform(c,b)
00260 SHA_CTX *c;
00261 unsigned char *b;
00262     {
00263     ULONG p[16];
00264 #ifndef B_ENDIAN
00265     ULONG *q;
00266     int i;
00267 #endif
00268 
00269 #if defined(B_ENDIAN) || defined(L_ENDIAN)
00270     memcpy(p,b,64);
00271 #ifdef L_ENDIAN
00272     q=p;
00273     for (i=(SHA_LBLOCK/4); i; i--)
00274         {
00275         Endian_Reverse32(q[0]);
00276         Endian_Reverse32(q[1]);
00277         Endian_Reverse32(q[2]);
00278         Endian_Reverse32(q[3]);
00279         q+=4;
00280         }
00281 #endif
00282 #else
00283     q=p;
00284     for (i=(SHA_LBLOCK/4); i; i--)
00285         {
00286         ULONG l;
00287         c2nl(b,l); *(q++)=l;
00288         c2nl(b,l); *(q++)=l;
00289         c2nl(b,l); *(q++)=l;
00290         c2nl(b,l); *(q++)=l; 
00291         } 
00292 #endif
00293     sha1_block(c,p,64);
00294     }
00295 
00296 #ifndef SHA1_ASM
00297 
00298 void sha1_block(c, W, num)
00299 SHA_CTX *c;
00300 register unsigned long *W;
00301 int num;
00302     {
00303     register ULONG A,B,C,D,E,T;
00304     ULONG X[16];
00305 
00306     A=c->h0;
00307     B=c->h1;
00308     C=c->h2;
00309     D=c->h3;
00310     E=c->h4;
00311 
00312     for (;;)
00313         {
00314     BODY_00_15( 0,A,B,C,D,E,T,W);
00315     BODY_00_15( 1,T,A,B,C,D,E,W);
00316     BODY_00_15( 2,E,T,A,B,C,D,W);
00317     BODY_00_15( 3,D,E,T,A,B,C,W);
00318     BODY_00_15( 4,C,D,E,T,A,B,W);
00319     BODY_00_15( 5,B,C,D,E,T,A,W);
00320     BODY_00_15( 6,A,B,C,D,E,T,W);
00321     BODY_00_15( 7,T,A,B,C,D,E,W);
00322     BODY_00_15( 8,E,T,A,B,C,D,W);
00323     BODY_00_15( 9,D,E,T,A,B,C,W);
00324     BODY_00_15(10,C,D,E,T,A,B,W);
00325     BODY_00_15(11,B,C,D,E,T,A,W);
00326     BODY_00_15(12,A,B,C,D,E,T,W);
00327     BODY_00_15(13,T,A,B,C,D,E,W);
00328     BODY_00_15(14,E,T,A,B,C,D,W);
00329     BODY_00_15(15,D,E,T,A,B,C,W);
00330     BODY_16_19(16,C,D,E,T,A,B,W,W,W,W);
00331     BODY_16_19(17,B,C,D,E,T,A,W,W,W,W);
00332     BODY_16_19(18,A,B,C,D,E,T,W,W,W,W);
00333     BODY_16_19(19,T,A,B,C,D,E,W,W,W,X);
00334 
00335     BODY_20_31(20,E,T,A,B,C,D,W,W,W,X);
00336     BODY_20_31(21,D,E,T,A,B,C,W,W,W,X);
00337     BODY_20_31(22,C,D,E,T,A,B,W,W,W,X);
00338     BODY_20_31(23,B,C,D,E,T,A,W,W,W,X);
00339     BODY_20_31(24,A,B,C,D,E,T,W,W,X,X);
00340     BODY_20_31(25,T,A,B,C,D,E,W,W,X,X);
00341     BODY_20_31(26,E,T,A,B,C,D,W,W,X,X);
00342     BODY_20_31(27,D,E,T,A,B,C,W,W,X,X);
00343     BODY_20_31(28,C,D,E,T,A,B,W,W,X,X);
00344     BODY_20_31(29,B,C,D,E,T,A,W,W,X,X);
00345     BODY_20_31(30,A,B,C,D,E,T,W,X,X,X);
00346     BODY_20_31(31,T,A,B,C,D,E,W,X,X,X);
00347     BODY_32_39(32,E,T,A,B,C,D,X);
00348     BODY_32_39(33,D,E,T,A,B,C,X);
00349     BODY_32_39(34,C,D,E,T,A,B,X);
00350     BODY_32_39(35,B,C,D,E,T,A,X);
00351     BODY_32_39(36,A,B,C,D,E,T,X);
00352     BODY_32_39(37,T,A,B,C,D,E,X);
00353     BODY_32_39(38,E,T,A,B,C,D,X);
00354     BODY_32_39(39,D,E,T,A,B,C,X);
00355 
00356     BODY_40_59(40,C,D,E,T,A,B,X);
00357     BODY_40_59(41,B,C,D,E,T,A,X);
00358     BODY_40_59(42,A,B,C,D,E,T,X);
00359     BODY_40_59(43,T,A,B,C,D,E,X);
00360     BODY_40_59(44,E,T,A,B,C,D,X);
00361     BODY_40_59(45,D,E,T,A,B,C,X);
00362     BODY_40_59(46,C,D,E,T,A,B,X);
00363     BODY_40_59(47,B,C,D,E,T,A,X);
00364     BODY_40_59(48,A,B,C,D,E,T,X);
00365     BODY_40_59(49,T,A,B,C,D,E,X);
00366     BODY_40_59(50,E,T,A,B,C,D,X);
00367     BODY_40_59(51,D,E,T,A,B,C,X);
00368     BODY_40_59(52,C,D,E,T,A,B,X);
00369     BODY_40_59(53,B,C,D,E,T,A,X);
00370     BODY_40_59(54,A,B,C,D,E,T,X);
00371     BODY_40_59(55,T,A,B,C,D,E,X);
00372     BODY_40_59(56,E,T,A,B,C,D,X);
00373     BODY_40_59(57,D,E,T,A,B,C,X);
00374     BODY_40_59(58,C,D,E,T,A,B,X);
00375     BODY_40_59(59,B,C,D,E,T,A,X);
00376 
00377     BODY_60_79(60,A,B,C,D,E,T,X);
00378     BODY_60_79(61,T,A,B,C,D,E,X);
00379     BODY_60_79(62,E,T,A,B,C,D,X);
00380     BODY_60_79(63,D,E,T,A,B,C,X);
00381     BODY_60_79(64,C,D,E,T,A,B,X);
00382     BODY_60_79(65,B,C,D,E,T,A,X);
00383     BODY_60_79(66,A,B,C,D,E,T,X);
00384     BODY_60_79(67,T,A,B,C,D,E,X);
00385     BODY_60_79(68,E,T,A,B,C,D,X);
00386     BODY_60_79(69,D,E,T,A,B,C,X);
00387     BODY_60_79(70,C,D,E,T,A,B,X);
00388     BODY_60_79(71,B,C,D,E,T,A,X);
00389     BODY_60_79(72,A,B,C,D,E,T,X);
00390     BODY_60_79(73,T,A,B,C,D,E,X);
00391     BODY_60_79(74,E,T,A,B,C,D,X);
00392     BODY_60_79(75,D,E,T,A,B,C,X);
00393     BODY_60_79(76,C,D,E,T,A,B,X);
00394     BODY_60_79(77,B,C,D,E,T,A,X);
00395     BODY_60_79(78,A,B,C,D,E,T,X);
00396     BODY_60_79(79,T,A,B,C,D,E,X);
00397     
00398     c->h0=(c->h0+E)&0xffffffffL; 
00399     c->h1=(c->h1+T)&0xffffffffL;
00400     c->h2=(c->h2+A)&0xffffffffL;
00401     c->h3=(c->h3+B)&0xffffffffL;
00402     c->h4=(c->h4+C)&0xffffffffL;
00403 
00404     num-=64;
00405     if (num <= 0) break;
00406 
00407     A=c->h0;
00408     B=c->h1;
00409     C=c->h2;
00410     D=c->h3;
00411     E=c->h4;
00412 
00413     W+=16;
00414         }
00415     }
00416 #endif
00417 
00418 void SHA1_Final(md, c)
00419 unsigned char *md;
00420 SHA_CTX *c;
00421     {
00422     register int i,j;
00423     register ULONG l;
00424     register ULONG *p;
00425     static unsigned char end[4]={0x80,0x00,0x00,0x00};
00426     unsigned char *cp=end;
00427 
00428     /* c->num should definitly have room for at least one more byte. */
00429     p=c->data;
00430     j=c->num;
00431     i=j>>2;
00432 #ifdef PURIFY
00433     if ((j&0x03) == 0) p[i]=0;
00434 #endif
00435     l=p[i];
00436     M_p_c2nl(cp,l,j&0x03);
00437     p[i]=l;
00438     i++;
00439     /* i is the next 'undefined word' */
00440     if (c->num >= SHA_LAST_BLOCK)
00441         {
00442         for (; i<SHA_LBLOCK; i++)
00443             p[i]=0;
00444         sha1_block(c,p,64);
00445         i=0;
00446         }
00447     for (; i<(SHA_LBLOCK-2); i++)
00448         p[i]=0;
00449     p[SHA_LBLOCK-2]=c->Nh;
00450     p[SHA_LBLOCK-1]=c->Nl;
00451 #if defined(L_ENDIAN) && defined(SHA1_ASM)
00452     Endian_Reverse32(p[SHA_LBLOCK-2]);
00453     Endian_Reverse32(p[SHA_LBLOCK-1]);
00454 #endif
00455     sha1_block(c,p,64);
00456     cp=md;
00457     l=c->h0; nl2c(l,cp);
00458     l=c->h1; nl2c(l,cp);
00459     l=c->h2; nl2c(l,cp);
00460     l=c->h3; nl2c(l,cp);
00461     l=c->h4; nl2c(l,cp);
00462 
00463     /* clear stuff, sha1_block may be leaving some stuff on the stack
00464      * but I'm not worried :-) */
00465     c->num=0;
00466 /*  memset((char *)&c,0,sizeof(c));*/
00467     }
00468 

Generated on Wed May 31 18:20:00 2006 for frontierkernel 10.1.10a by  doxygen 1.4.6