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 6 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
3 changes: 3 additions & 0 deletions .gitmodules
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
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ MD ?= @
# TLS related configuration
IOTC_BSP_TLS ?= mbedtls

# Cryptographic BSP implementation
IOTC_BSP_CRYPTO ?= mbedtls

#detect if the build happen on Travis
ifdef TRAVIS_OS_NAME
IOTC_TRAVIS_BUILD=1
Expand Down Expand Up @@ -143,7 +146,7 @@ clean_all: clean

libiotc: $(XI)

$(XI): $(IOTC_TLS_LIB_DEP) $(IOTC_PROTOFILES_C) $(IOTC_OBJS) $(IOTC_BUILD_PRECONDITIONS) | $(IOTC_BIN_DIRS)
$(XI): $(IOTC_TLS_LIB_DEP) $(IOTC_CRYPTO_LIB_DEP) $(IOTC_PROTOFILES_C) $(IOTC_OBJS) $(IOTC_BUILD_PRECONDITIONS) | $(IOTC_BIN_DIRS)
$(info [$(AR)] $@ )
$(MD) $(AR) $(IOTC_ARFLAGS) $(IOTC_OBJS) $(IOTC_EXTRA_ARFLAGS)

Expand Down
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 EmbeddedC 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: 2 additions & 0 deletions make/mt-config/mt-config.mk
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ ifneq (,$(findstring tls_bsp,$(CONFIG)))
include make/mt-config/mt-tls.mk
endif

include make/mt-config/mt-crypto.mk

IOTC_UNIT_TEST_TARGET ?= native

IOTC_OBJDIR_BASE ?= $(LIBIOTC)/obj
Expand Down
56 changes: 56 additions & 0 deletions make/mt-config/mt-crypto.mk
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)
Loading