SHA1.cc

Go to the documentation of this file.
00001 /*
00002         100% free public domain implementation of the SHA-1 algorithm
00003         by Dominik Reichl <dominik.reichl@t-online.de>
00004 
00005         Version 1.5 - 2005-01-01
00006         - 64-bit compiler compatibility added
00007         - Made variable wiping optional (define SHA1_WIPE_VARIABLES)
00008         - Removed unnecessary variable initializations
00009         - ROL32 improvement for the Microsoft compiler (using _rotl)
00010 
00011         ======== Test Vectors (from FIPS PUB 180-1) ========
00012 
00013         SHA1("abc") =
00014                 A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
00015 
00016         SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
00017                 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
00018 
00019         SHA1(A million repetitions of "a") =
00020                 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
00021 */
00022 
00023 
00029 #define SHA1_NO_UTILITY_FUNCTIONS
00030 
00031 #include <omnetpp.h>
00032 #include "SHA1.h"
00033 
00034 #ifdef SHA1_UTILITY_FUNCTIONS
00035 #define SHA1_MAX_FILE_BUFFER 8000
00036 #endif
00037 
00038 // Rotate x bits to the left
00039 #ifndef ROL32
00040 #ifdef _MSC_VER
00041 #define ROL32(_val32, _nBits) _rotl(_val32, _nBits)
00042 #else
00043 #define ROL32(_val32, _nBits) (((_val32)<<(_nBits))|((_val32)>>(32-(_nBits))))
00044 #endif
00045 #endif
00046 
00047 #ifdef SHA1_LITTLE_ENDIAN
00048 #define SHABLK0(i) (m_block->l[i] = \
00049         (ROL32(m_block->l[i],24) & 0xFF00FF00) | (ROL32(m_block->l[i],8) & 0x00FF00FF))
00050 #else
00051 #define SHABLK0(i) (m_block->l[i])
00052 #endif
00053 
00054 #define SHABLK(i) (m_block->l[i&15] = ROL32(m_block->l[(i+13)&15] ^ m_block->l[(i+8)&15] \
00055         ^ m_block->l[(i+2)&15] ^ m_block->l[i&15],1))
00056 
00057 // SHA-1 rounds
00058 #define _R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
00059 #define _R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); }
00060 #define _R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); }
00061 #define _R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); }
00062 #define _R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); }
00063 
00064 CSHA1::CSHA1()
00065 {
00066     m_block = (SHA1_WORKSPACE_BLOCK *)m_workspace;
00067 
00068     Reset();
00069 }
00070 
00071 CSHA1::~CSHA1()
00072 {
00073     Reset();
00074 }
00075 
00076 void CSHA1::Reset()
00077 {
00078     // SHA1 initialization constants
00079     m_state[0] = 0x67452301;
00080     m_state[1] = 0xEFCDAB89;
00081     m_state[2] = 0x98BADCFE;
00082     m_state[3] = 0x10325476;
00083     m_state[4] = 0xC3D2E1F0;
00084 
00085     m_count[0] = 0;
00086     m_count[1] = 0;
00087 }
00088 
00089 void CSHA1::Transform(UINT_32 *state, UINT_8 *buffer)
00090 {
00091     // Copy state[] to working vars
00092     UINT_32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4];
00093 
00094     memcpy(m_block, buffer, 64);
00095 
00096     // 4 rounds of 20 operations each. Loop unrolled.
00097     _R0(a,b,c,d,e, 0);
00098     _R0(e,a,b,c,d, 1);
00099     _R0(d,e,a,b,c, 2);
00100     _R0(c,d,e,a,b, 3);
00101     _R0(b,c,d,e,a, 4);
00102     _R0(a,b,c,d,e, 5);
00103     _R0(e,a,b,c,d, 6);
00104     _R0(d,e,a,b,c, 7);
00105     _R0(c,d,e,a,b, 8);
00106     _R0(b,c,d,e,a, 9);
00107     _R0(a,b,c,d,e,10);
00108     _R0(e,a,b,c,d,11);
00109     _R0(d,e,a,b,c,12);
00110     _R0(c,d,e,a,b,13);
00111     _R0(b,c,d,e,a,14);
00112     _R0(a,b,c,d,e,15);
00113     _R1(e,a,b,c,d,16);
00114     _R1(d,e,a,b,c,17);
00115     _R1(c,d,e,a,b,18);
00116     _R1(b,c,d,e,a,19);
00117     _R2(a,b,c,d,e,20);
00118     _R2(e,a,b,c,d,21);
00119     _R2(d,e,a,b,c,22);
00120     _R2(c,d,e,a,b,23);
00121     _R2(b,c,d,e,a,24);
00122     _R2(a,b,c,d,e,25);
00123     _R2(e,a,b,c,d,26);
00124     _R2(d,e,a,b,c,27);
00125     _R2(c,d,e,a,b,28);
00126     _R2(b,c,d,e,a,29);
00127     _R2(a,b,c,d,e,30);
00128     _R2(e,a,b,c,d,31);
00129     _R2(d,e,a,b,c,32);
00130     _R2(c,d,e,a,b,33);
00131     _R2(b,c,d,e,a,34);
00132     _R2(a,b,c,d,e,35);
00133     _R2(e,a,b,c,d,36);
00134     _R2(d,e,a,b,c,37);
00135     _R2(c,d,e,a,b,38);
00136     _R2(b,c,d,e,a,39);
00137     _R3(a,b,c,d,e,40);
00138     _R3(e,a,b,c,d,41);
00139     _R3(d,e,a,b,c,42);
00140     _R3(c,d,e,a,b,43);
00141     _R3(b,c,d,e,a,44);
00142     _R3(a,b,c,d,e,45);
00143     _R3(e,a,b,c,d,46);
00144     _R3(d,e,a,b,c,47);
00145     _R3(c,d,e,a,b,48);
00146     _R3(b,c,d,e,a,49);
00147     _R3(a,b,c,d,e,50);
00148     _R3(e,a,b,c,d,51);
00149     _R3(d,e,a,b,c,52);
00150     _R3(c,d,e,a,b,53);
00151     _R3(b,c,d,e,a,54);
00152     _R3(a,b,c,d,e,55);
00153     _R3(e,a,b,c,d,56);
00154     _R3(d,e,a,b,c,57);
00155     _R3(c,d,e,a,b,58);
00156     _R3(b,c,d,e,a,59);
00157     _R4(a,b,c,d,e,60);
00158     _R4(e,a,b,c,d,61);
00159     _R4(d,e,a,b,c,62);
00160     _R4(c,d,e,a,b,63);
00161     _R4(b,c,d,e,a,64);
00162     _R4(a,b,c,d,e,65);
00163     _R4(e,a,b,c,d,66);
00164     _R4(d,e,a,b,c,67);
00165     _R4(c,d,e,a,b,68);
00166     _R4(b,c,d,e,a,69);
00167     _R4(a,b,c,d,e,70);
00168     _R4(e,a,b,c,d,71);
00169     _R4(d,e,a,b,c,72);
00170     _R4(c,d,e,a,b,73);
00171     _R4(b,c,d,e,a,74);
00172     _R4(a,b,c,d,e,75);
00173     _R4(e,a,b,c,d,76);
00174     _R4(d,e,a,b,c,77);
00175     _R4(c,d,e,a,b,78);
00176     _R4(b,c,d,e,a,79);
00177 
00178     // Add the working vars back into state
00179     state[0] += a;
00180     state[1] += b;
00181     state[2] += c;
00182     state[3] += d;
00183     state[4] += e;
00184 
00185     // Wipe variables
00186 #ifdef SHA1_WIPE_VARIABLES
00187 
00188     a = b = c = d = e = 0;
00189 #endif
00190 }
00191 
00192 // Use this function to hash in binary data and strings
00193 void CSHA1::Update(UINT_8 *data, UINT_32 len)
00194 {
00195     UINT_32 i, j;
00196 
00197     j = (m_count[0] >> 3) & 63;
00198 
00199     if((m_count[0] += len << 3) < (len << 3))
00200         m_count[1]++;
00201 
00202     m_count[1] += (len >> 29);
00203 
00204     if((j + len) > 63) {
00205         i = 64 - j;
00206         memcpy(&m_buffer[j], data, i);
00207         Transform(m_state, m_buffer);
00208 
00209         for( ; i + 63 < len; i += 64)
00210             Transform(m_state, &data[i]);
00211 
00212         j = 0;
00213     } else
00214         i = 0;
00215 
00216     memcpy(&m_buffer[j], &data[i], len - i);
00217 }
00218 
00219 #ifdef SHA1_UTILITY_FUNCTIONS
00220 // Hash in file contents
00221 bool CSHA1::HashFile(char *szFileName)
00222 {
00223     unsigned long ulFileSize, ulRest, ulBlocks;
00224     unsigned long i;
00225     UINT_8 uData[SHA1_MAX_FILE_BUFFER];
00226     FILE *fIn;
00227 
00228     if(szFileName == NULL)
00229         return false;
00230 
00231     fIn = fopen(szFileName, "rb");
00232     if(fIn == NULL)
00233         return false;
00234 
00235     fseek(fIn, 0, SEEK_END);
00236     ulFileSize = (unsigned long)ftell(fIn);
00237     fseek(fIn, 0, SEEK_SET);
00238 
00239     if(ulFileSize != 0) {
00240         ulBlocks = ulFileSize / SHA1_MAX_FILE_BUFFER;
00241         ulRest = ulFileSize % SHA1_MAX_FILE_BUFFER;
00242     } else {
00243         ulBlocks = 0;
00244         ulRest = 0;
00245     }
00246 
00247     for(i = 0; i < ulBlocks; i++) {
00248         fread(uData, 1, SHA1_MAX_FILE_BUFFER, fIn);
00249         Update((UINT_8 *)uData, SHA1_MAX_FILE_BUFFER);
00250     }
00251 
00252     if(ulRest != 0) {
00253         fread(uData, 1, ulRest, fIn);
00254         Update((UINT_8 *)uData, ulRest);
00255     }
00256 
00257     fclose(fIn);
00258     fIn = NULL;
00259     return true;
00260 }
00261 #endif
00262 
00263 void CSHA1::Final()
00264 {
00265     UINT_32 i;
00266     UINT_8 finalcount[8];
00267 
00268     for(i = 0; i < 8; i++)
00269         finalcount[i] = (UINT_8)((m_count[((i >= 4) ? 0 : 1)]
00270                                   >> ((3 - (i & 3)) * 8) ) & 255); // Endian independent
00271 
00272     Update((UINT_8 *)"\200", 1);
00273 
00274     while ((m_count[0] & 504) != 448)
00275         Update((UINT_8 *)"\0", 1);
00276 
00277     Update(finalcount, 8); // Cause a SHA1Transform()
00278 
00279     for(i = 0; i < 20; i++) {
00280         m_digest[i] = (UINT_8)((m_state[i >> 2] >> ((3 - (i & 3)) * 8) ) & 255);
00281     }
00282 
00283     // Wipe variables for security reasons
00284 #ifdef SHA1_WIPE_VARIABLES
00285     i = 0;
00286     memset(m_buffer, 0, 64);
00287     memset(m_state, 0, 20);
00288     memset(m_count, 0, 8);
00289     memset(finalcount, 0, 8);
00290     Transform(m_state, m_buffer);
00291 #endif
00292 }
00293 
00294 #ifdef SHA1_UTILITY_FUNCTIONS
00295 // Get the final hash as a pre-formatted string
00296 void CSHA1::ReportHash(char *szReport, unsigned char uReportType)
00297 {
00298     unsigned char i;
00299     char szTemp[16];
00300 
00301     if(szReport == NULL)
00302         return;
00303 
00304     if(uReportType == REPORT_HEX) {
00305         //sprintf(szTemp, "%02x", m_digest[0]);
00306         //strcat(szReport, szTemp);
00307 
00308         for(i = 0; i < 20; i++) {
00309             sprintf(szTemp, "%02x", m_digest[i]);
00310             strcat(szReport, szTemp);
00311         }
00312     } else if(uReportType == REPORT_DIGIT) {
00313         sprintf(szTemp, "%u", m_digest[0]);
00314         strcat(szReport, szTemp);
00315 
00316         for(i = 1; i < 20; i++) {
00317             sprintf(szTemp, " %u", m_digest[i]);
00318             strcat(szReport, szTemp);
00319         }
00320     } else
00321         strcpy(szReport, "Error: Unknown report type!");
00322 }
00323 #endif
00324 
00325 // Get the raw message digest
00326 void CSHA1::GetHash(UINT_8 *puDest)
00327 {
00328     memcpy(puDest, m_digest, 20);
00329 }
Generated on Wed May 26 16:21:15 2010 for OverSim by  doxygen 1.6.3