]> git.piffa.net Git - arduino/blob - books/pdummies/Libraries/Sha/sha1.cpp
gio
[arduino] / books / pdummies / Libraries / Sha / sha1.cpp
1 #include <string.h>
2 #include <avr/io.h>
3 #include <avr/pgmspace.h>
4 #include "sha1.h"
5
6 #include "debugstuff.c"
7
8 #define SHA1_K0 0x5a827999
9 #define SHA1_K20 0x6ed9eba1
10 #define SHA1_K40 0x8f1bbcdc
11 #define SHA1_K60 0xca62c1d6
12
13 uint8_t sha1InitState[] PROGMEM = {
14   0x01,0x23,0x45,0x67, // H0
15   0x89,0xab,0xcd,0xef, // H1
16   0xfe,0xdc,0xba,0x98, // H2
17   0x76,0x54,0x32,0x10, // H3
18   0xf0,0xe1,0xd2,0xc3  // H4
19 };
20
21 void Sha1Class::init(void) {
22   memcpy_P(state.b,sha1InitState,HASH_LENGTH);
23   byteCount = 0;
24   bufferOffset = 0;
25 }
26
27 uint32_t Sha1Class::rol32(uint32_t number, uint8_t bits) {
28   return ((number << bits) | (number >> (32-bits)));
29 }
30
31 void Sha1Class::hashBlock() {
32   // SHA1 only for now
33   uint8_t i;
34   uint32_t a,b,c,d,e,t;
35
36   a=state.w[0];
37   b=state.w[1];
38   c=state.w[2];
39   d=state.w[3];
40   e=state.w[4];
41   for (i=0; i<80; i++) {
42     if (i>=16) {
43       t = buffer.w[(i+13)&15] ^ buffer.w[(i+8)&15] ^ buffer.w[(i+2)&15] ^ buffer.w[i&15];
44       buffer.w[i&15] = rol32(t,1);
45     }
46     if (i<20) {
47       t = (d ^ (b & (c ^ d))) + SHA1_K0;
48     } else if (i<40) {
49       t = (b ^ c ^ d) + SHA1_K20;
50     } else if (i<60) {
51       t = ((b & c) | (d & (b | c))) + SHA1_K40;
52     } else {
53       t = (b ^ c ^ d) + SHA1_K60;
54     }
55     t+=rol32(a,5) + e + buffer.w[i&15];
56     e=d;
57     d=c;
58     c=rol32(b,30);
59     b=a;
60     a=t;
61   }
62   state.w[0] += a;
63   state.w[1] += b;
64   state.w[2] += c;
65   state.w[3] += d;
66   state.w[4] += e;
67 }
68
69 void Sha1Class::addUncounted(uint8_t data) {
70   buffer.b[bufferOffset ^ 3] = data;
71   bufferOffset++;
72   if (bufferOffset == BLOCK_LENGTH) {
73     hashBlock();
74     bufferOffset = 0;
75   }
76 }
77
78 size_t Sha1Class::write(uint8_t data) {
79   ++byteCount;
80   addUncounted(data);
81   return 1;
82 }
83
84 void Sha1Class::pad() {
85   // Implement SHA-1 padding (fips180-2 ยง5.1.1)
86
87   // Pad with 0x80 followed by 0x00 until the end of the block
88   addUncounted(0x80);
89   while (bufferOffset != 56) addUncounted(0x00);
90
91   // Append length in the last 8 bytes
92   addUncounted(0); // We're only using 32 bit lengths
93   addUncounted(0); // But SHA-1 supports 64 bit lengths
94   addUncounted(0); // So zero pad the top bits
95   addUncounted(byteCount >> 29); // Shifting to multiply by 8
96   addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as
97   addUncounted(byteCount >> 13); // byte.
98   addUncounted(byteCount >> 5);
99   addUncounted(byteCount << 3);
100 }
101
102
103 uint8_t* Sha1Class::result(void) {
104   // Pad to complete the last block
105   pad();
106
107   // Swap byte order back
108   for (int i=0; i<5; i++) {
109     uint32_t a,b;
110     a=state.w[i];
111     b=a<<24;
112     b|=(a<<8) & 0x00ff0000;
113     b|=(a>>8) & 0x0000ff00;
114     b|=a>>24;
115     state.w[i]=b;
116   }
117
118   // Return pointer to hash (20 characters)
119   return state.b;
120 }
121
122
123 #define HMAC_IPAD 0x36
124 #define HMAC_OPAD 0x5c
125
126
127
128 void Sha1Class::initHmac(const uint8_t* key, int keyLength) {
129   uint8_t i;
130   memset(keyBuffer,0,BLOCK_LENGTH);
131   if (keyLength > BLOCK_LENGTH) {
132     // Hash long keys
133     init();
134     for (;keyLength--;) write(*key++);
135     memcpy(keyBuffer,result(),HASH_LENGTH);
136   } else {
137     // Block length keys are used as is
138     memcpy(keyBuffer,key,keyLength);
139   }
140   //for (i=0; i<BLOCK_LENGTH; i++) debugHH(keyBuffer[i]);
141   // Start inner hash
142   init();
143   for (i=0; i<BLOCK_LENGTH; i++) {
144     write(keyBuffer[i] ^ HMAC_IPAD);
145   }
146 }
147
148 uint8_t* Sha1Class::resultHmac(void) {
149   uint8_t i;
150     // Complete inner hash
151   memcpy(innerHash,result(),HASH_LENGTH);
152   // now innerHash[] contains H((K0 xor ipad)||text)
153
154   // Calculate outer hash
155   init();
156   for (i=0; i<BLOCK_LENGTH; i++) write(keyBuffer[i] ^ HMAC_OPAD);
157   for (i=0; i<HASH_LENGTH; i++) write(innerHash[i]);
158   return result();
159 }
160 Sha1Class Sha1;