-
Notifications
You must be signed in to change notification settings - Fork 83
Updating MQTT client example for CryptoAuthLib #32
base: feature_cryptoauthlib
Are you sure you want to change the base?
Changes from 6 commits
f524f61
956d94b
7dc8af3
982e7ac
ff3c68a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,6 @@ | ||
| [submodule "third_party/googletest"] | ||
| path = third_party/googletest | ||
| url = https://github.com/google/googletest | ||
| [submodule "third_party/cryptoauthlib"] | ||
| path = third_party/cryptoauthlib | ||
| url = https://github.com/MicrochipTech/cryptoauthlib.git |
| 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()) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,15 +43,22 @@ const char* iotc_publish_topic; | |
| const char* iotc_publish_message; | ||
| const char* iotc_private_key_filename; | ||
|
|
||
| #ifdef ENABLE_CRYPTOAUTHLIB | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: pattern with all places.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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[] = { | ||
|
|
@@ -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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if you'd call this |
||
| #endif | ||
|
|
||
| /* A callback function that will be invoked whenever the connection state | ||
| has changed. | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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)) { | ||
|
|
@@ -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(); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| # Copyright 2018 Google LLC | ||
| # | ||
| # This is part of the Google Cloud IoT Edge Embedded C Client, | ||
| # it is licensed under the BSD 3-Clause license; you may not use this file | ||
| # except in compliance with the License. | ||
| # | ||
| # You may obtain a copy of the License at: | ||
| # https://opensource.org/licenses/BSD-3-Clause | ||
| # | ||
| # Unless required by applicable law or agreed to in writing, software | ||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| # See the License for the specific language governing permissions and | ||
| # limitations under the License. | ||
|
|
||
| # Build configuration for Crypto BSP implementation | ||
|
|
||
| ifeq ($(IOTC_BSP_CRYPTO), mbedtls) | ||
| ifneq ($(IOTC_BSP_TLS), mbedtls) | ||
| $(error mbedtls as crypto BSP requires IOTC_BSP_TLS=mbedtls, was "$(IOTC_BSP_TLS)") | ||
| endif | ||
| # Nothing else to to, rely on IOTC_BSP_TLS to configure dependencies | ||
|
|
||
| else ifeq ($(IOTC_BSP_CRYPTO), wolfssl) | ||
| ifneq ($(IOTC_BSP_TLS), wolfssl) | ||
| $(error wolfssl as crypto BSP requires IOTC_BSP_TLS=wolfssl, was "$(IOTC_BSP_TLS)") | ||
| endif | ||
| # Nothing else to to, rely on IOTC_BSP_TLS to configure dependencies | ||
|
|
||
| else ifeq ($(IOTC_BSP_CRYPTO), cryptoauthlib) | ||
| CRYPTOAUTHLIB_DIR := ./third_party/cryptoauthlib/lib | ||
| CRYPTOAUTHLIB_SUBDIRS := basic crypto hal | ||
| CRYPTOAUTHLIB_BUILD_DIR := $(CRYPTOAUTHLIB_DIR)/../build | ||
| CRYPTOAUTHLIB_MAKEFILE := $(CRYPTOAUTHLIB_DIR)/../build/Makefile | ||
| CRYPTOAUTHLIB_LIBRARY := $(CRYPTOAUTHLIB_BUILD_DIR)/cryptoauthlib.a | ||
|
|
||
| $(CRYPTOAUTHLIB_BUILD_DIR): | ||
| mkdir -p $(CRYPTOAUTHLIB_BUILD_DIR) | ||
|
|
||
| $(CRYPTOAUTHLIB_MAKEFILE): | $(CRYPTOAUTHLIB_BUILD_DIR) | ||
| cmake -B$(CRYPTOAUTHLIB_BUILD_DIR) -H$(CRYPTOAUTHLIB_DIR) | ||
|
|
||
| $(CRYPTOAUTHLIB_LIBRARY): | $(CRYPTOAUTHLIB_MAKEFILE) | ||
| make -C $(CRYPTOAUTHLIB_BUILD_DIR) | ||
|
|
||
| IOTC_INCLUDE_FLAGS += -I$(CRYPTOAUTHLIB_DIR) | ||
| IOTC_INCLUDE_FLAGS += $(foreach d, $(CRYPTOAUTHLIB_SUBDIRS), -I$(CRYPTOAUTHLIB_DIR)/$d) | ||
| IOTC_CRYPTO_LIB_DEP ?= $(CRYPTOAUTHLIB_LIBRARY) | ||
| IOTC_LIB_FLAGS += -L$(CRYPTOAUTHLIB_BUILD_DIR) | ||
| IOTC_LIB_FLAGS += -lcryptoauth | ||
|
|
||
| else | ||
| $(error unsupported IOTC_BSP_CRYPTO value "$(IOTC_BSP_CRYPTO)") | ||
| endif | ||
|
|
||
| IOTC_SRCDIRS += $(IOTC_BSP_DIR)/crypto/$(IOTC_BSP_CRYPTO) |
Uh oh!
There was an error while loading. Please reload this page.