00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00031 { return(z ^ (x & (y ^ z))); }
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
00038 { return((x & y) | (z & (x | y))); }
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
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
00061
00062 void SHA0Hash::AtomicHash(const unsigned char *msg,uint32 *w)
00063 {
00064 register uint32 *p;
00065 uint32 *we=&w[16];
00066
00067
00068 for(p=w; p<we; p++)
00069 {
00070
00071
00072
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)
00085 { *(p++) = EXPAND(p_03,p_08,p_14,p_16); }
00086
00087
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
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;
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];
00170
00171 if(tmp_size)
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)
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];
00217 int pad80=0;
00218
00219
00220
00221
00222 length+=uint64(tmp_size);
00223 if(tmp_size>=56)
00224 {
00225 unsigned char *d=&tmpbuf[tmp_size];
00226 *(d++)=(unsigned char)0x80;
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
00235 uint64 len=length*8LLU;
00236
00237
00238
00239 unsigned char *d=&tmpbuf[tmp_size];
00240 if(!pad80)
00241 { *(d++)=(unsigned char)0x80; }
00242 for(unsigned char *de=&tmpbuf[56]; d<de; d++)
00243 { *d=(unsigned char)0; }
00244
00245
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
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 }