Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

/ray/src/lib/crypto/sha0hash.cc

Go to the documentation of this file.
00001 /*
00002  * lib/crypto/sha0hash.cc
00003  * 
00004  * Implementation of class SHA0Hash, a class for computing the SHA message 
00005  * digest / hash algorithm as originally specified by NIST/NSA. 
00006  * 
00007  * Copyright (c) 2000--2004 by Wolfgang Wieser ] wwieser (a) gmx <*> de [ 
00008  * 
00009  * This file may be distributed and/or modified under the terms of the 
00010  * GNU General Public License version 2 as published by the Free Software 
00011  * Foundation. (See COPYING.GPL for details.)
00012  * 
00013  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00014  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00015  * 
00016  */
00017 
00018 #include "sha0hash.h"
00019 
00020 const SecureHashBase::Parameters SHA0Hash::par=
00021 {
00022     INIT_FIELD(hash_size) 20,
00023     INIT_FIELD(block_size) 64,
00024     INIT_FIELD(hash_ID) 0x1000,
00025     INIT_FIELD(name) "SHA0"
00026 };
00027 
00028 
00029 static inline uint32 sha_func0(uint32 x,uint32 y,uint32 z)
00030     //{  return((x & y) | ((~x) & z));  }  // slower 
00031     {  return(z ^ (x & (y ^ z)));  }  // faster
00032 
00033 static inline uint32 sha_func1(uint32 x,uint32 y,uint32 z)
00034     {  return(x ^ y ^ z);  }
00035 
00036 static inline uint32 sha_func2(uint32 x,uint32 y,uint32 z)
00037     //{  return((x & y) | (x & z) | (y & z));  }  // slower
00038     {  return((x & y) | (z & (x | y)));  }  // faster
00039 
00040 static inline uint32 sha_func3(uint32 x,uint32 y,uint32 z)
00041     {  return(x ^ y ^ z);  }
00042 
00043 static inline uint32 rotate(uint32 x,int n)
00044     {  return((x<<n) | (x>>(32-n)));  }
00045 
00046 
00047 // All this magic stuff...
00048 static const uint32 sha_const0 = 0x5a827999U;
00049 static const uint32 sha_const1 = 0x6ed9eba1U;
00050 static const uint32 sha_const2 = 0x8f1bbcdcU;
00051 static const uint32 sha_const3 = 0xca62c1d6U;
00052 
00053 static const uint32 sha_init_state[5]=
00054     { 0x67452301U, 0xefcdab89U, 0x98badcfeU, 0x10325476U, 0xc3d2e1f0U };
00055 
00056 
00057 #define EXPAND(pa,pb,pc,pd)  (*(pa++) ^ *(pb++) ^ *(pc++) ^ *(pd++))
00058 
00059 
00060 // msg: size 64 bytes
00061 // w: temporary buffer where AtomicHash stores (expanded) input data (msg). 
00062 void SHA0Hash::AtomicHash(const unsigned char *msg,uint32 *w)
00063 {
00064     register uint32 *p;
00065     uint32 *we=&w[16];
00066     
00067     // Fill message into w-buffer. 
00068     for(p=w; p<we; p++)
00069     {
00070         // We want MSB first 
00071         // (htonl() converts LSBfirst -> MSBfirst in i386; but not used 
00072         // here as it would need word alignment of msg data.) 
00073         *p= uint32(*(msg++));   *p<<=8;
00074         *p|=uint32(*(msg++));   *p<<=8;
00075         *p|=uint32(*(msg++));   *p<<=8;
00076         *p|=uint32(*(msg++));
00077     }
00078     
00079     uint32 *p_03=p-3;
00080     uint32 *p_08=p-8;
00081     uint32 *p_14=p-14;
00082     uint32 *p_16=p-16;
00083     we=&w[20];
00084     while(p<we)   // 20-16=4 times
00085     {  *(p++) = EXPAND(p_03,p_08,p_14,p_16);  }
00086     
00087     // Now compute the loops: 
00088     uint32 a=state[0], b=state[1], c=state[2], d=state[3], e=state[4];
00089     uint32 tmp,sha_const=sha_const0;
00090     for(p=w; p<we; p++)
00091     {
00092         tmp = rotate(a,5) + sha_func0(b,c,d) + e + (*p) + sha_const;
00093         e=d;  d=c;
00094         c=rotate(b,30);
00095         b=a;  a=tmp;
00096     }
00097     sha_const=sha_const1;
00098     for(we+=20; p<we; p++)
00099     {
00100         *p = EXPAND(p_03,p_08,p_14,p_16);
00101         tmp = rotate(a,5) + sha_func1(b,c,d) + e + (*p) + sha_const;
00102         e=d;  d=c;
00103         c=rotate(b,30);
00104         b=a;  a=tmp;
00105     }
00106     sha_const=sha_const2;
00107     for(we+=20; p<we; p++)
00108     {
00109         *p = EXPAND(p_03,p_08,p_14,p_16);
00110         tmp = rotate(a,5) + sha_func2(b,c,d) + e + (*p) + sha_const;
00111         e=d;  d=c;
00112         c=rotate(b,30);
00113         b=a;  a=tmp;
00114     }
00115     sha_const=sha_const3;
00116     for(we+=20; p<we; p++)
00117     {
00118         *p = EXPAND(p_03,p_08,p_14,p_16);
00119         tmp = rotate(a,5) + sha_func3(b,c,d) + e + (*p) + sha_const;
00120         e=d;  d=c;
00121         c=rotate(b,30);
00122         b=a;  a=tmp;
00123     }
00124     
00125     // Add the result: 
00126     state[0]+=a;
00127     state[1]+=b;
00128     state[2]+=c;
00129     state[3]+=d;
00130     state[4]+=e;
00131 }
00132 
00133 
00134 void SHA0Hash::GetHash(char *buf) const
00135 {
00136     register unsigned char *hsh=(unsigned char*)buf+3;
00137     for(register const uint32 *i=state,*ie=&state[5]; i<ie; i++)
00138     {
00139         register uint32 j=*i;
00140         *(hsh--)=(unsigned char)(j & 0xffU);  j>>=8;
00141         *(hsh--)=(unsigned char)(j & 0xffU);  j>>=8;
00142         *(hsh--)=(unsigned char)(j & 0xffU);  j>>=8;
00143         *(hsh  )=(unsigned char)(j & 0xffU);
00144         hsh+=7;  // 4+3; would be 4+4 if the last *(hsh  )=... was *(hsh--)=...
00145     }
00146 }
00147 
00148 
00149 void SHA0Hash::reset()
00150 {
00151     length=0LLU;
00152     state[0]=sha_init_state[0];
00153     state[1]=sha_init_state[1];
00154     state[2]=sha_init_state[2];
00155     state[3]=sha_init_state[3];
00156     state[4]=sha_init_state[4];
00157     tmp_size=0;
00158     for(unsigned char *d=tmpbuf,*de=d+64; d<de; d++)
00159     {  *d=(unsigned char)0;  }
00160 }
00161 
00162 
00163 void SHA0Hash::feed(const char *_buf,size_t len)
00164 {
00165     if(!len)
00166     {  return;  }
00167     
00168     const unsigned char *buf=(const unsigned char*)_buf;
00169     uint32 w[80];   // Yes, this is 4*80 bytes, NOT 4*20 bytes. 
00170     
00171     if(tmp_size)  // There is some data left from last time. 
00172     {
00173         size_t needed=64-tmp_size;
00174         if(len>=needed)
00175         {
00176             for(unsigned char *d=&tmpbuf[tmp_size],*de=&tmpbuf[64]; d<de; d++)
00177             {  *d=*(buf++);  }
00178             AtomicHash(tmpbuf,w);
00179             len-=needed;
00180             tmp_size=0;
00181             length+=64LLU;
00182             if(!len)
00183             {  return;  }
00184         }
00185         else
00186         {
00187             unsigned char *d=&tmpbuf[tmp_size];
00188             tmp_size+=int(len);
00189             for(unsigned char *de=&tmpbuf[tmp_size]; d<de; d++)
00190             {  *d=*(buf++);  }
00191             return;
00192         }
00193     }
00194     
00195     size_t l=len;
00196     for(;;)
00197     {
00198         if(l<64)
00199         {  break;  }
00200         AtomicHash((const unsigned char*)buf,w);
00201         buf+=64;
00202         l-=64;
00203     }
00204     length+=uint64(len-l);
00205     if(l)  // Some bytes left; store them for later. 
00206     {
00207         for(unsigned char *d=tmpbuf,*de=d+l; d<de; d++)
00208         {  *d=*(buf++);  }
00209         tmp_size=int(l);
00210     }
00211 }
00212 
00213 
00214 void SHA0Hash::final()
00215 {
00216     uint32 w[80];   // Yes, this is 4*80 bytes, NOT 4*20 bytes. 
00217     int pad80=0;
00218     
00219     // Now, let's see if we need padding. 
00220     // We must check for >=56 as we always have to add one 0x80 padding. 
00221     // Padding does not count for the length, of course.
00222     length+=uint64(tmp_size);
00223     if(tmp_size>=56)  // We need to pad the tmpbuf with zeros and hash it. 
00224     {
00225         unsigned char *d=&tmpbuf[tmp_size];
00226         *(d++)=(unsigned char)0x80;   // append binary 10000000. 
00227         for(unsigned char *de=&tmpbuf[64]; d<de; d++)
00228         {  *d=(unsigned char)0;  }
00229         AtomicHash(tmpbuf,w);
00230         tmp_size=0;
00231         ++pad80;
00232     }
00233     
00234     // The length was counted in bytes, but we need the number of bits here: 
00235     uint64 len=length*8LLU;
00236     
00237     // Now, we have to fill up tmpbuf with zeros and add the length in bits 
00238     // as the last 8 bytes. 
00239     unsigned char *d=&tmpbuf[tmp_size];
00240     if(!pad80)
00241     {  *(d++)=(unsigned char)0x80;  }  // append binary 10000000. 
00242     for(unsigned char *de=&tmpbuf[56]; d<de; d++)
00243     {  *d=(unsigned char)0;  }
00244     
00245     // Add more significant word: 
00246     uint32 word = uint32(len >> 32);
00247     d+=3;
00248     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00249     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00250     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00251     *(d  )=(unsigned char)(word & 0xffU);
00252     
00253     // Add less significant word: 
00254     word = uint32(len & 0xffffffffLLU);
00255     d+=7;
00256     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00257     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00258     *(d--)=(unsigned char)(word & 0xffU);  word>>=8;
00259     *(d  )=(unsigned char)(word & 0xffU);
00260     
00261     AtomicHash(tmpbuf,w);
00262     tmp_size=0;
00263 }

Generated on Sat Feb 19 22:33:45 2005 for Ray by doxygen 1.3.5