Skip to content

Commit 2f5cd12

Browse files
Adding SHA256 implementation
1 parent 352256b commit 2f5cd12

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

src/SparkFun_ATECCX08a_Arduino_Library.cpp

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
*/
2323

2424
#include "SparkFun_ATECCX08a_Arduino_Library.h"
25+
#include <am_util_debug.h>
26+
#define uprintf am_util_debug_printf
2527

2628
/** \brief
2729
@@ -108,7 +110,7 @@ boolean ATECCX08A::wakeUp()
108110
void ATECCX08A::idleMode()
109111
{
110112
_i2cPort->beginTransmission(_i2caddr); // set up to write to address
111-
_i2cPort->write(WORD_ADDRESS_VALUE_IDLE); // enter idle command (aka word address - the first part of every communication to the IC)
113+
_i2cPort->write_byte(WORD_ADDRESS_VALUE_IDLE); // enter idle command (aka word address - the first part of every communication to the IC)
112114
_i2cPort->endTransmission(); // actually send it
113115
}
114116

@@ -452,15 +454,13 @@ long ATECCX08A::random(long min, long max)
452454
It needs length argument:
453455
length: length of data to receive (includes count + DATA + 2 crc bytes)
454456
*/
455-
456457
boolean ATECCX08A::receiveResponseData(uint8_t length, boolean debug)
457458
{
458459

459460
// pull in data 32 bytes at at time. (necessary to avoid overflow on atmega328)
460461
// if length is less than or equal to 32, then just pull it in.
461462
// if length is greater than 32, then we must first pull in 32, then pull in remainder.
462463
// lets use length as our tracker and we will subtract from it as we pull in data.
463-
464464
countGlobal = 0; // reset for each new message (most important, like wensleydale at a cheese party)
465465
cleanInputBuffer();
466466
byte requestAttempts = 0; // keep track of how many times we've attempted to request, to break out if necessary
@@ -481,12 +481,13 @@ boolean ATECCX08A::receiveResponseData(uint8_t length, boolean debug)
481481
requestAmount = length; // now we're ready to pull in the last chunk.
482482
}
483483

484-
_i2cPort->requestFrom(_i2caddr, requestAmount); // request bytes from slave
484+
uint32_t ret = _i2cPort->requestFrom(_i2caddr, requestAmount); // request bytes from slave
485+
485486
requestAttempts++;
486487

487-
while (_i2cPort->available()) // slave may send less than requested
488+
while (_i2cPort->available2()) // slave may send less than requested
488489
{
489-
uint8_t value = _i2cPort->read();
490+
uint8_t value = _i2cPort->read2();
490491

491492
/* Make sure not to read beyond buffer size */
492493
if (countGlobal < sizeof(inputBuffer))
@@ -499,7 +500,7 @@ boolean ATECCX08A::receiveResponseData(uint8_t length, boolean debug)
499500
if (requestAttempts == ATRCC508A_MAX_RETRIES)
500501
break; // this probably means that the device is not responding.
501502
}
502-
503+
#if 0
503504
if (debug)
504505
{
505506
_debugSerial->print("inputBuffer: ");
@@ -510,6 +511,7 @@ boolean ATECCX08A::receiveResponseData(uint8_t length, boolean debug)
510511
}
511512
_debugSerial->println();
512513
}
514+
#endif
513515

514516
return true;
515517
}
@@ -1006,6 +1008,65 @@ boolean ATECCX08A::verifySignature(uint8_t *message, uint8_t *signature, uint8_t
10061008
return err;
10071009
}
10081010

