3 #include <avr/pgmspace.h>
6 #include "debugstuff.c"
8 #define SHA1_K0 0x5a827999
9 #define SHA1_K20 0x6ed9eba1
10 #define SHA1_K40 0x8f1bbcdc
11 #define SHA1_K60 0xca62c1d6
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
21 void Sha1Class::init(void) {
22 memcpy_P(state.b,sha1InitState,HASH_LENGTH);
27 uint32_t Sha1Class::rol32(uint32_t number, uint8_t bits) {
28 return ((number << bits) | (number >> (32-bits)));
31 void Sha1Class::hashBlock() {
41 for (i=0; i<80; i++) {
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);
47 t = (d ^ (b & (c ^ d))) + SHA1_K0;
49 t = (b ^ c ^ d) + SHA1_K20;
51 t = ((b & c) | (d & (b | c))) + SHA1_K40;
53 t = (b ^ c ^ d) + SHA1_K60;
55 t+=rol32(a,5) + e + buffer.w[i&15];
69 void Sha1Class::addUncounted(uint8_t data) {
70 buffer.b[bufferOffset ^ 3] = data;
72 if (bufferOffset == BLOCK_LENGTH) {
78 size_t Sha1Class::write(uint8_t data) {
84 void Sha1Class::pad() {
85 // Implement SHA-1 padding (fips180-2 ยง5.1.1)
87 // Pad with 0x80 followed by 0x00 until the end of the block
89 while (bufferOffset != 56) addUncounted(0x00);
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);
103 uint8_t* Sha1Class::result(void) {
104 // Pad to complete the last block
107 // Swap byte order back
108 for (int i=0; i<5; i++) {
112 b|=(a<<8) & 0x00ff0000;
113 b|=(a>>8) & 0x0000ff00;
118 // Return pointer to hash (20 characters)
123 #define HMAC_IPAD 0x36
124 #define HMAC_OPAD 0x5c
128 void Sha1Class::initHmac(const uint8_t* key, int keyLength) {
130 memset(keyBuffer,0,BLOCK_LENGTH);
131 if (keyLength > BLOCK_LENGTH) {
134 for (;keyLength--;) write(*key++);
135 memcpy(keyBuffer,result(),HASH_LENGTH);
137 // Block length keys are used as is
138 memcpy(keyBuffer,key,keyLength);
140 //for (i=0; i<BLOCK_LENGTH; i++) debugHH(keyBuffer[i]);
143 for (i=0; i<BLOCK_LENGTH; i++) {
144 write(keyBuffer[i] ^ HMAC_IPAD);
148 uint8_t* Sha1Class::resultHmac(void) {
150 // Complete inner hash
151 memcpy(innerHash,result(),HASH_LENGTH);
152 // now innerHash[] contains H((K0 xor ipad)||text)
154 // Calculate outer hash
156 for (i=0; i<BLOCK_LENGTH; i++) write(keyBuffer[i] ^ HMAC_OPAD);
157 for (i=0; i<HASH_LENGTH; i++) write(innerHash[i]);