|
| 1 | +/* |
| 2 | + Using the SparkFun Cryptographic Co-processor Breakout ATECC508a (Qwiic) |
| 3 | + By: Pete Lewis |
| 4 | + SparkFun Electronics |
| 5 | + Date: April 23rd, 2020 |
| 6 | + License: This code is public domain but you can buy me a beer if you use this and we meet someday (Beerware license). |
| 7 | +
|
| 8 | + Feel like supporting our work? Please buy a board from SparkFun! |
| 9 | + https://www.sparkfun.com/products/15573 |
| 10 | +
|
| 11 | + This example shows how to create a hash on larger amounts of data. |
| 12 | + If you have only 32 bytes of data, then you can simply sign the data, |
| 13 | + But if you have more than that, then you mush send your data into an SHA256 algorithm, |
| 14 | + And this will create a 32-byte hash of the data. It's kind of like a signature, but it's created |
| 15 | + with a standard algorithm, and so anyone can make it. The Cryptographic Co-processor will make it |
| 16 | + for us easily in an embedded system. |
| 17 | +
|
| 18 | + Once you have your 32-byte hash of the data, then you can sign that. With this signature of your hash, |
| 19 | + you can authenticate a message that is any length. |
| 20 | +
|
| 21 | + Note, this requires that your device be configured with SparkFun Standard Configuration settings. |
| 22 | + By default, this example uses the private key securely stored and locked in slot 0. |
| 23 | +
|
| 24 | + Hardware Connections and initial setup: |
| 25 | + Install artemis in boards manager: http://boardsmanager/All#Sparkfun_artemis |
| 26 | + Plug in your controller board (e.g. Artemis Redboard, Nano, ATP) into your computer with USB cable. |
| 27 | + Connect your Cryptographic Co-processor to your controller board via a qwiic cable. |
| 28 | + Select TOOLS>>BOARD>>"SparkFun Redboard Artemis" |
| 29 | + Select TOOLS>>PORT>> "COM 3" (note, yours may be different) |
| 30 | + Click upload, and follow along on serial monitor at 115200. |
| 31 | +
|
| 32 | +*/ |
| 33 | + |
| 34 | +#include <SparkFun_ATECCX08a_Arduino_Library.h> //Click here to get the library: http://librarymanager/All#SparkFun_ATECCX08a |
| 35 | +#include <Wire.h> |
| 36 | + |
| 37 | +ATECCX08A atecc; |
| 38 | + |
| 39 | +// array to hold our message. Note, this can be greater than 32 bytes!! |
| 40 | +uint8_t message[] = { |
| 41 | + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
| 42 | + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
| 43 | +}; |
| 44 | + |
| 45 | +// larger example message array, uncomment this to try it out. |
| 46 | +// (don't forget to comment out previous message array) |
| 47 | +//uint8_t message[] = { |
| 48 | +// 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, |
| 49 | +// 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, |
| 50 | +// 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, |
| 51 | +// 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, |
| 52 | +// 0x40 |
| 53 | +//}; |
| 54 | + |
| 55 | +// array to hold our 32-byte hash. |
| 56 | +// Note, it must be 32 bytes, no more or less. |
| 57 | +// Also note, we will start with it blank, but the crypto co-processor will fill it in when we call atecc.sha256() |
| 58 | +uint8_t myHash[32] = { |
| 59 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
| 60 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |
| 61 | +}; |
| 62 | + |
| 63 | + |
| 64 | +void setup() { |
| 65 | + Wire.begin(); |
| 66 | + Serial.begin(115200); |
| 67 | + if (atecc.begin() == true) |
| 68 | + { |
| 69 | + Serial.println("Successful wakeUp(). I2C connections are good."); |
| 70 | + } |
| 71 | + else |
| 72 | + { |
| 73 | + Serial.println("Device not found. Check wiring."); |
| 74 | + while (1); // stall out forever |
| 75 | + } |
| 76 | + |
| 77 | + printInfo(); // see function below for library calls and data handling |
| 78 | + |
| 79 | + // check for configuration |
| 80 | + if (!(atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus)) |
| 81 | + { |
| 82 | + Serial.print("Device not configured. Please use the configuration sketch."); |
| 83 | + while (1); // stall out forever. |
| 84 | + } |
| 85 | + |
| 86 | + printMessage(); // nice debug to see what you're hashing. see function below |
| 87 | + |
| 88 | + //Let's create a hash! |
| 89 | + Serial.println("Creating SHA-256 Hash of data...\n\r"); |
| 90 | + |
| 91 | + atecc.sha256(message, sizeof(message), myHash); // send message and hash pointers |
| 92 | + |
| 93 | + printMyHash(); // nice debug to see your new hash. see function below |
| 94 | +} |
| 95 | + |
| 96 | +void loop() |
| 97 | +{ |
| 98 | + // do nothing. |
| 99 | +} |
| 100 | + |
| 101 | +void printMessage() |
| 102 | +{ |
| 103 | + Serial.println("uint8_t message[] = {"); |
| 104 | + for (int i = 0; i < sizeof(message) ; i++) |
| 105 | + { |
| 106 | + Serial.print("0x"); |
| 107 | + if ((message[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero |
| 108 | + Serial.print(message[i], HEX); |
| 109 | + if (i < (sizeof(message) - 1)) Serial.print(", "); |
| 110 | + if ((31 - i) % 16 == 0) Serial.println(); |
| 111 | + } |
| 112 | + Serial.println("};\n\r"); |
| 113 | +} |
| 114 | + |
| 115 | +void printMyHash() |
| 116 | +{ |
| 117 | + Serial.println("uint8_t myHash[32] = {"); |
| 118 | + for (int i = 0; i < sizeof(myHash) ; i++) |
| 119 | + { |
| 120 | + Serial.print("0x"); |
| 121 | + if ((myHash[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero |
| 122 | + Serial.print(myHash[i], HEX); |
| 123 | + if (i != 31) Serial.print(", "); |
| 124 | + if ((31 - i) % 16 == 0) Serial.println(); |
| 125 | + } |
| 126 | + Serial.println("};"); |
| 127 | +} |
| 128 | + |
| 129 | +void printInfo() |
| 130 | +{ |
| 131 | + // Read all 128 bytes of Configuration Zone |
| 132 | + // These will be stored in an array within the instance named: atecc.configZone[128] |
| 133 | + atecc.readConfigZone(false); // Debug argument false (OFF) |
| 134 | + |
| 135 | + // Print useful information from configuration zone data |
| 136 | + Serial.println(); |
| 137 | + |
| 138 | + Serial.print("Serial Number: \t"); |
| 139 | + for (int i = 0 ; i < 9 ; i++) |
| 140 | + { |
| 141 | + if ((atecc.serialNumber[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero |
| 142 | + Serial.print(atecc.serialNumber[i], HEX); |
| 143 | + } |
| 144 | + Serial.println(); |
| 145 | + |
| 146 | + Serial.print("Rev Number: \t"); |
| 147 | + for (int i = 0 ; i < 4 ; i++) |
| 148 | + { |
| 149 | + if ((atecc.revisionNumber[i] >> 4) == 0) Serial.print("0"); // print preceeding high nibble if it's zero |
| 150 | + Serial.print(atecc.revisionNumber[i], HEX); |
| 151 | + } |
| 152 | + Serial.println(); |
| 153 | + |
| 154 | + Serial.print("Config Zone: \t"); |
| 155 | + if (atecc.configLockStatus) Serial.println("Locked"); |
| 156 | + else Serial.println("NOT Locked"); |
| 157 | + |
| 158 | + Serial.print("Data/OTP Zone: \t"); |
| 159 | + if (atecc.dataOTPLockStatus) Serial.println("Locked"); |
| 160 | + else Serial.println("NOT Locked"); |
| 161 | + |
| 162 | + Serial.print("Data Slot 0: \t"); |
| 163 | + if (atecc.slot0LockStatus) Serial.println("Locked"); |
| 164 | + else Serial.println("NOT Locked"); |
| 165 | + |
| 166 | + Serial.println(); |
| 167 | + |
| 168 | + // if everything is locked up, then configuration is complete, so let's print the public key |
| 169 | + if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) |
| 170 | + { |
| 171 | + if (atecc.generatePublicKey() == false) |
| 172 | + { |
| 173 | + Serial.println("Failure to generate this device's Public Key"); |
| 174 | + Serial.println(); |
| 175 | + } |
| 176 | + } |
| 177 | +} |
0 commit comments