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 SHA1.cpp Source File

SHA1.cpp

00001 /**
00002     Implementation of SHA-1 as described here:
00003     http://tools.ietf.org/html/rfc1319
00004 */
00005 
00006 #include "SHA1.h"
00007 #include <string.h>
00008 
00009 #define F0(B,C,D) ((B & C) | ((~B) & D))
00010 #define F1(B,C,D) (B ^ C ^ D)
00011 #define F2(B,C,D) ((B & C) | (B & D) | (C & D))
00012 #define ROTL(W,N) (((W) << N) | ((W) >> (32-N)))
00013                         
00014 #define K0 0x5A827999
00015 #define K1 0x6ED9EBA1
00016 #define K2 0x8F1BBCDC
00017 #define K3 0xCA62C1D6
00018 
00019 
00020 #define H0 0x67452301
00021 #define H1 0xEFCDAB89
00022 #define H2 0x98BADCFE
00023 #define H3 0x10325476
00024 #define H4 0xC3D2E1F0
00025 
00026 #define MASK 0xF
00027 
00028 #define W(s) ( w[s] = ROTL(w[((s) + 13) & MASK] ^ w[((s) + 8) & MASK] ^ w[((s) + 2) & MASK] ^ w[s],1))
00029 
00030 #define R0(A,B,C,D,E,T) E += ROTL(A, 5) + F0(B, C, D) + w[T] + K0; \
00031                         B = ROTL(B,30);
00032 #define R1(A,B,C,D,E,T) E += ROTL(A, 5) + F0(B, C, D) + W(T & MASK) + K0; \
00033                         B = ROTL(B,30); 
00034 #define R2(A,B,C,D,E,T) E += ROTL(A, 5) + F1(B, C, D) + W(T & MASK) + K1; \
00035                         B = ROTL(B,30); 
00036 #define R3(A,B,C,D,E,T) E += ROTL(A, 5) + F2(B, C, D) + W(T & MASK) + K2; \
00037                         B = ROTL(B,30); 
00038 #define R4(A,B,C,D,E,T) E += ROTL(A, 5) + F1(B, C, D) + W(T & MASK) + K3; \
00039                         B = ROTL(B,30); 
00040 
00041 
00042 static uint32_t revWord(const uint32_t w)
00043 {
00044 #ifdef __CC_ARM
00045     return __rev(w);
00046 #else
00047     return (w >> 24)
00048          | ((w & 0x00FF0000) >> 8)
00049          | ((w & 0x0000FF00) << 8)
00050          | ((w & 0x000000FF) << 24);
00051 #endif
00052 } 
00053                         
00054 SHA1::SHA1():
00055 HashAlgorithm(),
00056 h0(H0),
00057 h1(H1),
00058 h2(H2),
00059 h3(H3),
00060 h4(H4),
00061 totalBufferLength(0),
00062 buffer(),
00063 bufferLength(0)
00064 {
00065 }
00066 
00067 uint8_t SHA1::outputSize() const
00068 {
00069     return 20;
00070 }
00071 
00072 void SHA1::update(uint8_t *data, uint32_t length)
00073 {
00074     if((int)length < 64-bufferLength)
00075     {
00076         memcpy(&buffer[bufferLength], data, length);
00077         bufferLength += length;
00078         totalBufferLength += length;
00079         return;
00080     }
00081     int offset = 64-bufferLength;
00082     memcpy(&buffer[bufferLength], data, offset);
00083     computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00084     while(length-offset > 64)
00085     {
00086         memcpy(buffer, &data[offset], 64);
00087         computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00088         offset += 64;
00089     }
00090     if(offset > (int)length)
00091         offset -= 64;
00092     bufferLength = length - offset;
00093     memcpy(buffer, &data[offset], bufferLength);
00094     totalBufferLength += length;
00095 }
00096 
00097 void SHA1::finalize(uint8_t *hash)
00098 {
00099     uint32_t *hash2 = (uint32_t*)hash;
00100     uint16_t padding;
00101     if(totalBufferLength % 64 < 56)
00102         padding = 56 - (totalBufferLength % 64);
00103     else
00104         padding = 56 + (64 - (totalBufferLength % 64));
00105         
00106     buffer[bufferLength++] = 0x80;
00107     padding--;
00108     if(padding+bufferLength == 56)
00109         memset(&buffer[bufferLength], 0, padding);
00110     else
00111     {
00112         memset(&buffer[bufferLength], 0, 64-bufferLength);
00113         computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00114         memset(buffer, 0, 56);
00115     }
00116     
00117     uint64_t lengthBit = totalBufferLength << 3;
00118     uint32_t lengthBitLow = lengthBit;
00119     uint32_t lengthBitHigh = lengthBit >> 32;
00120     lengthBitLow = revWord(lengthBitLow);
00121     lengthBitHigh = revWord(lengthBitHigh);
00122     memcpy(&buffer[56], &lengthBitHigh, 4);
00123     memcpy(&buffer[60], &lengthBitLow, 4);
00124     computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00125     
00126     hash2[0] = revWord(h0);
00127     hash2[1] = revWord(h1);
00128     hash2[2] = revWord(h2);
00129     hash2[3] = revWord(h3);
00130     hash2[4] = revWord(h4);
00131     
00132     // reset state
00133     h0 = H0;
00134     h1 = H1;
00135     h2 = H2;
00136     h3 = H3;
00137     h4 = H4;
00138     totalBufferLength = 0;
00139     bufferLength = 0;
00140 }
00141 
00142 
00143 void SHA1::computeHash(uint8_t *hash, uint8_t *data, uint32_t length)
00144 {
00145     uint32_t *hash2 = (uint32_t*)hash;
00146     uint64_t lengthBit = length << 3;
00147     uint32_t padding;
00148     if(length % 64 < 56)
00149         padding = 56 - (length % 64);
00150     else
00151         padding = 56 + (64 - (length % 64));
00152         
00153     uint32_t h0 = H0, h1 = H1, h2 = H2, h3 = H3, h4 = H4;
00154     while(length >= 64)
00155     {
00156         computeBlock(&h0,&h1,&h2,&h3,&h4, data);
00157         length -= 64;
00158         data += 64;
00159     }
00160    
00161     uint8_t buffer[64];
00162     memcpy(buffer, data, length);
00163     buffer[length++] = 0x80;
00164     padding--;
00165     if(padding+length+8 == 64)
00166         memset(&buffer[length], 0, padding);
00167     else
00168     {
00169         memset(&buffer[length], 0, 64-length);
00170         computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00171         memset(buffer, 0, 56);
00172     }
00173 
00174     uint32_t lengthBitLow = lengthBit;
00175     uint32_t lengthBitHigh = lengthBit >> 32;
00176     lengthBitLow = revWord(lengthBitLow);
00177     lengthBitHigh = revWord(lengthBitHigh);
00178     memcpy(&buffer[60], &lengthBitLow, 4);
00179     memcpy(&buffer[56], &lengthBitHigh, 4);
00180     
00181     computeBlock(&h0,&h1,&h2,&h3,&h4, buffer);
00182 
00183     hash2[0] = revWord(h0);
00184     hash2[1] = revWord(h1);
00185     hash2[2] = revWord(h2);
00186     hash2[3] = revWord(h3);
00187     hash2[4] = revWord(h4);
00188 }
00189 
00190 void SHA1::computeBlock(uint32_t *h02, uint32_t *h12, uint32_t *h22, uint32_t *h32, uint32_t *h42, uint8_t *buffer)
00191 {
00192     uint32_t *buffer2 = (uint32_t*)buffer;
00193     uint32_t w[16];
00194 
00195     for(int t = 0; t < 16; ++t)
00196         w[t] = revWord(buffer2[t]);
00197     
00198     uint32_t a = *h02, b = *h12, c = *h22, d = *h32, e = *h42;
00199     
00200     R0(a,b,c,d,e, 0) R0(e,a,b,c,d, 1) R0(d,e,a,b,c, 2) R0(c,d,e,a,b, 3)
00201     R0(b,c,d,e,a, 4) R0(a,b,c,d,e, 5) R0(e,a,b,c,d, 6) R0(d,e,a,b,c, 7)
00202     R0(c,d,e,a,b, 8) R0(b,c,d,e,a, 9) R0(a,b,c,d,e,10) R0(e,a,b,c,d,11)
00203     R0(d,e,a,b,c,12) R0(c,d,e,a,b,13) R0(b,c,d,e,a,14) R0(a,b,c,d,e,15)
00204     R1(e,a,b,c,d,16) R1(d,e,a,b,c,17) R1(c,d,e,a,b,18) R1(b,c,d,e,a,19)    
00205     
00206     
00207     R2(a,b,c,d,e,20) R2(e,a,b,c,d,21) R2(d,e,a,b,c,22) R2(c,d,e,a,b,23)
00208     R2(b,c,d,e,a,24) R2(a,b,c,d,e,25) R2(e,a,b,c,d,26) R2(d,e,a,b,c,27)
00209     R2(c,d,e,a,b,28) R2(b,c,d,e,a,29) R2(a,b,c,d,e,30) R2(e,a,b,c,d,31)
00210     R2(d,e,a,b,c,32) R2(c,d,e,a,b,33) R2(b,c,d,e,a,34) R2(a,b,c,d,e,35)
00211     R2(e,a,b,c,d,36) R2(d,e,a,b,c,37) R2(c,d,e,a,b,38) R2(b,c,d,e,a,39)    
00212     
00213     R3(a,b,c,d,e,40) R3(e,a,b,c,d,41) R3(d,e,a,b,c,42) R3(c,d,e,a,b,43)
00214     R3(b,c,d,e,a,44) R3(a,b,c,d,e,45) R3(e,a,b,c,d,46) R3(d,e,a,b,c,47)
00215     R3(c,d,e,a,b,48) R3(b,c,d,e,a,49) R3(a,b,c,d,e,50) R3(e,a,b,c,d,51)
00216     R3(d,e,a,b,c,52) R3(c,d,e,a,b,53) R3(b,c,d,e,a,54) R3(a,b,c,d,e,55)
00217     R3(e,a,b,c,d,56) R3(d,e,a,b,c,57) R3(c,d,e,a,b,58) R3(b,c,d,e,a,59)    
00218     
00219     
00220     R4(a,b,c,d,e,60) R4(e,a,b,c,d,61) R4(d,e,a,b,c,62) R4(c,d,e,a,b,63)
00221     R4(b,c,d,e,a,64) R4(a,b,c,d,e,65) R4(e,a,b,c,d,66) R4(d,e,a,b,c,67)
00222     R4(c,d,e,a,b,68) R4(b,c,d,e,a,69) R4(a,b,c,d,e,70) R4(e,a,b,c,d,71)
00223     R4(d,e,a,b,c,72) R4(c,d,e,a,b,73) R4(b,c,d,e,a,74) R4(a,b,c,d,e,75)
00224     R4(e,a,b,c,d,76) R4(d,e,a,b,c,77) R4(c,d,e,a,b,78) R4(b,c,d,e,a,79)    
00225         
00226     *h02 += a;
00227     *h12 += b;
00228     *h22 += c;
00229     *h32 += d;
00230     *h42 += e;
00231 }