Add Atmel CryptoAuthLib to extras
This is Atmel/Microchip's official library for interfacing to the Atmel ATECC508 chip. The submodule points to their repository in GitHub. Additionally, this includes the HAL necessary to use this library in esp_open_rtos using the i2c library in extras/i2c. I have also included a tool I wrote to play with the chip as an example under examples/atcatool. The extras module currently overrides atca_iface.h to fix bug in cryptoauthlib (c11-only feature, which breaks c++ builds that want to use cryptoauthlib)
This commit is contained in:
parent
8f378b41c8
commit
e66e87aa8e
18 changed files with 1466 additions and 0 deletions
12
examples/atcatool/FreeRTOSConfig.h
Normal file
12
examples/atcatool/FreeRTOSConfig.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* Terminal FreeRTOSConfig overrides.
|
||||
|
||||
This is intended as an example of overriding some of the default FreeRTOSConfig settings,
|
||||
which are otherwise found in FreeRTOS/Source/include/FreeRTOSConfig.h
|
||||
*/
|
||||
|
||||
/* The serial driver depends on counting semaphores */
|
||||
#define configUSE_COUNTING_SEMAPHORES 1
|
||||
|
||||
/* Use the defaults for everything else */
|
||||
#include_next<FreeRTOSConfig.h>
|
||||
|
5
examples/atcatool/Makefile
Normal file
5
examples/atcatool/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
|||
PROGRAM=atcatool
|
||||
EXTRA_COMPONENTS=extras/stdin_uart_interrupt extras/i2c extras/cryptoauthlib
|
||||
EXTRA_CFLAGS += -DATCAPRINTF
|
||||
ATEC_PRINTF_ENABLE = 1
|
||||
include ../../common.mk
|
56
examples/atcatool/cmd_ecdh.c
Normal file
56
examples/atcatool/cmd_ecdh.c
Normal file
|
@ -0,0 +1,56 @@
|
|||
|
||||
#include "uart_cmds.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
ATCA_STATUS cmd_ecdh(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num > 0x7){
|
||||
LOG("Invalid slot number %d; must be between 0 and 7 for private keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
printf("Performing ECDH key exchange in slot %d\n", slot_num);
|
||||
uint8_t pubkeybytes[100];
|
||||
int pubkeylen = sizeof(pubkeybytes);
|
||||
status = read_pubkey_stdin(pubkeybytes, &pubkeylen);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to read public key");
|
||||
}
|
||||
|
||||
LOG("Got valid looking pubkey; does this look correct?");
|
||||
uint8_t *keyptr = pubkeybytes + (pubkeylen - ATCA_PUB_KEY_SIZE);
|
||||
atcab_printbin_label((const uint8_t*)"pubkey ", keyptr, ATCA_PUB_KEY_SIZE);
|
||||
|
||||
if (!prompt_user()) {
|
||||
printf("Aborting\n");
|
||||
}else{
|
||||
printf("Performing ECDH key exchange\n");
|
||||
}
|
||||
|
||||
// Write key to device
|
||||
uint8_t pmk[ATCA_PRIV_KEY_SIZE];
|
||||
status = atcab_ecdh(slot_num, keyptr, pmk);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Failed to obtain pre-master key");
|
||||
}
|
||||
atcab_printbin_label((const uint8_t*)"pmk ", pmk, ATCA_PRIV_KEY_SIZE);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
91
examples/atcatool/cmd_priv.c
Normal file
91
examples/atcatool/cmd_priv.c
Normal file
|
@ -0,0 +1,91 @@
|
|||
|
||||
#include "uart_cmds.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
// get cert and priv key
|
||||
//> openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp256r1) -keyout cert.key -out cert.crt -days 3650
|
||||
|
||||
//#define PEM_PRIV_KEY_OFFSET 5
|
||||
#define PEM_PRIV_KEY_OFFSET 7
|
||||
|
||||
ATCA_STATUS cmd_priv(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num > 0x7){
|
||||
LOG("Invalid slot number %d; must be between 0 and 7 for private keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
uint8_t write_key_slot = 0;
|
||||
uint8_t *write_key = NULL;
|
||||
uint8_t random_num[RANDOM_NUM_SIZE];
|
||||
if (argc >= 3) {
|
||||
write_key_slot = atoi(argv[2]);
|
||||
if (write_key_slot == slot_num || write_key_slot < 0x0 || write_key_slot > 0xF) {
|
||||
LOG("Invalid slot for write key (%d); trying unencrypted write", (int)write_key_slot);
|
||||
write_key_slot = 0;
|
||||
write_key = NULL;
|
||||
} else {
|
||||
LOG("Writing write key to slot %d", (int)write_key_slot);
|
||||
if((status = atcab_random(random_num)) != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not make random number");
|
||||
}
|
||||
write_key = random_num;
|
||||
if((status = atcab_write_bytes_zone(ATCA_ZONE_DATA, write_key_slot, 0, write_key, RANDOM_NUM_SIZE)) != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not commit write key");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Programming private key in slot %d\n", slot_num);
|
||||
uint8_t privkeybytes[200];
|
||||
int privkeylen = sizeof(privkeybytes);
|
||||
status = read_privkey_stdin(privkeybytes, &privkeylen);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to read private key");
|
||||
}
|
||||
|
||||
LOG("Got valid looking private key; does this look correct?");
|
||||
uint8_t *keyptr = privkeybytes + PEM_PRIV_KEY_OFFSET;
|
||||
atcab_printbin_label((const uint8_t*)"privkey ", keyptr, ATCA_PRIV_KEY_SIZE);
|
||||
|
||||
if (!prompt_user()) {
|
||||
printf("Aborting\n");
|
||||
return ATCA_SUCCESS;
|
||||
}else{
|
||||
printf("Writing key\n");
|
||||
}
|
||||
|
||||
// Write key to device
|
||||
uint8_t priv_key[ATCA_PRIV_KEY_SIZE + 4] = {0};
|
||||
memcpy(priv_key + 4, keyptr, ATCA_PRIV_KEY_SIZE);
|
||||
status = atcab_priv_write(slot_num, priv_key, write_key_slot, write_key);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Failed to write key to slot");
|
||||
}
|
||||
|
||||
// Read public key
|
||||
uint8_t pub_key[ATCA_PUB_KEY_SIZE] = {0};
|
||||
if((status = atcab_get_pubkey(slot_num, pub_key)) != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not get public key");
|
||||
}
|
||||
atcab_printbin_label((const uint8_t*)"pubkey ", pub_key, sizeof(pub_key));
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
59
examples/atcatool/cmd_pub.c
Normal file
59
examples/atcatool/cmd_pub.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
#include "uart_cmds.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
// get cert and priv key
|
||||
//> openssl req -new -x509 -nodes -newkey ec:<(openssl ecparam -name secp256r1) -keyout cert.key -out cert.crt -days 3650
|
||||
// get pub key
|
||||
//> openssl x509 -in cert.crt -pubkey -noout > pubkey.pem
|
||||
|
||||
ATCA_STATUS cmd_pub(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num < 0x8 || slot_num > 0xF){
|
||||
LOG("Invalid slot number %d; must be between 8 and 15 for public keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
printf("Programming public key in slot %d\n", slot_num);
|
||||
uint8_t pubkeybytes[100];
|
||||
int pubkeylen = sizeof(pubkeybytes);
|
||||
status = read_pubkey_stdin(pubkeybytes, &pubkeylen);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to read public key");
|
||||
}
|
||||
|
||||
LOG("Got valid looking pubkey; does this look correct?");
|
||||
uint8_t *keyptr = pubkeybytes + (pubkeylen - ATCA_PUB_KEY_SIZE);
|
||||
atcab_printbin_label((const uint8_t*)"pubkey ", keyptr, ATCA_PUB_KEY_SIZE);
|
||||
|
||||
if (!prompt_user()) {
|
||||
printf("Aborting\n");
|
||||
}else{
|
||||
printf("Writing key\n");
|
||||
}
|
||||
|
||||
// Write key to device
|
||||
status = atcab_write_pubkey(slot_num, keyptr);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Failed to write key to slot");
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
97
examples/atcatool/cmd_verify.c
Normal file
97
examples/atcatool/cmd_verify.c
Normal file
|
@ -0,0 +1,97 @@
|
|||
|
||||
#include "uart_cmds.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
// make test hash
|
||||
//> openssl sha -sha256 cmd_pub.c
|
||||
// sign test hash
|
||||
//> openssl sha -sha256 -sign cert.key -hex cmd_pub.c
|
||||
|
||||
void get_line(char *buf, size_t buflen)
|
||||
{
|
||||
char ch;
|
||||
char cmd[200];
|
||||
int i = 0;
|
||||
while(1) {
|
||||
if (read(0, (void*)&ch, 1)) { // 0 is stdin
|
||||
printf("%c", ch);
|
||||
if (ch == '\n' || ch == '\r') {
|
||||
cmd[i] = 0;
|
||||
i = 0;
|
||||
printf("\n");
|
||||
strcpy(buf, cmd);
|
||||
return;
|
||||
} else {
|
||||
if (i < sizeof(cmd)) cmd[i++] = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ATCA_STATUS cmd_verify(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num < 0x8 || slot_num > 0xF){
|
||||
LOG("Invalid slot number %d; must be between 8 and 15 for public keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
printf("Verifying with public key in slot %d\n", slot_num);
|
||||
char hash[100]; uint8_t hashbin[100]; int hashlen = sizeof(hashbin);
|
||||
char sig[200]; uint8_t sigbin[200]; int siglen = sizeof(sigbin);
|
||||
|
||||
printf("Please paste hash in the terminal (hex format)\n");
|
||||
get_line(hash, sizeof(hash));
|
||||
|
||||
status = atcab_hex2bin(hash, strlen(hash), hashbin, &hashlen);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not parse hash hex");
|
||||
}
|
||||
|
||||
printf("Please paste signature in the terminal (hex format)\n");
|
||||
get_line(sig, sizeof(sig));
|
||||
|
||||
status = atcab_hex2bin(sig, strlen(sig), sigbin, &siglen);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not parse signature hex");
|
||||
}
|
||||
|
||||
bool isVerified = false;
|
||||
printf("Trying to verify with\n");
|
||||
atcab_printbin_label((const uint8_t*)"hash ", hashbin, hashlen);
|
||||
printf("Len %d\n", hashlen);
|
||||
atcab_printbin_label((const uint8_t*)"sig ", sigbin, siglen);
|
||||
printf("Len %d\n", siglen);
|
||||
|
||||
uint8_t atca_sig[ATCA_SIG_SIZE] = {0};
|
||||
if(!parse_asn1_signature(sigbin, siglen, atca_sig))
|
||||
{
|
||||
RETURN(ATCA_PARSE_ERROR, "Could not parse ASN.1 signature");
|
||||
}
|
||||
|
||||
atcab_printbin_label((const uint8_t*)"atca_sig ", atca_sig, ATCA_SIG_SIZE);
|
||||
printf("Len %d\n", ATCA_SIG_SIZE);
|
||||
|
||||
status = atcab_verify_stored(hashbin, atca_sig, slot_num, &isVerified);
|
||||
if(status != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not verify signature");
|
||||
}
|
||||
|
||||
printf(isVerified ? "Signature is valid\n" : "Signature is invalid\n");
|
||||
RETURN(status, "Done");
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
168
examples/atcatool/cmdutility.c
Normal file
168
examples/atcatool/cmdutility.c
Normal file
|
@ -0,0 +1,168 @@
|
|||
|
||||
#include "uart_cmds.h"
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#define RETURN_BOOL(result, message) {printf(": " message "\r\n"); return result;}
|
||||
|
||||
ATCA_STATUS read_key_stdin(const char* beginConst, const char* endConst, uint8_t *keyOut, int *len)
|
||||
{
|
||||
printf("Please paste key in the terminal (PEM format)\n");
|
||||
|
||||
char ch;
|
||||
char cmd[81];
|
||||
int i = 0;
|
||||
bool done = false;
|
||||
uint8_t keybuf[1000] = {0}; // max buffer we should need
|
||||
int buf_used = 0;
|
||||
while (!done && buf_used < (sizeof(keybuf) - 1))
|
||||
{
|
||||
if (read(0, (void *)&ch, 1))
|
||||
{ // 0 is stdin
|
||||
printf("%c", ch);
|
||||
if (ch == '\n' || ch == '\r')
|
||||
{
|
||||
cmd[i] = 0;
|
||||
printf("\n");
|
||||
// check for end of public key
|
||||
if (!strcmp(endConst, cmd))
|
||||
{
|
||||
done = true;
|
||||
printf("Got end of public key\n");
|
||||
}
|
||||
else if (strcmp(beginConst, cmd))
|
||||
{
|
||||
// only copy non-marker text
|
||||
strcat((char *)keybuf, cmd);
|
||||
buf_used += i;
|
||||
}
|
||||
i = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (i < sizeof(cmd))
|
||||
cmd[i++] = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try to parse
|
||||
uint8_t keybytes[(sizeof(keybuf) * 3) / 4];
|
||||
size_t arrayLen = sizeof(keybytes);
|
||||
ATCA_STATUS status = atcab_base64decode((const char *)keybuf, sizeof(keybuf), keybytes, &arrayLen);
|
||||
if(status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Error decoding base64 public key");
|
||||
}
|
||||
else if (arrayLen > *len)
|
||||
{
|
||||
LOG("Key was the wrong size (%d); expected at most %d", arrayLen, *len);
|
||||
atcab_printbin_label((const uint8_t*)"decoded ", keybytes, arrayLen);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
memcpy(keyOut, keybytes, arrayLen);
|
||||
*len = arrayLen;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
ATCA_STATUS read_pubkey_stdin(uint8_t *keyOut, int *len)
|
||||
{
|
||||
return read_key_stdin(BEGIN_PUB_KEY_CONST, END_PUB_KEY_CONST, keyOut, len);
|
||||
}
|
||||
|
||||
ATCA_STATUS read_privkey_stdin(uint8_t *keyOut, int *len)
|
||||
{
|
||||
return read_key_stdin(BEGIN_PRIV_KEY_CONST, END_PRIV_KEY_CONST, keyOut, len);
|
||||
}
|
||||
|
||||
bool prompt_user()
|
||||
{
|
||||
printf("(y/n)\n");
|
||||
char ch = 0;
|
||||
while(ch != 'y' && ch != 'n') {
|
||||
if (read(0, (void*)&ch, 1)) { // 0 is stdin
|
||||
//NOP
|
||||
}
|
||||
}
|
||||
|
||||
return ch == 'y';
|
||||
}
|
||||
|
||||
bool parse_asn1_signature(uint8_t *asn1Sig, size_t asn1SigLen, uint8_t signatureRintSintOUT[ATCA_SIG_SIZE])
|
||||
{
|
||||
if (asn1Sig == NULL || asn1SigLen < sizeof(signatureRintSintOUT)) return false;
|
||||
|
||||
// Parse ASN.1. We expect the following output:
|
||||
// 0x30 0xXX <--0x30 = sequence; 0xXX num bytes in sequence
|
||||
// 0x02 0xYY <--0x02 = integer (R); 0xYY num bytes in R integer (2's complement)
|
||||
// ... ... <-- YY bytes of R integer
|
||||
// 0x02 0xZZ <--0x02 = integer (S); 0xZZ num bytes in S integer (2's complement)
|
||||
// ... ... <-- ZZ bytes of S integer
|
||||
const uint8_t halfSigSize = ATCA_SIG_SIZE / 2;
|
||||
uint8_t *atca_sig_ptr = signatureRintSintOUT;
|
||||
if (asn1Sig[0] != 0x30)
|
||||
{ // sequence
|
||||
RETURN_BOOL(false, "Expected sequence code (0x30) at position 0");
|
||||
}
|
||||
uint8_t seq_len = asn1Sig[1];
|
||||
if (seq_len < ATCA_SIG_SIZE)
|
||||
{ // sanity check
|
||||
RETURN_BOOL(false, "Sequence does not seem to be long enough for a signature");
|
||||
}
|
||||
if (asn1Sig[2] != 0x02)
|
||||
{ // integer
|
||||
RETURN_BOOL(false, "Expected integer code (0x02) at position 2 (R integer)");
|
||||
}
|
||||
// Get R integer
|
||||
uint8_t r_len = asn1Sig[3];
|
||||
uint8_t *int_ptr = &asn1Sig[4];
|
||||
if (r_len < halfSigSize)
|
||||
{
|
||||
atca_sig_ptr += (halfSigSize - r_len);
|
||||
}
|
||||
else if (r_len > halfSigSize)
|
||||
{
|
||||
int_ptr += (r_len - halfSigSize);
|
||||
r_len = halfSigSize;
|
||||
}
|
||||
memcpy(atca_sig_ptr, int_ptr, r_len); // <--insert R integer into output
|
||||
atca_sig_ptr += r_len;
|
||||
int_ptr += r_len;
|
||||
// more checks
|
||||
if (*int_ptr++ != 0x02)
|
||||
{ // integer
|
||||
RETURN_BOOL(false, "Expected integer code (0x02) at next position (S integer)");
|
||||
}
|
||||
// Get S integer
|
||||
uint8_t s_len = *int_ptr++;
|
||||
if (s_len < halfSigSize)
|
||||
{
|
||||
atca_sig_ptr += (halfSigSize - s_len);
|
||||
}
|
||||
else if (s_len > halfSigSize)
|
||||
{
|
||||
int_ptr += (s_len - halfSigSize);
|
||||
s_len = halfSigSize;
|
||||
}
|
||||
memcpy(atca_sig_ptr, int_ptr, s_len); // <--insert S integer into output
|
||||
return true;
|
||||
}
|
||||
|
||||
void print_b64_pubkey(uint8_t pubkey[ATCA_PUB_KEY_SIZE])
|
||||
{
|
||||
char b64pubkey[100] = {0};
|
||||
size_t b64len = sizeof(b64pubkey);
|
||||
atcab_base64encode(pubkey, ATCA_PUB_KEY_SIZE, b64pubkey, &b64len);
|
||||
printf(BEGIN_PUB_KEY_CONST"\r\n");
|
||||
printf(b64pubkey);
|
||||
printf("\r\n"END_PUB_KEY_CONST"\r\n");
|
||||
}
|
245
examples/atcatool/pubkeyprog.c
Normal file
245
examples/atcatool/pubkeyprog.c
Normal file
|
@ -0,0 +1,245 @@
|
|||
/* pubkeyprog
|
||||
* Program public keys in the ATCA over UART
|
||||
* UART RX is interrupt driven
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <esp8266.h>
|
||||
#include <esp/uart.h>
|
||||
#include <stdio.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include "i2c/i2c.h"
|
||||
#include "cryptoauthlib_init.h"
|
||||
#include <cryptoauthlib.h>
|
||||
|
||||
#include "uart_cmds.h"
|
||||
|
||||
static ATCA_STATUS cmd_cfg(uint32_t argc, char *argv[])
|
||||
{
|
||||
uint8_t configData[ATCA_ECC_CONFIG_SIZE];
|
||||
ATCA_STATUS status = atcab_read_config_zone(configData);
|
||||
if(status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to retrieve config data");
|
||||
}
|
||||
|
||||
printf("Got config data:\n");
|
||||
atcab_printbin(configData, sizeof(configData), true);
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_otp(uint32_t argc, char *argv[])
|
||||
{
|
||||
uint8_t otpData[ATCA_OTP_SIZE];
|
||||
ATCA_STATUS status = atcab_read_bytes_zone(ATCA_ZONE_OTP, 0, 0, otpData, sizeof(otpData));
|
||||
if(status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to retrieve OTP data");
|
||||
}
|
||||
|
||||
printf("Got OTP data:\n");
|
||||
atcab_printbin(otpData, sizeof(otpData), true);
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
// Copied from unit tests
|
||||
uint8_t test_ecc_configdata[ATCA_ECC_CONFIG_SIZE] = {
|
||||
0x01, 0x23, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x04, 0x05, 0x06, 0x07, 0xEE, 0x00, 0x01, 0x00,
|
||||
0xC0, 0x00, 0x55, 0x00, 0x8F, 0x2F, 0xC4, 0x44, 0x87, 0x20, 0xC4, 0xF4, 0x8F, 0x0F, 0x8F, 0x8F,
|
||||
0x9F, 0x8F, 0x83, 0x64, 0xC4, 0x44, 0xC4, 0x64, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||
0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x33, 0x00, 0x1C, 0x00, 0x13, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0x33, 0x00,
|
||||
0x1C, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x30, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x32, 0x00, 0x30, 0x00
|
||||
};
|
||||
uint8_t g_otp_data[ATCA_OTP_SIZE] = "This is test data that can be read back out of the chip!huzzah!";
|
||||
|
||||
static ATCA_STATUS cmd_cfgwrite(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status = atcab_write_config_zone(test_ecc_configdata);
|
||||
if(status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to write ECC config data");
|
||||
}
|
||||
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_otpwrite(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status = atcab_write_bytes_zone(ATCA_ZONE_OTP, 0, 0, g_otp_data, ATCA_OTP_SIZE);
|
||||
if(status != ATCA_SUCCESS)
|
||||
{
|
||||
RETURN(status, "Failed to write OTP data");
|
||||
}
|
||||
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_cfglock(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status = atcab_lock_config_zone();
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
printf("Failed!\n");
|
||||
}
|
||||
|
||||
printf("Config Locked!\n");
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_otplock(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status = atcab_lock_data_zone();
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
printf("Failed!\n");
|
||||
}
|
||||
|
||||
printf("OTP Locked!\n");
|
||||
RETURN(status, "Done");
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_gen(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num > 0x7){
|
||||
LOG("Invalid slot number %d; must be between 0 and 7 for private keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
uint8_t pubkey[ATCA_PUB_KEY_SIZE] = {0};
|
||||
if ((status = atcab_genkey(slot_num, pubkey)) != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not generate private key");
|
||||
}
|
||||
|
||||
atcab_printbin_label("publickey ", pubkey, sizeof(pubkey));
|
||||
print_b64_pubkey(pubkey);
|
||||
RETURN(status, "Done");
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
static ATCA_STATUS cmd_getpub(uint32_t argc, char *argv[])
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
if (argc >= 2) {
|
||||
uint8_t slot_num = atoi(argv[1]);
|
||||
if (slot_num > 0x7){
|
||||
LOG("Invalid slot number %d; must be between 0 and 7 for private keys", slot_num);
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
uint8_t pubkey[ATCA_PUB_KEY_SIZE] = {0};
|
||||
if ((status = atcab_get_pubkey(slot_num, pubkey)) != ATCA_SUCCESS){
|
||||
RETURN(status, "Could not read/generate public key");
|
||||
}
|
||||
|
||||
atcab_printbin_label("publickey ", pubkey, sizeof(pubkey));
|
||||
print_b64_pubkey(pubkey);
|
||||
RETURN(status, "Done");
|
||||
} else {
|
||||
printf("Error: missing slot number.\n");
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_help(uint32_t argc, char *argv[])
|
||||
{
|
||||
printf("pub <slot number> Program public key to a slot\n");
|
||||
printf("priv <slot number> [slot number] Program private key to a slot using optional write key\n");
|
||||
printf("cfg Dump config\n");
|
||||
printf("otp Dump OTP zone\n");
|
||||
printf("verify <slot number> Verify signature with public key in slot\n");
|
||||
printf("cfgwrite Write test configuration\n");
|
||||
printf("otpwrite Write test OTP\n");
|
||||
printf("cfglock Lock config zone (not reversible!)\n");
|
||||
printf("otplock Lock OTP zone (not reversible!)\n");
|
||||
printf("gen <slot number> Generate private key in a slot\n");
|
||||
printf("getpub <slot number> Read/gen a public key from a private key slot\n");
|
||||
printf("ecdh <slot number> Perform ECDH key exchange in slot\n");
|
||||
printf("\nExample:\n");
|
||||
printf(" pub 12<enter> initiates public key programming in slot 12\n");
|
||||
}
|
||||
|
||||
static void handle_command(char *cmd)
|
||||
{
|
||||
char *argv[MAX_ARGC];
|
||||
int argc = 1;
|
||||
char *temp, *rover;
|
||||
memset((void*) argv, 0, sizeof(argv));
|
||||
argv[0] = cmd;
|
||||
rover = cmd;
|
||||
// Split string "<command> <argument 1> <argument 2> ... <argument N>"
|
||||
// into argv, argc style
|
||||
while(argc < MAX_ARGC && (temp = strstr(rover, " "))) {
|
||||
rover = &(temp[1]);
|
||||
argv[argc++] = rover;
|
||||
*temp = 0;
|
||||
}
|
||||
|
||||
if (strlen(argv[0]) > 0) {
|
||||
if (strcmp(argv[0], "help") == 0) cmd_help(argc, argv);
|
||||
else if (strcmp(argv[0], "pub") == 0) cmd_pub(argc, argv);
|
||||
else if (strcmp(argv[0], "priv") == 0) cmd_priv(argc, argv);
|
||||
else if (strcmp(argv[0], "cfg") == 0) cmd_cfg(argc, argv);
|
||||
else if (strcmp(argv[0], "otp") == 0) cmd_otp(argc, argv);
|
||||
else if (strcmp(argv[0], "verify") == 0) cmd_verify(argc, argv);
|
||||
else if (strcmp(argv[0], "cfgwrite") == 0) cmd_cfgwrite(argc, argv);
|
||||
else if (strcmp(argv[0], "otpwrite") == 0) cmd_otpwrite(argc, argv);
|
||||
else if (strcmp(argv[0], "cfglock") == 0) cmd_cfglock(argc, argv);
|
||||
else if (strcmp(argv[0], "otplock") == 0) cmd_otplock(argc, argv);
|
||||
else if (strcmp(argv[0], "gen") == 0) cmd_gen(argc, argv);
|
||||
else if (strcmp(argv[0], "getpub") == 0) cmd_getpub(argc, argv);
|
||||
else if (strcmp(argv[0], "ecdh") == 0) cmd_ecdh(argc, argv);
|
||||
else printf("Unknown command %s, try 'help'\n", argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void pubkeyprog_task(void *pvParameters)
|
||||
{
|
||||
char ch;
|
||||
char cmd[81];
|
||||
int i = 0;
|
||||
|
||||
init_cryptoauthlib(0x60);
|
||||
|
||||
printf("\n\n\nWelcome to atcatool. Type 'help<enter>' for, well, help\n");
|
||||
printf("%% ");
|
||||
while(1) {
|
||||
if (read(0, (void*)&ch, 1)) { // 0 is stdin
|
||||
printf("%c", ch);
|
||||
if (ch == '\n' || ch == '\r') {
|
||||
cmd[i] = 0;
|
||||
i = 0;
|
||||
printf("\n");
|
||||
handle_command((char*) cmd);
|
||||
printf("%% ");
|
||||
} else {
|
||||
if (i < sizeof(cmd)) cmd[i++] = ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define I2C_BUS (0)
|
||||
#define SDA_PIN (4)
|
||||
#define SCL_PIN (5)
|
||||
|
||||
void user_init(void)
|
||||
{
|
||||
uart_set_baud(0, 115200);
|
||||
i2c_init(I2C_BUS, SCL_PIN, SDA_PIN, I2C_FREQ_500K);
|
||||
xTaskCreate(&pubkeyprog_task, "pubkeyprog_task", 2048, NULL, 2, NULL);
|
||||
}
|
24
examples/atcatool/uart_cmds.h
Normal file
24
examples/atcatool/uart_cmds.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
|
||||
#include <cryptoauthlib.h>
|
||||
|
||||
#define MAX_ARGC (10)
|
||||
#define LOG(...) printf(__VA_ARGS__); printf("\r\n");
|
||||
#define LOG_SUCCESSFAIL(name, oper) if((oper) == ATCA_SUCCESS) { LOG("%s succeeded!\n", name); } else { LOG("%s failed!", name); }
|
||||
|
||||
#define BEGIN_PUB_KEY_CONST "-----BEGIN PUBLIC KEY-----"
|
||||
#define END_PUB_KEY_CONST "-----END PUBLIC KEY-----"
|
||||
|
||||
#define BEGIN_PRIV_KEY_CONST "-----BEGIN EC PRIVATE KEY-----"
|
||||
#define END_PRIV_KEY_CONST "-----END EC PRIVATE KEY-----"
|
||||
|
||||
ATCA_STATUS cmd_pub(uint32_t argc, char *argv[]);
|
||||
ATCA_STATUS cmd_priv(uint32_t argc, char *argv[]);
|
||||
ATCA_STATUS cmd_verify(uint32_t argc, char *argv[]);
|
||||
ATCA_STATUS cmd_ecdh(uint32_t argc, char *argv[]);
|
||||
|
||||
// Utility
|
||||
ATCA_STATUS read_pubkey_stdin(uint8_t *keyOut, int *len);
|
||||
ATCA_STATUS read_privkey_stdin(uint8_t *keyOut, int *len);
|
||||
bool prompt_user();
|
||||
bool parse_asn1_signature(uint8_t *asn1Sig, size_t asn1SigLen, uint8_t signatureRintSintOUT[ATCA_SIG_SIZE]);
|
||||
void print_b64_pubkey(uint8_t pubkey[ATCA_PUB_KEY_SIZE]);
|
Loading…
Add table
Add a link
Reference in a new issue