RealtimeCompLab2

Dependencies:   mbed

Fork of PPP-Blinky by Nicolas Nackel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sha1.cpp Source File

sha1.cpp

00001 /*
00002 SHA-1 in C
00003 By Steve Reid <steve@edmweb.com>
00004 100% Public Domain
00005 */
00006 
00007 #define SHA1HANDSOFF
00008 
00009 #include <stdio.h>
00010 #include <string.h>
00011 
00012 /* for uint32_t */
00013 #include <stdint.h>
00014 
00015 #include "sha1.h"
00016 
00017 
00018 #define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
00019 
00020 /* blk0() and blk() perform the initial expand. */
00021 /* I got the idea of expanding during the round function from SSLeay */
00022 #if BYTE_ORDER == LITTLE_ENDIAN
00023 #define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
00024     |(rol(block->l[i],8)&0x00FF00FF))
00025 #elif BYTE_ORDER == BIG_ENDIAN
00026 #define blk0(i) block->l[i]
00027 #else
00028 #error "Endianness not defined!"
00029 #endif
00030 #define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
00031     ^block->l[(i+2)&15]^block->l[i&15],1))
00032 
00033 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
00034 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
00035 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
00036 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
00037 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
00038 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
00039 
00040 
00041 /* Hash a single 512-bit block. This is the core of the algorithm. */
00042 
00043 void SHA1Transform(
00044     uint32_t state[5],
00045     const unsigned char buffer[64]
00046 )
00047 {
00048     uint32_t a, b, c, d, e;
00049 
00050     typedef union
00051     {
00052         unsigned char c[64];
00053         uint32_t l[16];
00054     } CHAR64LONG16;
00055 
00056 #ifdef SHA1HANDSOFF
00057     CHAR64LONG16 block[1];      /* use array to appear as a pointer */
00058 
00059     memcpy(block, buffer, 64);
00060 #else
00061     /* The following had better never be used because it causes the
00062      * pointer-to-const buffer to be cast into a pointer to non-const.
00063      * And the result is written through.  I threw a "const" in, hoping
00064      * this will cause a diagnostic.
00065      */
00066     CHAR64LONG16 *block = (const CHAR64LONG16 *) buffer;
00067 #endif
00068     /* Copy context->state[] to working vars */
00069     a = state[0];
00070     b = state[1];
00071     c = state[2];
00072     d = state[3];
00073     e = state[4];
00074     /* 4 rounds of 20 operations each. Loop unrolled. */
00075     R0(a, b, c, d, e, 0);
00076     R0(e, a, b, c, d, 1);
00077     R0(d, e, a, b, c, 2);
00078     R0(c, d, e, a, b, 3);
00079     R0(b, c, d, e, a, 4);
00080     R0(a, b, c, d, e, 5);
00081     R0(e, a, b, c, d, 6);
00082     R0(d, e, a, b, c, 7);
00083     R0(c, d, e, a, b, 8);
00084     R0(b, c, d, e, a, 9);
00085     R0(a, b, c, d, e, 10);
00086     R0(e, a, b, c, d, 11);
00087     R0(d, e, a, b, c, 12);
00088     R0(c, d, e, a, b, 13);
00089     R0(b, c, d, e, a, 14);
00090     R0(a, b, c, d, e, 15);
00091     R1(e, a, b, c, d, 16);
00092     R1(d, e, a, b, c, 17);
00093     R1(c, d, e, a, b, 18);
00094     R1(b, c, d, e, a, 19);
00095     R2(a, b, c, d, e, 20);
00096     R2(e, a, b, c, d, 21);
00097     R2(d, e, a, b, c, 22);
00098     R2(c, d, e, a, b, 23);
00099     R2(b, c, d, e, a, 24);
00100     R2(a, b, c, d, e, 25);
00101     R2(e, a, b, c, d, 26);
00102     R2(d, e, a, b, c, 27);
00103     R2(c, d, e, a, b, 28);
00104     R2(b, c, d, e, a, 29);
00105     R2(a, b, c, d, e, 30);
00106     R2(e, a, b, c, d, 31);
00107     R2(d, e, a, b, c, 32);
00108     R2(c, d, e, a, b, 33);
00109     R2(b, c, d, e, a, 34);
00110     R2(a, b, c, d, e, 35);
00111     R2(e, a, b, c, d, 36);
00112     R2(d, e, a, b, c, 37);
00113     R2(c, d, e, a, b, 38);
00114     R2(b, c, d, e, a, 39);
00115     R3(a, b, c, d, e, 40);
00116     R3(e, a, b, c, d, 41);
00117     R3(d, e, a, b, c, 42);
00118     R3(c, d, e, a, b, 43);
00119     R3(b, c, d, e, a, 44);
00120     R3(a, b, c, d, e, 45);
00121     R3(e, a, b, c, d, 46);
00122     R3(d, e, a, b, c, 47);
00123     R3(c, d, e, a, b, 48);
00124     R3(b, c, d, e, a, 49);
00125     R3(a, b, c, d, e, 50);
00126     R3(e, a, b, c, d, 51);
00127     R3(d, e, a, b, c, 52);
00128     R3(c, d, e, a, b, 53);
00129     R3(b, c, d, e, a, 54);
00130     R3(a, b, c, d, e, 55);
00131     R3(e, a, b, c, d, 56);
00132     R3(d, e, a, b, c, 57);
00133     R3(c, d, e, a, b, 58);
00134     R3(b, c, d, e, a, 59);
00135     R4(a, b, c, d, e, 60);
00136     R4(e, a, b, c, d, 61);
00137     R4(d, e, a, b, c, 62);
00138     R4(c, d, e, a, b, 63);
00139     R4(b, c, d, e, a, 64);
00140     R4(a, b, c, d, e, 65);
00141     R4(e, a, b, c, d, 66);
00142     R4(d, e, a, b, c, 67);
00143     R4(c, d, e, a, b, 68);
00144     R4(b, c, d, e, a, 69);
00145     R4(a, b, c, d, e, 70);
00146     R4(e, a, b, c, d, 71);
00147     R4(d, e, a, b, c, 72);
00148     R4(c, d, e, a, b, 73);
00149     R4(b, c, d, e, a, 74);
00150     R4(a, b, c, d, e, 75);
00151     R4(e, a, b, c, d, 76);
00152     R4(d, e, a, b, c, 77);
00153     R4(c, d, e, a, b, 78);
00154     R4(b, c, d, e, a, 79);
00155     /* Add the working vars back into context.state[] */
00156     state[0] += a;
00157     state[1] += b;
00158     state[2] += c;
00159     state[3] += d;
00160     state[4] += e;
00161     /* Wipe variables */
00162     a = b = c = d = e = 0;
00163 #ifdef SHA1HANDSOFF
00164     memset(block, '\0', sizeof(block));
00165 #endif
00166 }
00167 
00168 
00169 /* SHA1Init - Initialize new context */
00170 
00171 void SHA1Init(
00172     SHA1_CTX * context
00173 )
00174 {
00175     /* SHA1 initialization constants */
00176     context->state[0] = 0x67452301;
00177     context->state[1] = 0xEFCDAB89;
00178     context->state[2] = 0x98BADCFE;
00179     context->state[3] = 0x10325476;
00180     context->state[4] = 0xC3D2E1F0;
00181     context->count[0] = context->count[1] = 0;
00182 }
00183 
00184 
00185 /* Run your data through this. */
00186 
00187 void SHA1Update(
00188     SHA1_CTX * context,
00189     const unsigned char *data,
00190     uint32_t len
00191 )
00192 {
00193     uint32_t i;
00194 
00195     uint32_t j;
00196 
00197     j = context->count[0];
00198     if ((context->count[0] += len << 3) < j)
00199         context->count[1]++;
00200     context->count[1] += (len >> 29);
00201     j = (j >> 3) & 63;
00202     if ((j + len) > 63)
00203     {
00204         memcpy(&context->buffer[j], data, (i = 64 - j));
00205         SHA1Transform(context->state, context->buffer);
00206         for (; i + 63 < len; i += 64)
00207         {
00208             SHA1Transform(context->state, &data[i]);
00209         }
00210         j = 0;
00211     }
00212     else
00213         i = 0;
00214     memcpy(&context->buffer[j], &data[i], len - i);
00215 }
00216 
00217 
00218 /* Add padding and return the message digest. */
00219 
00220 void SHA1Final(
00221     unsigned char digest[20],
00222     SHA1_CTX * context
00223 )
00224 {
00225     unsigned i;
00226 
00227     unsigned char finalcount[8];
00228 
00229     unsigned char c;
00230 
00231 #if 0    /* untested "improvement" by DHR */
00232     /* Convert context->count to a sequence of bytes
00233      * in finalcount.  Second element first, but
00234      * big-endian order within element.
00235      * But we do it all backwards.
00236      */
00237     unsigned char *fcp = &finalcount[8];
00238 
00239     for (i = 0; i < 2; i++)
00240     {
00241         uint32_t t = context->count[i];
00242 
00243         int j;
00244 
00245         for (j = 0; j < 4; t >>= 8, j++)
00246             *--fcp = (unsigned char) t}
00247 #else
00248     for (i = 0; i < 8; i++)
00249     {
00250         finalcount[i] = (unsigned char) ((context->count[(i >= 4 ? 0 : 1)] >> ((3 - (i & 3)) * 8)) & 255);      /* Endian independent */
00251     }
00252 #endif
00253     c = 0200;
00254     SHA1Update(context, &c, 1);
00255     while ((context->count[0] & 504) != 448)
00256     {
00257         c = 0000;
00258         SHA1Update(context, &c, 1);
00259     }
00260     SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
00261     for (i = 0; i < 20; i++)
00262     {
00263         digest[i] = (unsigned char)
00264             ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & 255);
00265     }
00266     /* Wipe variables */
00267     memset(context, '\0', sizeof(*context));
00268     memset(&finalcount, '\0', sizeof(finalcount));
00269 }
00270 
00271 void sha1(
00272     char *hash_out,
00273     const char *str,
00274     int len)
00275 {
00276     SHA1_CTX ctx;
00277     unsigned int ii;
00278 
00279     SHA1Init(&ctx);
00280     for (ii=0; ii<len; ii+=1)
00281         SHA1Update(&ctx, (const unsigned char*)str + ii, 1);
00282     SHA1Final((unsigned char *)hash_out, &ctx);
00283     // hash_out[20] = '\0';
00284 }
00285