This library implements some hash and cryptographic algorithms.

Dependents:   mBuinoBlinky PB_Emma_Ethernet SLOTrashHTTP Garagem ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SHA2_32.cpp Source File

SHA2_32.cpp

00001 #include "SHA2_32.h"
00002 #include <string.h>
00003 
00004 
00005 
00006 static const uint8_t MASK = 0x0F;
00007 
00008 #define W(t) (w[(t)] = SSIG1(w[((t)+14)&MASK]) + w[((t)+9)&MASK] + SSIG0(w[((t)+1)&MASK]) + w[t])
00009 
00010 #define ROTL(W,N) (((W) << (N)) | ((W) >> (32-(N))))
00011 #define ROTR(W,N) (rotRWord(W,N)) 
00012 #define CH(X,Y,Z) (((X) & (Y)) ^ ((~(X)) & (Z)))
00013 #define MAJ(X,Y,Z) (((X) & (Y)) ^ ((X) & (Z)) ^ ((Y) & (Z)))
00014 #define BSIG0(X) (ROTR(X,2) ^ ROTR(X,13) ^ ROTR(X,22))
00015 #define BSIG1(X) (ROTR(X,6) ^ ROTR(X,11) ^ ROTR(X,25))
00016 #define SSIG0(X) (ROTR((X),7) ^ ROTR((X),18) ^ ((X) >> 3))
00017 #define SSIG1(X) (ROTR((X),17) ^ ROTR((X),19) ^ ((X) >> 10))
00018 #define R(A,B,C,D,E,F,G,H,T,K)  T1 = H + BSIG1(E) + CH(E,F,G) + K + (w[T] = revWord(buffer2[T])); \
00019                               T2 = BSIG0(A) + MAJ(A,B,C); \
00020                               D += T1; \
00021                               H = T1 + T2;
00022 #define R2(A,B,C,D,E,F,G,H,T,K)  T1 = H + BSIG1(E) + CH(E,F,G) + K + W(T&MASK); \
00023                               T2 = BSIG0(A) + MAJ(A,B,C); \
00024                               D += T1; \
00025                               H = T1 + T2;
00026         
00027 static const uint32_t H[] =
00028 {
00029     // SHA-224
00030     0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
00031     0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
00032     
00033     // SHA-256      
00034     0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
00035     0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
00036 };
00037 
00038 static uint32_t revWord(const uint32_t w)
00039 {
00040 #ifdef __CC_ARM
00041     return __rev(w);
00042 #else
00043     return (w >> 24)
00044          | ((w & 0x00FF0000) >> 8)
00045          | ((w & 0x0000FF00) << 8)
00046          | ((w & 0x000000FF) << 24);
00047 #endif
00048 } 
00049 
00050 static uint32_t rotRWord(const uint32_t w, const uint32_t n)
00051 {
00052 #ifdef __CC_ARM
00053     return __ror(w, n);
00054 #else
00055     return (w >> n) | (w << (32-n));
00056 #endif
00057 }
00058 
00059 SHA2_32::SHA2_32(SHA_32_TYPE t):
00060 type(t),
00061 totalBufferLength(0),
00062 bufferLength(0)
00063 {
00064     switch(type)
00065     {
00066         case SHA_224:
00067             h0 = H[0];
00068             h1 = H[1];
00069             h2 = H[2];
00070             h3 = H[3];
00071             h4 = H[4];
00072             h5 = H[5];
00073             h6 = H[6];
00074             h7 = H[7];
00075         break;
00076         
00077         case SHA_256:
00078             h0 = H[8];
00079             h1 = H[9];
00080             h2 = H[10];
00081             h3 = H[11];
00082             h4 = H[12];
00083             h5 = H[13];
00084             h6 = H[14];
00085             h7 = H[15];     
00086         break;
00087     }
00088 }
00089 
00090 void SHA2_32::update(uint8_t *data, uint32_t length)
00091 {
00092     if((int)length < 64-bufferLength)
00093     {
00094         memcpy(&buffer[bufferLength], data, length);
00095         bufferLength += length;
00096         totalBufferLength += length;
00097         return;
00098     }
00099     int offset = 64-bufferLength;
00100     memcpy(&buffer[bufferLength], data, offset);
00101     computeBlock(&h0,&h1,&h2,&h3,&h4,&h5,&h6,&h7,buffer);
00102     while(length-offset > 64)
00103     {
00104         memcpy(buffer, &data[offset], 64);
00105         computeBlock(&h0,&h1,&h2,&h3,&h4,&h5,&h6,&h7,buffer);
00106         offset += 64;
00107     }
00108     if(offset > (int)length)
00109         offset -= 64;
00110     bufferLength = length - offset;
00111     memcpy(buffer, &data[offset], bufferLength);
00112     totalBufferLength += length;
00113 }
00114 
00115 void SHA2_32::finalize(uint8_t *hash)
00116 {
00117     uint32_t *hash2 = (uint32_t*)hash;
00118     uint16_t padding;
00119     if(totalBufferLength % 64 < 56)
00120         padding = 56 - (totalBufferLength % 64);
00121     else
00122         padding = 56 + (64 - (totalBufferLength % 64));
00123 
00124     buffer[bufferLength++] = 0x80;
00125     padding--;
00126     if(padding+bufferLength == 56)
00127         memset(&buffer[bufferLength], 0, padding);
00128     else
00129     {
00130         memset(&buffer[bufferLength], 0, 64-bufferLength);
00131         computeBlock(&h0, &h1, &h2, &h3, &h4, &h5, &h6, &h7, buffer);
00132         memset(buffer, 0, 56);
00133     }
00134     
00135     uint64_t lengthBit = totalBufferLength << 3;
00136     uint32_t lengthBitLow = lengthBit;
00137     uint32_t lengthBitHigh = lengthBit >> 32;
00138     lengthBitLow = revWord(lengthBitLow);
00139     lengthBitHigh = revWord(lengthBitHigh);
00140     memcpy(&buffer[60], &lengthBitLow, 4);    
00141     memcpy(&buffer[56], &lengthBitHigh, 4);    
00142     computeBlock(&h0, &h1, &h2, &h3, &h4, &h5, &h6, &h7, buffer);
00143 
00144     hash2[0] = revWord(h0);
00145     hash2[1] = revWord(h1);
00146     hash2[2] = revWord(h2);
00147     hash2[3] = revWord(h3);
00148     hash2[4] = revWord(h4);
00149     hash2[5] = revWord(h5);
00150     hash2[6] = revWord(h6);
00151 
00152     
00153     if(type == SHA_256)
00154         hash2[7] = revWord(h7);
00155     
00156     // reset state
00157     switch(type)
00158     {
00159         case SHA_224:
00160             h0 = H[0];
00161             h1 = H[1];
00162             h2 = H[2];
00163             h3 = H[3];
00164             h4 = H[4];
00165             h5 = H[5];
00166             h6 = H[6];
00167             h7 = H[7];
00168         break;
00169         
00170         case SHA_256:
00171             h0 = H[8];
00172             h1 = H[9];
00173             h2 = H[10];
00174             h3 = H[11];
00175             h4 = H[12];
00176             h5 = H[13];
00177             h6 = H[14];
00178             h7 = H[15];     
00179         break;
00180     }
00181     totalBufferLength = 0;
00182     bufferLength = 0;
00183 }
00184 
00185 void SHA2_32::computeHash(SHA_32_TYPE type, uint8_t *hash, uint8_t *data, uint32_t length)
00186 {
00187     uint32_t *hash2 = (uint32_t*)hash;
00188     
00189     uint32_t h[8];
00190     h[0] = H[type*8];
00191     h[1] = H[type*8+1];
00192     h[2] = H[type*8+2];
00193     h[3] = H[type*8+3];
00194     h[4] = H[type*8+4];
00195     h[5] = H[type*8+5];
00196     h[6] = H[type*8+6];
00197     h[7] = H[type*8+7];
00198     
00199     uint64_t lengthBit = length << 3;
00200     uint32_t padding;
00201     if(length % 64 < 56)
00202         padding = 56 - (length % 64);
00203     else
00204         padding = 56 + (64 - (length % 64));
00205         
00206     while(length >= 64)
00207     {
00208         computeBlock(h, &h[1], &h[2], &h[3], &h[4], &h[5], &h[6], &h[7], data);
00209         length -= 64;
00210         data += 64;
00211     }
00212     uint8_t buffer[64];
00213     memcpy(buffer, data,length); 
00214     buffer[length++] = 0x80;
00215     padding--;
00216     if(padding+length == 56)
00217         memset(&buffer[length], 0, padding);
00218     else
00219     {
00220         memset(&buffer[length], 0, 64-length);
00221         computeBlock(h, &h[1], &h[2], &h[3], &h[4], &h[5], &h[6], &h[7], buffer);
00222         memset(buffer, 0, 56);
00223     }
00224     
00225     uint32_t lengthBitLow = lengthBit;
00226     uint32_t lengthBitHigh = lengthBit >> 32;
00227     lengthBitLow = revWord(lengthBitLow);
00228     memcpy(&buffer[60], &lengthBitLow, 4);
00229     lengthBitHigh = revWord(lengthBitHigh);
00230     memcpy(&buffer[56], &lengthBitHigh, 4);    
00231     computeBlock(h, &h[1], &h[2], &h[3], &h[4], &h[5], &h[6], &h[7], buffer);
00232 
00233     hash2[0] = revWord(h[0]);
00234     hash2[1] = revWord(h[1]);
00235     hash2[2] = revWord(h[2]);
00236     hash2[3] = revWord(h[3]);
00237     hash2[4] = revWord(h[4]);
00238     hash2[5] = revWord(h[5]);
00239     hash2[6] = revWord(h[6]);
00240 
00241     
00242     if(type == SHA_256)
00243         hash2[7] = revWord(h[7]);
00244 }
00245 
00246 
00247 #ifdef __CC_ARM
00248 __forceinline 
00249 #endif 
00250 void SHA2_32::computeBlock(uint32_t *h02, 
00251                         uint32_t *h12, 
00252                         uint32_t *h22, 
00253                         uint32_t *h32, 
00254                         uint32_t *h42, 
00255                         uint32_t *h52, 
00256                         uint32_t *h62,
00257                         uint32_t *h72,
00258                         uint8_t *buffer)
00259 {
00260     uint32_t w[16];
00261     uint32_t *buffer2 = (uint32_t*)buffer;
00262     uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42, f = *h52, g = *h62, h = *h72;
00263     uint32_t T1, T2;
00264 
00265     R(a,b,c,d,e,f,g,h,0,0x428a2f98)
00266     R(h,a,b,c,d,e,f,g,1,0x71374491)
00267     R(g,h,a,b,c,d,e,f,2,0xb5c0fbcf)
00268     R(f,g,h,a,b,c,d,e,3,0xe9b5dba5)
00269     R(e,f,g,h,a,b,c,d,4,0x3956c25b)
00270     R(d,e,f,g,h,a,b,c,5,0x59f111f1)
00271     R(c,d,e,f,g,h,a,b,6,0x923f82a4)
00272     R(b,c,d,e,f,g,h,a,7,0xab1c5ed5)
00273 
00274     R(a,b,c,d,e,f,g,h,8,0xd807aa98)
00275     R(h,a,b,c,d,e,f,g,9,0x12835b01)
00276     R(g,h,a,b,c,d,e,f,10,0x243185be)
00277     R(f,g,h,a,b,c,d,e,11,0x550c7dc3)
00278     R(e,f,g,h,a,b,c,d,12,0x72be5d74)
00279     R(d,e,f,g,h,a,b,c,13,0x80deb1fe)
00280     R(c,d,e,f,g,h,a,b,14,0x9bdc06a7)
00281     R(b,c,d,e,f,g,h,a,15,0xc19bf174)
00282 
00283     R2(a,b,c,d,e,f,g,h,16,0xe49b69c1)
00284     R2(h,a,b,c,d,e,f,g,17,0xefbe4786)
00285     R2(g,h,a,b,c,d,e,f,18,0x0fc19dc6)
00286     R2(f,g,h,a,b,c,d,e,19,0x240ca1cc)
00287     R2(e,f,g,h,a,b,c,d,20,0x2de92c6f)
00288     R2(d,e,f,g,h,a,b,c,21,0x4a7484aa)
00289     R2(c,d,e,f,g,h,a,b,22,0x5cb0a9dc)
00290     R2(b,c,d,e,f,g,h,a,23,0x76f988da)
00291     
00292     R2(a,b,c,d,e,f,g,h,24,0x983e5152)
00293     R2(h,a,b,c,d,e,f,g,25,0xa831c66d)
00294     R2(g,h,a,b,c,d,e,f,26,0xb00327c8)
00295     R2(f,g,h,a,b,c,d,e,27,0xbf597fc7)
00296     R2(e,f,g,h,a,b,c,d,28,0xc6e00bf3)
00297     R2(d,e,f,g,h,a,b,c,29,0xd5a79147)
00298     R2(c,d,e,f,g,h,a,b,30,0x06ca6351)
00299     R2(b,c,d,e,f,g,h,a,31,0x14292967) 
00300 
00301     R2(a,b,c,d,e,f,g,h,32,0x27b70a85)
00302     R2(h,a,b,c,d,e,f,g,33,0x2e1b2138)
00303     R2(g,h,a,b,c,d,e,f,34,0x4d2c6dfc)
00304     R2(f,g,h,a,b,c,d,e,35,0x53380d13)
00305     R2(e,f,g,h,a,b,c,d,36,0x650a7354)
00306     R2(d,e,f,g,h,a,b,c,37,0x766a0abb)
00307     R2(c,d,e,f,g,h,a,b,38,0x81c2c92e)
00308     R2(b,c,d,e,f,g,h,a,39,0x92722c85)
00309     
00310     R2(a,b,c,d,e,f,g,h,40,0xa2bfe8a1)
00311     R2(h,a,b,c,d,e,f,g,41,0xa81a664b)
00312     R2(g,h,a,b,c,d,e,f,42,0xc24b8b70)
00313     R2(f,g,h,a,b,c,d,e,43,0xc76c51a3)
00314     R2(e,f,g,h,a,b,c,d,44,0xd192e819)
00315     R2(d,e,f,g,h,a,b,c,45,0xd6990624)
00316     R2(c,d,e,f,g,h,a,b,46,0xf40e3585)
00317     R2(b,c,d,e,f,g,h,a,47,0x106aa070)
00318     
00319     R2(a,b,c,d,e,f,g,h,48,0x19a4c116)
00320     R2(h,a,b,c,d,e,f,g,49,0x1e376c08)
00321     R2(g,h,a,b,c,d,e,f,50,0x2748774c)
00322     R2(f,g,h,a,b,c,d,e,51,0x34b0bcb5)
00323     R2(e,f,g,h,a,b,c,d,52,0x391c0cb3)
00324     R2(d,e,f,g,h,a,b,c,53,0x4ed8aa4a)
00325     R2(c,d,e,f,g,h,a,b,54,0x5b9cca4f)
00326     R2(b,c,d,e,f,g,h,a,55,0x682e6ff3)
00327     
00328     R2(a,b,c,d,e,f,g,h,56,0x748f82ee)
00329     R2(h,a,b,c,d,e,f,g,57,0x78a5636f)
00330     R2(g,h,a,b,c,d,e,f,58,0x84c87814)
00331     R2(f,g,h,a,b,c,d,e,59,0x8cc70208)
00332     R2(e,f,g,h,a,b,c,d,60,0x90befffa)
00333     R2(d,e,f,g,h,a,b,c,61,0xa4506ceb)
00334     R2(c,d,e,f,g,h,a,b,62,0xbef9a3f7)
00335     R2(b,c,d,e,f,g,h,a,63,0xc67178f2)
00336     
00337     
00338     *h02 += a;
00339     *h12 += b;
00340     *h22 += c;
00341     *h32 += d;
00342     *h42 += e;
00343     *h52 += f;
00344     *h62 += g;
00345     *h72 += h;
00346 }