From 956d94b2de37f0239d9da6aab97bb817a6050751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rechtenstein?= Date: Wed, 20 Feb 2019 14:22:28 +0900 Subject: [PATCH 1/3] update mqtt_client example for Cryptoauthlib --- examples/common/atecc_get_pubkey.py | 40 +++++++++++++++++++ examples/common/rules.mk | 25 ++++++++++-- examples/common/src/commandline.c | 23 ++++++++++- examples/common/src/commandline.h | 6 ++- examples/common/src/example_utils.c | 32 +++++++++++++++ examples/common/src/example_utils.h | 9 +++++ .../src/iot_core_mqtt_client.c | 29 +++++++++++--- 7 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 examples/common/atecc_get_pubkey.py diff --git a/examples/common/atecc_get_pubkey.py b/examples/common/atecc_get_pubkey.py new file mode 100644 index 00000000..fe553e15 --- /dev/null +++ b/examples/common/atecc_get_pubkey.py @@ -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()) diff --git a/examples/common/rules.mk b/examples/common/rules.mk index 2aef74b1..f50b2405 100644 --- a/examples/common/rules.mk +++ b/examples/common/rules.mk @@ -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 EmbeddedC Client at compile time +IOTC_FLAGS_LINKER := -L$(IOTC_CLIENT_LIB_PATH) -liotc -lm -lpthread + # TLS BSP related configuration IOTC_BSP_TLS ?= mbedtls @@ -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 diff --git a/examples/common/src/commandline.c b/examples/common/src/commandline.c index 986c56dc..a1e7acda 100644 --- a/examples/common/src/commandline.c +++ b/examples/common/src/commandline.c @@ -43,6 +43,10 @@ const char* iotc_publish_topic; const char* iotc_publish_message; const char* iotc_private_key_filename; +#ifdef ENABLE_CRYPTOAUTHLIB +uint8_t iotc_private_key_slot; +#endif + int iotc_parse(int argc, char** argv, char* valid_options, unsigned options_length) { int c; @@ -50,8 +54,11 @@ int iotc_parse(int argc, char** argv, char* valid_options, 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[] = { @@ -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. */ @@ -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; @@ -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; diff --git a/examples/common/src/commandline.h b/examples/common/src/commandline.h index 13f91dd2..c9d34635 100644 --- a/examples/common/src/commandline.h +++ b/examples/common/src/commandline.h @@ -17,7 +17,7 @@ /* * This module implements a command line argument parser. */ - +#include #include /* Flags set by commandline arguments. */ @@ -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); diff --git a/examples/common/src/example_utils.c b/examples/common/src/example_utils.c index 14f0c00e..ec96a956 100644 --- a/examples/common/src/example_utils.c +++ b/examples/common/src/example_utils.c @@ -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; @@ -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; @@ -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"); @@ -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); + 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; diff --git a/examples/common/src/example_utils.h b/examples/common/src/example_utils.h index 6e897b53..02f11de7 100644 --- a/examples/common/src/example_utils.h +++ b/examples/common/src/example_utils.h @@ -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(); +#endif + /* A callback function that will be invoked whenever the connection state has changed. diff --git a/examples/iot_core_mqtt_client/src/iot_core_mqtt_client.c b/examples/iot_core_mqtt_client/src/iot_core_mqtt_client.c index 5a2edf49..3dc3dd71 100644 --- a/examples/iot_core_mqtt_client/src/iot_core_mqtt_client.c +++ b/examples/iot_core_mqtt_client/src/iot_core_mqtt_client.c @@ -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 + /* 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)) { @@ -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(); From 7dc8af3e16250490419b3edf873c1433026c3660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rechtenstein?= Date: Wed, 20 Feb 2019 22:20:02 +0900 Subject: [PATCH 2/3] Update rules.mk --- examples/common/rules.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/common/rules.mk b/examples/common/rules.mk index f50b2405..15728879 100644 --- a/examples/common/rules.mk +++ b/examples/common/rules.mk @@ -50,7 +50,7 @@ IOTC_FLAGS_COMPILER ?= -Wall -Werror -Wno-pointer-arith -Wno-format -fstrict-ali # -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 +# Google Cloud IoT Device SDK Client at compile time IOTC_FLAGS_LINKER := -L$(IOTC_CLIENT_LIB_PATH) -liotc -lm -lpthread # TLS BSP related configuration From ff3c68a5aad6538ff7a9d99c2bd964c84af6fab4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Rechtenstein?= Date: Wed, 6 Mar 2019 22:20:34 +0900 Subject: [PATCH 3/3] enable building Cryptoauthlib as static lib * Bump Cryptoauthlib version to 20190304 * Enable new option to build lib as static --- make/mt-config/mt-crypto.mk | 2 +- third_party/cryptoauthlib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/make/mt-config/mt-crypto.mk b/make/mt-config/mt-crypto.mk index 3464214d..0c15c201 100644 --- a/make/mt-config/mt-crypto.mk +++ b/make/mt-config/mt-crypto.mk @@ -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) diff --git a/third_party/cryptoauthlib b/third_party/cryptoauthlib index 411cd5cf..f86b9dbb 160000 --- a/third_party/cryptoauthlib +++ b/third_party/cryptoauthlib @@ -1 +1 @@ -Subproject commit 411cd5cfc314a875794a8fb5a4b6a1860384ec1b +Subproject commit f86b9dbb1e805d85a435456ca03450342dbdc43e