1011+
boolean ATECCX08A::sha256(uint8_t * plain, size_t len, uint8_t * hash)
1012+
{
1013+
int i;
1014+
int j;
1015+
size_t chunks = len / SHA_BLOCK_SIZE + !!(len % SHA_BLOCK_SIZE);
1016+
boolean err = false;
1017+
1018+
if (!sendCommand(COMMAND_OPCODE_SHA, SHA_START, 0))
1019+
goto error;
1020+
1021+
/* Divide into blocks of 64 bytes per chunk */
1022+
for (i = 0; i < chunks; ++i)
1023+
{
1024+
size_t data_size = SHA_BLOCK_SIZE;
1025+
uint8_t chunk[SHA_BLOCK_SIZE];
1026+
1027+
delay(9);
1028+
1029+
if (!receiveResponseData(RESPONSE_COUNT_SIZE + RESPONSE_SIGNAL_SIZE + CRC_SIZE))
1030+
goto error;
1031+
1032+
idleMode();
1033+
1034+
if (!checkCount() || !checkCrc())
1035+
goto error;
1036+
1037+
// If we hear a "0x00", that means it had a successful load
1038+
if (inputBuffer[RESPONSE_SIGNAL_INDEX] != ATRCC508A_SUCCESSFUL_SHA)
1039+
goto error;
1040+
1041+
if ((len % SHA_BLOCK_SIZE) && (i + 1 == chunks))
1042+
data_size = len % SHA_BLOCK_SIZE;
1043+
1044+
/* Send next */
1045+
if (!sendCommand(COMMAND_OPCODE_SHA, (i + 1 != chunks) ? SHA_UPDATE : SHA_END, data_size, plain + i * SHA_BLOCK_SIZE, data_size))
1046+
goto error;
1047+
}
1048+
1049+
/* Read digest */
1050+
delay(9);
1051+
1052+
if (!receiveResponseData(RESPONSE_COUNT_SIZE + RESPONSE_SHA_SIZE + CRC_SIZE))
1053+
goto error;
1054+
1055+
idleMode();
1056+
1057+
if (!checkCount() || !checkCrc())
1058+
goto error;
1059+
1060+
/* Copy digest */
1061+
for (i = 0; i < SHA256_SIZE; ++i)
1062+
{
1063+
hash[i] = inputBuffer[RESPONSE_SHA_INDEX + i];
1064+
}
1065+
1066+
err = true;
1067+
error:
1068+
return err;
1069+
}
10091070
/** \brief
10101071
10111072
writeConfigSparkFun()
@@ -1094,7 +1155,7 @@ boolean ATECCX08A::sendCommand(uint8_t command_opcode, uint8_t param1, uint16_t
10941155
wakeUp();
10951156

10961157
_i2cPort->beginTransmission(_i2caddr);
1097-
_i2cPort->write(total_transmission, total_transmission_length);
1158+
_i2cPort->write2(total_transmission, total_transmission_length);
10981159
_i2cPort->endTransmission();
10991160

11001161
err = true;

src/SparkFun_ATECCX08a_Arduino_Library.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,22 @@
3434
/* Protocol + Cryptographic defines */
3535
#define RESPONSE_COUNT_SIZE 1
3636
#define RESPONSE_SIGNAL_SIZE 1
37+
#define RESPONSE_SHA_SIZE 32
3738
#define RESPONSE_INFO_SIZE 4
3839
#define RESPONSE_RANDOM_SIZE 32
3940
#define CRC_SIZE 2
4041
#define CONFIG_ZONE_SIZE 128
4142
#define SERIAL_NUMBER_SIZE 10
4243

44+
#define SHA256_SIZE 32
4345
#define PUBLIC_KEY_SIZE 64
4446
#define SIGNATURE_SIZE 64
4547
#define BUFFER_SIZE 128
4648

4749
/* Response signals always come after the first count byte */
4850
#define RESPONSE_COUNT_INDEX 0
4951
#define RESPONSE_SIGNAL_INDEX RESPONSE_COUNT_SIZE
52+
#define RESPONSE_SHA_INDEX RESPONSE_COUNT_SIZE
5053
#define RESPONSE_GETINFO_SIGNAL_INDEX (RESPONSE_COUNT_SIZE + 2)
5154

5255
/* Protocol Indices */
@@ -72,6 +75,7 @@
7275
#define ATRCC508A_SUCCESSFUL_TEMPKEY 0x00
7376
#define ATRCC508A_SUCCESSFUL_VERIFY 0x00
7477
#define ATRCC508A_SUCCESSFUL_WRITE 0x00
78+
#define ATRCC508A_SUCCESSFUL_SHA 0x00
7579
#define ATRCC508A_SUCCESSFUL_LOCK 0x00
7680
#define ATRCC508A_SUCCESSFUL_WAKEUP 0x11
7781
#define ATRCC508A_SUCCESSFUL_GETINFO 0x50 /* Revision number */
@@ -119,6 +123,12 @@
119123
// _ _ ? ? ? ? _ _ Bits 5-2 Slot number (in this example, we use slot 0, so "0 0 0 0")
120124
// _ _ _ _ _ _ ? ? Bits 1-0 Zone or locktype. 00=Config, 01=Data/OTP, 10=Single Slot in Data, 11=illegal
121125

126+
// SHA Params
127+
#define SHA_START 0b00000000
128+
#define SHA_UPDATE 0b00000001
129+
#define SHA_END 0b00000010
130+
#define SHA_BLOCK_SIZE 64
131+
122132
#define LOCK_MODE_ZONE_CONFIG 0b10000000
123133
#define LOCK_MODE_ZONE_DATA_AND_OTP 0b10000001
124134
#define LOCK_MODE_SLOT0 0b10000010
@@ -188,6 +198,9 @@ class ATECCX08A {
188198
long random(long max);
189199
long random(long min, long max);
190200

201+
// SHA256
202+
boolean sha256(uint8_t * data, size_t len, uint8_t * hash);
203+
191204
uint8_t crc[CRC_SIZE] = {0, 0};
192205
void atca_calculate_crc(uint8_t length, uint8_t *data);
193206

0 commit comments

Comments
 (0)