├── library.properties ├── LICENSE.md ├── README.md ├── test_atsha204a_mac.js ├── src ├── sha256.h ├── sha204_includes │ └── sha204_lib_return_codes.h ├── sha256.c ├── sha204_i2c.h └── sha204_i2c.cpp └── examples └── atsha204_simple_example └── atsha204_simple_example.ino /library.properties: -------------------------------------------------------------------------------- 1 | name=atsha204_i2c 2 | version=1.0.1 3 | author=mengguang@gmail.com 4 | maintainer=Meng Guang 5 | sentence=Library for the ATSHA204 IC. 6 | paragraph= This code verifies basic functionality of the ATSHA204 IC, and allows the user to obtain the unique serial number. 7 | category=Other 8 | url= 9 | architectures=* -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | License Information 3 | ------------------- 4 | 5 | The hardware is released under [Creative Commons Share-alike 3.0](http://creativecommons.org/licenses/by-sa/3.0/). 6 | 7 | All other code is open source so please feel free to do anything you want with it; you buy me a beer if you use this and we meet someday ([Beerware license](http://en.wikipedia.org/wiki/Beerware)). 8 | 9 | ->Additional Licenses and attributions to original authors as needed.<- 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # atsha204_i2c 2 | Arduino Library for Atmel CryptoAuthentication ATSHA204A chip 3 | 4 | This project is based on https://github.com/sparkfun/SparkFun_ATSHA204_Arduino_Library . 5 | The SparkFun version is SWI (Single Wire Interface ). 6 | This version is I2C interface. 7 | Mainly tested on Arduino core for ESP8266 2.3.0 environment. 8 | 9 | I have added some simple function to get chip id and calculate mac. 10 | 11 | You can init the chip using hashlet on raspberry pi : https://github.com/cryptotronix/hashlet 12 | 13 | There is a test_atsha204a_mac.js to verify the mac result. 14 | 15 | Attention Please: we need to set BUFFER_LENGTH to at least 64 in Wire.h 16 | -------------------------------------------------------------------------------- /test_atsha204a_mac.js: -------------------------------------------------------------------------------- 1 | var _ = require("lodash"); 2 | var util = require("util"); 3 | var crypto = require("crypto"); 4 | 5 | var hex_key = "your atsha204a key here in hex format"; 6 | var buffer_key = Buffer.from(hex_key,"hex"); 7 | 8 | var challenge = Buffer.alloc(32); 9 | challenge.write("Are you OK?"); 10 | 11 | var opcode = Buffer.alloc(1); 12 | opcode[0] = 0x08; 13 | 14 | var mode = Buffer.alloc(1); 15 | mode[0] = 0x00; 16 | 17 | var param2 = Buffer.alloc(2); 18 | 19 | var otp_0_7 = Buffer.alloc(8); 20 | 21 | var otp_8_10 = Buffer.alloc(3); 22 | 23 | var sn_8 = Buffer.alloc(1); 24 | sn_8[0] = 0xEE; 25 | 26 | var sn_4_7 = Buffer.alloc(4); 27 | 28 | var sn_0_1 = Buffer.alloc(2); 29 | sn_0_1[0] = 0x01; 30 | sn_0_1[1] = 0x23; 31 | 32 | var sn_2_3 = Buffer.alloc(2); 33 | 34 | var data = Buffer.concat([buffer_key , challenge , opcode , mode , param2 , otp_0_7 , otp_8_10 , sn_8 , sn_4_7 , sn_0_1 , sn_2_3]); 35 | 36 | console.log(data); 37 | console.log(data.length); 38 | 39 | var mac = crypto.createHash('sha256').update(data).digest(); 40 | console.log(mac); 41 | 42 | 43 | -------------------------------------------------------------------------------- /src/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA-256 implementation. 3 | * 4 | * Copyright (c) 2010 Ilya O. Levin, http://www.literatecode.com 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | #ifdef _MSC_VER 19 | #ifndef uint8_t 20 | typedef unsigned __int8 uint8_t; 21 | #endif 22 | #ifndef uint32_t 23 | typedef unsigned __int32 uint32_t; 24 | #endif 25 | #ifndef uint64_t 26 | typedef __int64 int64_t; 27 | typedef unsigned __int64 uint64_t; 28 | #endif 29 | #else 30 | #include 31 | #endif 32 | 33 | #ifdef __cplusplus 34 | extern "C" 35 | { 36 | #endif 37 | 38 | typedef struct { 39 | uint32_t buf[16]; 40 | uint32_t hash[8]; 41 | uint32_t len[2]; 42 | } sha256_context; 43 | 44 | void sha256_init(sha256_context *); 45 | void sha256_hash(sha256_context *, uint8_t * /* data */, uint32_t /* len */); 46 | void sha256_done(sha256_context *, uint8_t * /* hash */); 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif 51 | -------------------------------------------------------------------------------- /src/sha204_includes/sha204_lib_return_codes.h: -------------------------------------------------------------------------------- 1 | // ---------------------------------------------------------------------------- 2 | // ATMEL Microcontroller Software Support - Colorado Springs, CO - 3 | // ---------------------------------------------------------------------------- 4 | // DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR 5 | // IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 6 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE 7 | // DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, 8 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 9 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 10 | // OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 11 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 12 | // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 13 | // EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 14 | // ---------------------------------------------------------------------------- 15 | 16 | /** \file 17 | * \brief SHA204 Library Return Code Definitions 18 | * \author Atmel Crypto Products 19 | * \date September 27, 2010 20 | */ 21 | 22 | #ifndef SHA204_LIB_RETURN_CODES_H 23 | # define SHA204_LIB_RETURN_CODES_H 24 | 25 | #include // data type definitions 26 | 27 | /** \todo Use same values for same meanings for SHA204 and AES132. 28 | * */ 29 | 30 | #define SHA204_SUCCESS ((uint8_t) 0x00) //!< Function succeeded. 31 | #define SHA204_PARSE_ERROR ((uint8_t) 0xD2) //!< response status byte indicates parsing error 32 | #define SHA204_CMD_FAIL ((uint8_t) 0xD3) //!< response status byte indicates command execution error 33 | #define SHA204_STATUS_CRC ((uint8_t) 0xD4) //!< response status byte indicates CRC error 34 | #define SHA204_STATUS_UNKNOWN ((uint8_t) 0xD5) //!< response status byte is unknown 35 | #define SHA204_FUNC_FAIL ((uint8_t) 0xE0) //!< Function could not execute due to incorrect condition / state. 36 | #define SHA204_GEN_FAIL ((uint8_t) 0xE1) //!< unspecified error 37 | #define SHA204_BAD_PARAM ((uint8_t) 0xE2) //!< bad argument (out of range, null pointer, etc.) 38 | #define SHA204_INVALID_ID ((uint8_t) 0xE3) //!< invalid device id, id not set 39 | #define SHA204_INVALID_SIZE ((uint8_t) 0xE4) //!< Count value is out of range or greater than buffer size. 40 | #define SHA204_BAD_CRC ((uint8_t) 0xE5) //!< incorrect CRC received 41 | #define SHA204_RX_FAIL ((uint8_t) 0xE6) //!< Timed out while waiting for response. Number of bytes received is > 0. 42 | #define SHA204_RX_NO_RESPONSE ((uint8_t) 0xE7) //!< Not an error while the Command layer is polling for a command response. 43 | #define SHA204_RESYNC_WITH_WAKEUP ((uint8_t) 0xE8) //!< re-synchronization succeeded, but only after generating a Wake-up 44 | 45 | #define SHA204_COMM_FAIL ((uint8_t) 0xF0) //!< Communication with device failed. Same as in hardware dependent modules. 46 | #define SHA204_TIMEOUT ((uint8_t) 0xF1) //!< Timed out while waiting for response. Number of bytes received is 0. 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /examples/atsha204_simple_example/atsha204_simple_example.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | uint8_t randomExample(); 6 | uint8_t serialNumberExample(); 7 | uint8_t macChallengeExample(); 8 | 9 | void hexDump(uint8_t *data, uint32_t length) 10 | { 11 | char buffer[3]; 12 | Serial.print("0x"); 13 | for (uint32_t i = 0; i < length; i++) 14 | { 15 | snprintf(buffer, sizeof(buffer), "%02X", data[i]); 16 | Serial.print(buffer); 17 | } 18 | Serial.println(); 19 | } 20 | 21 | int char2int(char input) 22 | { 23 | if (input >= '0' && input <= '9') 24 | return input - '0'; 25 | if (input >= 'A' && input <= 'F') 26 | return input - 'A' + 10; 27 | if (input >= 'a' && input <= 'f') 28 | return input - 'a' + 10; 29 | return 0; 30 | } 31 | 32 | // This function assumes src to be a zero terminated sanitized string with 33 | // an even number of [0-9a-f] characters, and target to be sufficiently large 34 | void hex2bin(const char *src, uint8_t *target) 35 | { 36 | while (*src && src[1]) 37 | { 38 | *(target++) = char2int(*src) * 16 + char2int(src[1]); 39 | src += 2; 40 | } 41 | } 42 | 43 | void loadKeyFromHex(const char *hex_key, uint8_t *key) 44 | { 45 | hex2bin(hex_key, key); 46 | } 47 | 48 | /* Attention: we need to set BUFFER_LENGTH to at least 64 in Wire.h */ 49 | atsha204Class sha204; 50 | 51 | void setup() 52 | { 53 | //Remember to set BUFFER_LENGTH to at 64 in Wire.h 54 | Wire.begin(); 55 | Serial.begin(115200); 56 | } 57 | void loop() 58 | { 59 | Serial.println("wake up device."); 60 | sha204.simpleWakeup(); 61 | Serial.print("Get Serial Number:"); 62 | serialNumberExample(); 63 | Serial.println("Put device to sleep mode."); 64 | sha204.simpleSleep(); 65 | delay(2000); 66 | 67 | Serial.println("Wake up device."); 68 | sha204.simpleWakeup(); 69 | Serial.println("Call random:"); 70 | randomExample(); 71 | Serial.println("Put device to sleep mode."); 72 | sha204.simpleSleep(); 73 | Serial.println(); 74 | 75 | delay(2000); 76 | 77 | Serial.println("Wake up device."); 78 | sha204.simpleWakeup(); 79 | Serial.println("Sending a MAC Challenge."); 80 | macChallengeExample(); 81 | Serial.println("Put device to sleep mode."); 82 | sha204.simpleSleep(); 83 | Serial.println(); 84 | delay(2000); 85 | } 86 | 87 | uint8_t randomExample() 88 | { 89 | uint8_t response[32]; 90 | uint8_t returnValue; 91 | returnValue = sha204.simpleGetRandom(response); 92 | hexDump(response, sizeof(response)); 93 | return returnValue; 94 | } 95 | 96 | uint8_t serialNumberExample() 97 | { 98 | uint8_t serialNumber[6]; 99 | uint8_t returnValue; 100 | 101 | returnValue = sha204.simpleGetSerialNumber(serialNumber); 102 | hexDump(serialNumber, sizeof(serialNumber)); 103 | 104 | return returnValue; 105 | } 106 | 107 | uint8_t macChallengeExample() 108 | { 109 | static uint32_t n = 0; 110 | uint8_t mac[32]; 111 | uint8_t challenge[MAC_CHALLENGE_SIZE] = {0}; 112 | sprintf((char *)challenge, "Are you OK? %lu", n++); 113 | Serial.print("Channenge: "); 114 | Serial.println((char *)challenge); 115 | 116 | uint8_t ret_code = sha204.simpleMac(challenge, mac); 117 | if (ret_code != SHA204_SUCCESS) 118 | { 119 | Serial.println("simpleMac failed."); 120 | return ret_code; 121 | } 122 | Serial.print("MAC:\n"); 123 | hexDump(mac, sizeof(mac)); 124 | 125 | uint8_t key[32]; 126 | //Change your key here. 127 | const char *hex_key = "A9CD7F1B6688159B54BBE862F638FF9D29E0FA5F87C69D27BFCD007814BA69C9"; 128 | loadKeyFromHex(hex_key, key); 129 | uint8_t mac_offline[32]; 130 | ret_code = sha204.simpleMacOffline(challenge, mac_offline, key); 131 | Serial.print("MAC Offline:\n"); 132 | hexDump(mac_offline, sizeof(mac_offline)); 133 | return ret_code; 134 | } 135 | -------------------------------------------------------------------------------- /src/sha256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * SHA-256 implementation. 3 | * 4 | * Copyright (c) 2010 Ilya O. Levin, http://www.literatecode.com 5 | * 6 | * Permission to use, copy, modify, and distribute this software for any 7 | * purpose with or without fee is hereby granted, provided that the above 8 | * copyright notice and this permission notice appear in all copies. 9 | * 10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 | */ 18 | #define SWAP_BYTES 19 | // #define USE_STD_MEMCPY 20 | // #define SELF_TEST 21 | 22 | #ifdef USE_STD_MEMCPY 23 | #include 24 | #endif 25 | #include "sha256.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | #define RL(x,n) (((x) << n) | ((x) >> (32 - n))) 32 | #define RR(x,n) (((x) >> n) | ((x) << (32 - n))) 33 | 34 | #define S0(x) (RR((x), 2) ^ RR((x),13) ^ RR((x),22)) 35 | #define S1(x) (RR((x), 6) ^ RR((x),11) ^ RR((x),25)) 36 | #define G0(x) (RR((x), 7) ^ RR((x),18) ^ ((x) >> 3)) 37 | #define G1(x) (RR((x),17) ^ RR((x),19) ^ ((x) >> 10)) 38 | 39 | #ifdef SWAP_BYTES 40 | #define BSWP(x,y) _bswapw((uint32_t *)(x), (uint32_t)(y)) 41 | #else 42 | #define BSWP(p,n) 43 | #endif 44 | #ifdef USE_STD_MEMCPY 45 | #define MEMCP(x,y,z) memcpy((x),(y),(z)) 46 | #else 47 | #define MEMCP(x,y,z) _memcp((x),(y),(z)) 48 | #endif 49 | 50 | #ifndef __cdecl 51 | #define __cdecl 52 | #endif 53 | 54 | static const uint32_t K[64] = { 55 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 56 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 57 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 58 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 59 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 60 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 61 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 62 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 63 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 64 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 65 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 66 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 67 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 68 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 69 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 70 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 71 | }; 72 | 73 | /* -------------------------------------------------------------------------- */ 74 | static void _bswapw(uint32_t *p, uint32_t i) 75 | { 76 | while (i--) p[i] = (RR(p[i],24) & 0x00ff00ff) | (RR(p[i],8) & 0xff00ff00); 77 | 78 | } /* _bswapw */ 79 | 80 | /* -------------------------------------------------------------------------- */ 81 | #ifndef USE_STD_MEMCPY 82 | void * __cdecl _memcp (void *d, const void *s, uint32_t sz) 83 | { 84 | void *rv = d; 85 | 86 | while (sz--) *(char *)d = *(char *)s, d = (char *)d + 1, s = (char *)s + 1; 87 | 88 | return(rv); 89 | } /* _memcp */ 90 | #endif 91 | 92 | /* -------------------------------------------------------------------------- */ 93 | static void _rtrf(uint32_t *b, uint32_t *p, uint32_t i, uint32_t j) 94 | { 95 | #define B(x, y) b[(x-y) & 7] 96 | #define P(x, y) p[(x+y) & 15] 97 | 98 | B(7,i) += (j ? (p[i & 15] += G1(P(i,14)) + P(i,9) + G0(P(i,1))) : p[i & 15]) 99 | + K[i+j] + S1(B(4,i)) 100 | + (B(6,i) ^ (B(4,i) & (B(5,i) ^ B(6,i)))); 101 | B(3,i) += B(7,i); 102 | B(7,i) += S0(B(0,i)) + ( (B(0,i) & B(1,i)) | (B(2,i) & (B(0,i) ^ B(1,i))) ); 103 | 104 | #undef P 105 | #undef B 106 | } /* _rtrf */ 107 | 108 | /* -------------------------------------------------------------------------- */ 109 | static void _hash(sha256_context *ctx) 110 | { 111 | uint32_t b[8], *p, j; 112 | 113 | b[0] = ctx->hash[0]; b[1] = ctx->hash[1]; b[2] = ctx->hash[2]; 114 | b[3] = ctx->hash[3]; b[4] = ctx->hash[4]; b[5] = ctx->hash[5]; 115 | b[6] = ctx->hash[6]; b[7] = ctx->hash[7]; 116 | 117 | for (p = ctx->buf, j = 0; j < 64; j += 16) 118 | _rtrf(b, p, 0, j), _rtrf(b, p, 1, j), _rtrf(b, p, 2, j), 119 | _rtrf(b, p, 3, j), _rtrf(b, p, 4, j), _rtrf(b, p, 5, j), 120 | _rtrf(b, p, 6, j), _rtrf(b, p, 7, j), _rtrf(b, p, 8, j), 121 | _rtrf(b, p, 9, j), _rtrf(b, p, 10, j), _rtrf(b, p, 11, j), 122 | _rtrf(b, p, 12, j), _rtrf(b, p, 13, j), _rtrf(b, p, 14, j), 123 | _rtrf(b, p, 15, j); 124 | 125 | ctx->hash[0] += b[0]; ctx->hash[1] += b[1]; ctx->hash[2] += b[2]; 126 | ctx->hash[3] += b[3]; ctx->hash[4] += b[4]; ctx->hash[5] += b[5]; 127 | ctx->hash[6] += b[6]; ctx->hash[7] += b[7]; 128 | 129 | } /* _hash */ 130 | 131 | /* -------------------------------------------------------------------------- */ 132 | void sha256_init(sha256_context *ctx) 133 | { 134 | ctx->len[0] = ctx->len[1] = 0; 135 | ctx->hash[0] = 0x6a09e667; ctx->hash[1] = 0xbb67ae85; 136 | ctx->hash[2] = 0x3c6ef372; ctx->hash[3] = 0xa54ff53a; 137 | ctx->hash[4] = 0x510e527f; ctx->hash[5] = 0x9b05688c; 138 | ctx->hash[6] = 0x1f83d9ab; ctx->hash[7] = 0x5be0cd19; 139 | 140 | } /* sha256_init */ 141 | 142 | /* -------------------------------------------------------------------------- */ 143 | void sha256_hash(sha256_context *ctx, uint8_t *dat, uint32_t sz) 144 | { 145 | register uint32_t i = ctx->len[0] & 63, l, j; 146 | 147 | if ((ctx->len[0] += sz) < sz) ++(ctx->len[1]); 148 | 149 | for (j = 0, l = 64-i; sz >= l; j += l, sz -= l, l = 64, i = 0) 150 | { 151 | MEMCP((char *)ctx->buf + i, &dat[j], l); 152 | BSWP(ctx->buf, 16 ); 153 | _hash(ctx); 154 | } 155 | MEMCP((char *)ctx->buf + i, &dat[j], sz); 156 | 157 | } /* _hash */ 158 | 159 | /* -------------------------------------------------------------------------- */ 160 | void sha256_done(sha256_context *ctx, uint8_t *buf) 161 | { 162 | uint32_t i = (uint32_t)(ctx->len[0] & 63), j = ((~i) & 3) << 3; 163 | 164 | BSWP(ctx->buf, (i + 3) >> 2); 165 | 166 | ctx->buf[i >> 2] &= 0xffffff80 << j; /* add padding */ 167 | ctx->buf[i >> 2] |= 0x00000080 << j; 168 | 169 | if (i < 56) i = (i >> 2) + 1; 170 | else ctx->buf[15] ^= (i < 60) ? ctx->buf[15] : 0, _hash(ctx), i = 0; 171 | 172 | while (i < 14) ctx->buf[i++] = 0; 173 | 174 | ctx->buf[14] = (ctx->len[1] << 3)|(ctx->len[0] >> 29); /* add length */ 175 | ctx->buf[15] = ctx->len[0] << 3; 176 | 177 | _hash(ctx); 178 | 179 | for (i = 0; i < 32; i++) 180 | ctx->buf[i % 16] = 0, /* may remove this line in case of a DIY cleanup */ 181 | buf[i] = (uint8_t)(ctx->hash[i >> 2] >> ((~i & 3) << 3)); 182 | 183 | } /* sha256_done */ 184 | 185 | 186 | #ifdef SELF_TEST 187 | #pragma warning (push, 0) 188 | #include 189 | #include 190 | #include 191 | #pragma warning(pop) 192 | 193 | char *buf[] = { 194 | "", 195 | "e3b0c442 98fc1c14 9afbf4c8 996fb924 27ae41e4 649b934c a495991b 7852b855", 196 | 197 | "abc", 198 | "ba7816bf 8f01cfea 414140de 5dae2223 b00361a3 96177a9c b410ff61 f20015ad", 199 | 200 | "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 201 | "248d6a61 d20638b8 e5c02693 0c3e6039 a33ce459 64ff2167 f6ecedd4 19db06c1", 202 | 203 | "The quick brown fox jumps over the lazy dog", 204 | "d7a8fbb3 07d78094 69ca9abc b0082e4f 8d5651e4 6d3cdb76 2d02d0bf 37c9e592", 205 | 206 | "The quick brown fox jumps over the lazy cog", /* avalanche effect test */ 207 | "e4c4d8f3 bf76b692 de791a17 3e053211 50f7a345 b46484fe 427f6acc 7ecc81be", 208 | 209 | "bhn5bjmoniertqea40wro2upyflkydsibsk8ylkmgbvwi420t44cq034eou1szc1k0mk46oeb7ktzmlxqkbte2sy", 210 | "9085df2f 02e0cc45 5928d0f5 1b27b4bf 1d9cd260 a66ed1fd a11b0a3f f5756d99" 211 | }; 212 | 213 | int main(int argc, char *argv[]) 214 | { 215 | sha256_context ctx; 216 | uint8_t hv[32]; 217 | uint32_t i, j; 218 | 219 | for (j = 0; j < (sizeof(buf)/sizeof(buf[0])); j += 2) 220 | { 221 | sha256_init(&ctx); 222 | sha256_hash(&ctx, (uint8_t *)buf[j], (uint32_t)strlen(buf[j])); 223 | sha256_done(&ctx, hv); 224 | printf("input = %s\ndigest: %s\nresult: ", buf[j], buf[j+1]); 225 | for (i = 0; i < 32; i++) printf("%02x%s", hv[i], ((i%4)==3)?" ":""); 226 | printf("\n\n"); 227 | } 228 | 229 | for (j = 1; j < (uint32_t)argc; j++) 230 | { 231 | printf("argv[%d]: %s\nresult: ", (int)j, argv[j]); 232 | sha256_init(&ctx); 233 | sha256_hash(&ctx, (uint8_t *)argv[j], (uint32_t)strlen(argv[j])); 234 | sha256_done(&ctx, hv); 235 | for (i = 0; i < 32; i++) printf("%02x%s", hv[i], ((i%4)==3)?" ":""); 236 | printf("\n\n"); 237 | } 238 | 239 | return 0; 240 | } /* main */ 241 | #endif 242 | 243 | #ifdef __cplusplus 244 | } 245 | #endif 246 | -------------------------------------------------------------------------------- /src/sha204_i2c.h: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | 3 | #ifndef sha204_library_H 4 | #define sha204_library_H 5 | #include "sha204_includes/sha204_lib_return_codes.h" 6 | 7 | /* bitbang_config.h */ 8 | 9 | #define PORT_ACCESS_TIME (630) //! time it takes to toggle the pin at CPU clock of 16 MHz (ns) 10 | #define START_PULSE_WIDTH (4340) //! width of start pulse (ns) 11 | #define BIT_DELAY (4) //! delay macro for width of one pulse (start pulse or zero pulse, in ns) 12 | #define RX_TX_DELAY (15) //! turn around time when switching from receive to transmit 13 | #define START_PULSE_TIME_OUT (255) //! This value is decremented while waiting for the falling edge of a start pulse. 14 | #define ZERO_PULSE_TIME_OUT (26) //! This value is decremented while waiting for the falling edge of a zero pulse. 15 | 16 | /* swi_phys.h */ 17 | 18 | #define SWI_FUNCTION_RETCODE_SUCCESS ((uint8_t) 0x00) //!< Communication with device succeeded. 19 | #define SWI_FUNCTION_RETCODE_TIMEOUT ((uint8_t) 0xF1) //!< Communication timed out. 20 | #define SWI_FUNCTION_RETCODE_RX_FAIL ((uint8_t) 0xF9) //!< Communication failed after at least one byte was received. 21 | 22 | /* sha204_physical.h */ 23 | 24 | #define SHA204_RSP_SIZE_MIN ((uint8_t) 4) //!< minimum number of bytes in response 25 | #define SHA204_RSP_SIZE_MAX ((uint8_t) 35) //!< maximum size of response packet 26 | #define SHA204_BUFFER_POS_COUNT (0) //!< buffer index of count byte in command or response 27 | #define SHA204_BUFFER_POS_DATA (1) //!< buffer index of data in response 28 | #define SHA204_WAKEUP_PULSE_WIDTH (uint8_t) (6.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! width of Wakeup pulse in 10 us units 29 | #define SHA204_WAKEUP_DELAY (uint8_t) (3.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5) //! delay between Wakeup pulse and communication in ms 30 | 31 | /* sha204_swi.c */ 32 | #define SHA204_SWI_FLAG_CMD ((uint8_t) 0x03) //!< flag preceding a command 33 | #define SHA204_SWI_FLAG_TX ((uint8_t) 0x00) //!< flag requesting a response 34 | #define SHA204_SWI_FLAG_IDLE ((uint8_t) 0x02) //!< flag requesting to go into Idle mode 35 | #define SHA204_SWI_FLAG_SLEEP ((uint8_t) 0x01) //!< flag requesting to go into Sleep mode 36 | 37 | /* sha204_comm_marshaling.h */ 38 | // command op-code definitions 39 | #define SHA204_CHECKMAC ((uint8_t) 0x28) //!< CheckMac command op-code 40 | #define SHA204_DERIVE_KEY ((uint8_t) 0x1C) //!< DeriveKey command op-code 41 | #define SHA204_DEVREV ((uint8_t) 0x30) //!< DevRev command op-code 42 | #define SHA204_GENDIG ((uint8_t) 0x15) //!< GenDig command op-code 43 | #define SHA204_HMAC ((uint8_t) 0x11) //!< HMAC command op-code 44 | #define SHA204_LOCK ((uint8_t) 0x17) //!< Lock command op-code 45 | #define SHA204_MAC ((uint8_t) 0x08) //!< MAC command op-code 46 | #define SHA204_NONCE ((uint8_t) 0x16) //!< Nonce command op-code 47 | #define SHA204_PAUSE ((uint8_t) 0x01) //!< Pause command op-code 48 | #define SHA204_RANDOM ((uint8_t) 0x1B) //!< Random command op-code 49 | #define SHA204_READ ((uint8_t) 0x02) //!< Read command op-code 50 | #define SHA204_UPDATE_EXTRA ((uint8_t) 0x20) //!< UpdateExtra command op-code 51 | #define SHA204_WRITE ((uint8_t) 0x12) //!< Write command op-code 52 | 53 | // packet size definitions 54 | #define SHA204_RSP_SIZE_VAL ((uint8_t) 7) //!< size of response packet containing four bytes of data 55 | 56 | // parameter range definitions 57 | #define SHA204_KEY_ID_MAX ((uint8_t) 15) //!< maximum value for key id 58 | #define SHA204_OTP_BLOCK_MAX ((uint8_t) 1) //!< maximum value for OTP block 59 | 60 | // definitions for command packet indexes common to all commands 61 | #define SHA204_COUNT_IDX ( 0) //!< command packet index for count 62 | #define SHA204_OPCODE_IDX ( 1) //!< command packet index for op-code 63 | #define SHA204_PARAM1_IDX ( 2) //!< command packet index for first parameter 64 | #define SHA204_PARAM2_IDX ( 3) //!< command packet index for second parameter 65 | #define SHA204_DATA_IDX ( 5) //!< command packet index for second parameter 66 | 67 | // zone definitions 68 | #define SHA204_ZONE_CONFIG ((uint8_t) 0x00) //!< Configuration zone 69 | #define SHA204_ZONE_OTP ((uint8_t) 0x01) //!< OTP (One Time Programming) zone 70 | #define SHA204_ZONE_DATA ((uint8_t) 0x02) //!< Data zone 71 | #define SHA204_ZONE_MASK ((uint8_t) 0x03) //!< Zone mask 72 | #define SHA204_ZONE_COUNT_FLAG ((uint8_t) 0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes. 73 | #define SHA204_ZONE_ACCESS_4 ((uint8_t) 4) //!< Read or write 4 bytes. 74 | #define SHA204_ZONE_ACCESS_32 ((uint8_t) 32) //!< Read or write 32 bytes. 75 | #define SHA204_ADDRESS_MASK_CONFIG ( 0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone. 76 | #define SHA204_ADDRESS_MASK_OTP ( 0x000F) //!< Address bits 4 to 7 are 0 for OTP zone. 77 | #define SHA204_ADDRESS_MASK ( 0x007F) //!< Address bit 7 to 15 are always 0. 78 | 79 | // CheckMAC command definitions 80 | #define CHECKMAC_MODE_IDX SHA204_PARAM1_IDX //!< CheckMAC command index for mode 81 | #define CHECKMAC_KEYID_IDX SHA204_PARAM2_IDX //!< CheckMAC command index for key identifier 82 | #define CHECKMAC_CLIENT_CHALLENGE_IDX SHA204_DATA_IDX //!< CheckMAC command index for client challenge 83 | #define CHECKMAC_CLIENT_RESPONSE_IDX (37) //!< CheckMAC command index for client response 84 | #define CHECKMAC_DATA_IDX (69) //!< CheckMAC command index for other data 85 | #define CHECKMAC_COUNT (84) //!< CheckMAC command packet size 86 | #define CHECKMAC_MODE_MASK ((uint8_t) 0x27) //!< CheckMAC mode bits 3, 4, 6, and 7 are 0. 87 | #define CHECKMAC_CLIENT_CHALLENGE_SIZE (32) //!< CheckMAC size of client challenge 88 | #define CHECKMAC_CLIENT_RESPONSE_SIZE (32) //!< CheckMAC size of client response 89 | #define CHECKMAC_OTHER_DATA_SIZE (13) //!< CheckMAC size of "other data" 90 | 91 | // DeriveKey command definitions 92 | #define DERIVE_KEY_RANDOM_IDX SHA204_PARAM1_IDX //!< DeriveKey command index for random bit 93 | #define DERIVE_KEY_TARGETKEY_IDX SHA204_PARAM2_IDX //!< DeriveKey command index for target slot 94 | #define DERIVE_KEY_MAC_IDX SHA204_DATA_IDX //!< DeriveKey command index for optional MAC 95 | #define DERIVE_KEY_COUNT_SMALL SHA204_CMD_SIZE_MIN //!< DeriveKey command packet size without MAC 96 | #define DERIVE_KEY_COUNT_LARGE (39) //!< DeriveKey command packet size with MAC 97 | #define DERIVE_KEY_RANDOM_FLAG ((uint8_t) 4) //!< DeriveKey 1. parameter 98 | #define DERIVE_KEY_MAC_SIZE (32) //!< DeriveKey MAC size 99 | 100 | // DevRev command definitions 101 | #define DEVREV_PARAM1_IDX SHA204_PARAM1_IDX //!< DevRev command index for 1. parameter (ignored) 102 | #define DEVREV_PARAM2_IDX SHA204_PARAM2_IDX //!< DevRev command index for 2. parameter (ignored) 103 | #define DEVREV_COUNT SHA204_CMD_SIZE_MIN //!< DevRev command packet size 104 | 105 | // GenDig command definitions 106 | #define GENDIG_ZONE_IDX SHA204_PARAM1_IDX //!< GenDig command index for zone 107 | #define GENDIG_KEYID_IDX SHA204_PARAM2_IDX //!< GenDig command index for key id 108 | #define GENDIG_DATA_IDX SHA204_DATA_IDX //!< GenDig command index for optional data 109 | #define GENDIG_COUNT SHA204_CMD_SIZE_MIN //!< GenDig command packet size without "other data" 110 | #define GENDIG_COUNT_DATA (11) //!< GenDig command packet size with "other data" 111 | #define GENDIG_OTHER_DATA_SIZE (4) //!< GenDig size of "other data" 112 | #define GENDIG_ZONE_CONFIG ((uint8_t) 0) //!< GenDig zone id config 113 | #define GENDIG_ZONE_OTP ((uint8_t) 1) //!< GenDig zone id OTP 114 | #define GENDIG_ZONE_DATA ((uint8_t) 2) //!< GenDig zone id data 115 | 116 | // HMAC command definitions 117 | #define HMAC_MODE_IDX SHA204_PARAM1_IDX //!< HMAC command index for mode 118 | #define HMAC_KEYID_IDX SHA204_PARAM2_IDX //!< HMAC command index for key id 119 | #define HMAC_COUNT SHA204_CMD_SIZE_MIN //!< HMAC command packet size 120 | #define HMAC_MODE_MASK ((uint8_t) 0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0. 121 | 122 | // Lock command definitions 123 | #define LOCK_ZONE_IDX SHA204_PARAM1_IDX //!< Lock command index for zone 124 | #define LOCK_SUMMARY_IDX SHA204_PARAM2_IDX //!< Lock command index for summary 125 | #define LOCK_COUNT SHA204_CMD_SIZE_MIN //!< Lock command packet size 126 | #define LOCK_ZONE_NO_CONFIG ((uint8_t) 0x01) //!< Lock zone is OTP or Data 127 | #define LOCK_ZONE_NO_CRC ((uint8_t) 0x80) //!< Lock command: Ignore summary. 128 | #define LOCK_ZONE_MASK (0x81) //!< Lock parameter 1 bits 2 to 6 are 0. 129 | 130 | // Mac command definitions 131 | #define MAC_MODE_IDX SHA204_PARAM1_IDX //!< MAC command index for mode 132 | #define MAC_KEYID_IDX SHA204_PARAM2_IDX //!< MAC command index for key id 133 | #define MAC_CHALLENGE_IDX SHA204_DATA_IDX //!< MAC command index for optional challenge 134 | #define MAC_COUNT_SHORT SHA204_CMD_SIZE_MIN //!< MAC command packet size without challenge 135 | #define MAC_COUNT_LONG (39) //!< MAC command packet size with challenge 136 | #define MAC_MODE_BLOCK2_TEMPKEY ((uint8_t) 0x01) //!< MAC mode bit 0: second SHA block from TempKey 137 | #define MAC_MODE_BLOCK1_TEMPKEY ((uint8_t) 0x02) //!< MAC mode bit 1: first SHA block from TempKey 138 | #define MAC_MODE_SOURCE_FLAG_MATCH ((uint8_t) 0x04) //!< MAC mode bit 2: match TempKey.SourceFlag 139 | #define MAC_MODE_PASSTHROUGH ((uint8_t) 0x07) //!< MAC mode bit 0-2: pass-through mode 140 | #define MAC_MODE_INCLUDE_OTP_88 ((uint8_t) 0x10) //!< MAC mode bit 4: include first 88 OTP bits 141 | #define MAC_MODE_INCLUDE_OTP_64 ((uint8_t) 0x20) //!< MAC mode bit 5: include first 64 OTP bits 142 | #define MAC_MODE_INCLUDE_SN ((uint8_t) 0x40) //!< MAC mode bit 6: include serial number 143 | #define MAC_CHALLENGE_SIZE (32) //!< MAC size of challenge 144 | #define MAC_MODE_MASK ((uint8_t) 0x77) //!< MAC mode bits 3 and 7 are 0. 145 | 146 | // Nonce command definitions 147 | #define NONCE_MODE_IDX SHA204_PARAM1_IDX //!< Nonce command index for mode 148 | #define NONCE_PARAM2_IDX SHA204_PARAM2_IDX //!< Nonce command index for 2. parameter 149 | #define NONCE_INPUT_IDX SHA204_DATA_IDX //!< Nonce command index for input data 150 | #define NONCE_COUNT_SHORT (27) //!< Nonce command packet size for 20 bytes of data 151 | #define NONCE_COUNT_LONG (39) //!< Nonce command packet size for 32 bytes of data 152 | #define NONCE_MODE_MASK ((uint8_t) 3) //!< Nonce mode bits 2 to 7 are 0. 153 | #define NONCE_MODE_SEED_UPDATE ((uint8_t) 0x00) //!< Nonce mode: update seed 154 | #define NONCE_MODE_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Nonce mode: do not update seed 155 | #define NONCE_MODE_INVALID ((uint8_t) 0x02) //!< Nonce mode 2 is invalid. 156 | #define NONCE_MODE_PASSTHROUGH ((uint8_t) 0x03) //!< Nonce mode: pass-through 157 | #define NONCE_NUMIN_SIZE (20) //!< Nonce data length 158 | #define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce data length in pass-through mode (mode = 3) 159 | 160 | // Pause command definitions 161 | #define PAUSE_SELECT_IDX SHA204_PARAM1_IDX //!< Pause command index for Selector 162 | #define PAUSE_PARAM2_IDX SHA204_PARAM2_IDX //!< Pause command index for 2. parameter 163 | #define PAUSE_COUNT SHA204_CMD_SIZE_MIN //!< Pause command packet size 164 | 165 | // Random command definitions 166 | #define RANDOM_MODE_IDX SHA204_PARAM1_IDX //!< Random command index for mode 167 | #define RANDOM_PARAM2_IDX SHA204_PARAM2_IDX //!< Random command index for 2. parameter 168 | #define RANDOM_COUNT SHA204_CMD_SIZE_MIN //!< Random command packet size 169 | #define RANDOM_SEED_UPDATE ((uint8_t) 0x00) //!< Random mode for automatic seed update 170 | #define RANDOM_NO_SEED_UPDATE ((uint8_t) 0x01) //!< Random mode for no seed update 171 | 172 | // Read command definitions 173 | #define READ_ZONE_IDX SHA204_PARAM1_IDX //!< Read command index for zone 174 | #define READ_ADDR_IDX SHA204_PARAM2_IDX //!< Read command index for address 175 | #define READ_COUNT SHA204_CMD_SIZE_MIN //!< Read command packet size 176 | #define READ_ZONE_MASK ((uint8_t) 0x83) //!< Read zone bits 2 to 6 are 0. 177 | #define READ_ZONE_MODE_32_BYTES ((uint8_t) 0x80) //!< Read mode: 32 bytes 178 | 179 | // UpdateExtra command definitions 180 | #define UPDATE_MODE_IDX SHA204_PARAM1_IDX //!< UpdateExtra command index for mode 181 | #define UPDATE_VALUE_IDX SHA204_PARAM2_IDX //!< UpdateExtra command index for new value 182 | #define UPDATE_COUNT SHA204_CMD_SIZE_MIN //!< UpdateExtra command packet size 183 | #define UPDATE_CONFIG_BYTE_86 ((uint8_t) 0x01) //!< UpdateExtra mode: update Config byte 86 184 | 185 | // Write command definitions 186 | #define WRITE_ZONE_IDX SHA204_PARAM1_IDX //!< Write command index for zone 187 | #define WRITE_ADDR_IDX SHA204_PARAM2_IDX //!< Write command index for address 188 | #define WRITE_VALUE_IDX SHA204_DATA_IDX //!< Write command index for data 189 | #define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data 190 | #define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data 191 | #define WRITE_COUNT_SHORT (11) //!< Write command packet size with short data and no MAC 192 | #define WRITE_COUNT_LONG (39) //!< Write command packet size with long data and no MAC 193 | #define WRITE_COUNT_SHORT_MAC (43) //!< Write command packet size with short data and MAC 194 | #define WRITE_COUNT_LONG_MAC (71) //!< Write command packet size with long data and MAC 195 | #define WRITE_MAC_SIZE (32) //!< Write MAC size 196 | #define WRITE_ZONE_MASK ((uint8_t) 0xC3) //!< Write zone bits 2 to 5 are 0. 197 | #define WRITE_ZONE_WITH_MAC ((uint8_t) 0x40) //!< Write zone bit 6: write encrypted with MAC 198 | 199 | // Response size definitions 200 | #define CHECKMAC_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command 201 | #define DERIVE_KEY_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of DeriveKey command 202 | #define DEVREV_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of DevRev command returns 4 bytes 203 | #define GENDIG_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of GenDig command 204 | #define HMAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of HMAC command 205 | #define LOCK_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Lock command 206 | #define MAC_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of MAC command 207 | #define NONCE_RSP_SIZE_SHORT SHA204_RSP_SIZE_MIN //!< response size of Nonce command with mode[0:1] = 3 208 | #define NONCE_RSP_SIZE_LONG SHA204_RSP_SIZE_MAX //!< response size of Nonce command 209 | #define PAUSE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Pause command 210 | #define RANDOM_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Random command 211 | #define READ_4_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of Read command when reading 4 bytes 212 | #define READ_32_RSP_SIZE SHA204_RSP_SIZE_MAX //!< response size of Read command when reading 32 bytes 213 | #define TEMP_SENSE_RSP_SIZE SHA204_RSP_SIZE_VAL //!< response size of TempSense command returns 4 bytes 214 | #define UPDATE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of UpdateExtra command 215 | #define WRITE_RSP_SIZE SHA204_RSP_SIZE_MIN //!< response size of Write command 216 | 217 | // command timing definitions for minimum execution times (ms) 218 | #define CHECKMAC_DELAY 12 219 | #define DERIVE_KEY_DELAY 14 220 | #define DEVREV_DELAY 1 221 | #define GENDIG_DELAY 11 222 | #define HMAC_DELAY 27 223 | #define LOCK_DELAY 5 224 | #define MAC_DELAY 12 225 | #define NONCE_DELAY 22 226 | #define PAUSE_DELAY 1 227 | #define RANDOM_DELAY 11 228 | #define READ_DELAY 1 229 | #define TEMP_SENSE_DELAY 1 230 | #define UPDATE_DELAY 8 231 | #define WRITE_DELAY 4 232 | 233 | // command timing definitions for maximum execution times (ms) 234 | #define CHECKMAC_EXEC_MAX 38 235 | #define DERIVE_KEY_EXEC_MAX 62 236 | #define DEVREV_EXEC_MAX 2 237 | #define GENDIG_EXEC_MAX 43 238 | #define HMAC_EXEC_MAX 69 239 | #define LOCK_EXEC_MAX 24 240 | #define MAC_EXEC_MAX 35 241 | #define NONCE_EXEC_MAX 60 242 | #define PAUSE_EXEC_MAX 2 243 | #define RANDOM_EXEC_MAX 50 244 | #define READ_EXEC_MAX 4 245 | #define TEMP_SENSE_EXEC_MAX 2 246 | #define UPDATE_EXEC_MAX 12 247 | #define WRITE_EXEC_MAX 42 248 | 249 | /* from sha204_config.h */ 250 | 251 | #define CPU_CLOCK_DEVIATION_POSITIVE (1.01) 252 | #define CPU_CLOCK_DEVIATION_NEGATIVE (0.99) 253 | #define SHA204_RETRY_COUNT (1) 254 | #define SWI_RECEIVE_TIME_OUT ((uint16_t) 163) //! #START_PULSE_TIME_OUT in us instead of loop counts 255 | #define SWI_US_PER_BYTE ((uint16_t) 313) //! It takes 312.5 us to send a byte (9 single-wire bits / 230400 Baud * 8 flag bits). 256 | #define SHA204_SYNC_TIMEOUT ((uint8_t) 85)//! delay before sending a transmit flag in the synchronization routine 257 | #define SHA204_RESPONSE_TIMEOUT ((uint16_t) SWI_RECEIVE_TIME_OUT + SWI_US_PER_BYTE) //! SWI response timeout is the sum of receive timeout and the time it takes to send the TX flag. 258 | 259 | /* from sha204_comm.h */ 260 | 261 | #define SHA204_COMMAND_EXEC_MAX ((uint8_t) (69.0 * CPU_CLOCK_DEVIATION_POSITIVE + 0.5)) //! maximum command delay 262 | #define SHA204_CMD_SIZE_MIN ((uint8_t) 7) //! minimum number of bytes in command (from count byte to second CRC byte) 263 | #define SHA204_CMD_SIZE_MAX ((uint8_t) 84) //! maximum size of command packet (CheckMac) 264 | #define SHA204_CRC_SIZE ((uint8_t) 2) //! number of CRC bytes 265 | #define SHA204_BUFFER_POS_STATUS (1) //! buffer index of status byte in status response 266 | #define SHA204_BUFFER_POS_DATA (1) //! buffer index of first data byte in data response 267 | #define SHA204_STATUS_BYTE_WAKEUP ((uint8_t) 0x11) //! command parse error 268 | #define SHA204_STATUS_BYTE_PARSE ((uint8_t) 0x03) //! command parse error 269 | #define SHA204_STATUS_BYTE_EXEC ((uint8_t) 0x0F) //! command execution error 270 | #define SHA204_STATUS_BYTE_COMM ((uint8_t) 0xFF) //! communication error 271 | 272 | /* EEPROM Addresses */ 273 | /* Configuration Zone */ 274 | #define ADDRESS_SN03 0 // SN[0:3] are bytes 0->3 of configuration zone 275 | #define ADDRESS_RevNum 4 // bytes 4->7 of config zone are RevNum 276 | #define ADDRESS_SN47 8 // SN[4:7] are bytes 8->11 of config zone 277 | #define ADDRESS_SN8 12 // SN[8] is byte 12 of config zone, should be 0xEE 278 | #define ADDRESS_I2CEN 14 // I2C Enable, bit 0 represents I2C enable status 279 | #define ADDRESS_I2CADD 16 // Defines I2C address of SHA204 280 | #define ADDRESS_OTPMODE 18 // Sets the One-time-programmable mode 281 | #define ADDRESS_SELECTOR 19 // Controls writability of Selector 282 | 283 | #define SHA204_I2C_ADDRESS 0x64 284 | 285 | class atsha204Class { 286 | private: 287 | void sha204c_calculate_crc(uint8_t length, uint8_t *data, uint8_t *crc); 288 | uint8_t sha204c_check_crc(uint8_t *response); 289 | uint8_t i2c_receive_bytes(uint8_t count, uint8_t *buffer); 290 | uint8_t i2c_send_bytes(uint8_t count, uint8_t *buffer); 291 | uint8_t i2c_send_byte(uint8_t value); 292 | 293 | uint8_t sha204p_receive_response(uint8_t size, uint8_t *response); 294 | uint8_t sha204p_send_command(uint8_t count, uint8_t * command); 295 | uint8_t sha204p_resync(uint8_t size, uint8_t *response); 296 | uint8_t sha204c_wakeup(uint8_t *response); 297 | uint8_t sha204c_send_and_receive(uint8_t *tx_buffer, uint8_t rx_size, 298 | uint8_t *rx_buffer, uint8_t execution_delay, 299 | uint8_t execution_timeout); 300 | uint8_t sha204c_resync(uint8_t size, uint8_t *response); 301 | uint8_t sha204m_random(uint8_t * tx_buffer, uint8_t * rx_buffer, 302 | uint8_t mode); 303 | uint8_t sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer); 304 | uint8_t sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, uint8_t zone, 305 | uint16_t address); 306 | uint8_t sha204m_execute(uint8_t op_code, uint8_t param1, uint16_t param2, 307 | uint8_t datalen1, uint8_t *data1, uint8_t datalen2, uint8_t *data2, 308 | uint8_t datalen3, uint8_t *data3, uint8_t tx_size, 309 | uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); 310 | uint8_t sha204m_check_parameters(uint8_t op_code, uint8_t param1, 311 | uint16_t param2, uint8_t datalen1, uint8_t *data1, uint8_t datalen2, 312 | uint8_t *data2, uint8_t datalen3, uint8_t *data3, uint8_t tx_size, 313 | uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer); 314 | 315 | uint8_t getSerialNumber(uint8_t *response); 316 | uint8_t sha204p_sleep(); 317 | uint8_t sha204p_wakeup(); 318 | 319 | public: 320 | atsha204Class(); 321 | uint8_t simpleMac(uint8_t *challenge, uint8_t *result, 322 | uint8_t key_slot = 0); 323 | uint8_t simpleWakeup(); 324 | uint8_t simpleSleep(); 325 | uint8_t simpleGetRandom(uint8_t *result); 326 | uint8_t simpleGetSerialNumber(uint8_t *result); 327 | uint8_t simpleMacOffline(uint8_t *challenge, 328 | uint8_t *result, uint8_t *key); 329 | }; 330 | 331 | #endif 332 | -------------------------------------------------------------------------------- /src/sha204_i2c.cpp: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | #include "sha204_i2c.h" 3 | #include "sha256.h" 4 | // remember to set BUFFER_LENGTH to at 64 in Wire.h 5 | #include "Wire.h" 6 | 7 | //Constructor 8 | atsha204Class::atsha204Class() 9 | { 10 | //call Wire.begin on your main function. 11 | //Wire.begin(); 12 | //Wire.setClock(100000); 13 | } 14 | 15 | // application simple wrapper functions. 16 | 17 | uint8_t atsha204Class::simpleSleep() 18 | { 19 | return sha204p_sleep(); 20 | } 21 | 22 | uint8_t atsha204Class::simpleWakeup() 23 | { 24 | uint8_t response[SHA204_RSP_SIZE_MIN]; 25 | return sha204c_wakeup(response); 26 | } 27 | 28 | /* Puts a the ATSHA204's unique, 4-byte serial number in the response array 29 | returns an SHA204 Return code */ 30 | uint8_t atsha204Class::getSerialNumber(uint8_t *response) 31 | { 32 | uint8_t readCommand[READ_COUNT]; 33 | uint8_t readResponse[READ_4_RSP_SIZE]; 34 | 35 | //sha204c_wakeup(); 36 | //return 0; 37 | /* read from bytes 0->3 of config zone */ 38 | uint8_t returnCode = sha204m_read(readCommand, readResponse, 39 | SHA204_ZONE_CONFIG, ADDRESS_SN03); 40 | if (!returnCode) // should return 0 if successful 41 | { 42 | for (int i = 0; i < 4; i++) // store bytes 0-3 into respones array 43 | response[i] = readResponse[SHA204_BUFFER_POS_DATA + i]; 44 | 45 | /* read from bytes 8->11 of config zone */ 46 | returnCode = sha204m_read(readCommand, readResponse, SHA204_ZONE_CONFIG, 47 | ADDRESS_SN47); 48 | 49 | for (int i = 4; i < 8; i++) // store bytes 4-7 of SN into response array 50 | response[i] = readResponse[SHA204_BUFFER_POS_DATA + (i - 4)]; 51 | 52 | if (!returnCode) 53 | { /* Finally if last two reads were successful, read byte 8 of the SN */ 54 | returnCode = sha204m_read(readCommand, readResponse, 55 | SHA204_ZONE_CONFIG, ADDRESS_SN8); 56 | // Byte 8 of SN should always be 0xEE 57 | response[8] = readResponse[SHA204_BUFFER_POS_DATA]; 58 | } 59 | } 60 | 61 | return returnCode; 62 | } 63 | 64 | uint8_t atsha204Class::simpleGetSerialNumber(uint8_t *result) 65 | { 66 | uint8_t serialNumber[9]; 67 | uint8_t ret_code = getSerialNumber(serialNumber); 68 | if (ret_code == SHA204_SUCCESS) 69 | { 70 | memcpy(result, serialNumber + 2, 6); 71 | } 72 | return ret_code; 73 | } 74 | 75 | uint8_t atsha204Class::simpleGetRandom(uint8_t *result) 76 | { 77 | uint8_t response[RANDOM_RSP_SIZE]; 78 | byte ret_code; 79 | uint8_t tx_buffer[RANDOM_COUNT] = {0}; 80 | ret_code = sha204m_random(tx_buffer, response, 81 | RANDOM_NO_SEED_UPDATE); 82 | if (ret_code == SHA204_SUCCESS) 83 | { 84 | memcpy(result, response + 1, 32); 85 | return SHA204_SUCCESS; 86 | } 87 | else 88 | { 89 | return ret_code; 90 | } 91 | } 92 | 93 | uint8_t atsha204Class::simpleMac(uint8_t *challenge, uint8_t *result, 94 | uint8_t key_slot) 95 | { 96 | uint8_t command[MAC_COUNT_LONG]; 97 | uint8_t response[MAC_RSP_SIZE]; 98 | 99 | uint8_t ret_code = sha204m_execute(SHA204_MAC, 0, key_slot, 100 | MAC_CHALLENGE_SIZE, (uint8_t *)challenge, 0, NULL, 0, NULL, 101 | sizeof(command), &command[0], sizeof(response), &response[0]); 102 | 103 | if (ret_code == SHA204_SUCCESS) 104 | { 105 | memcpy(result, response + 1, 32); 106 | return SHA204_SUCCESS; 107 | } 108 | else 109 | { 110 | return ret_code; 111 | } 112 | } 113 | 114 | //verify Mac offline using sha256. 115 | uint8_t atsha204Class::simpleMacOffline(uint8_t *challenge, 116 | uint8_t *result, uint8_t *key) 117 | { 118 | uint8_t temp[8]; 119 | sha256_context ctx; 120 | sha256_init(&ctx); 121 | sha256_hash(&ctx, key, 32); 122 | sha256_hash(&ctx, challenge, 32); 123 | //opcode 124 | temp[0] = 0x08; 125 | sha256_hash(&ctx, temp, 1); 126 | //mode 127 | temp[0] = 0x00; 128 | sha256_hash(&ctx, temp, 1); 129 | //param2 130 | temp[0] = 0; 131 | temp[1] = 0; 132 | sha256_hash(&ctx, temp, 2); 133 | //otp 134 | memset(temp, 0, sizeof(temp)); 135 | //otp 0-7 136 | sha256_hash(&ctx, temp, 8); 137 | //otp 8-10 138 | sha256_hash(&ctx, temp, 3); 139 | //sn 8 140 | temp[0] = 0xEE; 141 | sha256_hash(&ctx, temp, 1); 142 | //sn 4-7 143 | memset(temp, 0, sizeof(temp)); 144 | sha256_hash(&ctx, temp, 4); 145 | //sn 0-1 146 | temp[0] = 0x01; 147 | temp[1] = 0x23; 148 | sha256_hash(&ctx, temp, 2); 149 | //sn 2-3; 150 | memset(temp, 0, sizeof(temp)); 151 | sha256_hash(&ctx, temp, 2); 152 | 153 | sha256_done(&ctx, result); 154 | return SHA204_SUCCESS; 155 | } 156 | 157 | // I2C HAL functions 158 | 159 | uint8_t atsha204Class::i2c_send_bytes(uint8_t count, uint8_t *buffer) 160 | { 161 | Wire.beginTransmission(SHA204_I2C_ADDRESS); 162 | Wire.write(buffer, count); 163 | uint8_t ret = Wire.endTransmission(); 164 | if (ret == 0) 165 | { 166 | return SWI_FUNCTION_RETCODE_SUCCESS; 167 | } 168 | else 169 | { 170 | return SHA204_COMM_FAIL; 171 | } 172 | } 173 | 174 | uint8_t atsha204Class::i2c_send_byte(uint8_t value) 175 | { 176 | return i2c_send_bytes(1, &value); 177 | } 178 | 179 | uint8_t atsha204Class::i2c_receive_bytes(uint8_t count, uint8_t *buffer) 180 | { 181 | /* we need to set BUFFER_LENGTH to at least 64 in Wire.h */ 182 | Wire.requestFrom((uint8_t)SHA204_I2C_ADDRESS, count); 183 | uint8_t pos = 0; 184 | uint32_t wait = 0; 185 | while (pos < count) 186 | { 187 | while (Wire.available() == 0) 188 | { 189 | delay(1); 190 | wait++; 191 | if (wait > 10) 192 | { 193 | return SWI_FUNCTION_RETCODE_TIMEOUT; 194 | } 195 | }; 196 | buffer[pos] = Wire.read(); 197 | pos++; 198 | } 199 | return SWI_FUNCTION_RETCODE_SUCCESS; 200 | } 201 | 202 | /* Physical functions */ 203 | 204 | uint8_t atsha204Class::sha204p_wakeup() 205 | { 206 | //wake up by send 0x00 207 | Wire.beginTransmission(0x00); 208 | Wire.endTransmission(); 209 | //wait Twhi 210 | delay(3); 211 | return SHA204_SUCCESS; 212 | } 213 | 214 | uint8_t atsha204Class::sha204p_sleep() 215 | { 216 | return i2c_send_byte(SHA204_SWI_FLAG_SLEEP); 217 | } 218 | 219 | uint8_t atsha204Class::sha204p_resync(uint8_t size, uint8_t *response) 220 | { 221 | delay(SHA204_SYNC_TIMEOUT); 222 | return sha204p_receive_response(size, response); 223 | } 224 | 225 | uint8_t atsha204Class::sha204p_receive_response(uint8_t size, 226 | uint8_t *response) 227 | { 228 | uint8_t count_byte; 229 | uint8_t i; 230 | uint8_t ret_code; 231 | 232 | for (i = 0; i < size; i++) 233 | response[i] = 0; 234 | 235 | ret_code = i2c_receive_bytes(size, response); 236 | if (ret_code == SWI_FUNCTION_RETCODE_SUCCESS || ret_code == SWI_FUNCTION_RETCODE_RX_FAIL) 237 | { 238 | 239 | count_byte = response[SHA204_BUFFER_POS_COUNT]; 240 | if ((count_byte < SHA204_RSP_SIZE_MIN) || (count_byte > size)) 241 | return SHA204_INVALID_SIZE; 242 | 243 | return SHA204_SUCCESS; 244 | } 245 | 246 | // Translate error so that the Communication layer 247 | // can distinguish between a real error or the 248 | // device being busy executing a command. 249 | if (ret_code == SWI_FUNCTION_RETCODE_TIMEOUT) 250 | return SHA204_RX_NO_RESPONSE; 251 | else 252 | return SHA204_RX_FAIL; 253 | } 254 | 255 | uint8_t atsha204Class::sha204p_send_command(uint8_t count, uint8_t *command) 256 | { 257 | Wire.beginTransmission(0x64); 258 | Wire.write(SHA204_SWI_FLAG_CMD); 259 | Wire.write(command, count); 260 | uint8_t ret = Wire.endTransmission(); 261 | if (ret == 0) 262 | { 263 | return SHA204_SUCCESS; 264 | } 265 | else 266 | { 267 | return SHA204_COMM_FAIL; 268 | } 269 | } 270 | 271 | /* Communication functions */ 272 | 273 | uint8_t atsha204Class::sha204c_wakeup(uint8_t *response) 274 | { 275 | uint8_t ret_code = sha204p_wakeup(); 276 | if (ret_code != SHA204_SUCCESS) 277 | return ret_code; 278 | 279 | ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response); 280 | if (ret_code != SHA204_SUCCESS) 281 | return ret_code; 282 | 283 | // Verify status response. 284 | if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN) 285 | ret_code = SHA204_INVALID_SIZE; 286 | else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP) 287 | ret_code = SHA204_COMM_FAIL; 288 | else 289 | { 290 | if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33) || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43)) 291 | ret_code = SHA204_BAD_CRC; 292 | } 293 | if (ret_code != SHA204_SUCCESS) 294 | delay(SHA204_COMMAND_EXEC_MAX); 295 | 296 | return ret_code; 297 | } 298 | 299 | uint8_t atsha204Class::sha204c_resync(uint8_t size, uint8_t *response) 300 | { 301 | // Try to re-synchronize without sending a Wake token 302 | // (step 1 of the re-synchronization process). 303 | uint8_t ret_code = sha204p_resync(size, response); 304 | if (ret_code == SHA204_SUCCESS) 305 | return ret_code; 306 | 307 | // We lost communication. Send a Wake pulse and try 308 | // to receive a response (steps 2 and 3 of the 309 | // re-synchronization process). 310 | (void)sha204p_sleep(); 311 | ret_code = sha204c_wakeup(response); 312 | 313 | // Translate a return value of success into one 314 | // that indicates that the device had to be woken up 315 | // and might have lost its TempKey. 316 | return (ret_code == SHA204_SUCCESS ? SHA204_RESYNC_WITH_WAKEUP : ret_code); 317 | } 318 | 319 | uint8_t atsha204Class::sha204c_send_and_receive(uint8_t *tx_buffer, 320 | uint8_t rx_size, uint8_t *rx_buffer, uint8_t execution_delay, 321 | uint8_t execution_timeout) 322 | { 323 | uint8_t ret_code = SHA204_FUNC_FAIL; 324 | uint8_t ret_code_resync; 325 | uint8_t n_retries_send; 326 | uint8_t n_retries_receive; 327 | uint8_t i; 328 | uint8_t status_byte; 329 | uint8_t count = tx_buffer[SHA204_BUFFER_POS_COUNT]; 330 | uint8_t count_minus_crc = count - SHA204_CRC_SIZE; 331 | uint16_t execution_timeout_us = (uint16_t)(execution_timeout * 1000) + SHA204_RESPONSE_TIMEOUT; 332 | volatile uint16_t timeout_countdown; 333 | 334 | // Append CRC. 335 | sha204c_calculate_crc(count_minus_crc, tx_buffer, 336 | tx_buffer + count_minus_crc); 337 | 338 | // Retry loop for sending a command and receiving a response. 339 | n_retries_send = SHA204_RETRY_COUNT + 1; 340 | 341 | while ((n_retries_send-- > 0) && (ret_code != SHA204_SUCCESS)) 342 | { 343 | // Send command. 344 | ret_code = sha204p_send_command(count, tx_buffer); 345 | if (ret_code != SHA204_SUCCESS) 346 | { 347 | if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) 348 | return ret_code; // The device seems to be dead in the water. 349 | else 350 | continue; 351 | } 352 | 353 | // Wait minimum command execution time and then start polling for a response. 354 | delay(execution_delay); 355 | 356 | // Retry loop for receiving a response. 357 | n_retries_receive = SHA204_RETRY_COUNT + 1; 358 | while (n_retries_receive-- > 0) 359 | { 360 | // Reset response buffer. 361 | for (i = 0; i < rx_size; i++) 362 | rx_buffer[i] = 0; 363 | 364 | // Poll for response. 365 | timeout_countdown = execution_timeout_us; 366 | do 367 | { 368 | ret_code = sha204p_receive_response(rx_size, rx_buffer); 369 | timeout_countdown -= SHA204_RESPONSE_TIMEOUT; 370 | } while ((timeout_countdown > SHA204_RESPONSE_TIMEOUT) && (ret_code == SHA204_RX_NO_RESPONSE)); 371 | 372 | if (ret_code == SHA204_RX_NO_RESPONSE) 373 | { 374 | // We did not receive a response. Re-synchronize and send command again. 375 | if (sha204c_resync(rx_size, rx_buffer) == SHA204_RX_NO_RESPONSE) 376 | // The device seems to be dead in the water. 377 | return ret_code; 378 | else 379 | break; 380 | } 381 | 382 | // Check whether we received a valid response. 383 | if (ret_code == SHA204_INVALID_SIZE) 384 | { 385 | // We see 0xFF for the count when communication got out of sync. 386 | ret_code_resync = sha204c_resync(rx_size, rx_buffer); 387 | if (ret_code_resync == SHA204_SUCCESS) 388 | // We did not have to wake up the device. Try receiving response again. 389 | continue; 390 | if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) 391 | // We could re-synchronize, but only after waking up the device. 392 | // Re-send command. 393 | break; 394 | else 395 | // We failed to re-synchronize. 396 | return ret_code; 397 | } 398 | 399 | // We received a response of valid size. 400 | // Check the consistency of the response. 401 | ret_code = sha204c_check_crc(rx_buffer); 402 | if (ret_code == SHA204_SUCCESS) 403 | { 404 | // Received valid response. 405 | if (rx_buffer[SHA204_BUFFER_POS_COUNT] > SHA204_RSP_SIZE_MIN) 406 | // Received non-status response. We are done. 407 | return ret_code; 408 | 409 | // Received status response. 410 | status_byte = rx_buffer[SHA204_BUFFER_POS_STATUS]; 411 | 412 | // Translate the three possible device status error codes 413 | // into library return codes. 414 | if (status_byte == SHA204_STATUS_BYTE_PARSE) 415 | return SHA204_PARSE_ERROR; 416 | if (status_byte == SHA204_STATUS_BYTE_EXEC) 417 | return SHA204_CMD_FAIL; 418 | if (status_byte == SHA204_STATUS_BYTE_COMM) 419 | { 420 | // In case of the device status byte indicating a communication 421 | // error this function exits the retry loop for receiving a response 422 | // and enters the overall retry loop 423 | // (send command / receive response). 424 | ret_code = SHA204_STATUS_CRC; 425 | break; 426 | } 427 | 428 | // Received status response from CheckMAC, DeriveKey, GenDig, 429 | // Lock, Nonce, Pause, UpdateExtra, or Write command. 430 | return ret_code; 431 | } 432 | 433 | else 434 | { 435 | Serial.println("checksum failed."); 436 | // Received response with incorrect CRC. 437 | ret_code_resync = sha204c_resync(rx_size, rx_buffer); 438 | if (ret_code_resync == SHA204_SUCCESS) 439 | // We did not have to wake up the device. Try receiving response again. 440 | continue; 441 | if (ret_code_resync == SHA204_RESYNC_WITH_WAKEUP) 442 | // We could re-synchronize, but only after waking up the device. 443 | // Re-send command. 444 | break; 445 | else 446 | // We failed to re-synchronize. 447 | return ret_code; 448 | } // block end of check response consistency 449 | 450 | } // block end of receive retry loop 451 | 452 | } // block end of send and receive retry loop 453 | 454 | return ret_code; 455 | } 456 | 457 | /* Marshaling functions */ 458 | 459 | uint8_t atsha204Class::sha204m_random(uint8_t *tx_buffer, uint8_t *rx_buffer, 460 | uint8_t mode) 461 | { 462 | if (!tx_buffer || !rx_buffer || (mode > RANDOM_NO_SEED_UPDATE)) 463 | return SHA204_BAD_PARAM; 464 | 465 | tx_buffer[SHA204_COUNT_IDX] = RANDOM_COUNT; 466 | tx_buffer[SHA204_OPCODE_IDX] = SHA204_RANDOM; 467 | tx_buffer[RANDOM_MODE_IDX] = mode & RANDOM_SEED_UPDATE; 468 | 469 | tx_buffer[RANDOM_PARAM2_IDX] = tx_buffer[RANDOM_PARAM2_IDX + 1] = 0; 470 | 471 | return sha204c_send_and_receive(&tx_buffer[0], RANDOM_RSP_SIZE, 472 | &rx_buffer[0], RANDOM_DELAY, RANDOM_EXEC_MAX - RANDOM_DELAY); 473 | } 474 | 475 | uint8_t atsha204Class::sha204m_dev_rev(uint8_t *tx_buffer, uint8_t *rx_buffer) 476 | { 477 | if (!tx_buffer || !rx_buffer) 478 | return SHA204_BAD_PARAM; 479 | 480 | tx_buffer[SHA204_COUNT_IDX] = DEVREV_COUNT; 481 | tx_buffer[SHA204_OPCODE_IDX] = SHA204_DEVREV; 482 | 483 | // Parameters are 0. 484 | tx_buffer[DEVREV_PARAM1_IDX] = tx_buffer[DEVREV_PARAM2_IDX] = 485 | tx_buffer[DEVREV_PARAM2_IDX + 1] = 0; 486 | 487 | return sha204c_send_and_receive(&tx_buffer[0], DEVREV_RSP_SIZE, 488 | &rx_buffer[0], 489 | DEVREV_DELAY, DEVREV_EXEC_MAX - DEVREV_DELAY); 490 | } 491 | 492 | uint8_t atsha204Class::sha204m_read(uint8_t *tx_buffer, uint8_t *rx_buffer, 493 | uint8_t zone, uint16_t address) 494 | { 495 | uint8_t rx_size; 496 | 497 | if (!tx_buffer || !rx_buffer || ((zone & ~READ_ZONE_MASK) != 0) || ((zone & READ_ZONE_MODE_32_BYTES) && (zone == SHA204_ZONE_OTP))) 498 | return SHA204_BAD_PARAM; 499 | 500 | address >>= 2; 501 | if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_CONFIG) 502 | { 503 | if (address > SHA204_ADDRESS_MASK_CONFIG) 504 | return SHA204_BAD_PARAM; 505 | } 506 | else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_OTP) 507 | { 508 | if (address > SHA204_ADDRESS_MASK_OTP) 509 | return SHA204_BAD_PARAM; 510 | } 511 | else if ((zone & SHA204_ZONE_MASK) == SHA204_ZONE_DATA) 512 | { 513 | if (address > SHA204_ADDRESS_MASK) 514 | return SHA204_BAD_PARAM; 515 | } 516 | 517 | tx_buffer[SHA204_COUNT_IDX] = READ_COUNT; 518 | tx_buffer[SHA204_OPCODE_IDX] = SHA204_READ; 519 | tx_buffer[READ_ZONE_IDX] = zone; 520 | tx_buffer[READ_ADDR_IDX] = (uint8_t)(address & SHA204_ADDRESS_MASK); 521 | tx_buffer[READ_ADDR_IDX + 1] = 0; 522 | 523 | rx_size = (zone & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; 524 | 525 | return sha204c_send_and_receive(&tx_buffer[0], rx_size, &rx_buffer[0], 526 | READ_DELAY, READ_EXEC_MAX - READ_DELAY); 527 | } 528 | 529 | uint8_t atsha204Class::sha204m_execute(uint8_t op_code, uint8_t param1, 530 | uint16_t param2, uint8_t datalen1, uint8_t *data1, uint8_t datalen2, 531 | uint8_t *data2, uint8_t datalen3, uint8_t *data3, uint8_t tx_size, 532 | uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) 533 | { 534 | uint8_t poll_delay, poll_timeout, response_size; 535 | uint8_t *p_buffer; 536 | uint8_t len; 537 | 538 | uint8_t ret_code = sha204m_check_parameters(op_code, param1, param2, 539 | datalen1, data1, datalen2, data2, datalen3, data3, tx_size, 540 | tx_buffer, rx_size, rx_buffer); 541 | if (ret_code != SHA204_SUCCESS) 542 | return ret_code; 543 | 544 | // Supply delays and response size. 545 | switch (op_code) 546 | { 547 | case SHA204_CHECKMAC: 548 | poll_delay = CHECKMAC_DELAY; 549 | poll_timeout = CHECKMAC_EXEC_MAX - CHECKMAC_DELAY; 550 | response_size = CHECKMAC_RSP_SIZE; 551 | break; 552 | 553 | case SHA204_DERIVE_KEY: 554 | poll_delay = DERIVE_KEY_DELAY; 555 | poll_timeout = DERIVE_KEY_EXEC_MAX - DERIVE_KEY_DELAY; 556 | response_size = DERIVE_KEY_RSP_SIZE; 557 | break; 558 | 559 | case SHA204_DEVREV: 560 | poll_delay = DEVREV_DELAY; 561 | poll_timeout = DEVREV_EXEC_MAX - DEVREV_DELAY; 562 | response_size = DEVREV_RSP_SIZE; 563 | break; 564 | 565 | case SHA204_GENDIG: 566 | poll_delay = GENDIG_DELAY; 567 | poll_timeout = GENDIG_EXEC_MAX - GENDIG_DELAY; 568 | response_size = GENDIG_RSP_SIZE; 569 | break; 570 | 571 | case SHA204_HMAC: 572 | poll_delay = HMAC_DELAY; 573 | poll_timeout = HMAC_EXEC_MAX - HMAC_DELAY; 574 | response_size = HMAC_RSP_SIZE; 575 | break; 576 | 577 | case SHA204_LOCK: 578 | poll_delay = LOCK_DELAY; 579 | poll_timeout = LOCK_EXEC_MAX - LOCK_DELAY; 580 | response_size = LOCK_RSP_SIZE; 581 | break; 582 | 583 | case SHA204_MAC: 584 | poll_delay = MAC_DELAY; 585 | poll_timeout = MAC_EXEC_MAX - MAC_DELAY; 586 | response_size = MAC_RSP_SIZE; 587 | break; 588 | 589 | case SHA204_NONCE: 590 | poll_delay = NONCE_DELAY; 591 | poll_timeout = NONCE_EXEC_MAX - NONCE_DELAY; 592 | response_size = param1 == NONCE_MODE_PASSTHROUGH ? NONCE_RSP_SIZE_SHORT : NONCE_RSP_SIZE_LONG; 593 | break; 594 | 595 | case SHA204_PAUSE: 596 | poll_delay = PAUSE_DELAY; 597 | poll_timeout = PAUSE_EXEC_MAX - PAUSE_DELAY; 598 | response_size = PAUSE_RSP_SIZE; 599 | break; 600 | 601 | case SHA204_RANDOM: 602 | poll_delay = RANDOM_DELAY; 603 | poll_timeout = RANDOM_EXEC_MAX - RANDOM_DELAY; 604 | response_size = RANDOM_RSP_SIZE; 605 | break; 606 | 607 | case SHA204_READ: 608 | poll_delay = READ_DELAY; 609 | poll_timeout = READ_EXEC_MAX - READ_DELAY; 610 | response_size = (param1 & SHA204_ZONE_COUNT_FLAG) ? READ_32_RSP_SIZE : READ_4_RSP_SIZE; 611 | break; 612 | 613 | case SHA204_UPDATE_EXTRA: 614 | poll_delay = UPDATE_DELAY; 615 | poll_timeout = UPDATE_EXEC_MAX - UPDATE_DELAY; 616 | response_size = UPDATE_RSP_SIZE; 617 | break; 618 | 619 | case SHA204_WRITE: 620 | poll_delay = WRITE_DELAY; 621 | poll_timeout = WRITE_EXEC_MAX - WRITE_DELAY; 622 | response_size = WRITE_RSP_SIZE; 623 | break; 624 | 625 | default: 626 | poll_delay = 0; 627 | poll_timeout = SHA204_COMMAND_EXEC_MAX; 628 | response_size = rx_size; 629 | } 630 | 631 | // Assemble command. 632 | len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; 633 | p_buffer = tx_buffer; 634 | *p_buffer++ = len; 635 | *p_buffer++ = op_code; 636 | *p_buffer++ = param1; 637 | *p_buffer++ = param2 & 0xFF; 638 | *p_buffer++ = param2 >> 8; 639 | 640 | if (datalen1 > 0) 641 | { 642 | memcpy(p_buffer, data1, datalen1); 643 | p_buffer += datalen1; 644 | } 645 | if (datalen2 > 0) 646 | { 647 | memcpy(p_buffer, data2, datalen2); 648 | p_buffer += datalen2; 649 | } 650 | if (datalen3 > 0) 651 | { 652 | memcpy(p_buffer, data3, datalen3); 653 | p_buffer += datalen3; 654 | } 655 | 656 | //fill crc is done in sha204c_send_and_receive 657 | //sha204c_calculate_crc(len - SHA204_CRC_SIZE, tx_buffer, p_buffer); 658 | 659 | // Send command and receive response. 660 | //Serial.println("Sending execute command."); 661 | return sha204c_send_and_receive(&tx_buffer[0], response_size, &rx_buffer[0], 662 | poll_delay, poll_timeout); 663 | } 664 | 665 | uint8_t atsha204Class::sha204m_check_parameters(uint8_t op_code, uint8_t param1, 666 | uint16_t param2, uint8_t datalen1, uint8_t *data1, uint8_t datalen2, 667 | uint8_t *data2, uint8_t datalen3, uint8_t *data3, uint8_t tx_size, 668 | uint8_t *tx_buffer, uint8_t rx_size, uint8_t *rx_buffer) 669 | { 670 | #ifdef SHA204_CHECK_PARAMETERS 671 | 672 | uint8_t len = datalen1 + datalen2 + datalen3 + SHA204_CMD_SIZE_MIN; 673 | if (!tx_buffer || tx_size < len || rx_size < SHA204_RSP_SIZE_MIN || !rx_buffer) 674 | return SHA204_BAD_PARAM; 675 | 676 | if ((datalen1 > 0 && !data1) || (datalen2 > 0 && !data2) || (datalen3 > 0 && !data3)) 677 | return SHA204_BAD_PARAM; 678 | 679 | // Check parameters depending on op-code. 680 | switch (op_code) 681 | { 682 | case SHA204_CHECKMAC: 683 | if ( 684 | // no null pointers allowed 685 | !data1 || !data2 686 | // No reserved bits should be set. 687 | || (param1 | CHECKMAC_MODE_MASK) != CHECKMAC_MODE_MASK 688 | // key_id > 15 not allowed 689 | || param2 > SHA204_KEY_ID_MAX) 690 | return SHA204_BAD_PARAM; 691 | break; 692 | 693 | case SHA204_DERIVE_KEY: 694 | if (param2 > SHA204_KEY_ID_MAX) 695 | return SHA204_BAD_PARAM; 696 | break; 697 | 698 | case SHA204_DEVREV: 699 | break; 700 | 701 | case SHA204_GENDIG: 702 | if ((param1 != GENDIG_ZONE_OTP) && (param1 != GENDIG_ZONE_DATA)) 703 | return SHA204_BAD_PARAM; 704 | break; 705 | 706 | case SHA204_HMAC: 707 | if ((param1 & ~HMAC_MODE_MASK) != 0) 708 | return SHA204_BAD_PARAM; 709 | break; 710 | 711 | case SHA204_LOCK: 712 | if (((param1 & ~LOCK_ZONE_MASK) != 0) || ((param1 & LOCK_ZONE_NO_CRC) && (param2 != 0))) 713 | return SHA204_BAD_PARAM; 714 | break; 715 | 716 | case SHA204_MAC: 717 | if (((param1 & ~MAC_MODE_MASK) != 0) || (((param1 & MAC_MODE_BLOCK2_TEMPKEY) == 0) && !data1)) 718 | return SHA204_BAD_PARAM; 719 | break; 720 | 721 | case SHA204_NONCE: 722 | if (!data1 || (param1 > NONCE_MODE_PASSTHROUGH) || (param1 == NONCE_MODE_INVALID)) 723 | return SHA204_BAD_PARAM; 724 | break; 725 | 726 | case SHA204_PAUSE: 727 | break; 728 | 729 | case SHA204_RANDOM: 730 | if (param1 > RANDOM_NO_SEED_UPDATE) 731 | return SHA204_BAD_PARAM; 732 | break; 733 | 734 | case SHA204_READ: 735 | if (((param1 & ~READ_ZONE_MASK) != 0) || ((param1 & READ_ZONE_MODE_32_BYTES) && (param1 == SHA204_ZONE_OTP))) 736 | return SHA204_BAD_PARAM; 737 | break; 738 | 739 | case SHA204_TEMPSENSE: 740 | break; 741 | 742 | case SHA204_UPDATE_EXTRA: 743 | if (param1 > UPDATE_CONFIG_BYTE_86) 744 | return SHA204_BAD_PARAM; 745 | break; 746 | 747 | case SHA204_WRITE: 748 | if (!data1 || ((param1 & ~WRITE_ZONE_MASK) != 0)) 749 | return SHA204_BAD_PARAM; 750 | break; 751 | 752 | default: 753 | // unknown op-code 754 | return SHA204_BAD_PARAM; 755 | } 756 | 757 | return SHA204_SUCCESS; 758 | 759 | #else 760 | return SHA204_SUCCESS; 761 | #endif 762 | } 763 | 764 | /* CRC Calculator and Checker */ 765 | 766 | void atsha204Class::sha204c_calculate_crc(uint8_t length, uint8_t *data, 767 | uint8_t *crc) 768 | { 769 | uint8_t counter; 770 | uint16_t crc_register = 0; 771 | uint16_t polynom = 0x8005; 772 | uint8_t shift_register; 773 | uint8_t data_bit, crc_bit; 774 | 775 | for (counter = 0; counter < length; counter++) 776 | { 777 | for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 778 | 1) 779 | { 780 | data_bit = (data[counter] & shift_register) ? 1 : 0; 781 | crc_bit = crc_register >> 15; 782 | 783 | // Shift CRC to the left by 1. 784 | crc_register <<= 1; 785 | 786 | if ((data_bit ^ crc_bit) != 0) 787 | crc_register ^= polynom; 788 | } 789 | } 790 | crc[0] = (uint8_t)(crc_register & 0x00FF); 791 | crc[1] = (uint8_t)(crc_register >> 8); 792 | } 793 | 794 | uint8_t atsha204Class::sha204c_check_crc(uint8_t *response) 795 | { 796 | uint8_t crc[SHA204_CRC_SIZE]; 797 | uint8_t count = response[SHA204_BUFFER_POS_COUNT]; 798 | 799 | count -= SHA204_CRC_SIZE; 800 | sha204c_calculate_crc(count, response, crc); 801 | 802 | return (crc[0] == response[count] && crc[1] == response[count + 1]) ? SHA204_SUCCESS : SHA204_BAD_CRC; 803 | } 804 | --------------------------------------------------------------------------------