Skip to content
This repository was archived by the owner on Jul 22, 2023. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions examples/common/atecc_get_pubkey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3

"""Tool to pull public keys from Microchip ATECC* secure element.

Dependencies installation:
pip install cryptoauthlib ecdsa

Usage example:
$ python atecc_get_pubkey.py --slot 2
"""

from cryptoauthlib import *
from ecdsa import VerifyingKey
from ecdsa.curves import NIST256p

ATCA_SUCCESS = 0x00


def key_to_pem(key_raw):
k = VerifyingKey.from_string(key_raw, curve=NIST256p)
return k.to_pem()

def hex_str(bytearray):
return ''.join(format(x, '02X') for x in bytearray)

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser(description='Get the public key from a slot')
parser.add_argument('slot', type=int, help='Slot ID')
args = parser.parse_args()

load_cryptoauthlib()
assert ATCA_SUCCESS == atcab_init(cfg_ateccx08a_kithid_default())

key = bytearray(64)
assert ATCA_SUCCESS == atcab_get_pubkey(args.slot, key)
print("Public key from slot %d: %s" % (args.slot, hex_str(key)))
print()
print("In PEM format:\n%s" % key_to_pem(key).decode())
25 changes: 21 additions & 4 deletions examples/common/rules.mk
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ IOTC_FLAGS_INCLUDE += $(foreach i,$(IOTC_CLIENT_INC_PATH),-I$i)

IOTC_FLAGS_COMPILER ?= -Wall -Werror -Wno-pointer-arith -Wno-format -fstrict-aliasing -Os -Wextra

# -lm is only needed by linux
# -lpthread only if both linux and multithreading is enabled in the
# Google Cloud IoT Device SDK Client at compile time
IOTC_FLAGS_LINKER := -L$(IOTC_CLIENT_LIB_PATH) -liotc -lm -lpthread

# TLS BSP related configuration
IOTC_BSP_TLS ?= mbedtls

Expand All @@ -58,9 +63,21 @@ ifneq ("$(IOTC_BSP_TLS)", "")

TLS_LIB_CONFIG_FLAGS := -L$(addprefix $(IOTC_CLIENT_PATH),$(IOTC_TLS_LIB_DIR))
TLS_LIB_CONFIG_FLAGS += $(foreach d, $(IOTC_TLS_LIB_NAME), -l$d)
IOTC_FLAGS_LINKER += $(TLS_LIB_CONFIG_FLAGS)
endif

# -lm is only needed by linux
# -lpthread only if both linux and multithreading is enabled in the
# Google Cloud IoT EmbeddedC Client at compile time
IOTC_FLAGS_LINKER := -L$(IOTC_CLIENT_LIB_PATH) -liotc -lpthread $(TLS_LIB_CONFIG_FLAGS) -lm
# Crypto BSP related configuration
IOTC_BSP_CRYPTO ?= mbedtls

ifeq ("$(IOTC_BSP_CRYPTO)", "cryptoauthlib")
IOTC_FLAGS_INCLUDE += -I$(addprefix $(IOTC_CLIENT_PATH), third_party/cryptoauthlib/lib)
CRYPTO_LIB_CONFIG_FLAGS := -L$(addprefix $(IOTC_CLIENT_PATH), third_party/cryptoauthlib/build)
CRYPTO_LIB_CONFIG_FLAGS += -lcryptoauth
IOTC_FLAGS_LINKER += $(CRYPTO_LIB_CONFIG_FLAGS)

# For a secure element connected via USB
IOTC_FLAGS_LINKER += -ludev -lusb -lusb-1.0

# For selectively enabling Cryptoauthlib in the examples
IOTC_FLAGS_COMPILER += -DENABLE_CRYPTOAUTHLIB=1
endif
23 changes: 22 additions & 1 deletion examples/common/src/commandline.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,22 @@ const char* iotc_publish_topic;
const char* iotc_publish_message;
const char* iotc_private_key_filename;

#ifdef ENABLE_CRYPTOAUTHLIB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So if cryptoauthlib is enabled, then private_key_filename is not necessary. So we could go with the ugly:

#ifdef XXX
#else 
#endif

pattern with all places.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we handle this with slack? Use all variables and all commandline arguments for each configuration. Although this won't be full correct: since one could ask "Why do you allow to pass both a private key filename and a slotid at the same time?" The answer is because of code simplicity. And we trust our users know what they do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we go with the slack version then most of the #ifdef can be removed easing the reader's job, keeping code simpler, easier to maintain.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

