diff --git a/examples/ECCX08HMAC/ECCX08HMAC.ino b/examples/ECCX08HMAC/ECCX08HMAC.ino new file mode 100644 index 0000000..935334d --- /dev/null +++ b/examples/ECCX08HMAC/ECCX08HMAC.ino @@ -0,0 +1,78 @@ +/* + ECCX08 HMAC functionality example + + This sketch uses the ECC608 to generate an hmac on some data. + Stores key using nonce. + + Tested on the Arduino Nano RP2040. + + created 10 October 2022 + by Raul Leclair +*/ + +#include + +#define TEMPKEY_SLOT 0xFFFF + +byte nonceKey[] = { + 0x10, 0x10, 0x10, 0x10 +}; + +byte data[] = { + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, +}; + +int dataLength = sizeof(data); + +void setup() { + Serial.begin(115200); + while (!Serial); + + if (!ECCX08.begin()) { + Serial.println("Failed to initialize ECCX08 board."); + while (1); + } + + // Perform nonce + if (!ECCX08.nonce(nonceKey)) + { + Serial.println("Failed to perform nonce."); + while (1); + } + + // Starting HMAC operation on tempkey slot + if (!ECCX08.beginHMAC(TEMPKEY_SLOT)) { + Serial.println("Failed to start HMAC operation."); + while (1); + } + + if (!ECCX08.updateHMAC(data, dataLength)) { + Serial.println("Failed to update HMAC operation."); + while (1); + } + + byte resultHMAC[32]; + if (!ECCX08.endHMAC(resultHMAC)) { + Serial.println("Failed to end HMAC operation"); + while (1); + } + + Serial.println("HMAC Result: "); + for (int i = 0; i < sizeof(resultHMAC); i++) { + char hexChar[2]; + sprintf(hexChar, "%02X", resultHMAC[i]); + Serial.print(hexChar); + Serial.print(" "); + } +} + +void loop() { +} diff --git a/src/ECCX08.cpp b/src/ECCX08.cpp index 6145dd4..a858668 100644 --- a/src/ECCX08.cpp +++ b/src/ECCX08.cpp @@ -440,6 +440,114 @@ int ECCX08Class::lock() return 1; } + +int ECCX08Class::beginHMAC(uint16_t keySlot) +{ + // HMAC implementation is only for ATECC608 + uint8_t status; + long ecc608ver = 0x0600000; + long eccCurrVer = version() & 0x0F00000; + + if (eccCurrVer != ecc608ver) { + return 0; + } + + if (!wakeup()) { + return 0; + } + + if (!sendCommand(0x47, 0x04, keySlot)) { + return 0; + } + + delay(9); + + if (!receiveResponse(&status, sizeof(status))) { + return 0; + } + + delay(1); + idle(); + + if (status != 0) { + return 0; + } + + return 1; +} + +int ECCX08Class::updateHMAC(const byte data[], int length) { + uint8_t status; + + if (!wakeup()) { + return 0; + } + + // Processing message + int currLength = 0; + while (length) { + data += currLength; + + if (length > 64) { + currLength = 64; + } else { + currLength = length; + } + length -= currLength; + + if (!sendCommand(0x47, 0x01, currLength, data, currLength)) { + return 0; + } + + delay(9); + + if (!receiveResponse(&status, sizeof(status))) { + return 0; + } + + delay(1); + } + idle(); + + if (status != 0) { + return 0; + } + + return 1; +} + +int ECCX08Class::endHMAC(byte result[]) +{ + return endHMAC(NULL, 0, result); +} + +int ECCX08Class::endHMAC(const byte data[], int length, byte result[]) +{ + if (!wakeup()) { + return 0; + } + + if (!sendCommand(0x47, 0x02, length, data, length)) { + return 0; + } + + delay(9); + + if (!receiveResponse(result, 32)) { + return 0; + } + + delay(1); + idle(); + + return 1; +} + +int ECCX08Class::nonce(const byte data[]) +{ + return challenge(data); +} + int ECCX08Class::wakeup() { _wire->setClock(_wakeupFrequency); diff --git a/src/ECCX08.h b/src/ECCX08.h index 0439b17..54fdc3a 100644 --- a/src/ECCX08.h +++ b/src/ECCX08.h @@ -59,6 +59,13 @@ class ECCX08Class int readConfiguration(byte data[]); int lock(); + int beginHMAC(uint16_t keySlot); + int updateHMAC(const byte data[], int length); + int endHMAC(byte result[]); + int endHMAC(const byte data[], int length, byte result[]); + + int nonce(const byte data[]); + private: int wakeup(); int sleep();