-
Notifications
You must be signed in to change notification settings - Fork 2.1k
pkg: add library for Microchip CryptoAuth devices as package #13014
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
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 |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| PKG_NAME=cryptoauthlib | ||
| PKG_URL=https://github.com/MicrochipTech/cryptoauthlib | ||
| PKG_VERSION=af8187776cd3f3faf8bed412eaf6ff7221862e19 | ||
| PKG_LICENSE=LGPL-2.1 | ||
| PKG_TEST_NAME=cryptoauthlib_test | ||
| PKG_TESTINCLDIR = $(PKG_BUILDDIR)/test | ||
|
|
||
| include $(RIOTBASE)/pkg/pkg.mk | ||
|
|
||
| .PHONY: all..cmake_version_supported | ||
|
|
||
| CMAKE_MINIMAL_VERSION = 3.6.0 | ||
|
|
||
| CFLAGS += -Wno-missing-field-initializers -Wno-unused-function | ||
| CFLAGS += -Wno-type-limits -Wno-strict-aliasing -Wno-unused-variable -DATCA_HAL_I2C | ||
| CFLAGS += -Wno-unused-parameter -Wno-sign-compare -Wno-overflow -Wno-pointer-to-int-cast | ||
|
|
||
| TOOLCHAIN_FILE=$(PKG_BUILDDIR)/xcompile-toolchain.cmake | ||
|
|
||
| ifneq (,$(filter $(PKG_TEST_NAME),$(USEMODULE))) | ||
| all: cryptoauth build_tests | ||
| else | ||
| all: cryptoauth | ||
| endif | ||
|
|
||
| cryptoauth: $(PKG_BUILDDIR)/lib/Makefile | ||
| $(MAKE) -C $(PKG_BUILDDIR)/lib | ||
| cp $(PKG_BUILDDIR)/lib/libcryptoauth.a $(BINDIR)/$(PKG_NAME).a | ||
|
|
||
| $(PKG_BUILDDIR)/lib/Makefile: $(TOOLCHAIN_FILE) | ||
| cd $(PKG_BUILDDIR)/lib && \ | ||
| cmake -DCMAKE_TOOLCHAIN_FILE=$(TOOLCHAIN_FILE) \ | ||
| -Wno-dev \ | ||
| -DBUILD_TESTS=OFF \ | ||
| -DATCA_HAL_I2C:BOOL=TRUE . | ||
|
|
||
| $(TOOLCHAIN_FILE): git-download | ||
| $(RIOTTOOLS)/cmake/generate-xcompile-toolchain.sh > $(TOOLCHAIN_FILE) | ||
|
|
||
| build_tests: | ||
| cp $(PKG_TESTINCLDIR)/*.c $(PKG_BUILDDIR) | ||
| cp $(PKG_TESTINCLDIR)/jwt/*.c $(PKG_BUILDDIR) | ||
| cp $(PKG_TESTINCLDIR)/tng/*.c $(PKG_BUILDDIR) | ||
| cp $(PKG_TESTINCLDIR)/atcacert/*.c $(PKG_BUILDDIR) | ||
|
|
||
| echo "MODULE = $(PKG_TEST_NAME)" > $(PKG_BUILDDIR)/Makefile | ||
| echo "include \$$(RIOTBASE)/Makefile.base" >> $(PKG_BUILDDIR)/Makefile | ||
|
|
||
| "$(MAKE)" -C $(PKG_BUILDDIR) | ||
|
|
||
| git-download: | ..cmake_version_supported | ||
|
|
||
| ..cmake_version_supported: | ||
| @ # Remove '-rcX' from version as they are not well handled | ||
| $(Q)\ | ||
| CMAKE_VERSION=$$(cmake --version | sed -n '1 {s/cmake version //;s/-rc.*//;p;}'); \ | ||
| $(RIOTTOOLS)/has_minimal_version/has_minimal_version.sh "$${CMAKE_VERSION}" "$(CMAKE_MINIMAL_VERSION)" cmake | ||
|
|
||
| clean:: | ||
| @rm -rf $(BINDIR)/$(PKG_NAME).a | ||
|
leandrolanzieri marked this conversation as resolved.
|
||
| @rm -rf $(BINDIR)/$(PKG_TEST_NAME).a | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| MODULE = cryptoauthlib | ||
|
|
||
| include $(RIOTBASE)/Makefile.base |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| USEMODULE += xtimer | ||
| FEATURES_REQUIRED += periph_i2c | ||
| USEMODULE += auto_init_security | ||
| USEMODULE += cryptoauthlib_contrib |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| PKG_BUILDDIR ?= $(PKGDIRBASE)/cryptoauthlib | ||
|
PeterKietzmann marked this conversation as resolved.
|
||
| PKG_TESTINCLDIR = $(PKG_BUILDDIR)/test | ||
|
|
||
| INCLUDES += -I$(PKG_BUILDDIR) | ||
| INCLUDES += -I$(PKG_BUILDDIR)/lib | ||
| INCLUDES += -I$(PKG_BUILDDIR)/app | ||
| INCLUDES += -I$(RIOTPKG)/cryptoauthlib/include | ||
|
|
||
| DIRS += $(RIOTPKG)/cryptoauthlib/contrib | ||
|
|
||
| ifneq (,$(filter cryptoauthlib_test,$(USEMODULE))) | ||
| INCLUDES += -I$(PKG_TESTINCLDIR) | ||
| INCLUDES += -I$(PKG_TESTINCLDIR)/jwt | ||
| INCLUDES += -I$(PKG_TESTINCLDIR)/tng | ||
| INCLUDES += -I$(PKG_TESTINCLDIR)/atcacert | ||
| endif | ||
|
|
||
| ifneq (,$(filter cortex-m%,$(CPU_ARCH))) | ||
| TOOLCHAINS_BLACKLIST += llvm | ||
| endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| MODULE = cryptoauthlib_contrib | ||
|
|
||
| include $(RIOTBASE)/Makefile.base |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| /* | ||
| * Copyright (C) 2019 HAW Hamburg | ||
| * | ||
| * This file is subject to the terms and conditions of the GNU Lesser | ||
| * General Public License v2.1. See the file LICENSE in the top level | ||
| * directory for more details. | ||
| */ | ||
|
|
||
| /** | ||
| * @ingroup pkg_cryptoauthlib | ||
| * @{ | ||
| * | ||
| * @file | ||
| * @brief HAL implementation for the library Microchip CryptoAuth devices | ||
| * | ||
| * @author Lena Boeckmann <[email protected]> | ||
| * | ||
| * @} | ||
| */ | ||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
| #include "xtimer.h" | ||
| #include "periph/i2c.h" | ||
| #include "periph/gpio.h" | ||
|
|
||
| #include "atca.h" | ||
| #include "atca_params.h" | ||
|
|
||
|
|
||
| /* Timer functions */ | ||
| void atca_delay_us(uint32_t delay) | ||
| { | ||
| xtimer_usleep(delay); | ||
| } | ||
|
|
||
| void atca_delay_10us(uint32_t delay) | ||
| { | ||
| xtimer_usleep(delay * 10); | ||
| } | ||
|
|
||
| void atca_delay_ms(uint32_t delay) | ||
| { | ||
| xtimer_usleep(delay * 1000); | ||
| } | ||
|
|
||
| /* Hal I2C implementation */ | ||
| ATCA_STATUS hal_i2c_init(void *hal, ATCAIfaceCfg *cfg) | ||
| { | ||
| (void)hal; | ||
| if (cfg->iface_type != ATCA_I2C_IFACE) { | ||
| return ATCA_BAD_PARAM; | ||
| } | ||
|
|
||
| atcab_wakeup(); | ||
|
|
||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_post_init(ATCAIface iface) | ||
| { | ||
| (void)iface; | ||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_send(ATCAIface iface, uint8_t *txdata, int txlength) | ||
| { | ||
| ATCAIfaceCfg *cfg = atgetifacecfg(iface); | ||
| int ret; | ||
|
|
||
| /* The first byte of the command package contains the word address */ | ||
| txdata[0] = ATCA_DATA_ADDR; | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| ret = i2c_write_bytes(cfg->atcai2c.bus, (cfg->atcai2c.slave_address >> 1), | ||
| txdata, txlength + 1, 0); | ||
| i2c_release(cfg->atcai2c.bus); | ||
|
|
||
| if (ret != 0) { | ||
| return ATCA_TX_FAIL; | ||
| } | ||
|
|
||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_receive(ATCAIface iface, uint8_t *rxdata, | ||
| uint16_t *rxlength) | ||
| { | ||
| ATCAIfaceCfg *cfg = atgetifacecfg(iface); | ||
| uint8_t retries = cfg->rx_retries; | ||
|
Member
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. Could you please "group" variables of the type? |
||
| uint8_t length_package = 0; | ||
| uint8_t bytes_to_read; | ||
| int ret = -1; | ||
|
|
||
| /* Every command needs some time to be executed. We check whether the device is done | ||
| by polling, so we don't have to wait for the max execution time. For that there's | ||
| a number of retries (specified in the device descriptor). If polling is not successful | ||
| this function returns an error code. */ | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| while (retries-- > 0 && ret != 0) { | ||
| /* read first byte (size of output data) and store it in variable length_package | ||
| to check if output will fit into rxdata */ | ||
| ret = i2c_read_byte(cfg->atcai2c.bus, (cfg->atcai2c.slave_address >> 1), | ||
| &length_package, 0); | ||
| } | ||
| i2c_release(cfg->atcai2c.bus); | ||
|
|
||
| if (ret != 0) { | ||
| return ATCA_RX_TIMEOUT; | ||
| } | ||
|
|
||
| bytes_to_read = length_package - 1; | ||
|
|
||
| if (bytes_to_read > *rxlength) { | ||
| return ATCA_SMALL_BUFFER; | ||
| } | ||
|
|
||
| /* CRC function calculates value of the whole output package, so to get a correct | ||
| result we need to include the length of the package we got before into rxdata as first byte. */ | ||
| rxdata[0] = length_package; | ||
|
|
||
| /* reset ret and retries to read the rest of the output */ | ||
| ret = -1; | ||
| retries = cfg->rx_retries; | ||
|
|
||
| /* read rest of output and insert into rxdata array after first byte */ | ||
| i2c_acquire(cfg->atcai2c.bus); | ||
| while (retries-- > 0 && ret != 0) { | ||
| ret = i2c_read_bytes(cfg->atcai2c.bus, | ||
| (cfg->atcai2c.slave_address >> 1), (rxdata + 1), | ||
| bytes_to_read, 0); | ||
| } | ||
| i2c_release(cfg->atcai2c.bus); | ||
|
|
||
| if (ret != 0) { | ||
| return ATCA_RX_TIMEOUT; | ||
| } | ||
|
|
||
| *rxlength = length_package; | ||
|
|
||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_wake(ATCAIface iface) | ||
| { | ||
| ATCAIfaceCfg *cfg = atgetifacecfg(iface); | ||
| uint8_t data[4] = { 0 }; | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| i2c_write_byte(cfg->atcai2c.bus, ATCA_WAKE_ADDR, data[0], 0); | ||
| i2c_release(cfg->atcai2c.bus); | ||
|
|
||
| atca_delay_us(cfg->wake_delay); | ||
|
|
||
| uint8_t retries = cfg->rx_retries; | ||
| int status = -1; | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| while (retries-- > 0 && status != 0) { | ||
| status = i2c_read_bytes(cfg->atcai2c.bus, | ||
| (cfg->atcai2c.slave_address >> 1), | ||
| &data[0], 4, 0); | ||
| } | ||
| i2c_release(cfg->atcai2c.bus); | ||
|
|
||
| if (status != ATCA_SUCCESS) { | ||
| return ATCA_COMM_FAIL; | ||
| } | ||
|
|
||
| return hal_check_wake(data, 4); | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_idle(ATCAIface iface) | ||
| { | ||
| ATCAIfaceCfg *cfg = atgetifacecfg(iface); | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| i2c_write_byte(cfg->atcai2c.bus, (cfg->atcai2c.slave_address >> 1), | ||
| ATCA_IDLE_ADDR, 0); | ||
| i2c_release(cfg->atcai2c.bus); | ||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_sleep(ATCAIface iface) | ||
| { | ||
| ATCAIfaceCfg *cfg = atgetifacecfg(iface); | ||
|
|
||
| i2c_acquire(cfg->atcai2c.bus); | ||
| i2c_write_byte(cfg->atcai2c.bus, (cfg->atcai2c.slave_address >> 1), | ||
| ATCA_SLEEP_ADDR, 0); | ||
| i2c_release(cfg->atcai2c.bus); | ||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_release(void *hal_data) | ||
| { | ||
| (void)hal_data; | ||
| /* This function is unimplemented, because currently the bus gets acquired | ||
| and released before and after each read or write operation. It returns | ||
| a success code, in case it gets called somewhere in the library. */ | ||
| return ATCA_SUCCESS; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_discover_buses(int i2c_buses[], int max_buses) | ||
| { | ||
| (void)i2c_buses; | ||
| (void)max_buses; | ||
| return ATCA_UNIMPLEMENTED; | ||
| } | ||
|
|
||
| ATCA_STATUS hal_i2c_discover_devices(int bus_num, ATCAIfaceCfg *cfg, int *found) | ||
| { | ||
| (void)bus_num; | ||
| (void)cfg; | ||
| (void)found; | ||
| return ATCA_UNIMPLEMENTED; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| /** | ||
| * @defgroup pkg_cryptoauthlib Microchip CryptoAuthentication Library | ||
| * @ingroup pkg drivers sys_crypto | ||
| * @brief Provides the library for Microchip CryptoAuth devices | ||
| * @see https://github.com/MicrochipTech/cryptoauthlib | ||
| * | ||
| * # Introduction | ||
| * | ||
| * This package provides support for the official library for Microchip CryptoAuth devices. | ||
| * | ||
| * | ||
|
Member
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. I think it would be useful if we had a paragraph here that exmpalins about the special wakeup procedure because this eventually affects other devices connected to the same bus. |
||
| * ## Warning | ||
| * | ||
| * Some functions can only be used, when the data, config and otp zones of the | ||
| * device are locked. Locking is permanent and cannot be undone. Be careful if | ||
| * you're not sure you've configured everything correctly. | ||
| * For more information we refer to the data sheet of the device. | ||
| * | ||
| * | ||
| * ## Usage | ||
| * | ||
| * Add | ||
| * USEPKG += cryptoauthlib | ||
| * to your Makefile. | ||
| * | ||
| * | ||
| * ## Implementation status | ||
| * | ||
| * This implementation was partly tested with ATECC508A and ATECC608A devices. | ||
| * We haven't tested the functions that require locking the device, yet. There's | ||
| * a wrapper in the cryptoauthlib/contrib folder, which implements most of the | ||
| * HAL functions. | ||
| * Currently the functions hal_i2c_discover_devices and hal_i2c_discover_buses | ||
| * are unimplemented, as well as hal_i2c_post_init. | ||
| * | ||
| * ### Wake function | ||
| * | ||
| * The wake function only works when a 0x00 byte is sent on an i2c interface that | ||
| * runs with with 133kHz or less. | ||
| * Currently RIOT sets the baudrate to the default value of 100 kHz and there's | ||
| * no interface to change that. If the default speed ever changes to a value | ||
| * higher than 133 kHz the wake function needs to be adapted. | ||
| * For more information on how to send a proper wake condition we refer to the | ||
| * data sheet of the device. | ||
| * | ||
| * ## Tests | ||
| * | ||
| * The library provides unittests for the library functions. There | ||
| * is a directory called "pkg_cryptoauthlib_internal_tests" in the RIOT testfolder | ||
| * which runs part of the unittests. | ||
| * Some of the provided tests can only be run when the config, data and/or otp zones | ||
| * of the device are locked. Some tests (but not all) will automatically lock zones | ||
|
Member
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. But we omit these tests right? Then, please mention it. |
||
| * as needed. We omit those tests at the moment, because zones can only be locked | ||
| * permanently. Unlocking is not possible! | ||
| * Also there is a test for comparing the runtime of the RIOT software implementation | ||
| * and the CryptoAuth hardware implementation for calculating a SHA-256 hash value. | ||
| */ | ||
|
Member
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. The performance metrics are interesting as part of the discussion (PR description) but please remove them here. |
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cgundogan, @leandrolanzieri could you please review this Makefile?