e.g. all #ifdefs can go away in this file if we decide so.

uint8_t iotc_private_key_slot;
#endif

int iotc_parse(int argc, char** argv, char* valid_options,
unsigned options_length) {
int c;
int iotc_help_flag = 0;
iotc_project_id = NULL;
iotc_device_path = NULL;
iotc_publish_topic = NULL;
iotc_private_key_filename = DEFAULT_PRIVATE_KEY_FIILENAME;
iotc_publish_message = "Hello From Your IoTC client!";
iotc_private_key_filename = DEFAULT_PRIVATE_KEY_FIILENAME;
#ifdef ENABLE_CRYPTOAUTHLIB
iotc_private_key_slot = 0xFF;
#endif

while (1) {
static struct option long_options[] = {
Expand All @@ -61,6 +68,9 @@ int iotc_parse(int argc, char** argv, char* valid_options,
{"publish_topic", required_argument, 0, 't'},
{"publish_message", required_argument, 0, 'm'},
{"private_key_filename", optional_argument, 0, 'f'},
#ifdef ENABLE_CRYPTOAUTHLIB
{"private_key_slot", required_argument, 0, 's'},
#endif
{0, 0, 0, 0}};

/* getopt_long stores the option index here. */
Expand Down Expand Up @@ -89,6 +99,11 @@ int iotc_parse(int argc, char** argv, char* valid_options,
case 'f':
iotc_private_key_filename = optarg;
break;
#ifdef ENABLE_CRYPTOAUTHLIB
case 's':
iotc_private_key_slot = (uint8_t) strtol(optarg, NULL, 10);
break;
#endif
case 'h':
default:
iotc_help_flag = 1;
Expand Down Expand Up @@ -155,6 +170,12 @@ void iotc_usage(const char* options, unsigned options_length) {
printf(" \t of the device identifying private_key. Defaults to: %s\n",
DEFAULT_PRIVATE_KEY_FIILENAME);
break;
#ifdef ENABLE_CRYPTOAUTHLIB
case 's':
printf(
"-s --private_key_slot\n\tThe secure element slot ID containing "
"\tthe device identifying private_key.");
#endif
case 'h': /* Don't print anything for the help option since we're printing
usage */
break;
Expand Down
6 changes: 5 additions & 1 deletion examples/common/src/commandline.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
/*
* This module implements a command line argument parser.
*/

#include <stdint.h>
#include <iotc_mqtt.h>

/* Flags set by commandline arguments. */
Expand All @@ -30,5 +30,9 @@ extern const char* iotc_publish_topic;
extern const char* iotc_publish_message;
extern const char* iotc_private_key_filename;

#ifdef ENABLE_CRYPTOAUTHLIB
extern uint8_t iotc_private_key_slot;
#endif

int iotc_parse(int argc, char** argv, char* valid_options,
const unsigned options_length);
32 changes: 32 additions & 0 deletions examples/common/src/example_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
#include "example_utils.h"
#include "commandline.h"

#ifdef ENABLE_CRYPTOAUTHLIB
#include "cryptoauthlib.h"
#endif


#define IOTC_UNUSED(x) (void)(x)

extern iotc_crypto_key_data_t iotc_connect_private_key_data;
Expand All @@ -28,7 +33,13 @@ static iotc_timed_task_handle_t delayed_publish_task =
IOTC_INVALID_TIMED_TASK_HANDLE;

int iotc_example_handle_command_line_args(int argc, char* argv[]) {

#ifdef ENABLE_CRYPTOAUTHLIB
char options[] = "h:p:d:t:m:f:s:";
#else
char options[] = "h:p:d:t:m:f:";
#endif

int missingparameter = 0;
int retval = 0;

Expand Down Expand Up @@ -62,6 +73,13 @@ int iotc_example_handle_command_line_args(int argc, char* argv[]) {
printf("-t --publish_topic is required\n");
}

#ifdef ENABLE_CRYPTOAUTHLIB
if (0xFF == iotc_private_key_slot) {
missingparameter = 1;
printf("-s --private_key_slot is required\n");
}
#endif

if (1 == missingparameter) {
/* Error has already been logged, above. Silently exit here */
printf("\n");
Expand Down Expand Up @@ -110,6 +128,20 @@ int load_ec_private_key_pem_from_posix_fs(char* buf_ec_private_key_pem, size_t b
return 0;
}

#ifdef ENABLE_CRYPTOAUTHLIB
int init_cryptoauthlib() {
ATCA_STATUS atca_status;
if ((atca_status = atcab_init(&cfg_ateccx08a_kithid_default)) != ATCA_SUCCESS) {
printf("Unable to initialize interface, status: %x\n", atca_status);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the only #ifdef is required here (and the #include "cryptoauthlib.h")

return -1;
} else {
printf("Successfully initialized secure element.\n");
}

return 0;
}
#endif

void on_connection_state_changed(iotc_context_handle_t in_context_handle,
void* data, iotc_state_t state) {
iotc_connection_data_t* conn_data = (iotc_connection_data_t*)data;
Expand Down
9 changes: 9 additions & 0 deletions examples/common/src/example_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ int iotc_example_handle_command_line_args(int argc, char* argv[]);
also be used. Please see the Crypto BSP for more information. */
int load_ec_private_key_pem_from_posix_fs(char* buf_ec_private_key_pem, size_t buf_len);

#ifdef ENABLE_CRYPTOAUTHLIB
/**
* Initializes Microchip's Cryptoauthlib.
*
* Used to sign tokens using the private key stored in a secure element.
*/
int init_cryptoauthlib();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you'd call this init_example_dependencies (+1 abstraction layer and not being specific) then 2 more #ifdefs could be removed. One here and one in the example since the example could call it all the way.

#endif

/* A callback function that will be invoked whenever the connection state
has changed.

Expand Down
29 changes: 24 additions & 5 deletions examples/iot_core_mqtt_client/src/iot_core_mqtt_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,20 @@ int main(int argc, char* argv[]) {
return -1;
}

/* This example assumes the private key to be used to sign the IoT Core
Connect JWT credential is a PEM encoded ES256 private key,
and passes it IoT Core Device Client functions as a byte array.
There are other ways of passing key data to the client, including
passing Key Slot IDs for using keys stored in secure elements.
/* This example assumes the key used to sign the IoT Core
Connect JWT credential is an ES256 private key.
It demonstrates two ways of passing the key:
- from a PEM encoded string in a byte array
- from a key stored in a secure element

This behaviour can be selected using the ENABLE_CRYPTOAUTHLIB
preprocessor variable.
For more information, please see the iotc_crypto_key_data_t
documentation in include/iotc_types.h. */

#ifndef ENABLE_CRYPTOAUTHLIB
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be removed too if we decide to branch at runtime: if we have private_key_filename, then load it, if there is no filename given, try to use the slotid (if available). If neither is available, then it is a parametrization issue, report an error message.

/* Using a private key in PEM format. */

/* Use the example utils function to load the key from disk into memory. */
if (0 != load_ec_private_key_pem_from_posix_fs(ec_private_key_pem,
PRIVATE_KEY_BUFFER_SIZE)) {
Expand All @@ -71,6 +77,19 @@ int main(int argc, char* argv[]) {
iotc_connect_private_key_data.crypto_key_union.key_pem.key =
ec_private_key_pem;

#else
/* Using a private key stored in a secure element. */

init_cryptoauthlib(); // Initialize the secure element

iotc_connect_private_key_data.crypto_key_signature_algorithm =
IOTC_CRYPTO_KEY_SIGNATURE_ALGORITHM_ES256;
iotc_connect_private_key_data.crypto_key_union_type =
IOTC_CRYPTO_KEY_UNION_TYPE_SLOT_ID;
iotc_connect_private_key_data.crypto_key_union.key_slot.slot_id =
iotc_private_key_slot;
#endif

/* Initialize iotc library and create a context to use to connect to the
* GCP IoT Core Service. */
const iotc_state_t error_init = iotc_initialize();
Expand Down
2 changes: 1 addition & 1 deletion make/mt-config/mt-crypto.mk
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ $(CRYPTOAUTHLIB_BUILD_DIR):
mkdir -p $(CRYPTOAUTHLIB_BUILD_DIR)

$(CRYPTOAUTHLIB_MAKEFILE): | $(CRYPTOAUTHLIB_BUILD_DIR)
cmake -B$(CRYPTOAUTHLIB_BUILD_DIR) -H$(CRYPTOAUTHLIB_DIR)
cmake -B$(CRYPTOAUTHLIB_BUILD_DIR) -H$(CRYPTOAUTHLIB_DIR) -DATCA_BUILD_SHARED_LIBS=OFF

$(CRYPTOAUTHLIB_LIBRARY): | $(CRYPTOAUTHLIB_MAKEFILE)
make -C $(CRYPTOAUTHLIB_BUILD_DIR)
Expand Down
2 changes: 1 addition & 1 deletion third_party/cryptoauthlib
Submodule cryptoauthlib updated 1020 files