├── Sha ├── .gitignore ├── examples │ ├── hmacsha256test │ │ ├── runtests.sh │ │ ├── test.ex │ │ ├── hmacsha256test.pde │ │ └── Jamfile │ ├── sha1test │ │ └── sha1test.pde │ └── sha256test │ │ └── sha256test.pde ├── keywords.txt ├── sha1.h ├── sha256.h ├── readme.txt ├── sha1.cpp └── sha256.cpp └── README /Sha/.gitignore: -------------------------------------------------------------------------------- 1 | 16000000/ 2 | .*.swp 3 | .*.swo 4 | version.h 5 | -------------------------------------------------------------------------------- /Sha/examples/hmacsha256test/runtests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | jam u0 && expect test.ex 4 | -------------------------------------------------------------------------------- /Sha/examples/hmacsha256test/test.ex: -------------------------------------------------------------------------------- 1 | #/usr/bin/expect 2 | 3 | set timeout 100 4 | spawn picocom -b 9600 /dev/ttyUSB0 5 | expect "+OK" 6 | -------------------------------------------------------------------------------- /Sha/keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For Cryptolib 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | Sha1 KEYWORD1 9 | Sha256 KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | init KEYWORD2 16 | initHmac KEYWORD2 17 | add KEYWORD2 18 | result KEYWORD2 19 | resultHmac KEYWORD2 20 | 21 | ####################################### 22 | # Constants (LITERAL1) 23 | ####################################### 24 | 25 | -------------------------------------------------------------------------------- /Sha/sha1.h: -------------------------------------------------------------------------------- 1 | #ifndef Sha1_h 2 | #define Sha1_h 3 | 4 | #include 5 | #include "Print.h" 6 | 7 | #if ARDUINO < 100 8 | #define __WRITE_RESULT void 9 | #define __WRITE_RETURN(x) return; 10 | #else 11 | #define __WRITE_RESULT size_t 12 | #define __WRITE_RETURN(x) return x; 13 | #endif 14 | 15 | #define HASH_LENGTH 20 16 | #define BLOCK_LENGTH 64 17 | 18 | union _buffer { 19 | uint8_t b[BLOCK_LENGTH]; 20 | uint32_t w[BLOCK_LENGTH/4]; 21 | }; 22 | union _state { 23 | uint8_t b[HASH_LENGTH]; 24 | uint32_t w[HASH_LENGTH/4]; 25 | }; 26 | 27 | class Sha1Class : public Print 28 | { 29 | public: 30 | void init(void); 31 | void initHmac(const uint8_t* secret, int secretLength); 32 | uint8_t* result(void); 33 | uint8_t* resultHmac(void); 34 | virtual __WRITE_RESULT write(uint8_t); 35 | using Print::write; 36 | private: 37 | void pad(); 38 | void addUncounted(uint8_t data); 39 | void hashBlock(); 40 | uint32_t rol32(uint32_t number, uint8_t bits); 41 | _buffer buffer; 42 | uint8_t bufferOffset; 43 | _state state; 44 | uint32_t byteCount; 45 | uint8_t keyBuffer[BLOCK_LENGTH]; 46 | uint8_t innerHash[HASH_LENGTH]; 47 | 48 | }; 49 | extern Sha1Class Sha1; 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /Sha/sha256.h: -------------------------------------------------------------------------------- 1 | #ifndef Sha256_h 2 | #define Sha256_h 3 | 4 | #include 5 | #include "Print.h" 6 | 7 | #if ARDUINO < 100 8 | #define __WRITE_RESULT void 9 | #define __WRITE_RETURN(x) return; 10 | #else 11 | #define __WRITE_RESULT size_t 12 | #define __WRITE_RETURN(x) return x; 13 | #endif 14 | 15 | #define HASH_LENGTH 32 16 | #define BLOCK_LENGTH 64 17 | 18 | union _buffer { 19 | uint8_t b[BLOCK_LENGTH]; 20 | uint32_t w[BLOCK_LENGTH/4]; 21 | }; 22 | union _state { 23 | uint8_t b[HASH_LENGTH]; 24 | uint32_t w[HASH_LENGTH/4]; 25 | }; 26 | 27 | class Sha256Class : public Print 28 | { 29 | public: 30 | void init(void); 31 | void initHmac(const uint8_t* secret, int secretLength); 32 | uint8_t* result(void); 33 | uint8_t* resultHmac(void); 34 | virtual __WRITE_RESULT write(uint8_t); 35 | using Print::write; 36 | private: 37 | void pad(); 38 | void addUncounted(uint8_t data); 39 | void hashBlock(); 40 | uint32_t ror32(uint32_t number, uint8_t bits); 41 | _buffer buffer; 42 | uint8_t bufferOffset; 43 | _state state; 44 | uint32_t byteCount; 45 | uint8_t keyBuffer[BLOCK_LENGTH]; 46 | uint8_t innerHash[HASH_LENGTH]; 47 | }; 48 | extern Sha256Class Sha256; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /Sha/readme.txt: -------------------------------------------------------------------------------- 1 | SHA implements secure hash functions that can be used for cryptography, data integrity and security purposes. 2 | 3 | Sha covers the following standards: 4 | SHA-1 (FIPS 180-2) 5 | SHA-256 (FIPS 180-2) 6 | HMAC-SHA-1 (FIPS 198a) 7 | HMAC-SHA-256 (FIPS 198a) 8 | 9 | What is a hash function? 10 | A hash function takes a message, and generates a number. 11 | A good hash function has the following properties: 12 | The number is large enough that you will never find two messages with the same number (a 'collision') 13 | It is computationally unfeasible to extract message information from its hash (without trying every possible combination) 14 | A small (1 bit) change in the message will produce a huge (approximately half of all bits) change in the hash. 15 | Fast to calculate 16 | 17 | SHA is slower than simple hashes (eg. parity), but has very high security - high enough to be used in currency transactions and confidential documents. 18 | SHA-1 is currently secure, but there is some suggestion it may not be for much longer. 19 | SHA-256 is slightly slower, but has higher security. 20 | 21 | What is an HMAC? 22 | HMACs are Hashed Message Authentication Codes. Using them, it is possible to prove that you have a secret key without actually disclosing it. 23 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Cryptosuite is a cryptographic library for Arduino (including SHA and HMAC-SHA) 2 | 3 | It currently supports secure hashing and hashed message authentication using SHA-1, SHA-256, HMAC-SHA-1 and HMAC-SHA-256. 4 | 5 | Installation: 6 | Make a 'libraries' directory with your Arduino sketches folder if you do not already have one. 7 | Copy the 'Sha' directory into that directory. 8 | Restart Arduino to rescan for new libraries. 9 | 10 | Using SHA-1: 11 | #include "sha1.h" 12 | ... 13 | uint8_t *hash; 14 | Sha1.init(); 15 | Sha1.print("This is a message to hash"); 16 | hash = Sha1.result(); 17 | 18 | The hash result is then stored in hash[0], hash[1] .. hash[19]. 19 | 20 | Using HMAC-SHA-1: 21 | #include "sha1.h" 22 | ... 23 | uint8_t *hash; 24 | Sha1.initHmac("hash key",8); // key, and length of key in bytes 25 | Sha1.print("This is a message to hash"); 26 | hash = Sha1.resultHmac(); 27 | 28 | The hash result is then stored in hash[0], hash[1] .. hash[19]. 29 | 30 | Using SHA-256: 31 | #include "sha256.h" 32 | ... 33 | uint8_t *hash; 34 | Sha256.init(); 35 | Sha256.print("This is a message to hash"); 36 | hash = Sha256.result(); 37 | 38 | The hash result is then stored in hash[0], hash[1] .. hash[31]. 39 | 40 | Using HMAC-SHA-256: 41 | #include "sha256.h" 42 | ... 43 | uint8_t *hash; 44 | Sha256.initHmac("hash key",8); // key, and length of key in bytes 45 | Sha256.print("This is a message to hash"); 46 | hash = Sha256.resultHmac(); 47 | 48 | The hash result is then stored in hash[0], hash[1] .. hash[31]. 49 | 50 | 51 | Verification: 52 | The provided example code tests against published test vectors. 53 | SHA-1: FIPS 180-2, RFC3174 compliant 54 | HMAC-SHA-1: FIPS 198a compliant 55 | SHA-256: FIPS 180-2, RFC4231 compliant 56 | HMAC-SHA-256: RFC4231 compliant 57 | -------------------------------------------------------------------------------- /Sha/sha1.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "sha1.h" 5 | 6 | #define SHA1_K0 0x5a827999 7 | #define SHA1_K20 0x6ed9eba1 8 | #define SHA1_K40 0x8f1bbcdc 9 | #define SHA1_K60 0xca62c1d6 10 | 11 | const uint8_t sha1InitState[] PROGMEM = { 12 | 0x01,0x23,0x45,0x67, // H0 13 | 0x89,0xab,0xcd,0xef, // H1 14 | 0xfe,0xdc,0xba,0x98, // H2 15 | 0x76,0x54,0x32,0x10, // H3 16 | 0xf0,0xe1,0xd2,0xc3 // H4 17 | }; 18 | 19 | void Sha1Class::init(void) { 20 | memcpy_P(state.b,sha1InitState,HASH_LENGTH); 21 | byteCount = 0; 22 | bufferOffset = 0; 23 | } 24 | 25 | uint32_t Sha1Class::rol32(uint32_t number, uint8_t bits) { 26 | return ((number << bits) | (number >> (32-bits))); 27 | } 28 | 29 | void Sha1Class::hashBlock() { 30 | uint8_t i; 31 | uint32_t a,b,c,d,e,t; 32 | 33 | a=state.w[0]; 34 | b=state.w[1]; 35 | c=state.w[2]; 36 | d=state.w[3]; 37 | e=state.w[4]; 38 | for (i=0; i<80; i++) { 39 | if (i>=16) { 40 | t = buffer.w[(i+13)&15] ^ buffer.w[(i+8)&15] ^ buffer.w[(i+2)&15] ^ buffer.w[i&15]; 41 | buffer.w[i&15] = rol32(t,1); 42 | } 43 | if (i<20) { 44 | t = (d ^ (b & (c ^ d))) + SHA1_K0; 45 | } else if (i<40) { 46 | t = (b ^ c ^ d) + SHA1_K20; 47 | } else if (i<60) { 48 | t = ((b & c) | (d & (b | c))) + SHA1_K40; 49 | } else { 50 | t = (b ^ c ^ d) + SHA1_K60; 51 | } 52 | t+=rol32(a,5) + e + buffer.w[i&15]; 53 | e=d; 54 | d=c; 55 | c=rol32(b,30); 56 | b=a; 57 | a=t; 58 | } 59 | state.w[0] += a; 60 | state.w[1] += b; 61 | state.w[2] += c; 62 | state.w[3] += d; 63 | state.w[4] += e; 64 | } 65 | 66 | void Sha1Class::addUncounted(uint8_t data) { 67 | buffer.b[bufferOffset ^ 3] = data; 68 | bufferOffset++; 69 | if (bufferOffset == BLOCK_LENGTH) { 70 | hashBlock(); 71 | bufferOffset = 0; 72 | } 73 | } 74 | 75 | __WRITE_RESULT Sha1Class::write(uint8_t data) { 76 | ++byteCount; 77 | addUncounted(data); 78 | 79 | __WRITE_RETURN(1); 80 | } 81 | 82 | void Sha1Class::pad() { 83 | // Implement SHA-1 padding (fips180-2 §5.1.1) 84 | 85 | // Pad with 0x80 followed by 0x00 until the end of the block 86 | addUncounted(0x80); 87 | while (bufferOffset != 56) addUncounted(0x00); 88 | 89 | // Append length in the last 8 bytes 90 | addUncounted(0); // We're only using 32 bit lengths 91 | addUncounted(0); // But SHA-1 supports 64 bit lengths 92 | addUncounted(0); // So zero pad the top bits 93 | addUncounted(byteCount >> 29); // Shifting to multiply by 8 94 | addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as 95 | addUncounted(byteCount >> 13); // byte. 96 | addUncounted(byteCount >> 5); 97 | addUncounted(byteCount << 3); 98 | } 99 | 100 | 101 | uint8_t* Sha1Class::result(void) { 102 | // Pad to complete the last block 103 | pad(); 104 | 105 | // Swap byte order back 106 | for (int i=0; i<5; i++) { 107 | uint32_t a,b; 108 | a=state.w[i]; 109 | b=a<<24; 110 | b|=(a<<8) & 0x00ff0000; 111 | b|=(a>>8) & 0x0000ff00; 112 | b|=a>>24; 113 | state.w[i]=b; 114 | } 115 | 116 | // Return pointer to hash (20 characters) 117 | return state.b; 118 | } 119 | 120 | #define HMAC_IPAD 0x36 121 | #define HMAC_OPAD 0x5c 122 | 123 | void Sha1Class::initHmac(const uint8_t* key, int keyLength) { 124 | uint8_t i; 125 | memset(keyBuffer,0,BLOCK_LENGTH); 126 | if (keyLength > BLOCK_LENGTH) { 127 | // Hash long keys 128 | init(); 129 | for (;keyLength--;) write(*key++); 130 | memcpy(keyBuffer,result(),HASH_LENGTH); 131 | } else { 132 | // Block length keys are used as is 133 | memcpy(keyBuffer,key,keyLength); 134 | } 135 | // Start inner hash 136 | init(); 137 | for (i=0; i>4]); 30 | Serial.print("0123456789abcdef"[hash[i]&0xf]); 31 | } 32 | Serial.println(); 33 | } 34 | 35 | void setup() { 36 | uint8_t* hash; 37 | uint32_t a; 38 | 39 | Serial.begin(9600); 40 | 41 | // HMAC tests 42 | Serial.println("Test: RFC4231 4.2"); 43 | Serial.println("Expect:b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); 44 | Serial.print("Result:"); 45 | Sha256.initHmac(hmacKey1,20); 46 | Sha256.print("Hi There"); 47 | printHash(Sha256.resultHmac()); 48 | Serial.println(); 49 | 50 | Serial.println("Test: RFC4231 4.3"); 51 | Serial.println("Expect:5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); 52 | Serial.print("Result:"); 53 | Sha256.initHmac((uint8_t*)"Jefe",4); 54 | Sha256.print("what do ya want for nothing?"); 55 | printHash(Sha256.resultHmac()); 56 | Serial.println(); 57 | 58 | Serial.println("Test: RFC4231 4.4"); 59 | Serial.println("Expect:773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"); 60 | Serial.print("Result:"); 61 | Sha256.initHmac(hmacKey3,20); 62 | for (a=0; a<50; a++) Sha256.write(0xdd); 63 | printHash(Sha256.resultHmac()); 64 | Serial.println(); 65 | 66 | Serial.println("Test: RFC4231 4.5"); 67 | Serial.println("Expect:82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"); 68 | Serial.print("Result:"); 69 | Sha256.initHmac(hmacKey2,25); 70 | for (a=0; a<50; a++) Sha256.write(0xcd); 71 | printHash(Sha256.resultHmac()); 72 | Serial.println(); 73 | 74 | Serial.println("Test: RFC4231 4.6"); 75 | Serial.println("Expect:a3b6167473100ee06e0c796c2955552b-------------------------------"); 76 | Serial.print("Result:"); 77 | Sha256.initHmac(hmacKey4,20); 78 | Sha256.print("Test With Truncation"); 79 | printHash(Sha256.resultHmac()); 80 | Serial.println(); 81 | 82 | Serial.println("Test: RFC4231 4.7"); 83 | Serial.println("Expect:60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"); 84 | Serial.print("Result:"); 85 | Sha256.initHmac(hmacKey5,131); 86 | Sha256.print("Test Using Larger Than Block-Size Key - Hash Key First"); 87 | printHash(Sha256.resultHmac()); 88 | Serial.println(); 89 | 90 | Serial.println("Test: RFC4231 4.8"); 91 | Serial.println("Expect:9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); 92 | Serial.print("Result:"); 93 | Sha256.initHmac(hmacKey5,131); 94 | Sha256.print("This is a test using a larger than block-size key and a larger than " 95 | "block-size data. The key needs to be hashed before being used by the HMAC algorithm."); 96 | printHash(Sha256.resultHmac()); 97 | Serial.println(); 98 | Serial.println("+OK"); 99 | 100 | } 101 | 102 | void loop() { 103 | } 104 | -------------------------------------------------------------------------------- /Sha/examples/sha1test/sha1test.pde: -------------------------------------------------------------------------------- 1 | #include "sha1.h" 2 | 3 | void printHash(uint8_t* hash) { 4 | int i; 5 | for (i=0; i<20; i++) { 6 | Serial.print("0123456789abcdef"[hash[i]>>4]); 7 | Serial.print("0123456789abcdef"[hash[i]&0xf]); 8 | } 9 | Serial.println(); 10 | } 11 | 12 | uint8_t hmacKey1[]={ 13 | 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 14 | 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 15 | 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 16 | 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f 17 | }; 18 | uint8_t hmacKey2[]={ 19 | 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 20 | 0x40,0x41,0x42,0x43 21 | }; 22 | uint8_t hmacKey3[]={ 23 | 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 24 | 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 25 | 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 26 | 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 27 | 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 28 | 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 29 | 0xb0,0xb1,0xb2,0xb3 30 | }; 31 | uint8_t hmacKey4[]={ 32 | 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 33 | 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 34 | 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 35 | 0xa0 36 | }; 37 | 38 | 39 | void setup() { 40 | uint8_t* hash; 41 | uint32_t a; 42 | 43 | Serial.begin(9600); 44 | 45 | // SHA tests 46 | Serial.println("Test: FIPS 180-2 C.1 and RFC3174 7.3 TEST1"); 47 | Serial.println("Expect:a9993e364706816aba3e25717850c26c9cd0d89d"); 48 | Serial.print("Result:"); 49 | Sha1.init(); 50 | Sha1.print("abc"); 51 | printHash(Sha1.result()); 52 | Serial.println(); 53 | 54 | Serial.println("Test: FIPS 180-2 C.2 and RFC3174 7.3 TEST2"); 55 | Serial.println("Expect:84983e441c3bd26ebaae4aa1f95129e5e54670f1"); 56 | Serial.print("Result:"); 57 | Sha1.init(); 58 | Sha1.print("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); 59 | printHash(Sha1.result()); 60 | Serial.println(); 61 | 62 | Serial.println("Test: RFC3174 7.3 TEST4"); 63 | Serial.println("Expect:dea356a2cddd90c7a7ecedc5ebb563934f460452"); 64 | Serial.print("Result:"); 65 | Sha1.init(); 66 | for (a=0; a<80; a++) Sha1.print("01234567"); 67 | printHash(Sha1.result()); 68 | Serial.println(); 69 | 70 | // HMAC tests 71 | Serial.println("Test: FIPS 198a A.1"); 72 | Serial.println("Expect:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a"); 73 | Serial.print("Result:"); 74 | Sha1.initHmac(hmacKey1,64); 75 | Sha1.print("Sample #1"); 76 | printHash(Sha1.resultHmac()); 77 | Serial.println(); 78 | 79 | Serial.println("Test: FIPS 198a A.2"); 80 | Serial.println("Expect:0922d3405faa3d194f82a45830737d5cc6c75d24"); 81 | Serial.print("Result:"); 82 | Sha1.initHmac(hmacKey2,20); 83 | Sha1.print("Sample #2"); 84 | printHash(Sha1.resultHmac()); 85 | Serial.println(); 86 | 87 | Serial.println("Test: FIPS 198a A.3"); 88 | Serial.println("Expect:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa"); 89 | Serial.print("Result:"); 90 | Sha1.initHmac(hmacKey3,100); 91 | Sha1.print("Sample #3"); 92 | printHash(Sha1.resultHmac()); 93 | Serial.println(); 94 | 95 | Serial.println("Test: FIPS 198a A.4"); 96 | Serial.println("Expect:9ea886efe268dbecce420c7524df32e0751a2a26"); 97 | Serial.print("Result:"); 98 | Sha1.initHmac(hmacKey4,49); 99 | Sha1.print("Sample #4"); 100 | printHash(Sha1.resultHmac()); 101 | Serial.println(); 102 | 103 | // Long tests 104 | Serial.println("Test: FIPS 180-2 C.3 and RFC3174 7.3 TEST3 (Processing 1000000 characters. This will take a while.)"); 105 | Serial.println("Expect:34aa973cd4c4daa4f61eeb2bdbad27316534016f"); 106 | Serial.print("Result:"); 107 | Sha1.init(); 108 | for (a=0; a<1000000; a++) Sha1.write('a'); 109 | printHash(Sha1.result()); 110 | } 111 | 112 | void loop() { 113 | } -------------------------------------------------------------------------------- /Sha/examples/sha256test/sha256test.pde: -------------------------------------------------------------------------------- 1 | #include "sha256.h" 2 | 3 | uint8_t hmacKey1[]={ 4 | 0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b 5 | }; 6 | uint8_t hmacKey2[]={ 7 | 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14, 8 | 0x15,0x16,0x17,0x18,0x19 9 | }; 10 | uint8_t hmacKey3[]={ 11 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa 12 | }; 13 | uint8_t hmacKey4[]={ 14 | 0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c,0x0c 15 | }; 16 | uint8_t hmacKey5[]={ 17 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 18 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 19 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 20 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 21 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 22 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa, 23 | 0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa 24 | }; 25 | 26 | void printHash(uint8_t* hash) { 27 | int i; 28 | for (i=0; i<32; i++) { 29 | Serial.print("0123456789abcdef"[hash[i]>>4]); 30 | Serial.print("0123456789abcdef"[hash[i]&0xf]); 31 | } 32 | Serial.println(); 33 | } 34 | 35 | void setup() { 36 | uint8_t* hash; 37 | uint32_t a; 38 | 39 | Serial.begin(9600); 40 | 41 | // SHA tests 42 | Serial.println("Test: FIPS 180-2 B.1"); 43 | Serial.println("Expect:ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); 44 | Serial.print("Result:"); 45 | Sha256.init(); 46 | Sha256.print("abc"); 47 | printHash(Sha256.result()); 48 | Serial.println(); 49 | 50 | Serial.println("Test: FIPS 180-2 B.2"); 51 | Serial.println("Expect:248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); 52 | Serial.print("Result:"); 53 | Sha256.init(); 54 | Sha256.print("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"); 55 | printHash(Sha256.result()); 56 | Serial.println(); 57 | 58 | // HMAC tests 59 | Serial.println("Test: RFC4231 4.2"); 60 | Serial.println("Expect:b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"); 61 | Serial.print("Result:"); 62 | Sha256.initHmac(hmacKey1,20); 63 | Sha256.print("Hi There"); 64 | printHash(Sha256.resultHmac()); 65 | Serial.println(); 66 | 67 | Serial.println("Test: RFC4231 4.3"); 68 | Serial.println("Expect:5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843"); 69 | Serial.print("Result:"); 70 | Sha256.initHmac((uint8_t*)"Jefe",4); 71 | Sha256.print("what do ya want for nothing?"); 72 | printHash(Sha256.resultHmac()); 73 | Serial.println(); 74 | 75 | Serial.println("Test: RFC4231 4.4"); 76 | Serial.println("Expect:773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe"); 77 | Serial.print("Result:"); 78 | Sha256.initHmac(hmacKey3,20); 79 | for (a=0; a<50; a++) Sha256.write(0xdd); 80 | printHash(Sha256.resultHmac()); 81 | Serial.println(); 82 | 83 | Serial.println("Test: RFC4231 4.5"); 84 | Serial.println("Expect:82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b"); 85 | Serial.print("Result:"); 86 | Sha256.initHmac(hmacKey2,25); 87 | for (a=0; a<50; a++) Sha256.write(0xcd); 88 | printHash(Sha256.resultHmac()); 89 | Serial.println(); 90 | 91 | Serial.println("Test: RFC4231 4.6"); 92 | Serial.println("Expect:a3b6167473100ee06e0c796c2955552b-------------------------------"); 93 | Serial.print("Result:"); 94 | Sha256.initHmac(hmacKey4,20); 95 | Sha256.print("Test With Truncation"); 96 | printHash(Sha256.resultHmac()); 97 | Serial.println(); 98 | 99 | Serial.println("Test: RFC4231 4.7"); 100 | Serial.println("Expect:60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54"); 101 | Serial.print("Result:"); 102 | Sha256.initHmac(hmacKey5,131); 103 | Sha256.print("Test Using Larger Than Block-Size Key - Hash Key First"); 104 | printHash(Sha256.resultHmac()); 105 | Serial.println(); 106 | 107 | Serial.println("Test: RFC4231 4.8"); 108 | Serial.println("Expect:9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2"); 109 | Serial.print("Result:"); 110 | Sha256.initHmac(hmacKey5,131); 111 | // Sha256.print("This is a test using a larger than block-size key and a larger than " 112 | // "block-size data. The key needs to be hashed before being used by the HMAC algorithm."); 113 | printHash(Sha256.resultHmac()); 114 | Serial.println(); 115 | 116 | // Long tests 117 | Serial.println("Test: FIPS 180-2 B.3 (Processing 1000000 characters. This will take a while.)"); 118 | Serial.println("Expect:cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); 119 | Serial.print("Result:"); 120 | Sha256.init(); 121 | for (a=0; a<1000000; a++) Sha256.write('a'); 122 | printHash(Sha256.result()); 123 | } 124 | 125 | void loop() { 126 | } -------------------------------------------------------------------------------- /Sha/sha256.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "sha256.h" 5 | 6 | const uint32_t sha256K[] PROGMEM = { 7 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 8 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 9 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 10 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 11 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 12 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 13 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 14 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 15 | }; 16 | 17 | #define BUFFER_SIZE 64 18 | 19 | const uint8_t sha256InitState[] PROGMEM = { 20 | 0x67,0xe6,0x09,0x6a, // H0 21 | 0x85,0xae,0x67,0xbb, // H1 22 | 0x72,0xf3,0x6e,0x3c, // H2 23 | 0x3a,0xf5,0x4f,0xa5, // H3 24 | 0x7f,0x52,0x0e,0x51, // H4 25 | 0x8c,0x68,0x05,0x9b, // H5 26 | 0xab,0xd9,0x83,0x1f, // H6 27 | 0x19,0xcd,0xe0,0x5b // H7 28 | }; 29 | 30 | void Sha256Class::init(void) { 31 | memcpy_P(state.b,sha256InitState,32); 32 | byteCount = 0; 33 | bufferOffset = 0; 34 | } 35 | 36 | uint32_t Sha256Class::ror32(uint32_t number, uint8_t bits) { 37 | return ((number << (32-bits)) | (number >> bits)); 38 | } 39 | 40 | void Sha256Class::hashBlock() { 41 | uint8_t i; 42 | uint32_t a,b,c,d,e,f,g,h,t1,t2; 43 | 44 | a=state.w[0]; 45 | b=state.w[1]; 46 | c=state.w[2]; 47 | d=state.w[3]; 48 | e=state.w[4]; 49 | f=state.w[5]; 50 | g=state.w[6]; 51 | h=state.w[7]; 52 | 53 | for (i=0; i<64; i++) { 54 | if (i>=16) { 55 | t1 = buffer.w[i&15] + buffer.w[(i-7)&15]; 56 | t2 = buffer.w[(i-2)&15]; 57 | t1 += ror32(t2,17) ^ ror32(t2,19) ^ (t2>>10); 58 | t2 = buffer.w[(i-15)&15]; 59 | t1 += ror32(t2,7) ^ ror32(t2,18) ^ (t2>>3); 60 | buffer.w[i&15] = t1; 61 | } 62 | t1 = h; 63 | t1 += ror32(e,6) ^ ror32(e,11) ^ ror32(e,25); // ∑1(e) 64 | t1 += g ^ (e & (g ^ f)); // Ch(e,f,g) 65 | t1 += pgm_read_dword(sha256K+i); // Ki 66 | t1 += buffer.w[i&15]; // Wi 67 | t2 = ror32(a,2) ^ ror32(a,13) ^ ror32(a,22); // ∑0(a) 68 | t2 += ((b & c) | (a & (b | c))); // Maj(a,b,c) 69 | h=g; g=f; f=e; e=d+t1; d=c; c=b; b=a; a=t1+t2; 70 | } 71 | state.w[0] += a; 72 | state.w[1] += b; 73 | state.w[2] += c; 74 | state.w[3] += d; 75 | state.w[4] += e; 76 | state.w[5] += f; 77 | state.w[6] += g; 78 | state.w[7] += h; 79 | } 80 | 81 | void Sha256Class::addUncounted(uint8_t data) { 82 | buffer.b[bufferOffset ^ 3] = data; 83 | bufferOffset++; 84 | if (bufferOffset == BUFFER_SIZE) { 85 | hashBlock(); 86 | bufferOffset = 0; 87 | } 88 | } 89 | 90 | __WRITE_RESULT Sha256Class::write(uint8_t data) { 91 | ++byteCount; 92 | addUncounted(data); 93 | 94 | __WRITE_RETURN(1); 95 | } 96 | 97 | void Sha256Class::pad() { 98 | // Implement SHA-256 padding (fips180-2 §5.1.1) 99 | 100 | // Pad with 0x80 followed by 0x00 until the end of the block 101 | addUncounted(0x80); 102 | while (bufferOffset != 56) addUncounted(0x00); 103 | 104 | // Append length in the last 8 bytes 105 | addUncounted(0); // We're only using 32 bit lengths 106 | addUncounted(0); // But SHA-1 supports 64 bit lengths 107 | addUncounted(0); // So zero pad the top bits 108 | addUncounted(byteCount >> 29); // Shifting to multiply by 8 109 | addUncounted(byteCount >> 21); // as SHA-1 supports bitstreams as well as 110 | addUncounted(byteCount >> 13); // byte. 111 | addUncounted(byteCount >> 5); 112 | addUncounted(byteCount << 3); 113 | } 114 | 115 | 116 | uint8_t* Sha256Class::result(void) { 117 | // Pad to complete the last block 118 | pad(); 119 | 120 | // Swap byte order back 121 | for (int i=0; i<8; i++) { 122 | uint32_t a,b; 123 | a=state.w[i]; 124 | b=a<<24; 125 | b|=(a<<8) & 0x00ff0000; 126 | b|=(a>>8) & 0x0000ff00; 127 | b|=a>>24; 128 | state.w[i]=b; 129 | } 130 | 131 | // Return pointer to hash (20 characters) 132 | return state.b; 133 | } 134 | 135 | #define HMAC_IPAD 0x36 136 | #define HMAC_OPAD 0x5c 137 | 138 | uint8_t keyBuffer[BLOCK_LENGTH]; // K0 in FIPS-198a 139 | uint8_t innerHash[HASH_LENGTH]; 140 | 141 | void Sha256Class::initHmac(const uint8_t* key, int keyLength) { 142 | uint8_t i; 143 | memset(keyBuffer,0,BLOCK_LENGTH); 144 | if (keyLength > BLOCK_LENGTH) { 145 | // Hash long keys 146 | init(); 147 | for (;keyLength--;) write(*key++); 148 | memcpy(keyBuffer,result(),HASH_LENGTH); 149 | } else { 150 | // Block length keys are used as is 151 | memcpy(keyBuffer,key,keyLength); 152 | } 153 | // Start inner hash 154 | init(); 155 | for (i=0; i $(<) 97 | git log -1 --pretty=format:%h >> $(<) 98 | echo "\";" >> $(<) 99 | } 100 | 101 | GitVersion version.h ; 102 | 103 | rule Pde 104 | { 105 | Depends $(<) : $(>) ; 106 | MakeLocate $(<) : $(LOCATE_SOURCE) ; 107 | Clean clean : $(<) ; 108 | } 109 | 110 | if ( $(ARDUINO_VERSION) < 100 ) 111 | { 112 | ARDUINO_H = WProgram.h ; 113 | } 114 | else 115 | { 116 | ARDUINO_H = Arduino.h ; 117 | } 118 | 119 | actions Pde 120 | { 121 | echo "#include <$(ARDUINO_H)>" > $(<) 122 | echo "#line 1 \"$(>)\"" >> $(<) 123 | cat $(>) >> $(<) 124 | } 125 | 126 | rule C++Pde 127 | { 128 | local _CPP = $(>:B).cpp ; 129 | Pde $(_CPP) : $(>) ; 130 | C++ $(<) : $(_CPP) ; 131 | } 132 | 133 | rule UserObject 134 | { 135 | switch $(>:S) 136 | { 137 | case .ino : C++Pde $(<) : $(>) ; 138 | case .pde : C++Pde $(<) : $(>) ; 139 | } 140 | } 141 | 142 | rule Objects 143 | { 144 | local _i ; 145 | 146 | for _i in [ FGristFiles $(<) ] 147 | { 148 | local _b = $(_i:B)$(SUFOBJ) ; 149 | local _o = $(_b:G=$(SOURCE_GRIST:E)) ; 150 | Object $(_o) : $(_i) ; 151 | Depends obj : $(_o) ; 152 | } 153 | } 154 | 155 | rule Library 156 | { 157 | LibraryFromObjects $(<) : $(>:B)$(SUFOBJ) ; 158 | Objects $(>) ; 159 | } 160 | 161 | rule Main 162 | { 163 | MainFromObjects $(<) : $(>:B)$(SUFOBJ) ; 164 | Objects $(>) ; 165 | } 166 | 167 | rule Hex 168 | { 169 | Depends $(<) : $(>) ; 170 | MakeLocate $(<) : $(LOCATE_TARGET) ; 171 | Depends hex : $(<) ; 172 | Clean clean : $(<) ; 173 | } 174 | 175 | actions Hex 176 | { 177 | $(OBJCOPY) -O ihex -R .eeprom $(>) $(<) 178 | } 179 | 180 | rule Upload 181 | { 182 | Depends $(1) : $(2) ; 183 | Depends $(2) : $(3) ; 184 | NotFile $(1) ; 185 | Always $(1) ; 186 | Always $(2) ; 187 | UploadAction $(2) : $(3) ; 188 | } 189 | 190 | actions UploadAction 191 | { 192 | $(AVRDUDE) $(AVRDUDEFLAGS) -P $(<) $(AVRDUDE_WRITE_FLASH) -U flash:w:$(>):i 193 | } 194 | 195 | rule Arduino 196 | { 197 | LINKFLAGS on $(<) = $(LINKFLAGS) -Wl,-Map=$(LOCATE_TARGET)/$(<:B).map ; 198 | Main $(<) : $(>) ; 199 | LinkLibraries $(<) : libs core ; 200 | Hex $(<:B).hex : $(<) ; 201 | for _p in $(PORTS) 202 | { 203 | Upload $(_p) : $(PORT_$(_p)) : $(<:B).hex ; 204 | } 205 | } 206 | 207 | # 208 | # Targets 209 | # 210 | 211 | # Grab everything from the core directory 212 | Library core : [ GLOB $(ARDUINO_CORE) : *.c *.cpp ] ; 213 | 214 | # Grab everything from libraries. To avoid this "grab everything" behaviour, you 215 | # can specify specific modules to pick up in PROJECT_MODULES 216 | Library libs : [ GLOB $(ARDUINO_LIB)/$(PROJECT_LIBS) $(ARDUINO_LIB)/$(PROJECT_LIBS)/utility $(SKETCH_LIB)/$(PROJECT_LIBS) : *.cpp *.c ] ; 217 | 218 | # Main output executable 219 | Arduino $(PWD:B).elf : $(PROJECT_MODULES) [ GLOB $(PROJECT_DIRS) : *.c *.cpp *.pde *.ino ] ; 220 | --------------------------------------------------------------------------------