mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-19 17:35:54 +08:00
添加智能灯固件代码
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
# The following lines of boilerplate have to be in your project's CMakeLists
|
||||
# in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(atecc608a_ecdsa)
|
||||
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := atecc608a_ecdsa
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
| Supported Targets | ESP32 |
|
||||
| ----------------- | ----- |
|
||||
|
||||
# ESP32-WROOM-32SE ECDSA sign/verify example
|
||||
## Description
|
||||
This example requires [ESP32-WROOM-32SE](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32se_datasheet_en.pdf) which has Microchip's [ATECC608A](https://www.microchip.com/wwwproducts/en/ATECC608A) (Secure Element) integrated on the module. The example performs `ECDSA sign/verify` functions on sample data using hardware private key stored in ATECC608A chip.If you want to use bare `ATECC608A` chip (Secure Element) with `ESP32-WROOM-32` module by making external connections, please refer [this](https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#using-atecc608a-with-esp32-wroom-32) for details.
|
||||
See the README.md file in the upper level examples directory for more information about examples.
|
||||
## Hardware
|
||||
To get started you will need a `ESP32-WROOM-32SE` development board which integrates Microchip’s ATECC608A CryptoAuth chip in the module.
|
||||
|
||||
## Configuration
|
||||
ATECC608A chip on ESP32-WROOM-32SE should be configured to run the example, for details on configuration of ATECC608A chip, please refer [esp_cryptoauth_utility](https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#esp_cryptoauth_utility)
|
||||
|
||||
1) Set type of `ATECC608A` chip in menuconfig.
|
||||
|
||||
* `menuconfig->Component config->esp-cryptoauthlib->Choose Type of ATECC608A chip`.
|
||||
for more details refer [Find ATECC608A chip type](https://github.com/espressif/esp-cryptoauthlib/blob/master/esp_cryptoauth_utility/README.md#find-type-of-atecc608a-chip-connected-to-esp32-wroom32-se).
|
||||
|
||||
2) Enable `Hardware ECDSA sign/verify` in menuconfig as by enabling following. (Enabled by default for this example)
|
||||
|
||||
* `menuconfig->Component config->esp-cryptoauthlib->Enable Hardware ECDSA keys for mbedTLS`
|
||||
* `menuconfig->Component config->esp-cryptoauthlib->Enable ATECC608A sign operations in mbedTLS`
|
||||
* `menuconfig->Component config->esp-cryptoauthlib->Enable ATECC608A verify operations in mbedTLS`
|
||||
|
||||
## Build and Flash
|
||||
|
||||
Run following command to build and flash the project.
|
||||
```
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html) for full steps to configure and use ESP-IDF to build projects.
|
||||
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# CMakeLists.txt file for cryptoauthlib
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
set(CRYPTOAUTHLIB_DIR "cryptoauthlib/lib")
|
||||
set(COMPONENT_SRCDIRS "${CRYPTOAUTHLIB_DIR}/atcacert"
|
||||
"${CRYPTOAUTHLIB_DIR}/basic"
|
||||
"${CRYPTOAUTHLIB_DIR}/crypto"
|
||||
"${CRYPTOAUTHLIB_DIR}/crypto/hashes"
|
||||
"${CRYPTOAUTHLIB_DIR}/host"
|
||||
"${CRYPTOAUTHLIB_DIR}/mbedtls"
|
||||
"${CRYPTOAUTHLIB_DIR}"
|
||||
"${CRYPTOAUTHLIB_DIR}/../app/tng"
|
||||
"port"
|
||||
)
|
||||
|
||||
set(COMPONENT_SRCS "${COMPONENT_DIR}/cryptoauthlib/lib/hal/atca_hal.c"
|
||||
"${COMPONENT_DIR}/cryptoauthlib/lib/hal/hal_freertos.c"
|
||||
"${COMPONENT_DIR}/cryptoauthlib/lib/hal/hal_esp32_i2c.c"
|
||||
"${COMPONENT_DIR}/cryptoauthlib/lib/hal/hal_esp32_timer.c"
|
||||
)
|
||||
|
||||
set(COMPONENT_INCLUDEDIRS "${CRYPTOAUTHLIB_DIR}/"
|
||||
"${CRYPTOAUTHLIB_DIR}/hal"
|
||||
"${CRYPTOAUTHLIB_DIR}/../app/tng"
|
||||
"port"
|
||||
)
|
||||
|
||||
set(COMPONENT_REQUIRES "mbedtls" "freertos" "driver")
|
||||
|
||||
# Don't include the default interface configurations from cryptoauthlib
|
||||
set(COMPONENT_EXCLUDE_SRCS "${CRYPTOAUTHLIB_DIR}/atca_cfgs.c")
|
||||
set(COMPONENT_CFLAGS "ESP32" "ATCA_HAL_I2C" "ATCA_USE_RTOS_TIMER")
|
||||
|
||||
idf_component_register( SRC_DIRS "${COMPONENT_SRCDIRS}"
|
||||
INCLUDE_DIRS "${COMPONENT_INCLUDEDIRS}"
|
||||
REQUIRES "${COMPONENT_REQUIRES}"
|
||||
EXCLUDE_SRCS "${COMPONENT_EXCLUDE_SRCS}"
|
||||
)
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${COMPONENT_SRCS})
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE ${COMPONENT_CFLAGS})
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-pointer-sign)
|
||||
|
||||
idf_component_get_property(freertos_dir freertos COMPONENT_DIR)
|
||||
set_source_files_properties(${CRYPTOAUTHLIB_DIR}/hal/hal_freertos.c PROPERTIES COMPILE_FLAGS -I${freertos_dir}/include/freertos)
|
||||
|
||||
# Turn off some warnings for some files that have been checked
|
||||
set_source_files_properties(${CRYPTOAUTHLIB_DIR}/hal/hal_esp32_i2c.c PROPERTIES COMPILE_FLAGS "-Wno-unused-variable -Wno-unused-but-set-variable")
|
||||
set_source_files_properties(${CRYPTOAUTHLIB_DIR}/basic/atca_helpers.c PROPERTIES COMPILE_FLAGS "-Wno-type-limits")
|
||||
set_source_files_properties(${CRYPTOAUTHLIB_DIR}/crypto/hashes/sha1_routines.c PROPERTIES COMPILE_FLAGS "-Wno-strict-aliasing")
|
||||
@@ -0,0 +1,44 @@
|
||||
menu "esp-cryptoauthlib"
|
||||
|
||||
choice ATECC608A_TYPE
|
||||
prompt "Choose the type of ATECC608A chip"
|
||||
default ATECC608A_TNG
|
||||
help
|
||||
There are three types of ATECC608A ( Secure Element) chips, which are
|
||||
Trust & GO, TrustFLex and Trust Custom. For more details consult README
|
||||
file of esp_cryptoauth_utility which is part of esp-cryptoauthlib component.
|
||||
config ATECC608A_TNG
|
||||
bool "ATECC608A chip type Trust & GO"
|
||||
config ATECC608A_TFLEX
|
||||
bool "ATECC608A chip type TrustFlex"
|
||||
config ATECC608A_TCUSTOM
|
||||
bool "ATECC608A chip type TrustCustom"
|
||||
endchoice
|
||||
|
||||
config ATCA_MBEDTLS_ECDSA
|
||||
bool "Enable Hardware ECDSA keys for mbedTLS"
|
||||
depends on MBEDTLS_ECDSA_C
|
||||
help
|
||||
Enable Hardware ECDSA
|
||||
|
||||
config ATCA_MBEDTLS_ECDSA_SIGN
|
||||
bool "Enable ATECC608A sign operations in mbedTLS"
|
||||
depends on ATCA_MBEDTLS_ECDSA
|
||||
select MBEDTLS_ATCA_HW_ECDSA_SIGN
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
|
||||
config ATCA_MBEDTLS_ECDSA_VERIFY
|
||||
bool "Enable ATECC608A verify operations in mbedTLS"
|
||||
depends on ATCA_MBEDTLS_ECDSA
|
||||
select MBEDTLS_ATCA_HW_ECDSA_VERIFY
|
||||
select MBEDTLS_ECP_DP_SECP256R1_ENABLED
|
||||
|
||||
config ACTA_I2C_SDA_PIN
|
||||
int "I2C SDA pin used to communicate with the ATECC608A"
|
||||
default 16
|
||||
|
||||
config ACTA_I2C_SCL_PIN
|
||||
int "I2C SCL pin used to communicate with the ATECC608A"
|
||||
default 17
|
||||
|
||||
endmenu # cryptoauthlib
|
||||
@@ -0,0 +1,32 @@
|
||||
# ESP-CRYPTOAUTHLIB
|
||||
|
||||
This is a port of Microchip's [cryptoauthlib](https://github.com/MicrochipTech/cryptoauthlib) for ESP-IDF. It contains necessary build support to use cryptoauthlib with ESP-IDF as well as `esp_cryptoauthlib_utility` for configuring and provisiong ATECC608A chip integrated with [ESP32-WROOM-32SE](https://www.espressif.com/sites/default/files/documentation/esp32-wroom-32se_datasheet_en.pdf). The cryptoauthlib folder which is a subset of Microchip's [cryptoauthlib](https://github.com/MicrochipTech/cryptoauthlib) is created with help of script [generate_component.sh](./generate_component.sh).
|
||||
|
||||
## Requirements
|
||||
|
||||
* [ESP-IDF](https://github.com/espressif/esp-idf) version should be `release/v4.3` or newer.
|
||||
* Environment variable `IDF_PATH` should be set
|
||||
|
||||
## How to use esp-cryptoauthlib with ESP-IDF
|
||||
---
|
||||
There are two ways to use `esp-cryptoauthlib` in your project
|
||||
|
||||
1) Directly add `esp-cryptoauthlib` as a component in your project with following three commands.
|
||||
|
||||
(First change directory (cd) to your project directory)
|
||||
```
|
||||
mkdir components
|
||||
cd components
|
||||
git clone https://github.com/espressif/esp-cryptoauthlib.git
|
||||
```
|
||||
2) Add `esp-cryptoauthlib` as an extra component in your project.
|
||||
|
||||
* Download `esp-cryptoauthlib` with:
|
||||
```
|
||||
git clone https://github.com/espressif/esp-cryptoauthlib.git
|
||||
```
|
||||
* Include `esp-cryptoauthlib` in `ESP-IDF` with setting `EXTRA_COMPONENT_DIRS` in CMakeLists.txt/Makefile of your project.For reference see [Optional Project Variables](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/build-system.html#optional-project-variables)
|
||||
|
||||
## How to configure and provision ATECC608A on ESP32-WROOM-32SE
|
||||
The python utilty `esp_cryptoauth_utility` helps to configure, generate resources as well as provision ATECC608A chip integrated with `ESP32-WROOM-32SE`.
|
||||
For detailed instructions on how to use the utility please refer utility [README.md](esp_cryptoauth_utility/README.md)
|
||||
@@ -0,0 +1,41 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
CRYPTOAUTHLIB_DIR := cryptoauthlib/lib
|
||||
|
||||
COMPONENT_SRCDIRS := $(CRYPTOAUTHLIB_DIR)/atcacert \
|
||||
$(CRYPTOAUTHLIB_DIR)/basic \
|
||||
$(CRYPTOAUTHLIB_DIR)/crypto \
|
||||
$(CRYPTOAUTHLIB_DIR)/crypto/hashes \
|
||||
$(CRYPTOAUTHLIB_DIR)/host \
|
||||
$(CRYPTOAUTHLIB_DIR)/mbedtls \
|
||||
$(CRYPTOAUTHLIB_DIR)/../app/tng \
|
||||
$(CRYPTOAUTHLIB_DIR) \
|
||||
port
|
||||
|
||||
COMPONENT_OBJS := $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.c,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.c))) \
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/atca_hal.o \
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/hal_freertos.o \
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/hal_esp32_i2c.o \
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/hal_esp32_timer.o
|
||||
|
||||
# Make relative by removing COMPONENT_PATH from all found object paths
|
||||
COMPONENT_OBJS := $(patsubst $(COMPONENT_PATH)/%,%,$(COMPONENT_OBJS))
|
||||
|
||||
# Don't include the default interface configurations from cryptoauthlib
|
||||
COMPONENT_OBJEXCLUDE := $(CRYPTOAUTHLIB_DIR)/atca_cfgs.o
|
||||
|
||||
# Add the hal directory back in for source search paths
|
||||
COMPONENT_SRCDIRS += $(CRYPTOAUTHLIB_DIR)/hal
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := $(CRYPTOAUTHLIB_DIR) $(CRYPTOAUTHLIB_DIR)/hal $(CRYPTOAUTHLIB_DIR)/../app/tng port
|
||||
|
||||
# Library requires some global defines
|
||||
CFLAGS+=-DESP32 -DATCA_HAL_I2C -DATCA_USE_RTOS_TIMER -Wno-pointer-sign
|
||||
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/hal_freertos.o: CFLAGS+= -I$(IDF_PATH)/components/freertos/include/freertos
|
||||
|
||||
# Turn off some warnings for some files that have been checked
|
||||
$(CRYPTOAUTHLIB_DIR)/hal/hal_esp32_i2c.o: CFLAGS+= -Wno-unused-but-set-variable -Wno-unused-variable
|
||||
$(CRYPTOAUTHLIB_DIR)/basic/atca_helpers.o: CFLAGS+= -Wno-type-limits
|
||||
$(CRYPTOAUTHLIB_DIR)/crypto/hashes/sha1_routines.c.o: CFLAGS+= -Wno-strict-aliasing
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,475 @@
|
||||
CryptoAuthLib - Microchip CryptoAuthentication Library
|
||||
====================================================
|
||||
|
||||
Introduction
|
||||
------------------------
|
||||
This code base implements an object-oriented C library which supports
|
||||
Microchip CryptoAuth devices. The family of devices supported currently are:
|
||||
|
||||
- [ATSHA204A](http://www.microchip.com/ATSHA204A)
|
||||
- [ATECC108A](http://www.microchip.com/ATECC108A)
|
||||
- [ATECC508A](http://www.microchip.com/ATECC508A)
|
||||
- [ATECC608A](http://www.microchip.com/ATECC608A)
|
||||
|
||||
Online documentation is at https://microchiptech.github.io/cryptoauthlib/
|
||||
|
||||
Latest software and examples can be found at:
|
||||
- http://www.microchip.com/SWLibraryWeb/product.aspx?product=CryptoAuthLib
|
||||
- https://github.com/MicrochipTech/cryptoauthtools
|
||||
|
||||
Prerequisite skills:
|
||||
- strong C programming and code reading
|
||||
- Atmel Studio familiarity
|
||||
- Knowledge of flashing microcontrollers with new code
|
||||
- Familiarity with Microchip CryptoAuth device functionality
|
||||
|
||||
Prerequisite hardware to run CryptoAuthLib examples:
|
||||
- [ATSAMR21 Xplained Pro]( http://www.microchip.com/atsamr21-xpro )
|
||||
or [ATSAMD21 Xplained Pro]( http://www.microchip.com/ATSAMD21-XPRO )
|
||||
- [CryptoAuth Xplained Pro Extension](http://www.microchip.com/developmenttools/productdetails.aspx?partno=atcryptoauth-xpro-b )
|
||||
or [CryptoAuthentication SOIC Socket Board](http://www.microchip.com/developmenttools/productdetails.aspx?partno=at88ckscktsoic-xpro )
|
||||
to accept SOIC parts
|
||||
|
||||
For most development, using socketed top-boards is preferable until your
|
||||
configuration is well tested, then you can commit it to a CryptoAuth Xplained
|
||||
Pro Extension, for example. Keep in mind that once you lock a device, it will
|
||||
not be changeable.
|
||||
|
||||
There are two major compiler defines that affect the operation of the library.
|
||||
- ATCA_NO_POLL can be used to revert to a non-polling mechanism for device
|
||||
responses. Normally responses are polled for after sending a command,
|
||||
giving quicker response times. However, if ATCA_NO_POLL is defined, then
|
||||
the library will simply delay the max execution time of a command before
|
||||
reading the response.
|
||||
- ATCA_NO_HEAP can be used to remove the use of malloc/free from the main
|
||||
library. This can be helpful for smaller MCUs that don't have a heap
|
||||
implemented. If just using the basic API, then there shouldn't be any code
|
||||
changes required. The lower-level API will no longer use the new/delete
|
||||
functions and the init/release functions should be used directly.
|
||||
|
||||
Examples
|
||||
-----------
|
||||
|
||||
- Watch [CryptoAuthLib Documents](http://www.microchip.com/design-centers/security-ics/cryptoauthentication/overview )
|
||||
for new examples coming online.
|
||||
- Node Authentication Example Using Asymmetric PKI is a complete, all-in-one
|
||||
example demonstrating all the stages of crypto authentication starting from
|
||||
provisioning the Crypto Authentication device ATECC608A/ATECC508A with keys
|
||||
and certificates to demonstrating an authentication sequence using
|
||||
asymmetric techniques.
|
||||
http://www.microchip.com/SWLibraryWeb/product.aspx?product=CryptoAuthLib
|
||||
|
||||
Release notes
|
||||
-----------
|
||||
11/22/2019
|
||||
- Patches for CVE-2019-16128 & CVE-2019-16129: Ensure reported packet length
|
||||
is valid for the packet being processed.
|
||||
- Improvement to encrypted read operations to allow supply of a host nonce
|
||||
(prevent replay of a read sequence to the host). Default API is changed
|
||||
but can be reverted by setting the option ATCA_USE_CONSTANT_HOST_NONCE
|
||||
- Added Azure compatible TNGTLS and TNGLORA certificates. Use the TNG client
|
||||
API to retrieve the proper certificate based on the device.
|
||||
- Misc Python updates (updated APIs for encrypted reads to match the C-API change)
|
||||
atcacert_cert_element_t now initializes properly
|
||||
|
||||
08/30/2019
|
||||
- Added big-endian architecture support
|
||||
- Fixes to atcah_gen_dig() and atcah_nonce()
|
||||
|
||||
05/17/2019
|
||||
- Added support for TNG devices (cert transforms, new API)
|
||||
- atcab_write_pub_key() now works when the data zone is unlocked
|
||||
|
||||
03/04/2019
|
||||
- mbed TLS wrapper added
|
||||
- Minor bug fixes
|
||||
|
||||
01/25/2019
|
||||
- Python JWT support
|
||||
- Python configuration structures added
|
||||
- Restructure of secure boot app
|
||||
|
||||
01/04/2019
|
||||
- Added GCM functions
|
||||
- Split AES modes into separate files
|
||||
- Bug fix in SWI START driver
|
||||
|
||||
10/25/2018
|
||||
- Added basic certificate functions to the python wrapper.
|
||||
- Added Espressif ESP32 I2C driver.
|
||||
- Made generic Atmel START drivers to support most MCUs in START.
|
||||
- Added AES-CTR mode functions.
|
||||
- Python wrapper functions now return single values with AtcaReference.
|
||||
- Added mutex support to HAL and better support for freeRTOS.
|
||||
|
||||
08/17/2018
|
||||
- Better support for multiple kit protocol devices
|
||||
|
||||
07/25/2018
|
||||
- Clean up python wrapper
|
||||
|
||||
07/18/2018
|
||||
- Added ATCA_NO_HEAP define to remove use of malloc/free.
|
||||
- Moved PEM functions to their own file in atcacert.
|
||||
- Added wake retry to accomodate power on self test delay.
|
||||
- Added ca_cert_def member to atcacert_def_s so cert chains can be traversed
|
||||
as a linked list.
|
||||
|
||||
03/29/2018
|
||||
- Added support for response polling by default, which will make commands
|
||||
return faster (define ATCA_NO_POLL to use old delay method).
|
||||
- Removed atcatls related files as they were of limited value.
|
||||
- Test framework generates a prompt before locking test configuration.
|
||||
- Test framework puts device to sleep between tests.
|
||||
- Fixed mode parameter issue in atcah_gen_key_msg().
|
||||
- ATECC608A health test error code added.
|
||||
|
||||
01/15/2018
|
||||
- Added AES-128 CBC implementation using AES command
|
||||
- Added AES-128 CMAC implementation using AES command
|
||||
|
||||
11/22/2017
|
||||
- Added support for FLEXCOM6 on SAMG55 driver
|
||||
|
||||
11/17/2017
|
||||
- Added library support for the ATECC608A device
|
||||
- Added support for Counter command
|
||||
- atca_basic functions and tests now split into multiple files based on
|
||||
command
|
||||
- Added support for multiple base64 encoding rules
|
||||
- Added support for JSON Web Tokens (jwt)
|
||||
- Fixed atcab_write_enc() function to encrypt the data even when the device
|
||||
is unlocked
|
||||
- Fixed atcab_base64encode_() for the extra newline
|
||||
- Updated atcab_ecdh_enc() to work more consistently
|
||||
|
||||
07/01/2017
|
||||
- Removed assumption of SN[0:1]=0123, SN[8]=EE. SN now needs to be passed in
|
||||
for functions in atca_host and atca_basic functions will now read the
|
||||
config zone for the SN if needed.
|
||||
- Renamed atcab_gendig_host() to atcab_gendig() since it's not a host
|
||||
function. Removed original atcab_gendig(), which had limited scope.
|
||||
- Fixed atcah_hmac() for host side HMAC calculations. Added atcab_hmac().
|
||||
- Removed unnecessary ATCADeviceType parameters from some atca_basic
|
||||
functions.
|
||||
- Added atcacert_create_csr() to create a signed CSR.
|
||||
- New HAL implementation for Kit protocol over HID on Linux. Please see the
|
||||
Incorporating CryptoAuthLib in a Linux project using USB HID devices
|
||||
section in this file for more information.
|
||||
- Added atcacert_write_cert() for writing certificates to the device.
|
||||
- Added support for dynamic length certificate serial numbers in atcacert.
|
||||
- Added atcab_write() for lower level write commands.
|
||||
- Fixed atcah_write_auth_mac(), which had wrong OpCode.
|
||||
- Added atcab_verify() command for lower level verify commands.
|
||||
- Added atcab_verify_stored() for verifying data with a stored public key.
|
||||
- Removed atcab_write_bytes_slot(). Use atcab_write_bytes_zone() instead.
|
||||
- Modified atcab_write_bytes_zone() and atcab_read_bytes_zone() to specify a
|
||||
slot
|
||||
- Added atcab_verify_validate() and atcab_verify_invalidate()
|
||||
- Improvements to host functions to handle more cases.
|
||||
- Added atcab_updateextra(), atcab_derive_key()
|
||||
- Added support for more certificate formats.
|
||||
- Added general purpose hardware SHA256 functions. See atcab_hw_sha2_256().
|
||||
- Removed device specific config read/write. Generic now handles both.
|
||||
- Removed unnecessary response parameter from lock commands.
|
||||
- Enhanced and added unit tests.
|
||||
- Encrypted read and write functions now handle keys with SlotConfig.NoMac
|
||||
set
|
||||
- atcab_cmp_config_zone() handles all devices now.
|
||||
- Fixed some edge cases in atcab_read_bytes_zone().
|
||||
- Updated atSHA() to work with all devices.
|
||||
- Fixed atcacert_get_device_locs() when using stored sn.
|
||||
|
||||
01/08/2016
|
||||
- New HAL implementations for
|
||||
- Single Wire interface for SAMD21 / SAMR21
|
||||
- SAMV71 I2C HAL implementation
|
||||
- XMega A3Bu HAL implementation
|
||||
- Added atcab_version() method to return current version string of libary to
|
||||
application
|
||||
- New Bus and Discovery API
|
||||
- returns a list of ATCA device configurations for each CryptoAuth device
|
||||
found
|
||||
- currently implemented on SAMD21/R21 I2C, SAMV71
|
||||
- additional discovery implementations to come
|
||||
- TLS APIs solidified and documented
|
||||
- Added missing doxygen documentation for some CryptoAuthLib methods
|
||||
- Stubs for HAL SPI removed as they are unused for SHA204A and ECC508A
|
||||
support
|
||||
- bug fixes
|
||||
- updated atcab_sha() to accept a variable length message that is > 64 bytes
|
||||
and not a multiple of 64 bytes (the SHA block size).
|
||||
- refactored Cert I/O and Cert Data tests to be smaller
|
||||
- 'uncrustify' source formatting
|
||||
- published on GitHub
|
||||
|
||||
9/19/2015
|
||||
- Kit protocol over HID on Windows
|
||||
- Kit protocol over CDC on Linux
|
||||
- TLS integration with ATECC508A
|
||||
- Certificate I/O and reconstruction
|
||||
- New SHA2 implementation
|
||||
- Major update to API docs, Doxygen files found in cryptoauthlib/docs
|
||||
- load cryptoauthlib/docs/index.html with your browser
|
||||
|
||||
Host Device Support
|
||||
---------------
|
||||
|
||||
CryptoAuthLib will run on a variety of platforms from small micro-controllers
|
||||
to desktop host systems. The current list of hardware abstraction layer
|
||||
support includes:
|
||||
|
||||
Rich OS Hosts:
|
||||
- Linux Kit Protocol over CDC USB
|
||||
- Linux Kit Protocol over HID USB
|
||||
- Linux I2C protocol.
|
||||
- Windows Kit Protocol over CDC USB
|
||||
- Windows Kit Protocol over HID USB
|
||||
|
||||
Microcontrollers:
|
||||
- SAMD21 (I2C, SWI, and Bit Banging)
|
||||
- SAMR21 (I2C and SWI)
|
||||
- SAM4S (I2C)
|
||||
- SAMV71 (I2C)
|
||||
- SAMB11 (I2C)
|
||||
- SAMG55 (I2C)
|
||||
- AVR XMEGA A3BU (I2C and SWI)
|
||||
- AVR AT90USB1287 (I2C and SWI)
|
||||
- PIC32MX695F512H (I2C)
|
||||
|
||||
If you have specific microcontrollers or Rich OS platforms you need support
|
||||
for, please contact us through the Microchip portal with your request.
|
||||
|
||||
CryptoAuthLib Architecture
|
||||
----------------------------
|
||||
See the 'docs' directory of CryptoAuthLib for supporting documentation
|
||||
including architecture diagrams and more detailed usage docs.
|
||||
|
||||
The library is structured to support portability to:
|
||||
- multiple hardware/microcontroller platforms
|
||||
- multiple environments including bare-metal, Windows, and Linux OS
|
||||
- multiple chip communication protocols (I2C, SPI, UART, and SWI)
|
||||
|
||||
All platform dependencies are contained within the HAL (hardware abstraction
|
||||
layer).
|
||||
|
||||

|
||||
|
||||
There are three primary object types in CryptoAuthLib:
|
||||
- Device (ATCADevice)
|
||||
- Command (ATCACommand)
|
||||
- Interface (ATCAIface)
|
||||
|
||||
ATCADevice is a composite object made up of ATCACommand ATCAIface.
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
Currently, the vast majority of testing has been performed on:
|
||||
|
||||
- ATSAMR21 Xplained Pro
|
||||
- ATSAMD21 Xplained Pro
|
||||
- ATSAMV71 Xplained Pro
|
||||
- Windows (kit protocol HID)
|
||||
|
||||
These host containers implement a host test environment and
|
||||
test console to exercise tests. They presume that a CryptoAuth Xplained Pro
|
||||
or other I2C socket for an ATECC608A/ATECC508A/ATECC108A/ATSHA204A are
|
||||
connected to the I2C pins of the host Xplained Pro development board or in the
|
||||
case of windows is using a HID connection to an ATCK101 or ATCK590.
|
||||
|
||||
The unit tests and basic tests exercise the core datasheet commands of
|
||||
the device as well as the more convenient, basic API methods.
|
||||
|
||||
If you need an example of how to use a command, these hosts and tests are a
|
||||
good place to reference.
|
||||
|
||||
Object Architecture
|
||||
--------------------------
|
||||
Even though this is a C library, it follows object-oriented design patterns.
|
||||
|
||||
An object is minimally defined to be data and the actions which operate on that
|
||||
data.
|
||||
|
||||
Each CryptoAuth device is a composite object, a structure which includes
|
||||
the command table (list of commands) which are valid for the device, and the
|
||||
data used to hold the state of that device.
|
||||
|
||||
ATCADevice is the object which represents the Microchip CryptAuth device
|
||||
|
||||
ATCACommand is the object which represents the valid methods of the Device.
|
||||
|
||||
ATCAInterface is the physical interface object (I2C or SWI instance).
|
||||
Currently, each Device may have a single OATCAInterface.
|
||||
|
||||
ATCADevice represents an ATSHA or ATECC family device.
|
||||
|
||||
In order to add new protocol support for a platform, you provide a HAL
|
||||
(hardware abstraction layer) C file for the protocol and target. In your
|
||||
project's IDE or Makefile, you select which HAL support you need for the
|
||||
hardware configuration. Generally, there are separate files for each
|
||||
protocol and platform combination - (ie: samd21_i2c_asf.c would target SAMD21
|
||||
MCUs with I2C using the ASF low-level driver support.)
|
||||
|
||||
Directory Structure
|
||||
-----------------------
|
||||
```bash
|
||||
docs - AppNotes and Doxygen HTML documentation for the library API. Load "docs/html/index.html" in your browser
|
||||
lib - primary library source code
|
||||
lib/atcacert - certificate data and i/o methods
|
||||
lib/basic - the Basic API way to access the core classes
|
||||
lib/crypto - Software crypto implementations (primarily SHA1 and SHA256)
|
||||
lib/hal - hardware abstraction layer code for supporting specific platforms
|
||||
lib/host - support functions for common host-side calculations
|
||||
lib/jwt - json web token functions
|
||||
test - unit tests. See test/cmd-processor.c for main() implementation.
|
||||
|
||||
For production code, test directories should be excluded by not compiling it
|
||||
into a project, so it is up to the developer to include or not as needed. Test
|
||||
code adds significant bulk to an application - it's not intended to be included
|
||||
in production code.
|
||||
```
|
||||
|
||||
Tests
|
||||
------------
|
||||
|
||||
There is a set of unit tests found in the test directory which will at least
|
||||
partially demonstrate the use of the objects. Some tests may depend upon a
|
||||
certain device being configured in a certain way and may not work for all
|
||||
devices or specific configurations of the device.
|
||||
|
||||
The test/cmd-processor.c file contains a main() function for running the tests.
|
||||
It implements a command-line interface. Typing help will bring up the list of
|
||||
commands available.
|
||||
|
||||
One first selects a device type, with one of the following commands:
|
||||
- 204 (ATSHA204A)
|
||||
- 108 (ATECC108A)
|
||||
- 508 (ATECC508A)
|
||||
- 608 (ATECC608A)
|
||||
|
||||
From there the following unit test sweets are available:
|
||||
- unit (test command builder functions)
|
||||
- basic (test basic API functions)
|
||||
- cio (test certification i/o functions)
|
||||
- cd (test certificate data functions)
|
||||
- util (test utility functions)
|
||||
- crypto (test software crypto functions)
|
||||
|
||||
Unit tests available depend on the lock level of the device. The unit tests
|
||||
won't lock the config or data zones automatically to allow retesting at desired
|
||||
lock levels. Therefore, some commands will need to be repeated after locking
|
||||
to exercise all available tests.
|
||||
|
||||
Starting from a blank device, the sequence of commands to exercise all unit
|
||||
tests is:
|
||||
```text
|
||||
unit
|
||||
basic
|
||||
lockcfg
|
||||
unit
|
||||
basic
|
||||
lockdata
|
||||
unit
|
||||
basic
|
||||
cio
|
||||
cd
|
||||
util
|
||||
crypto
|
||||
```
|
||||
|
||||
Using CryptoAuthLib (Microchip CryptoAuth Library)
|
||||
===========================================
|
||||
|
||||
Using a new library is often easier when you can load an example and see how
|
||||
it works. We've provided examples in the form of "host containers" which are
|
||||
host projects that incorporate CryptoAuthLib and target various processors
|
||||
or communication APIs.
|
||||
|
||||
We maintain host test containers for each of the HAL layers we support.
|
||||
We've published the host container for SAMD21 which demonstrates a simple
|
||||
console interface to invoke test runners.
|
||||
|
||||
Look for SAMD21 Unit Tests CryptoAuthLib at
|
||||
http://www.microchip.com/SWLibraryWeb/product.aspx?product=CryptoAuthLib
|
||||
|
||||
The best way to learn how to use CryptoAuthLib is to study the host test
|
||||
projects that exercise the library and ATECC and ATSHA devices.
|
||||
|
||||
New examples will be forthcoming as the software matures. Continue checking
|
||||
the [CryptoAuthentication](http://www.microchip.com/design-centers/security-ics/cryptoauthentication/overview)
|
||||
web page for new updates.
|
||||
|
||||
Using Git to Incorporate CryptoAuthLib as a Submodule
|
||||
-----------------------------------
|
||||
You can include this project in your own project under git.
|
||||
|
||||
Using CryptoAuthLib as a git submodule, you can maintain your application
|
||||
separately from CryptoAuthLib.
|
||||
|
||||
If your project is already in git but you haven't yet intergrated
|
||||
CryptoAuthLib, change to the directory where you want to put CryptoAuthLib
|
||||
|
||||
```bash
|
||||
git submodule add -b master <giturl to CryptoAuthLib>
|
||||
```
|
||||
|
||||
This adds CryptoAuthLib as a subdirectory and separate git repo within your
|
||||
own project. Changes and commits to your project vs CryptoAuthLib will remain
|
||||
separated into each respective repository.
|
||||
|
||||
If there is a project you want to checkout that already incorporates
|
||||
CryptoAuthLib as a submodule if you clone the repo that incorporates
|
||||
CryptoAuthLib, after cloning, you'll still need to fill out the CryptoAuthLib
|
||||
submodule after cloning:
|
||||
```bash
|
||||
git submodule init
|
||||
git submodule update --remote
|
||||
cd cryptoauthlib
|
||||
git checkout master
|
||||
```
|
||||
|
||||
Now that CryptoAuthLib is a full-fledged submodule in your git project, in
|
||||
order to easily add it to your project within Atmel Studio, please see this
|
||||
[tip](http://avrstudio5.wordpress.com/2011/07/12/tip-add-existing-multiple-files-and-folders-to-an-avr-studio-project-quickly/)
|
||||
|
||||
Incorporating CryptoAuthLib in a project
|
||||
-----------------------------------------
|
||||
1) In your Makefile or IDE, choose the HAL support you need from the HAL
|
||||
directory and exclude other HAL files from your project.
|
||||
|
||||
2) For I2C interfaces, define the symbol ATCA_HAL_I2C in your compiler's symbol
|
||||
definitions. This will hook up the CryptoAuthLib interface class with your
|
||||
HAL implementation of I2C methods.
|
||||
|
||||
3) HAL implementations for CDC and HID interfaces to the ATCK101 are also
|
||||
included for use with Windows or Linux versions of the test host.
|
||||
|
||||
Incorporating CryptoAuthLib in a Linux project using USB HID devices
|
||||
-----------------------------------------
|
||||
The Linux HID HAL files use the Linux udev development software package.
|
||||
|
||||
To install the udev development package under Ubuntu Linux, please type the
|
||||
following command at the terminal window:
|
||||
|
||||
```bash
|
||||
sudo apt-get install libudev-dev
|
||||
```
|
||||
|
||||
This adds the udev development development software package to the Ubuntu Linux
|
||||
installation.
|
||||
|
||||
The Linux HID HAL files also require a udev rule to be added to change the
|
||||
permissions of the USB HID Devices. Please add a new udev rule for the
|
||||
Microchip CryptoAuth USB devices.
|
||||
|
||||
```bash
|
||||
cd /etc/udev/rules.d
|
||||
sudo touch mchp-cryptoauth.rules
|
||||
```
|
||||
|
||||
Edit the mchp-cryptoauth.rules file and add the following line to the file:
|
||||
```text
|
||||
SUBSYSTEM=="hidraw", ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="2312", MODE="0666"
|
||||
```
|
||||
@@ -0,0 +1,8 @@
|
||||
app directory - Purpose
|
||||
===================
|
||||
|
||||
This directory is for application specific implementation of various use cases.
|
||||
|
||||
Methods in this directory provide a simple API to perform potentially complex
|
||||
combinations of calls to the main library or API.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
IP Protection with Symmetric Authentication
|
||||
------------------------
|
||||
The IP protection can be easily integrated to the existing projects.The user project should include symmetric_authentication.c & symmetric_authentication.h files which contains the api
|
||||
- **symmetric_authenticate()** - For Performing the authentication between host & device.
|
||||
|
||||
User Considerations
|
||||
-----------
|
||||
- The user should take care on how the master key should be stored on the MCU side.
|
||||
- The api's in the file doesn't do the provisioning of the chip and user should take care of the provisioning.
|
||||
|
||||
With the provisioned cryptoauthentication device and after doing the cryptoauthlib initialisation,user should only be calling the function symmetric_authenticate() with its necessary parameters for the authentication. The returned authentication status should be used in the application.
|
||||
|
||||
Examples
|
||||
-----------
|
||||
For more information about IP protection and its example project refer [Microchip github](https://github.com/MicrochipTech)
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Contains API for performing the symmetric Authentication between the Host and the device
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "cryptoauthlib.h"
|
||||
#include "host/atca_host.h"
|
||||
#include "symmetric_authentication.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/** \brief Function which does the authentication between the host and device.
|
||||
* \param[in] slot The slot number used for the symmetric authentication.
|
||||
* \param[in] master_key The master key used for the calculating the symmetric key.
|
||||
* \param[in] rand_number The 20 byte rand_number from the host.
|
||||
* \return ATCA_SUCCESS on successful authentication, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS symmetric_authenticate(uint8_t slot, const uint8_t *master_key, const uint8_t *rand_number)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t sn[ATCA_SERIAL_NUM_SIZE];
|
||||
uint8_t symmetric_key[ATCA_KEY_SIZE];
|
||||
atca_temp_key_t temp_key, temp_key_derive;
|
||||
uint8_t rand_out[RANDOM_NUM_SIZE];
|
||||
atca_nonce_in_out_t nonce_params;
|
||||
atca_mac_in_out_t mac_params;
|
||||
uint8_t host_mac[MAC_SIZE];
|
||||
uint8_t device_mac[MAC_SIZE];
|
||||
struct atca_derive_key_in_out derivekey_params;
|
||||
|
||||
do
|
||||
{
|
||||
// Read serial number for host-side MAC calculations
|
||||
if ((status = atcab_read_serial_number(sn)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Setup nonce command
|
||||
memset(&temp_key, 0, sizeof(temp_key));
|
||||
memset(&nonce_params, 0, sizeof(nonce_params));
|
||||
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
|
||||
nonce_params.zero = 0;
|
||||
nonce_params.num_in = rand_number;
|
||||
nonce_params.rand_out = rand_out;
|
||||
nonce_params.temp_key = &temp_key;
|
||||
|
||||
// Create random nonce
|
||||
if ((status = atcab_nonce_rand(nonce_params.num_in, rand_out)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate nonce in host
|
||||
if ((status = atcah_nonce(&nonce_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
memset(&temp_key_derive, 0, sizeof(temp_key_derive));
|
||||
temp_key_derive.valid = 1;
|
||||
memcpy(temp_key_derive.value, sn, sizeof(sn)); // 32 bytes TempKey ( SN[0:8] with padded 23 zeros used in symmetric key calculation)
|
||||
|
||||
// Parameters used deriving the symmetric key
|
||||
derivekey_params.mode = 0;
|
||||
derivekey_params.target_key_id = slot;
|
||||
derivekey_params.parent_key = master_key;
|
||||
derivekey_params.sn = sn;
|
||||
derivekey_params.target_key = symmetric_key;
|
||||
derivekey_params.temp_key = &temp_key_derive;
|
||||
|
||||
// calculate the symmetric_diversified_key
|
||||
if ((status = atcah_derive_key(&derivekey_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Setup MAC command
|
||||
memset(&mac_params, 0, sizeof(mac_params));
|
||||
mac_params.mode = MAC_MODE_BLOCK2_TEMPKEY | MAC_MODE_INCLUDE_SN; // Block 1 is a key, block 2 is TempKey
|
||||
mac_params.key_id = slot;
|
||||
mac_params.challenge = NULL;
|
||||
mac_params.key = symmetric_key;
|
||||
mac_params.otp = NULL;
|
||||
mac_params.sn = sn;
|
||||
mac_params.response = host_mac;
|
||||
mac_params.temp_key = &temp_key;
|
||||
|
||||
// Generate the MAC command from the device
|
||||
if ((status = atcab_mac(mac_params.mode, mac_params.key_id, mac_params.challenge, device_mac)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate the MAC on the host side
|
||||
if (( status = atcah_mac(&mac_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
//Check whether the MAC calculated on host is same as that generated from the device
|
||||
if (memcmp(device_mac, host_mac, 32) != 0)
|
||||
{
|
||||
status = ATCA_CHECKMAC_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Contains API for performing the symmetric Authentication between the Host and the device
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SYMMETRIC_AUTHENTICATION_H_
|
||||
#define SYMMETRIC_AUTHENTICATION_H_
|
||||
|
||||
#include "cryptoauthlib.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ATCA_STATUS symmetric_authenticate(uint8_t slot, const uint8_t *master_key, const uint8_t *rand_number);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* SYMMETRIC_AUTHENTICATION_H_ */
|
||||
@@ -0,0 +1,83 @@
|
||||
# Secure boot using ATECC608A
|
||||
|
||||
The SecureBoot command is a new feature on the
|
||||
[ATECC608A](https://www.microchip.com/wwwproducts/en/ATECC608A) device compared
|
||||
to earlier CryptoAuthentication devices from Microchip. This feature helps the
|
||||
MCU to identify fraudulent code installed on it. When this feature is
|
||||
implemented, the MCU can send a firmware digest and signature to the ATECC608A.
|
||||
The ATECC608A validates this information (ECDSA verify) and responds to host
|
||||
with a yes or no answer.
|
||||
|
||||
The ATECC608A provides options to reduce the firmware verification time by
|
||||
storing the signature or digest after a good full verification (FullStore mode
|
||||
of the SecureBoot command).
|
||||
|
||||
- When the ATECC608A stores the digest (SecureBootMode is FullDig), the host
|
||||
only needs to send the firmware digest, which is compared to the stored
|
||||
copy. This skips the comparatively lengthy ECDSA verify, speeding up the
|
||||
secure boot process.
|
||||
|
||||
- When the ATECC608A stores the signature (SecureBootMode is FullSig), the
|
||||
host only needs to send the firmware digest, which is verified against the
|
||||
stored signature using ECDSA. This saves time by not needing to send the
|
||||
signature in the command over the bus.
|
||||
|
||||
The ATECC608A also provides wire protection features for the SecureBoot
|
||||
command, which can be used to encrypt the digest being sent from the host to
|
||||
the ATECC608A and add a MAC to the verify result coming back to the host so it
|
||||
can't be forced to a success state. This feature makes use of a shared secret
|
||||
between the host and ATECC608A, called the IO protection key.
|
||||
|
||||
The secure boot feature can be easily integrated to an existing project. The
|
||||
project should include the following files from the secure_boot folder:
|
||||
- secure_boot.c
|
||||
- secure_boot.h
|
||||
- secure_boot_memory.h
|
||||
- io_protection_key.h
|
||||
|
||||
The project should also implement the following platform-specific APIs:
|
||||
- secure_boot_init_memory()
|
||||
- secure_boot_read_memory()
|
||||
- secure_boot_deinit_memory()
|
||||
- secure_boot_mark_full_copy_completion()
|
||||
- secure_boot_check_full_copy_completion()
|
||||
- io_protection_get_key()
|
||||
- io_protection_set_key()
|
||||
|
||||
The project can set the secure boot configuration with the following defines:
|
||||
- SECURE_BOOT_CONFIGURATION
|
||||
- SECURE_BOOT_DIGEST_ENCRYPT_ENABLED
|
||||
- SECURE_BOOT_UPGRADE_SUPPORT
|
||||
|
||||
The secure boot process is performed by initializing CryptoAuthLib and calling
|
||||
the secure_boot_process() function.
|
||||
|
||||
## Implementation Considerations
|
||||
|
||||
- Need to perform SHA256 calculations on the host. CryptoAuthLib provides a
|
||||
software implementation in lib/crypto/atca_crypto_sw_sha2.c
|
||||
|
||||
- When using the wire protection features:
|
||||
|
||||
- The host needs to be able to generate a nonce (number used once).
|
||||
This is the NumIn parameter to the Nonce command that is sent before the
|
||||
SecureBoot command. The ATECC608A can not be used to generate NumIn, but
|
||||
it should come from a good random or non-repeating source in the host.
|
||||
|
||||
- If the host has any protected internal memory, it should be used to store
|
||||
its copy of the IO protection key.
|
||||
|
||||
- Secure boot depends on proper protections of the boot loader code in the
|
||||
host. If the code can be easily changed, then the secure boot process can be
|
||||
easily skipped. Boot loader should ideally be stored in an immutable
|
||||
(unchangeable) location like a boot ROM or write-protected flash.
|
||||
|
||||
- Note that these APIs don't provision the ATECC608A. They assume the
|
||||
ATECC608A has already been configured and provisioned with the necessary
|
||||
keys for secure boot.
|
||||
|
||||
Examples
|
||||
-----------
|
||||
For more information about secure boot, please see the example implementation
|
||||
project and documentation at:
|
||||
https://github.com/MicrochipTech/cryptoauth_usecase_secureboot
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Provides required interface to access IO protection key.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef IO_PROTECTION_H
|
||||
#define IO_PROTECTION_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "atca_status.h"
|
||||
|
||||
extern ATCA_STATUS io_protection_get_key(uint8_t* io_key);
|
||||
extern ATCA_STATUS io_protection_set_key(uint8_t* io_key);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Provides required APIs to manage secure boot under various scenarios.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "secure_boot.h"
|
||||
#include "io_protection_key.h"
|
||||
#include "basic/atca_basic.h"
|
||||
|
||||
/*Initialization routines */
|
||||
static ATCA_STATUS secure_boot_init(secure_boot_parameters* secure_boot_params);
|
||||
|
||||
/*Secure boot process routines */
|
||||
static ATCA_STATUS secure_boot_calc_app_digest(secure_boot_parameters* secure_boot_params);
|
||||
|
||||
/** \brief Handles secure boot functionality through initialization, execution,
|
||||
* and de-initialization.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS secure_boot_process(void)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
secure_boot_parameters secure_boot_params;
|
||||
uint8_t secure_boot_mode;
|
||||
bool secure_boot_app_valid = false;
|
||||
|
||||
/*Initialize secure boot */
|
||||
if ((status = secure_boot_init(&secure_boot_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Calculate application digest */
|
||||
if ((status = secure_boot_calc_app_digest(&secure_boot_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#if (SECURE_BOOT_CONFIGURATION == SECURE_BOOT_CONFIG_FULL_BOTH)
|
||||
secure_boot_mode = SECUREBOOT_MODE_FULL;
|
||||
#else
|
||||
secure_boot_mode = SECUREBOOT_MODE_FULL_STORE;
|
||||
#endif
|
||||
|
||||
#if SECURE_BOOT_UPGRADE_SUPPORT
|
||||
/*Check need for full copy */
|
||||
if (false == secure_boot_check_full_copy_completion())
|
||||
{
|
||||
secure_boot_mode = SECUREBOOT_MODE_FULL_COPY;
|
||||
}
|
||||
#endif //#if SECURE_BOOT_UPGRADE_SUPPORT
|
||||
|
||||
#if SECURE_BOOT_DIGEST_ENCRYPT_ENABLED
|
||||
/*Get Random number from Host*/
|
||||
if ((status = host_generate_random_number(secure_boot_params.randomnum)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/*Get IO Protection Key*/
|
||||
if ((status = io_protection_get_key(secure_boot_params.io_protection_key)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((status = atcab_secureboot_mac(secure_boot_mode,
|
||||
(const uint8_t*)&secure_boot_params.app_digest,
|
||||
(const uint8_t*)&secure_boot_params.memory_params.signature,
|
||||
(const uint8_t*)secure_boot_params.randomnum,
|
||||
(const uint8_t*)secure_boot_params.io_protection_key,
|
||||
&secure_boot_app_valid)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if ((status = atcab_secureboot(secure_boot_mode,
|
||||
0,
|
||||
(const uint8_t*)&secure_boot_params.app_digest,
|
||||
(const uint8_t*)&secure_boot_params.memory_params.signature,
|
||||
NULL)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
secure_boot_app_valid = true;
|
||||
#endif
|
||||
|
||||
/*Check whether the secure boot command executed successfully with the correct return mac */
|
||||
if (!secure_boot_app_valid)
|
||||
{
|
||||
status = ATCA_CHECKMAC_VERIFY_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Mark to indicate full copy is executed */
|
||||
if ((SECUREBOOT_MODE_FULL_COPY == secure_boot_mode) && ((status = secure_boot_mark_full_copy_completion()) != ATCA_SUCCESS))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
/* De-initialize memory interface and release its resources*/
|
||||
secure_boot_deinit_memory(&secure_boot_params.memory_params);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Verifies configuration as well as memory initialization.
|
||||
* \param[inout] secure_boot_params Secure boot parameters
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS secure_boot_init(secure_boot_parameters* secure_boot_params)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint16_t secure_boot_config;
|
||||
uint8_t buf[2];
|
||||
|
||||
/*Reset all parameters before starting the process */
|
||||
memset((void*)secure_boot_params, 0, sizeof(secure_boot_parameters));
|
||||
|
||||
/*Read Configuration data & verify device configuration settings*/
|
||||
if ((status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, SECUREBOOTCONFIG_OFFSET, buf, 2)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
secure_boot_config = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
|
||||
/*Return error status if configuration and device settings doesn't match */
|
||||
if ((secure_boot_config & SECUREBOOTCONFIG_MODE_MASK) != SECURE_BOOT_CONFIGURATION)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
|
||||
/*Initialize memory interface and get its parameters*/
|
||||
if ((status = secure_boot_init_memory(&secure_boot_params->memory_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
/** \brief Calculates the application digest using software SHA256
|
||||
* implementation.
|
||||
* \param[inout] secure_boot_params Secure boot parameters
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS secure_boot_calc_app_digest(secure_boot_parameters* secure_boot_params)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t sha_data[ATCA_SHA256_BLOCK_SIZE];
|
||||
uint32_t total_data_count = 0;
|
||||
uint32_t current_data_count;
|
||||
|
||||
/*Initialize SHA engine*/
|
||||
if ((status = atcac_sw_sha2_256_init(&secure_boot_params->s_sha_context)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
/*Loop through SHA calculation for given memory*/
|
||||
while (total_data_count < secure_boot_params->memory_params.memory_size)
|
||||
{
|
||||
/*Default set to data size*/
|
||||
current_data_count = sizeof(sha_data);
|
||||
|
||||
/*Check if data exceeds available memory*/
|
||||
if ((total_data_count + current_data_count) > secure_boot_params->memory_params.memory_size)
|
||||
{
|
||||
/*Restrict to upper limit of memory*/
|
||||
current_data_count = secure_boot_params->memory_params.memory_size - total_data_count;
|
||||
}
|
||||
|
||||
/*Read data from memory*/
|
||||
if ((status = secure_boot_read_memory(sha_data, ¤t_data_count)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
total_data_count += current_data_count;
|
||||
|
||||
/*Calculate SHA for the current set of data*/
|
||||
if ((status = atcac_sw_sha2_256_update(&secure_boot_params->s_sha_context, sha_data, current_data_count)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/*Initiate final step and get SHA output*/
|
||||
if ((status = atcac_sw_sha2_256_finish(&secure_boot_params->s_sha_context, secure_boot_params->app_digest)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
/** \brief Binds host MCU and Secure element with IO protection key.
|
||||
* \param[in] slot The slot number of IO protection Key.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS bind_host_and_secure_element_with_io_protection(uint16_t slot)
|
||||
{
|
||||
bool is_locked;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t io_prot_key[ATCA_KEY_SIZE];
|
||||
|
||||
/*IO protection key is not on host... Get bind with device */
|
||||
do
|
||||
{
|
||||
/* First check Lock status on device */
|
||||
if ((status = atcab_is_slot_locked(slot, &is_locked)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_locked)
|
||||
{
|
||||
/*IO Protection Key shouldn't have already locked */
|
||||
status = ATCA_GEN_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*Get random number from device */
|
||||
if ((status = atcab_random(io_prot_key)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*Load the random number as IO Protection key on the device */
|
||||
if ((status = atcab_write_zone(ATCA_ZONE_DATA, slot, 0, 0, io_prot_key, ATCA_KEY_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*Store the same as IO Protection Key on host*/
|
||||
if ((status = io_protection_set_key(io_prot_key)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/*Lock IO protection key slot */
|
||||
if ((status = atcab_lock_data_slot(slot)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Provides required APIs to manage secure boot under various scenarios.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SECURE_BOOT_H
|
||||
#define SECURE_BOOT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "atca_status.h"
|
||||
#include "secure_boot_memory.h"
|
||||
#include "atca_command.h"
|
||||
#include "crypto/atca_crypto_sw_sha2.h"
|
||||
|
||||
#define SECURE_BOOT_CONFIG_DISABLE 0
|
||||
#define SECURE_BOOT_CONFIG_FULL_BOTH 1
|
||||
#define SECURE_BOOT_CONFIG_FULL_SIGN 2
|
||||
#define SECURE_BOOT_CONFIG_FULL_DIG 3
|
||||
|
||||
#ifndef SECURE_BOOT_CONFIGURATION
|
||||
#define SECURE_BOOT_CONFIGURATION SECURE_BOOT_CONFIG_FULL_DIG
|
||||
#endif
|
||||
|
||||
#ifndef SECURE_BOOT_DIGEST_ENCRYPT_ENABLED
|
||||
#define SECURE_BOOT_DIGEST_ENCRYPT_ENABLED true
|
||||
#endif
|
||||
|
||||
#ifndef SECURE_BOOT_UPGRADE_SUPPORT
|
||||
#define SECURE_BOOT_UPGRADE_SUPPORT true
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t secure_boot_mode : 2;
|
||||
uint16_t secure_boot_reserved1 : 1;
|
||||
uint16_t secure_boot_persistent_enable : 1;
|
||||
uint16_t secure_boot_rand_nonce : 1;
|
||||
uint16_t secure_boot_reserved2 : 3;
|
||||
uint16_t secure_boot_sig_dig : 4;
|
||||
uint16_t secure_boot_pub_key : 4;
|
||||
}secure_boot_config_bits;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
memory_parameters memory_params;
|
||||
atcac_sha2_256_ctx s_sha_context;
|
||||
uint8_t app_digest[ATCA_SHA_DIGEST_SIZE];
|
||||
#if SECURE_BOOT_DIGEST_ENCRYPT_ENABLED
|
||||
uint8_t randomnum[RANDOM_RSP_SIZE];
|
||||
uint8_t io_protection_key[ATCA_KEY_SIZE];
|
||||
#endif
|
||||
}secure_boot_parameters;
|
||||
|
||||
ATCA_STATUS secure_boot_process(void);
|
||||
ATCA_STATUS bind_host_and_secure_element_with_io_protection(uint16_t slot);
|
||||
extern ATCA_STATUS host_generate_random_number(uint8_t *rand);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Provides interface to memory component for the secure boot.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SECURE_BOOT_MEMORY_H
|
||||
#define SECURE_BOOT_MEMORY_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "atca_status.h"
|
||||
#include "atca_command.h"
|
||||
|
||||
|
||||
/*Blocking last USER_APPLICATION_HEADER_SIZE bytes for Signature and memory/application specific information*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t start_address;
|
||||
uint32_t memory_size;
|
||||
uint32_t version_info;
|
||||
uint8_t reserved[52]; //Reserving bytes for Application information and aligning to page
|
||||
uint8_t signature[ATCA_SIG_SIZE];
|
||||
}memory_parameters;
|
||||
|
||||
extern ATCA_STATUS secure_boot_init_memory(memory_parameters* memory_params);
|
||||
extern ATCA_STATUS secure_boot_read_memory(uint8_t* pu8_data, uint32_t* pu32_target_length);
|
||||
extern ATCA_STATUS secure_boot_write_memory(uint8_t* pu8_data, uint32_t* pu32_target_length);
|
||||
extern void secure_boot_deinit_memory(memory_parameters* memory_params);
|
||||
extern ATCA_STATUS secure_boot_mark_full_copy_completion(void);
|
||||
extern bool secure_boot_check_full_copy_completion(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
# TNG Functions
|
||||
|
||||
This folder has a number of convenience functions for working with TNG devices
|
||||
(currently ATECC608A-MAHTN-T).
|
||||
|
||||
These devices have standard certificates that can be easily read using the
|
||||
functions in tng_atcacert_client.h
|
||||
@@ -0,0 +1,108 @@
|
||||
#include <string.h>
|
||||
#include "tng_atca.h"
|
||||
#include "tnglora_cert_def_2_device.h"
|
||||
#include "tnglora_cert_def_4_device.h"
|
||||
#include "tngtls_cert_def_2_device.h"
|
||||
#include "tngtls_cert_def_3_device.h"
|
||||
|
||||
|
||||
ATCA_STATUS tng_get_type(tng_type_t* type)
|
||||
{
|
||||
ATCA_STATUS ret;
|
||||
uint8_t sn[ATCA_SERIAL_NUM_SIZE];
|
||||
|
||||
if (type == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
ret = atcab_read_serial_number(sn);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sn[8] == 0x10 || sn[8] == 0x27)
|
||||
{
|
||||
*type = TNGTYPE_LORA;
|
||||
}
|
||||
else
|
||||
{
|
||||
*type = TNGTYPE_TLS;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
ATCA_STATUS tng_get_device_cert_def(const atcacert_def_t **cert_def)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t sn[ATCA_SERIAL_NUM_SIZE];
|
||||
uint8_t otpcode[32];
|
||||
|
||||
if (cert_def == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
//Set default certificate definition
|
||||
*cert_def = &g_tngtls_cert_def_2_device;
|
||||
|
||||
status = atcab_read_serial_number(sn);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if (sn[8] == 0x01 || sn[8] == 0x10 || sn[8] == 0x27)
|
||||
{
|
||||
status = atcab_read_zone(ATCA_ZONE_OTP, 0, 0, 0, otpcode, 32);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((strncmp("wdNxAjae", otpcode, 8) == 0) || (strncmp("Rsuy5YJh", otpcode, 8) == 0))
|
||||
{
|
||||
*cert_def = &g_tngtls_cert_def_2_device;
|
||||
}
|
||||
else if ((strncmp("KQp2ZkD8", otpcode, 8) == 0) || (strncmp("x6tjuZMy", otpcode, 8) == 0))
|
||||
{
|
||||
*cert_def = &g_tngtls_cert_def_3_device;
|
||||
}
|
||||
else if (strncmp("BxZvm6q2", otpcode, 8) == 0)
|
||||
{
|
||||
*cert_def = &g_tnglora_cert_def_2_device;
|
||||
}
|
||||
else if ((strncmp("jsMu7iYO", otpcode, 8) == 0) || (strncmp("09qJNxI3", otpcode, 8) == 0))
|
||||
{
|
||||
*cert_def = &g_tnglora_cert_def_4_device;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Nothing to do...Already initialized to default
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
ATCA_STATUS tng_get_device_pubkey(uint8_t *public_key)
|
||||
{
|
||||
ATCA_STATUS ret;
|
||||
tng_type_t type;
|
||||
|
||||
ret = tng_get_type(&type);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type == TNGTYPE_LORA)
|
||||
{
|
||||
return atcab_get_pubkey(TNGLORA_PRIMARY_KEY_SLOT, public_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
return atcab_get_pubkey(TNGTLS_PRIMARY_KEY_SLOT, public_key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef TNG_ATCA_H
|
||||
#define TNG_ATCA_H
|
||||
|
||||
#include "basic/atca_basic.h"
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup tng_ TNG API (tng_)
|
||||
*
|
||||
* \brief These methods provide some convenience functions (mostly around
|
||||
* certificates) for TNG devices, which currently include
|
||||
* ATECC608A-MAHTN-T.
|
||||
*
|
||||
@{ */
|
||||
|
||||
#define TNGTLS_PRIMARY_KEY_SLOT 0
|
||||
#define TNGLORA_PRIMARY_KEY_SLOT 1
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TNGTYPE_UNKNOWN,
|
||||
TNGTYPE_TLS,
|
||||
TNGTYPE_LORA
|
||||
} tng_type_t;
|
||||
|
||||
/** \brief Get the type of TNG device.
|
||||
*
|
||||
* \param[out] type TNG device type is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS tng_get_type(tng_type_t* type);
|
||||
|
||||
/** \brief Get the TNG device certificate definition.
|
||||
*
|
||||
* \param[out] cert_def TNG device certificate defnition is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS tng_get_device_cert_def(const atcacert_def_t **cert_def);
|
||||
|
||||
/** \brief Uses GenKey command to calculate the public key from the primary
|
||||
* device public key.
|
||||
*
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS tng_get_device_pubkey(uint8_t *public_key);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Client side certificate I/O functions for TNG devices.
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "tng_atca.h"
|
||||
#include "atcacert/atcacert_client.h"
|
||||
#include "tng_atcacert_client.h"
|
||||
#include "tngtls_cert_def_1_signer.h"
|
||||
#include "tngtls_cert_def_2_device.h"
|
||||
#include "tngtls_cert_def_3_device.h"
|
||||
#include "tnglora_cert_def_1_signer.h"
|
||||
#include "tnglora_cert_def_2_device.h"
|
||||
#include "tnglora_cert_def_4_device.h"
|
||||
#include "tng_root_cert.h"
|
||||
|
||||
int tng_atcacert_max_device_cert_size(size_t* max_cert_size)
|
||||
{
|
||||
return atcacert_max_cert_size(&g_tnglora_cert_def_4_device, max_cert_size);
|
||||
}
|
||||
|
||||
int tng_atcacert_read_device_cert(uint8_t* cert, size_t* cert_size, const uint8_t* signer_cert)
|
||||
{
|
||||
int ret;
|
||||
const atcacert_def_t* cert_def = NULL;
|
||||
uint8_t ca_public_key[72];
|
||||
|
||||
ret = tng_get_device_cert_def(&cert_def);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
// Get the CA (signer) public key
|
||||
if (signer_cert != NULL)
|
||||
{
|
||||
// Signer certificate is supplied, get the public key from there
|
||||
ret = atcacert_get_subj_public_key(
|
||||
cert_def->ca_cert_def,
|
||||
signer_cert,
|
||||
cert_def->ca_cert_def->cert_template_size, // Cert size doesn't need to be accurate
|
||||
ca_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No signer certificate supplied, read from the device
|
||||
ret = atcacert_read_device_loc(&cert_def->ca_cert_def->public_key_dev_loc, ca_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (cert_def->ca_cert_def->public_key_dev_loc.count == 72)
|
||||
{
|
||||
// Public key is formatted with padding bytes in front of the X and Y components
|
||||
atcacert_public_key_remove_padding(ca_public_key, ca_public_key);
|
||||
}
|
||||
}
|
||||
|
||||
return atcacert_read_cert(cert_def, ca_public_key, cert, cert_size);
|
||||
}
|
||||
|
||||
int tng_atcacert_device_public_key(uint8_t* public_key, uint8_t* cert)
|
||||
{
|
||||
int ret;
|
||||
const atcacert_def_t* cert_def = NULL;
|
||||
uint8_t raw_public_key[72];
|
||||
|
||||
if (public_key == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = tng_get_device_cert_def(&cert_def);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcacert_read_device_loc(&cert_def->public_key_dev_loc, raw_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (cert_def->public_key_dev_loc.count == 72)
|
||||
{
|
||||
// Public key is formatted with padding bytes in front of the X and Y components
|
||||
atcacert_public_key_remove_padding(raw_public_key, public_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(public_key, raw_public_key, 64);
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int tng_atcacert_max_signer_cert_size(size_t* max_cert_size)
|
||||
{
|
||||
return atcacert_max_cert_size(&g_tngtls_cert_def_1_signer, max_cert_size);
|
||||
}
|
||||
|
||||
int tng_atcacert_read_signer_cert(uint8_t* cert, size_t* cert_size)
|
||||
{
|
||||
int ret;
|
||||
tng_type_t type;
|
||||
const atcacert_def_t* cert_def = NULL;
|
||||
const uint8_t* ca_public_key = NULL;
|
||||
|
||||
ret = tng_get_type(&type);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type == TNGTYPE_LORA)
|
||||
{
|
||||
cert_def = &g_tnglora_cert_def_1_signer;
|
||||
}
|
||||
else
|
||||
{
|
||||
cert_def = &g_tngtls_cert_def_1_signer;
|
||||
}
|
||||
|
||||
// Get the CA (root) public key
|
||||
ca_public_key = &g_cryptoauth_root_ca_002_cert[CRYPTOAUTH_ROOT_CA_002_PUBLIC_KEY_OFFSET];
|
||||
|
||||
return atcacert_read_cert(cert_def, ca_public_key, cert, cert_size);
|
||||
}
|
||||
|
||||
int tng_atcacert_signer_public_key(uint8_t* public_key, uint8_t* cert)
|
||||
{
|
||||
int ret;
|
||||
tng_type_t type;
|
||||
const atcacert_def_t* cert_def = NULL;
|
||||
uint8_t raw_public_key[72];
|
||||
|
||||
if (public_key == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (cert != NULL)
|
||||
{
|
||||
// TNG TLS cert def will work for either if the certificate is supplied
|
||||
return atcacert_get_subj_public_key(
|
||||
&g_tngtls_cert_def_1_signer,
|
||||
cert,
|
||||
g_tngtls_cert_def_1_signer.cert_template_size, // cert size doesn't need to be accurate
|
||||
public_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = tng_get_type(&type);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (type == TNGTYPE_LORA)
|
||||
{
|
||||
cert_def = &g_tnglora_cert_def_1_signer;
|
||||
}
|
||||
else
|
||||
{
|
||||
cert_def = &g_tngtls_cert_def_1_signer;
|
||||
}
|
||||
|
||||
ret = atcacert_read_device_loc(&cert_def->public_key_dev_loc, raw_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (cert_def->public_key_dev_loc.count == 72)
|
||||
{
|
||||
// Public key is formatted with padding bytes in front of the X and Y components
|
||||
atcacert_public_key_remove_padding(raw_public_key, public_key);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(public_key, raw_public_key, 64);
|
||||
}
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int tng_atcacert_root_cert_size(size_t* cert_size)
|
||||
{
|
||||
if (cert_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
*cert_size = g_cryptoauth_root_ca_002_cert_size;
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int tng_atcacert_root_cert(uint8_t* cert, size_t* cert_size)
|
||||
{
|
||||
if (cert == NULL || cert_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (*cert_size < g_cryptoauth_root_ca_002_cert_size)
|
||||
{
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
memcpy(cert, g_cryptoauth_root_ca_002_cert, g_cryptoauth_root_ca_002_cert_size);
|
||||
*cert_size = g_cryptoauth_root_ca_002_cert_size;
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int tng_atcacert_root_public_key(uint8_t* public_key)
|
||||
{
|
||||
if (public_key == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
memcpy(public_key, &g_cryptoauth_root_ca_002_cert[CRYPTOAUTH_ROOT_CA_002_PUBLIC_KEY_OFFSET], 64);
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Client side certificate I/O functions for TNG devices.
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNG_ATCACERT_CLIENT_H
|
||||
#define TNG_ATCACERT_CLIENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "atcacert/atcacert.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** \brief Return the maximum possible certificate size in bytes for a TNG
|
||||
* device certificate. Certificate can be variable size, so this
|
||||
* gives an appropriate buffer size when reading the certificate.
|
||||
*
|
||||
* \param[out] max_cert_size Maximum certificate size will be returned here
|
||||
* in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_max_device_cert_size(size_t* max_cert_size);
|
||||
|
||||
/**
|
||||
* \brief Reads the device certificate for a TNG device.
|
||||
*
|
||||
* \param[out] cert Buffer to received the certificate (DER format).
|
||||
* \param[inout] cert_size As input, the size of the cert buffer in bytes.
|
||||
* As output, the size of the certificate returned
|
||||
* in cert in bytes.
|
||||
* \param[in] signer_cert If supplied, the signer public key is used from
|
||||
* this certificate. If set to NULL, the signer
|
||||
* public key is read from the device.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_read_device_cert(uint8_t* cert, size_t* cert_size, const uint8_t* signer_cert);
|
||||
|
||||
/**
|
||||
* \brief Reads the device public key.
|
||||
*
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve.
|
||||
* \param[in] cert If supplied, the device public key is used from
|
||||
* this certificate. If set to NULL, the device
|
||||
* public key is read from the device.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_device_public_key(uint8_t* public_key, uint8_t* cert);
|
||||
|
||||
/** \brief Return the maximum possible certificate size in bytes for a TNG
|
||||
* signer certificate. Certificate can be variable size, so this
|
||||
* gives an appropriate buffer size when reading the certificate.
|
||||
*
|
||||
* \param[out] max_cert_size Maximum certificate size will be returned here
|
||||
* in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_max_signer_cert_size(size_t* max_cert_size);
|
||||
|
||||
/**
|
||||
* \brief Reads the signer certificate for a TNG device.
|
||||
*
|
||||
* \param[out] cert Buffer to received the certificate (DER format).
|
||||
* \param[inout] cert_size As input, the size of the cert buffer in bytes.
|
||||
* As output, the size of the certificate returned
|
||||
* in cert in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_read_signer_cert(uint8_t* cert, size_t* cert_size);
|
||||
|
||||
/**
|
||||
* \brief Reads the signer public key.
|
||||
*
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve.
|
||||
* \param[in] cert If supplied, the signer public key is used from
|
||||
* this certificate. If set to NULL, the signer
|
||||
* public key is read from the device.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_signer_public_key(uint8_t* public_key, uint8_t* cert);
|
||||
|
||||
/** \brief Get the size of the TNG root cert.
|
||||
*
|
||||
* \param[out] cert_size Certificate size will be returned here in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_root_cert_size(size_t* cert_size);
|
||||
|
||||
/** \brief Get the TNG root cert.
|
||||
*
|
||||
* \param[out] cert Buffer to received the certificate (DER format).
|
||||
* \param[inout] cert_size As input, the size of the cert buffer in bytes.
|
||||
* As output, the size of the certificate returned
|
||||
* in cert in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_root_cert(uint8_t* cert, size_t* cert_size);
|
||||
|
||||
/**
|
||||
* \brief Gets the root public key.
|
||||
*
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int tng_atcacert_root_public_key(uint8_t* public_key);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG root certificate (DER)
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
const uint8_t g_cryptoauth_root_ca_002_cert[501] = {
|
||||
0x30, 0x82, 0x01, 0xf1, 0x30, 0x82, 0x01, 0x97, 0xa0, 0x03, 0x02, 0x01,
|
||||
0x02, 0x02, 0x10, 0x77, 0xd3, 0x6d, 0x95, 0x6e, 0xc8, 0xae, 0x62, 0x05,
|
||||
0xe5, 0x8e, 0x3a, 0xcb, 0x98, 0x5a, 0x81, 0x30, 0x0a, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4f, 0x31, 0x21, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72,
|
||||
0x6f, 0x63, 0x68, 0x69, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f,
|
||||
0x6c, 0x6f, 0x67, 0x79, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x2a, 0x30, 0x28,
|
||||
0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74,
|
||||
0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
|
||||
0x20, 0x30, 0x30, 0x32, 0x30, 0x20, 0x17, 0x0d, 0x31, 0x38, 0x31, 0x31,
|
||||
0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x31, 0x39, 0x5a, 0x18, 0x0f, 0x32,
|
||||
0x30, 0x35, 0x38, 0x31, 0x31, 0x30, 0x38, 0x31, 0x39, 0x31, 0x32, 0x31,
|
||||
0x39, 0x5a, 0x30, 0x4f, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04,
|
||||
0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x63, 0x68, 0x69, 0x70,
|
||||
0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20,
|
||||
0x49, 0x6e, 0x63, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03,
|
||||
0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x20, 0x41, 0x75, 0x74,
|
||||
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
|
||||
0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x30, 0x30, 0x32, 0x30,
|
||||
0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
|
||||
0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42,
|
||||
0x00, 0x04, 0xbd, 0x54, 0xe6, 0x6d, 0xe3, 0x87, 0x54, 0x84, 0x00, 0x6b,
|
||||
0x53, 0xae, 0x15, 0x80, 0xd5, 0x0a, 0xa0, 0x69, 0xe7, 0x8a, 0xdf, 0x55,
|
||||
0x78, 0xd8, 0x5c, 0xe2, 0xd5, 0x4d, 0xd5, 0xb8, 0x30, 0x29, 0x6b, 0xff,
|
||||
0xdd, 0x6e, 0x6f, 0x72, 0x56, 0xfb, 0xd9, 0x9e, 0xf1, 0xa1, 0x16, 0xb1,
|
||||
0x1d, 0x33, 0xad, 0x49, 0x10, 0x3a, 0xa1, 0x85, 0x87, 0x39, 0xdc, 0xfa,
|
||||
0xe4, 0x37, 0xe1, 0x9d, 0x63, 0x4e, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d,
|
||||
0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x7a, 0xed, 0x7d,
|
||||
0x6d, 0xc6, 0xb7, 0x78, 0x9d, 0xb2, 0x38, 0x01, 0xa5, 0xe8, 0x4a, 0x8c,
|
||||
0xb0, 0xa4, 0x0e, 0x2a, 0x8c, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23,
|
||||
0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x7a, 0xed, 0x7d, 0x6d, 0xc6, 0xb7,
|
||||
0x78, 0x9d, 0xb2, 0x38, 0x01, 0xa5, 0xe8, 0x4a, 0x8c, 0xb0, 0xa4, 0x0e,
|
||||
0x2a, 0x8c, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
|
||||
0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0a, 0x06, 0x08, 0x2a,
|
||||
0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45,
|
||||
0x02, 0x21, 0x00, 0xa1, 0xdc, 0x63, 0x45, 0x90, 0xec, 0x81, 0x9e, 0xe1,
|
||||
0xde, 0x5b, 0x81, 0x12, 0x65, 0x51, 0xad, 0xd4, 0xc2, 0xc4, 0xf8, 0xe5,
|
||||
0x95, 0x28, 0x2e, 0xe0, 0x4b, 0xe7, 0x68, 0xec, 0x7c, 0x02, 0x73, 0x02,
|
||||
0x20, 0x3e, 0x6b, 0xa7, 0x4e, 0x9e, 0x4c, 0x0a, 0xd6, 0x8c, 0x24, 0xb0,
|
||||
0xfb, 0x2e, 0xe7, 0x93, 0xd2, 0xe6, 0xbe, 0x94, 0x65, 0xca, 0x15, 0xd0,
|
||||
0xea, 0x5b, 0xc8, 0x7f, 0x55, 0x79, 0x99, 0x5c, 0xad
|
||||
};
|
||||
|
||||
const size_t g_cryptoauth_root_ca_002_cert_size = sizeof(g_cryptoauth_root_ca_002_cert);
|
||||
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG root certificate (DER)
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNG_ROOT_CERT_H
|
||||
#define TNG_ROOT_CERT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define CRYPTOAUTH_ROOT_CA_002_PUBLIC_KEY_OFFSET 266
|
||||
|
||||
extern const uint8_t g_cryptoauth_root_ca_002_cert[];
|
||||
extern const size_t g_cryptoauth_root_ca_002_cert_size;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA signer certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tngtls_cert_def_1_signer.h"
|
||||
|
||||
extern const uint8_t g_tngtls_cert_template_1_signer[];
|
||||
|
||||
const atcacert_def_t g_tnglora_cert_def_1_signer = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 1,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 430
|
||||
},
|
||||
.expire_years = 31,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 8,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 72
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 8,
|
||||
.is_genkey = 0,
|
||||
.offset = 144,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 266,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 446,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 235,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 414,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 381,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = NULL,
|
||||
.cert_elements_count = 0,
|
||||
.cert_template = g_tngtls_cert_template_1_signer,
|
||||
.cert_template_size = TNGTLS_CERT_TEMPLATE_1_SIGNER_SIZE,
|
||||
.ca_cert_def = NULL
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA signer certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGLORA_CERT_DEF_1_SIGNER_H
|
||||
#define TNGLORA_CERT_DEF_1_SIGNER_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern const atcacert_def_t g_tnglora_cert_def_1_signer;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,108 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tngtls_cert_def_2_device.h"
|
||||
#include "tnglora_cert_def_1_signer.h"
|
||||
|
||||
extern const uint8_t g_tngtls_cert_template_2_device[];
|
||||
extern const atcacert_cert_element_t g_tngtls_cert_elements_2_device[];
|
||||
|
||||
const atcacert_def_t g_tnglora_cert_def_2_device = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 2,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 415
|
||||
},
|
||||
.expire_years = 28,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 1,
|
||||
.is_genkey = 1,
|
||||
.offset = 0,
|
||||
.count = 64
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 8,
|
||||
.is_genkey = 0,
|
||||
.offset = 72,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 257,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 431,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 120,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 399,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 366,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = g_tngtls_cert_elements_2_device,
|
||||
.cert_elements_count = TNGTLS_CERT_ELEMENTS_2_DEVICE_COUNT,
|
||||
.cert_template = g_tngtls_cert_template_2_device,
|
||||
.cert_template_size = TNGTLS_CERT_TEMPLATE_2_DEVICE_SIZE,
|
||||
.ca_cert_def = &g_tnglora_cert_def_1_signer
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGLORA_CERT_DEF_2_DEVICE_H
|
||||
#define TNGLORA_CERT_DEF_2_DEVICE_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern const atcacert_def_t g_tnglora_cert_def_2_device;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tnglora_cert_def_4_device.h"
|
||||
#include "tnglora_cert_def_1_signer.h"
|
||||
|
||||
const uint8_t g_tnglora_cert_template_4_device[TNGLORA_CERT_TEMPLATE_4_DEVICE_SIZE] = {
|
||||
0x30, 0x82, 0x02, 0x24, 0x30, 0x82, 0x01, 0xc9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x55,
|
||||
0xce, 0x2e, 0x8f, 0xf6, 0x1c, 0x62, 0x50, 0xb7, 0xe1, 0x68, 0x03, 0x54, 0x14, 0x1c, 0x94, 0x30,
|
||||
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4f, 0x31, 0x21, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x63, 0x68, 0x69,
|
||||
0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20, 0x49, 0x6e, 0x63,
|
||||
0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74,
|
||||
0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x46, 0x46, 0x46, 0x46, 0x30, 0x20, 0x17, 0x0d,
|
||||
0x31, 0x38, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
|
||||
0x30, 0x34, 0x36, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42,
|
||||
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f,
|
||||
0x63, 0x68, 0x69, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20,
|
||||
0x49, 0x6e, 0x63, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x73, 0x6e,
|
||||
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36,
|
||||
0x32, 0x37, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
|
||||
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0xf1, 0xa7,
|
||||
0x0d, 0xa3, 0x79, 0xa3, 0xfd, 0xed, 0x6b, 0x50, 0x10, 0xbd, 0xad, 0x6e, 0x1f, 0xb9, 0xe8, 0xeb,
|
||||
0xa7, 0xdf, 0x2c, 0x4b, 0x5c, 0x67, 0xd3, 0x5e, 0xba, 0x84, 0xda, 0x09, 0xe7, 0x7a, 0xe8, 0xdb,
|
||||
0x2c, 0xcb, 0x96, 0x28, 0xee, 0xeb, 0x85, 0xcd, 0xaa, 0xb3, 0x5c, 0x92, 0xe5, 0x3e, 0x1c, 0x44,
|
||||
0xd5, 0x5a, 0x2b, 0xa7, 0xa0, 0x24, 0xaa, 0x92, 0x60, 0x3b, 0x68, 0x94, 0x8a, 0xa3, 0x81, 0x91,
|
||||
0x30, 0x81, 0x8e, 0x30, 0x2e, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x27, 0x30, 0x25, 0xa4, 0x23,
|
||||
0x30, 0x21, 0x31, 0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x16, 0x65, 0x75, 0x69,
|
||||
0x36, 0x34, 0x5f, 0x30, 0x30, 0x30, 0x34, 0x41, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x30, 0x30, 0x30, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30,
|
||||
0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x03,
|
||||
0x88, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1a, 0x90, 0xb2, 0x22,
|
||||
0x37, 0xa4, 0x51, 0xb7, 0x57, 0xdd, 0x36, 0xd1, 0x3a, 0x85, 0x2b, 0xe1, 0x3d, 0x2e, 0xf2, 0xca,
|
||||
0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xbc, 0xd4, 0xfd,
|
||||
0xe8, 0x80, 0x8a, 0x2d, 0xc9, 0x0b, 0x6d, 0x01, 0xa8, 0xc5, 0xb9, 0xb2, 0x47, 0x33, 0x7e, 0xbd,
|
||||
0xda, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00,
|
||||
0x30, 0x46, 0x02, 0x21, 0x00, 0xa8, 0x34, 0x1a, 0xf3, 0x21, 0xbc, 0xb1, 0x9c, 0xcc, 0x8f, 0x0f,
|
||||
0x1c, 0xe8, 0x90, 0x7c, 0xf8, 0xed, 0x4c, 0x24, 0x5f, 0x93, 0x4c, 0x50, 0xbd, 0x83, 0x30, 0xb6,
|
||||
0x1c, 0x87, 0x27, 0xd2, 0xc8, 0x02, 0x21, 0x00, 0xfc, 0x1e, 0x80, 0xca, 0x01, 0xe9, 0xd9, 0xd9,
|
||||
0x6b, 0x3e, 0xcb, 0x41, 0x79, 0x7b, 0x95, 0x99, 0x10, 0x21, 0x6e, 0xf2, 0x90, 0x2c, 0x0b, 0x13,
|
||||
0x22, 0x7f, 0x91, 0x9c, 0xd2, 0x63, 0x34, 0x82
|
||||
};
|
||||
|
||||
const atcacert_cert_element_t g_tnglora_cert_elements_4_device[] = {
|
||||
{
|
||||
.id = "SN03",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 4
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 208,
|
||||
.count = 8
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
},
|
||||
{
|
||||
.id = "SN48",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 8,
|
||||
.count = 5
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 216,
|
||||
.count = 10
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
},
|
||||
{
|
||||
.id = "EUI-64",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 10,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 16
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 355,
|
||||
.count = 16
|
||||
},
|
||||
.transforms ={
|
||||
TF_NONE,
|
||||
TF_NONE
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const atcacert_def_t g_tnglora_cert_def_4_device = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 4,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 461
|
||||
},
|
||||
.expire_years = 28,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 1,
|
||||
.is_genkey = 1,
|
||||
.offset = 0,
|
||||
.count = 64
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 8,
|
||||
.is_genkey = 0,
|
||||
.offset = 72,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 253,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 477,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 120,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 445,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 412,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = g_tnglora_cert_elements_4_device,
|
||||
.cert_elements_count = sizeof(g_tnglora_cert_elements_4_device) / sizeof(g_tnglora_cert_elements_4_device[0]),
|
||||
.cert_template = g_tnglora_cert_template_4_device,
|
||||
.cert_template_size = sizeof(g_tnglora_cert_template_4_device),
|
||||
.ca_cert_def = &g_tnglora_cert_def_1_signer
|
||||
};
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGLORA_CERT_DEF_4_DEVICE_H
|
||||
#define TNGLORA_CERT_DEF_4_DEVICE_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
#define TNGLORA_CERT_TEMPLATE_4_DEVICE_SIZE 552
|
||||
extern const atcacert_def_t g_tnglora_cert_def_4_device;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG TLS signer certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tngtls_cert_def_1_signer.h"
|
||||
|
||||
const uint8_t g_tngtls_cert_template_1_signer[TNGTLS_CERT_TEMPLATE_1_SIGNER_SIZE] = {
|
||||
0x30, 0x82, 0x02, 0x04, 0x30, 0x82, 0x01, 0xaa, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x44,
|
||||
0x0e, 0xe4, 0x17, 0x0c, 0xb5, 0x45, 0xce, 0x59, 0x69, 0x8e, 0x30, 0x56, 0x99, 0x0a, 0x5d, 0x30,
|
||||
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4f, 0x31, 0x21, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x63, 0x68, 0x69,
|
||||
0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20, 0x49, 0x6e, 0x63,
|
||||
0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74,
|
||||
0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41, 0x20, 0x30, 0x30, 0x32, 0x30, 0x20, 0x17, 0x0d,
|
||||
0x31, 0x38, 0x31, 0x31, 0x30, 0x38, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
|
||||
0x30, 0x34, 0x39, 0x31, 0x31, 0x30, 0x38, 0x30, 0x34, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x4f,
|
||||
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f,
|
||||
0x63, 0x68, 0x69, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20,
|
||||
0x49, 0x6e, 0x63, 0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72,
|
||||
0x79, 0x70, 0x74, 0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x46, 0x46, 0x46, 0x46, 0x30,
|
||||
0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86,
|
||||
0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x84, 0x98, 0x44, 0x0a, 0x31, 0x9b,
|
||||
0x3f, 0x71, 0xe2, 0x5d, 0x52, 0x26, 0x00, 0x90, 0x00, 0xc7, 0x56, 0xbd, 0x5c, 0x0f, 0xae, 0x4a,
|
||||
0x1b, 0x84, 0x1a, 0xd4, 0xa3, 0x3f, 0x21, 0xab, 0xa0, 0x9a, 0x48, 0x10, 0x1c, 0x75, 0xc8, 0x28,
|
||||
0x24, 0x90, 0xb3, 0xb6, 0x5a, 0x52, 0x80, 0x27, 0x29, 0xbd, 0x3a, 0x75, 0x2c, 0x3d, 0xf0, 0xdd,
|
||||
0x1b, 0x04, 0xa2, 0xa1, 0xb5, 0x7e, 0x0c, 0x92, 0x24, 0x47, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x0e,
|
||||
0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x12,
|
||||
0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02,
|
||||
0x01, 0x00, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0xbc, 0xd4, 0xfd,
|
||||
0xe8, 0x80, 0x8a, 0x2d, 0xc9, 0x0b, 0x6d, 0x01, 0xa8, 0xc5, 0xb9, 0xb2, 0x47, 0x33, 0x7e, 0xbd,
|
||||
0xda, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x7a, 0xed,
|
||||
0x7d, 0x6d, 0xc6, 0xb7, 0x78, 0x9d, 0xb2, 0x38, 0x01, 0xa5, 0xe8, 0x4a, 0x8c, 0xb0, 0xa4, 0x0e,
|
||||
0x2a, 0x8c, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48,
|
||||
0x00, 0x30, 0x45, 0x02, 0x21, 0x00, 0xc5, 0x07, 0xb8, 0x2a, 0x7b, 0xf9, 0xa3, 0x3a, 0x1b, 0x78,
|
||||
0xdc, 0xeb, 0x01, 0xc9, 0x26, 0x92, 0x9e, 0xf3, 0x78, 0x3d, 0x46, 0x8e, 0x69, 0xa2, 0x84, 0xd3,
|
||||
0x6a, 0xba, 0xb9, 0x25, 0x1b, 0xef, 0x02, 0x20, 0x0e, 0x6d, 0x7f, 0x76, 0x8d, 0x65, 0xa7, 0x49,
|
||||
0xfa, 0x71, 0x2d, 0xda, 0x2b, 0x69, 0x25, 0x35, 0xcd, 0x57, 0x7d, 0x65, 0x01, 0x96, 0xa3, 0xd2,
|
||||
0xbf, 0x3b, 0x22, 0x78, 0x8e, 0x75, 0x41, 0x86
|
||||
};
|
||||
|
||||
const atcacert_def_t g_tngtls_cert_def_1_signer = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 1,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 430
|
||||
},
|
||||
.expire_years = 31,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 11,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 72
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 12,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 266,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 446,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 235,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 414,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 381,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = NULL,
|
||||
.cert_elements_count = 0,
|
||||
.cert_template = g_tngtls_cert_template_1_signer,
|
||||
.cert_template_size = sizeof(g_tngtls_cert_template_1_signer),
|
||||
.ca_cert_def = NULL
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG TLS signer certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGTLS_CERT_DEF_1_SIGNER_H
|
||||
#define TNGTLS_CERT_DEF_1_SIGNER_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define TNGTLS_CERT_TEMPLATE_1_SIGNER_SIZE 520
|
||||
extern const atcacert_def_t g_tngtls_cert_def_1_signer;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG TLS device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tngtls_cert_def_2_device.h"
|
||||
#include "tngtls_cert_def_1_signer.h"
|
||||
|
||||
const uint8_t g_tngtls_cert_template_2_device[TNGTLS_CERT_TEMPLATE_2_DEVICE_SIZE] = {
|
||||
0x30, 0x82, 0x01, 0xf5, 0x30, 0x82, 0x01, 0x9b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x55,
|
||||
0xce, 0x2e, 0x8f, 0xf6, 0x1c, 0x62, 0x50, 0xb7, 0xe1, 0x68, 0x03, 0x54, 0x14, 0x1c, 0x94, 0x30,
|
||||
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4f, 0x31, 0x21, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x63, 0x68, 0x69,
|
||||
0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20, 0x49, 0x6e, 0x63,
|
||||
0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74,
|
||||
0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x46, 0x46, 0x46, 0x46, 0x30, 0x20, 0x17, 0x0d,
|
||||
0x31, 0x38, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
|
||||
0x30, 0x34, 0x36, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x46,
|
||||
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f,
|
||||
0x63, 0x68, 0x69, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20,
|
||||
0x49, 0x6e, 0x63, 0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x18, 0x30, 0x31,
|
||||
0x32, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, 0x30, 0x31,
|
||||
0x20, 0x41, 0x54, 0x45, 0x43, 0x43, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce,
|
||||
0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00,
|
||||
0x04, 0x71, 0xf1, 0xa7, 0x0d, 0xa3, 0x79, 0xa3, 0xfd, 0xed, 0x6b, 0x50, 0x10, 0xbd, 0xad, 0x6e,
|
||||
0x1f, 0xb9, 0xe8, 0xeb, 0xa7, 0xdf, 0x2c, 0x4b, 0x5c, 0x67, 0xd3, 0x5e, 0xba, 0x84, 0xda, 0x09,
|
||||
0xe7, 0x7a, 0xe8, 0xdb, 0x2c, 0xcb, 0x96, 0x28, 0xee, 0xeb, 0x85, 0xcd, 0xaa, 0xb3, 0x5c, 0x92,
|
||||
0xe5, 0x3e, 0x1c, 0x44, 0xd5, 0x5a, 0x2b, 0xa7, 0xa0, 0x24, 0xaa, 0x92, 0x60, 0x3b, 0x68, 0x94,
|
||||
0x8a, 0xa3, 0x60, 0x30, 0x5e, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04,
|
||||
0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03,
|
||||
0x02, 0x03, 0x88, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1a, 0x90,
|
||||
0xb2, 0x22, 0x37, 0xa4, 0x51, 0xb7, 0x57, 0xdd, 0x36, 0xd1, 0x3a, 0x85, 0x2b, 0xe1, 0x3d, 0x2e,
|
||||
0xf2, 0xca, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xbc,
|
||||
0xd4, 0xfd, 0xe8, 0x80, 0x8a, 0x2d, 0xc9, 0x0b, 0x6d, 0x01, 0xa8, 0xc5, 0xb9, 0xb2, 0x47, 0x33,
|
||||
0x7e, 0xbd, 0xda, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
|
||||
0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x31, 0x0d, 0x58, 0xc9, 0xd5, 0xf8, 0x96, 0xd3, 0xfa, 0x8b,
|
||||
0xea, 0x6a, 0x13, 0x53, 0x7e, 0x14, 0x10, 0x54, 0xb5, 0xad, 0x17, 0x38, 0xa6, 0x65, 0xb1, 0x42,
|
||||
0xf8, 0xff, 0xe9, 0xef, 0xbc, 0xa8, 0x02, 0x21, 0x00, 0xd6, 0x23, 0x3a, 0x8b, 0x1a, 0x10, 0x93,
|
||||
0xae, 0xa1, 0x43, 0xb1, 0x0c, 0x96, 0x80, 0x56, 0x6e, 0x19, 0x41, 0x82, 0xeb, 0x84, 0xff, 0x1f,
|
||||
0xd3, 0x9f, 0x3d, 0xf6, 0x3e, 0xe5, 0xb3, 0x7a, 0x19
|
||||
};
|
||||
|
||||
const atcacert_cert_element_t g_tngtls_cert_elements_2_device[TNGTLS_CERT_ELEMENTS_2_DEVICE_COUNT] = {
|
||||
{
|
||||
.id = "SN03",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 4
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 206,
|
||||
.count = 8
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
},
|
||||
{
|
||||
.id = "SN48",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 8,
|
||||
.count = 5
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 214,
|
||||
.count = 10
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const atcacert_def_t g_tngtls_cert_def_2_device = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 2,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 415
|
||||
},
|
||||
.expire_years = 28,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 0,
|
||||
.is_genkey = 1,
|
||||
.offset = 0,
|
||||
.count = 64
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 10,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 257,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 431,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 120,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 399,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 366,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = g_tngtls_cert_elements_2_device,
|
||||
.cert_elements_count = sizeof(g_tngtls_cert_elements_2_device) / sizeof(g_tngtls_cert_elements_2_device[0]),
|
||||
.cert_template = g_tngtls_cert_template_2_device,
|
||||
.cert_template_size = sizeof(g_tngtls_cert_template_2_device),
|
||||
.ca_cert_def = &g_tngtls_cert_def_1_signer
|
||||
};
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG TLS device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGTLS_CERT_DEF_2_DEVICE_H
|
||||
#define TNGTLS_CERT_DEF_2_DEVICE_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define TNGTLS_CERT_TEMPLATE_2_DEVICE_SIZE 505
|
||||
#define TNGTLS_CERT_ELEMENTS_2_DEVICE_COUNT 2
|
||||
extern const atcacert_def_t g_tngtls_cert_def_2_device;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,173 @@
|
||||
#include "atcacert/atcacert_def.h"
|
||||
#include "tngtls_cert_def_3_device.h"
|
||||
#include "tngtls_cert_def_1_signer.h"
|
||||
|
||||
const uint8_t g_tngtls_cert_template_3_device[TNGTLS_CERT_TEMPLATE_3_DEVICE_SIZE] = {
|
||||
0x30, 0x82, 0x02, 0x1e, 0x30, 0x82, 0x01, 0xc5, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x55,
|
||||
0xce, 0x2e, 0x8f, 0xf6, 0x1c, 0x62, 0x50, 0xb7, 0xe1, 0x68, 0x03, 0x54, 0x14, 0x1c, 0x94, 0x30,
|
||||
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x4f, 0x31, 0x21, 0x30,
|
||||
0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x63, 0x68, 0x69,
|
||||
0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20, 0x49, 0x6e, 0x63,
|
||||
0x31, 0x2a, 0x30, 0x28, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x21, 0x43, 0x72, 0x79, 0x70, 0x74,
|
||||
0x6f, 0x20, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x20, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x72, 0x20, 0x46, 0x46, 0x46, 0x46, 0x30, 0x20, 0x17, 0x0d,
|
||||
0x31, 0x38, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
|
||||
0x30, 0x34, 0x36, 0x31, 0x31, 0x30, 0x38, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x42,
|
||||
0x31, 0x21, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x18, 0x4d, 0x69, 0x63, 0x72, 0x6f,
|
||||
0x63, 0x68, 0x69, 0x70, 0x20, 0x54, 0x65, 0x63, 0x68, 0x6e, 0x6f, 0x6c, 0x6f, 0x67, 0x79, 0x20,
|
||||
0x49, 0x6e, 0x63, 0x31, 0x1d, 0x30, 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x14, 0x73, 0x6e,
|
||||
0x30, 0x31, 0x32, 0x33, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36,
|
||||
0x30, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
|
||||
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x71, 0xf1, 0xa7,
|
||||
0x0d, 0xa3, 0x79, 0xa3, 0xfd, 0xed, 0x6b, 0x50, 0x10, 0xbd, 0xad, 0x6e, 0x1f, 0xb9, 0xe8, 0xeb,
|
||||
0xa7, 0xdf, 0x2c, 0x4b, 0x5c, 0x67, 0xd3, 0x5e, 0xba, 0x84, 0xda, 0x09, 0xe7, 0x7a, 0xe8, 0xdb,
|
||||
0x2c, 0xcb, 0x96, 0x28, 0xee, 0xeb, 0x85, 0xcd, 0xaa, 0xb3, 0x5c, 0x92, 0xe5, 0x3e, 0x1c, 0x44,
|
||||
0xd5, 0x5a, 0x2b, 0xa7, 0xa0, 0x24, 0xaa, 0x92, 0x60, 0x3b, 0x68, 0x94, 0x8a, 0xa3, 0x81, 0x8d,
|
||||
0x30, 0x81, 0x8a, 0x30, 0x2a, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x23, 0x30, 0x21, 0xa4, 0x1f,
|
||||
0x30, 0x1d, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x12, 0x65, 0x75, 0x69,
|
||||
0x34, 0x38, 0x5f, 0x36, 0x38, 0x32, 0x37, 0x31, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
|
||||
0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x03, 0x88, 0x30, 0x1d, 0x06,
|
||||
0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x1a, 0x90, 0xb2, 0x22, 0x37, 0xa4, 0x51, 0xb7,
|
||||
0x57, 0xdd, 0x36, 0xd1, 0x3a, 0x85, 0x2b, 0xe1, 0x3d, 0x2e, 0xf2, 0xca, 0x30, 0x1f, 0x06, 0x03,
|
||||
0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xbc, 0xd4, 0xfd, 0xe8, 0x80, 0x8a, 0x2d,
|
||||
0xc9, 0x0b, 0x6d, 0x01, 0xa8, 0xc5, 0xb9, 0xb2, 0x47, 0x33, 0x7e, 0xbd, 0xda, 0x30, 0x0a, 0x06,
|
||||
0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, 0x20,
|
||||
0x79, 0x11, 0xd8, 0xea, 0x9c, 0xb4, 0x08, 0x32, 0x0c, 0x2f, 0x0c, 0xce, 0xe6, 0x9b, 0x84, 0x5a,
|
||||
0x17, 0xd2, 0x36, 0xf2, 0x13, 0x09, 0x90, 0x89, 0x4f, 0xc0, 0x0f, 0x7e, 0x67, 0xfb, 0xc7, 0x99,
|
||||
0x02, 0x20, 0x5d, 0x61, 0xbb, 0xbb, 0x46, 0x3a, 0x0a, 0xd3, 0xf6, 0xe3, 0x81, 0xdb, 0x95, 0x3d,
|
||||
0x08, 0xec, 0x66, 0x10, 0x4f, 0x01, 0xc8, 0x83, 0x13, 0x4d, 0x63, 0x9e, 0x6d, 0xc8, 0x05, 0x22,
|
||||
0x15, 0xe2
|
||||
};
|
||||
|
||||
const atcacert_cert_element_t g_tngtls_cert_elements_3_device[] = {
|
||||
{
|
||||
.id = "SN03",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 4
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 208,
|
||||
.count = 8
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
},
|
||||
{
|
||||
.id = "SN48",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_CONFIG,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 8,
|
||||
.count = 5
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 216,
|
||||
.count = 10
|
||||
},
|
||||
.transforms ={
|
||||
TF_BIN2HEX_UC,
|
||||
TF_NONE
|
||||
}
|
||||
},
|
||||
{
|
||||
.id = "EUI-48",
|
||||
.device_loc ={
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 5,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 12
|
||||
},
|
||||
.cert_loc ={
|
||||
.offset = 355,
|
||||
.count = 12
|
||||
},
|
||||
.transforms ={
|
||||
TF_NONE,
|
||||
TF_NONE
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const atcacert_def_t g_tngtls_cert_def_3_device = {
|
||||
.type = CERTTYPE_X509,
|
||||
.template_id = 3,
|
||||
.chain_id = 0,
|
||||
.private_key_slot = 0,
|
||||
.sn_source = SNSRC_PUB_KEY_HASH,
|
||||
.cert_sn_dev_loc = {
|
||||
.zone = DEVZONE_NONE,
|
||||
.slot = 0,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 0
|
||||
},
|
||||
.issue_date_format = DATEFMT_RFC5280_UTC,
|
||||
.expire_date_format = DATEFMT_RFC5280_GEN,
|
||||
.tbs_cert_loc = {
|
||||
.offset = 4,
|
||||
.count = 457
|
||||
},
|
||||
.expire_years = 28,
|
||||
.public_key_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 0,
|
||||
.is_genkey = 1,
|
||||
.offset = 0,
|
||||
.count = 64
|
||||
},
|
||||
.comp_cert_dev_loc = {
|
||||
.zone = DEVZONE_DATA,
|
||||
.slot = 10,
|
||||
.is_genkey = 0,
|
||||
.offset = 0,
|
||||
.count = 72
|
||||
},
|
||||
.std_cert_elements = {
|
||||
{ // STDCERT_PUBLIC_KEY
|
||||
.offset = 253,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_SIGNATURE
|
||||
.offset = 473,
|
||||
.count = 64
|
||||
},
|
||||
{ // STDCERT_ISSUE_DATE
|
||||
.offset = 128,
|
||||
.count = 13
|
||||
},
|
||||
{ // STDCERT_EXPIRE_DATE
|
||||
.offset = 143,
|
||||
.count = 15
|
||||
},
|
||||
{ // STDCERT_SIGNER_ID
|
||||
.offset = 120,
|
||||
.count = 4
|
||||
},
|
||||
{ // STDCERT_CERT_SN
|
||||
.offset = 15,
|
||||
.count = 16
|
||||
},
|
||||
{ // STDCERT_AUTH_KEY_ID
|
||||
.offset = 441,
|
||||
.count = 20
|
||||
},
|
||||
{ // STDCERT_SUBJ_KEY_ID
|
||||
.offset = 408,
|
||||
.count = 20
|
||||
}
|
||||
},
|
||||
.cert_elements = g_tngtls_cert_elements_3_device,
|
||||
.cert_elements_count = sizeof(g_tngtls_cert_elements_3_device) / sizeof(g_tngtls_cert_elements_3_device[0]),
|
||||
.cert_template = g_tngtls_cert_template_3_device,
|
||||
.cert_template_size = sizeof(g_tngtls_cert_template_3_device),
|
||||
.ca_cert_def = &g_tngtls_cert_def_1_signer
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief TNG LORA device certificate definition
|
||||
*
|
||||
* \copyright (c) 2015-2019 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef TNGTLS_CERT_DEF_3_DEVICE_H
|
||||
#define TNGTLS_CERT_DEF_3_DEVICE_H
|
||||
|
||||
#include "atcacert/atcacert_def.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \ingroup tng_
|
||||
* @{
|
||||
*/
|
||||
#define TNGTLS_CERT_TEMPLATE_3_DEVICE_SIZE 546
|
||||
extern const atcacert_def_t g_tngtls_cert_def_3_device;
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
cmake_minimum_required(VERSION 3.1.0)
|
||||
project(cryptoauth)
|
||||
|
||||
# Various Options for Build
|
||||
option(ATCA_HAL_KIT_HID "Include the HID HAL Driver")
|
||||
option(ATCA_HAL_KIT_CDC "Include the CDC HAL Driver (Legacy)" OFF)
|
||||
option(ATCA_HAL_I2C "Include the I2C Hal Driver - Linux & MCU only")
|
||||
option(ATCA_HAL_CUSTOM "Include support for Custom/Plug-in Hal Driver")
|
||||
option(ATCA_PRINTF "Enable Debug print statements in library")
|
||||
option(ATCA_PKCS11 "Build PKCS11 Library")
|
||||
option(ATCA_MBEDTLS "Integrate with mbedtls")
|
||||
option(ATCA_BUILD_SHARED_LIBS "Build CryptoAuthLib as shared library" ON)
|
||||
set(BUILD_SHARED_LIBS ${ATCA_BUILD_SHARED_LIBS})
|
||||
|
||||
# Collect Library Sources
|
||||
file(GLOB LIB_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.c")
|
||||
file(GLOB ATCACERT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "atcacert/*.c")
|
||||
file(GLOB BASIC_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "basic/*.c")
|
||||
file(GLOB_RECURSE CRYPTO_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "crypto/*.c")
|
||||
file(GLOB HOST_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "host/*.c")
|
||||
file(GLOB JWT_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "jwt/*.c")
|
||||
file(GLOB PKCS11_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "pkcs11/*.c")
|
||||
file(GLOB MBEDTLS_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "mbedtls/*.c")
|
||||
file(GLOB TNG_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "../app/tng/*.c")
|
||||
|
||||
# Add the basic sources to the library
|
||||
set(CRYPTOAUTH_SRC ${LIB_SRC} ${ATCACERT_SRC} ${BASIC_SRC} ${CRYPTO_SRC} ${HOST_SRC} ${JWT_SRC} hal/atca_hal.c ${TNG_SRC})
|
||||
|
||||
if(ATCA_HAL_KIT_HID OR ATCA_HAL_KIT_CDC)
|
||||
set(NEED_USB true)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/hal_win_timer.c)
|
||||
set(HID_SRC ../third_party/hidapi/windows/hid.c)
|
||||
set(CDC_SRC hal/hal_win_kit_cdc.c)
|
||||
elseif(APPLE)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/hal_linux_timer.c)
|
||||
set(HID_SRC ../third_party/hidapi/mac/hid.c)
|
||||
elseif(UNIX)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/hal_linux_timer.c)
|
||||
set(TWI_SRC hal/hal_linux_i2c_userspace.c)
|
||||
set(LINUX TRUE)
|
||||
endif()
|
||||
|
||||
if(LINUX AND NEED_USB)
|
||||
find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h PATH_SUFFIXES "include" "libusb" "libusb-1.0")
|
||||
find_path(LIBUDEV_INCLUDE_DIR NAMES libudev.h PATH_SUFFIXES "include")
|
||||
find_library(HAS_LIBUSB usb-1.0)
|
||||
find_library(HAS_LIBUDEV udev)
|
||||
|
||||
if(HAS_LIBUSB AND LIBUSB_INCLUDE_DIR)
|
||||
set(LIBUSB_GOOD TRUE)
|
||||
endif()
|
||||
|
||||
if(HAS_LIBUDEV AND LIBUDEV_INCLUDE_DIR)
|
||||
set(LIBUDEV_GOOD TRUE)
|
||||
endif()
|
||||
|
||||
if(ATCA_HAL_KIT_CDC AND LIBUDEV_GOOD)
|
||||
set(USE_UDEV TRUE)
|
||||
elseif(LIBUSB_GOOD AND NOT ATCA_HAL_KIT_CDC)
|
||||
set(USE_LIBUSB TRUE)
|
||||
else()
|
||||
message(FATAL_ERROR, "Missing Build Dependencies for USB - install libusb-1.0-0-dev or libudev-dev")
|
||||
endif()
|
||||
|
||||
endif(LINUX AND NEED_USB)
|
||||
|
||||
if(USE_UDEV)
|
||||
set(USB_INCLUDE_DIR ${LIBUDEV_INCLUDE_DIR})
|
||||
set(HID_SRC ../third_party/hidapi/linux/hid.c)
|
||||
set(CDC_SRC hal/hal_linux_kit_cdc.c)
|
||||
endif(USE_UDEV)
|
||||
|
||||
if(USE_LIBUSB)
|
||||
set(USB_INCLUDE_DIR ${LIBUSB_INCLUDE_DIR})
|
||||
set(HID_SRC ../third_party/hidapi/libusb/hid.c)
|
||||
endif(USE_LIBUSB)
|
||||
|
||||
if(NEED_USB)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} hal/kit_protocol.c)
|
||||
endif()
|
||||
|
||||
if(ATCA_HAL_KIT_HID)
|
||||
add_definitions(-DATCA_HAL_KIT_HID)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${HID_SRC} hal/hal_all_platforms_kit_hidapi.c)
|
||||
endif(ATCA_HAL_KIT_HID)
|
||||
|
||||
if(ATCA_HAL_KIT_CDC)
|
||||
add_definitions(-DATCA_HAL_KIT_CDC)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${CDC_SRC})
|
||||
endif(ATCA_HAL_KIT_CDC)
|
||||
|
||||
if(ATCA_HAL_I2C)
|
||||
add_definitions(-DATCA_HAL_I2C)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${TWI_SRC})
|
||||
endif(ATCA_HAL_I2C)
|
||||
|
||||
if(ATCA_HAL_CUSTOM)
|
||||
add_definitions(-DATCA_HAL_CUSTOM)
|
||||
endif()
|
||||
|
||||
# Add Remaining Sources depending on target library type
|
||||
if(ATCA_MBEDTLS)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${MBEDTLS_SRC})
|
||||
endif()
|
||||
|
||||
if(ATCA_PKCS11)
|
||||
set(CRYPTOAUTH_SRC ${CRYPTOAUTH_SRC} ${PKCS11_SRC})
|
||||
endif()
|
||||
|
||||
add_library(cryptoauth ${CRYPTOAUTH_SRC} ${ATCACERT_DEF_SRC})
|
||||
|
||||
set_property(TARGET cryptoauth PROPERTY C_STANDARD 99)
|
||||
|
||||
# Add Remaining Sources depending on target library type
|
||||
if(ATCA_PKCS11)
|
||||
set_target_properties(cryptoauth PROPERTIES OUTPUT_NAME "ateccx08pkcs11")
|
||||
endif(ATCA_PKCS11)
|
||||
|
||||
if(ATCA_PRINTF)
|
||||
add_definitions(-DATCAPRINTF)
|
||||
endif(ATCA_PRINTF)
|
||||
|
||||
include_directories(cryptoauth PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} ../third_party/hidapi/hidapi ${USB_INCLUDE_DIR})
|
||||
|
||||
if(WIN32)
|
||||
set_target_properties(cryptoauth PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS true)
|
||||
target_link_libraries(cryptoauth setupapi.lib)
|
||||
endif(WIN32)
|
||||
|
||||
if(APPLE)
|
||||
find_library(IO_KIT_LIB IOKit)
|
||||
find_library(CORE_LIB CoreFoundation)
|
||||
target_link_libraries(cryptoauth ${IO_KIT_LIB} ${CORE_LIB})
|
||||
endif()
|
||||
|
||||
if(LINUX)
|
||||
if(USE_LIBUSB)
|
||||
target_link_libraries(cryptoauth usb-1.0)
|
||||
elseif(USE_UDEV)
|
||||
target_link_libraries(cryptoauth udev)
|
||||
endif()
|
||||
target_link_libraries(cryptoauth rt)
|
||||
endif(LINUX)
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief bool define for systems that don't have it
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ATCA_BOOL_H
|
||||
#define _ATCA_BOOL_H
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER <= 1700)
|
||||
// VS2012 and earlier don't support stdbool.h
|
||||
#ifndef __cplusplus
|
||||
#define bool unsigned char
|
||||
#define false 0
|
||||
#define true 1
|
||||
#endif
|
||||
#else
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,143 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief a set of default configurations for various ATCA devices and interfaces
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include "atca_cfgs.h"
|
||||
#include "atca_iface.h"
|
||||
#include "atca_device.h"
|
||||
|
||||
/** \defgroup config Configuration (cfg_)
|
||||
* \brief Logical device configurations describe the CryptoAuth device type and logical interface.
|
||||
@{ */
|
||||
|
||||
/* if the number of these configurations grows large, we can #ifdef them based on required device support */
|
||||
|
||||
/** \brief default configuration for an ECCx08A device */
|
||||
ATCAIfaceCfg cfg_ateccx08a_i2c_default = {
|
||||
.iface_type = ATCA_I2C_IFACE,
|
||||
.devtype = ATECC608A,
|
||||
{
|
||||
.atcai2c.slave_address = 0xC0,
|
||||
.atcai2c.bus = 2,
|
||||
.atcai2c.baud = 400000,
|
||||
//.atcai2c.baud = 100000,
|
||||
},
|
||||
.wake_delay = 1500,
|
||||
.rx_retries = 20
|
||||
};
|
||||
|
||||
/** \brief default configuration for an ECCx08A device on the logical SWI bus over UART*/
|
||||
ATCAIfaceCfg cfg_ateccx08a_swi_default = {
|
||||
.iface_type = ATCA_SWI_IFACE,
|
||||
.devtype = ATECC608A,
|
||||
{
|
||||
.atcaswi.bus = 4,
|
||||
},
|
||||
.wake_delay = 1500,
|
||||
.rx_retries = 10
|
||||
};
|
||||
|
||||
/** \brief default configuration for Kit protocol over the device's async interface */
|
||||
ATCAIfaceCfg cfg_ateccx08a_kitcdc_default = {
|
||||
.iface_type = ATCA_UART_IFACE,
|
||||
.devtype = ATECC608A,
|
||||
{
|
||||
.atcauart.port = 0,
|
||||
.atcauart.baud = 115200,
|
||||
.atcauart.wordsize = 8,
|
||||
.atcauart.parity = 2,
|
||||
.atcauart.stopbits = 1,
|
||||
},
|
||||
.rx_retries = 1,
|
||||
};
|
||||
|
||||
/** \brief default configuration for Kit protocol over the device's async interface */
|
||||
ATCAIfaceCfg cfg_ateccx08a_kithid_default = {
|
||||
.iface_type = ATCA_HID_IFACE,
|
||||
.devtype = ATECC608A,
|
||||
{
|
||||
.atcahid.dev_interface = ATCA_KIT_AUTO_IFACE,
|
||||
.atcahid.dev_identity = 0,
|
||||
.atcahid.idx = 0,
|
||||
.atcahid.vid = 0x03EB,
|
||||
.atcahid.pid = 0x2312,
|
||||
.atcahid.packetsize = 64,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** \brief default configuration for a SHA204A device on the first logical I2C bus */
|
||||
ATCAIfaceCfg cfg_atsha204a_i2c_default = {
|
||||
.iface_type = ATCA_I2C_IFACE,
|
||||
.devtype = ATSHA204A,
|
||||
{
|
||||
.atcai2c.slave_address = 0xC8,
|
||||
.atcai2c.bus = 2,
|
||||
.atcai2c.baud = 400000,
|
||||
},
|
||||
.wake_delay = 2560,
|
||||
.rx_retries = 20
|
||||
};
|
||||
|
||||
/** \brief default configuration for an SHA204A device on the logical SWI bus over UART*/
|
||||
ATCAIfaceCfg cfg_atsha204a_swi_default = {
|
||||
.iface_type = ATCA_SWI_IFACE,
|
||||
.devtype = ATSHA204A,
|
||||
{
|
||||
.atcaswi.bus = 4,
|
||||
},
|
||||
.wake_delay = 2560,
|
||||
.rx_retries = 10
|
||||
};
|
||||
|
||||
/** \brief default configuration for Kit protocol over the device's async interface */
|
||||
ATCAIfaceCfg cfg_atsha204a_kitcdc_default = {
|
||||
.iface_type = ATCA_UART_IFACE,
|
||||
.devtype = ATSHA204A,
|
||||
{
|
||||
.atcauart.port = 0,
|
||||
.atcauart.baud = 115200,
|
||||
.atcauart.wordsize = 8,
|
||||
.atcauart.parity = 2,
|
||||
.atcauart.stopbits = 1,
|
||||
},
|
||||
.rx_retries = 1,
|
||||
};
|
||||
|
||||
/** \brief default configuration for Kit protocol over the device's async interface */
|
||||
ATCAIfaceCfg cfg_atsha204a_kithid_default = {
|
||||
.iface_type = ATCA_HID_IFACE,
|
||||
.devtype = ATSHA204A,
|
||||
.atcahid.dev_interface = ATCA_KIT_AUTO_IFACE,
|
||||
.atcahid.dev_identity = 0,
|
||||
.atcahid.idx = 0,
|
||||
.atcahid.vid = 0x03EB,
|
||||
.atcahid.pid = 0x2312,
|
||||
.atcahid.packetsize = 64,
|
||||
};
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief a set of default configurations for various ATCA devices and interfaces
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCA_CFGS_H_
|
||||
#define ATCA_CFGS_H_
|
||||
|
||||
#include "atca_iface.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief default configuration for an ECCx08A device on the first logical I2C bus */
|
||||
extern ATCAIfaceCfg cfg_ateccx08a_i2c_default;
|
||||
|
||||
/** \brief default configuration for an ECCx08A device on the logical SWI bus over UART*/
|
||||
extern ATCAIfaceCfg cfg_ateccx08a_swi_default;
|
||||
|
||||
/** \brief default configuration for Kit protocol over a CDC interface */
|
||||
extern ATCAIfaceCfg cfg_ateccx08a_kitcdc_default;
|
||||
|
||||
/** \brief default configuration for Kit protocol over a HID interface */
|
||||
extern ATCAIfaceCfg cfg_ateccx08a_kithid_default;
|
||||
|
||||
|
||||
/** \brief default configuration for a SHA204A device on the first logical I2C bus */
|
||||
extern ATCAIfaceCfg cfg_atsha204a_i2c_default;
|
||||
|
||||
/** \brief default configuration for an SHA204A device on the logical SWI bus over UART*/
|
||||
extern ATCAIfaceCfg cfg_atsha204a_swi_default;
|
||||
|
||||
/** \brief default configuration for Kit protocol over a CDC interface */
|
||||
extern ATCAIfaceCfg cfg_atsha204a_kitcdc_default;
|
||||
|
||||
/** \brief default configuration for Kit protocol over a HID interface for SHA204 */
|
||||
extern ATCAIfaceCfg cfg_atsha204a_kithid_default;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* ATCA_CFGS_H_ */
|
||||
@@ -0,0 +1,767 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Microchip CryptoAuthentication device command builder - this is the main object that builds the command
|
||||
* byte strings for the given device. It does not execute the command. The basic flow is to call
|
||||
* a command method to build the command you want given the parameters and then send that byte string
|
||||
* through the device interface.
|
||||
*
|
||||
* The primary goal of the command builder is to wrap the given parameters with the correct packet size and CRC.
|
||||
* The caller should first fill in the parameters required in the ATCAPacket parameter given to the command.
|
||||
* The command builder will deal with the mechanics of creating a valid packet using the parameter information.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "atca_command.h"
|
||||
#include "atca_devtypes.h"
|
||||
|
||||
/** \brief ATCACommand CheckMAC method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atCheckMAC(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_CHECKMAC;
|
||||
packet->txsize = CHECKMAC_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Counter method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atCounter(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_COUNTER;
|
||||
packet->txsize = COUNTER_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand DeriveKey method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \param[in] has_mac hasMAC determines if MAC data is present in the packet input
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atDeriveKey(ATCACommand ca_cmd, ATCAPacket *packet, bool has_mac)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_DERIVE_KEY;
|
||||
|
||||
// hasMAC must be given since the packet does not have any implicit information to
|
||||
// know if it has a mac or not unless the size is preset
|
||||
if (has_mac)
|
||||
{
|
||||
packet->txsize = DERIVE_KEY_COUNT_LARGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize = DERIVE_KEY_COUNT_SMALL;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand ECDH method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atECDH(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_ECDH;
|
||||
packet->txsize = ECDH_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Generate Digest method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \param[in] is_no_mac_key Should be true if GenDig is being run on a slot that has its SlotConfig.NoMac bit set
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atGenDig(ATCACommand ca_cmd, ATCAPacket *packet, bool is_no_mac_key)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_GENDIG;
|
||||
|
||||
if (packet->param1 == GENDIG_ZONE_SHARED_NONCE) // shared nonce mode
|
||||
{
|
||||
packet->txsize = GENDIG_COUNT + 32;
|
||||
}
|
||||
else if (is_no_mac_key)
|
||||
{
|
||||
packet->txsize = GENDIG_COUNT + 4; // noMac keys use 4 bytes of OtherData in calculation
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize = GENDIG_COUNT;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Generate Key method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atGenKey(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_GENKEY;
|
||||
|
||||
if (packet->param1 & GENKEY_MODE_PUBKEY_DIGEST)
|
||||
{
|
||||
packet->txsize = GENKEY_COUNT_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize = GENKEY_COUNT;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand HMAC method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atHMAC(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_HMAC;
|
||||
packet->txsize = HMAC_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Info method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atInfo(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_INFO;
|
||||
packet->txsize = INFO_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Lock method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atLock(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_LOCK;
|
||||
packet->txsize = LOCK_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand MAC method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atMAC(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
// variable packet size
|
||||
packet->opcode = ATCA_MAC;
|
||||
if (!(packet->param1 & MAC_MODE_BLOCK2_TEMPKEY))
|
||||
{
|
||||
packet->txsize = MAC_COUNT_LONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize = MAC_COUNT_SHORT;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Nonce method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atNonce(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
// variable packet size
|
||||
uint8_t calc_mode = packet->param1 & NONCE_MODE_MASK;
|
||||
|
||||
packet->opcode = ATCA_NONCE;
|
||||
|
||||
if ((calc_mode == NONCE_MODE_SEED_UPDATE || calc_mode == NONCE_MODE_NO_SEED_UPDATE))
|
||||
{
|
||||
// Calculated nonce mode, 20 byte NumInm
|
||||
packet->txsize = NONCE_COUNT_SHORT;
|
||||
}
|
||||
else if (calc_mode == NONCE_MODE_PASSTHROUGH)
|
||||
{
|
||||
// PAss-through nonce mode
|
||||
if ((packet->param1 & NONCE_MODE_INPUT_LEN_MASK) == NONCE_MODE_INPUT_LEN_64)
|
||||
{
|
||||
// 64 byte NumIn
|
||||
packet->txsize = NONCE_COUNT_LONG_64;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 32 byte NumIn
|
||||
packet->txsize = NONCE_COUNT_LONG;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Pause method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atPause(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_PAUSE;
|
||||
packet->txsize = PAUSE_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand PrivWrite method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atPrivWrite(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_PRIVWRITE;
|
||||
packet->txsize = PRIVWRITE_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Random method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atRandom(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_RANDOM;
|
||||
packet->txsize = RANDOM_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Read method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atRead(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_READ;
|
||||
packet->txsize = READ_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand SecureBoot method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atSecureBoot(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
packet->opcode = ATCA_SECUREBOOT;
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN;
|
||||
|
||||
//variable transmit size based on mode encoding
|
||||
switch (packet->param1 & SECUREBOOT_MODE_MASK)
|
||||
{
|
||||
case SECUREBOOT_MODE_FULL:
|
||||
case SECUREBOOT_MODE_FULL_COPY:
|
||||
packet->txsize += (SECUREBOOT_DIGEST_SIZE + SECUREBOOT_SIGNATURE_SIZE);
|
||||
break;
|
||||
|
||||
case SECUREBOOT_MODE_FULL_STORE:
|
||||
packet->txsize += SECUREBOOT_DIGEST_SIZE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand SHA method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \param[in] write_context_size the length of the sha write_context data
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atSHA(ATCACommand ca_cmd, ATCAPacket *packet, uint16_t write_context_size)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_SHA;
|
||||
|
||||
switch (packet->param1 & SHA_MODE_MASK)
|
||||
{
|
||||
case SHA_MODE_SHA256_START: // START
|
||||
case SHA_MODE_HMAC_START:
|
||||
case SHA_MODE_SHA256_PUBLIC:
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN;
|
||||
break;
|
||||
|
||||
case SHA_MODE_SHA256_UPDATE: // UPDATE
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN + packet->param2;
|
||||
break;
|
||||
|
||||
case SHA_MODE_SHA256_END: // END
|
||||
case SHA_MODE_HMAC_END:
|
||||
// check the given packet for a size variable in param2. If it is > 0, it should
|
||||
// be 0-63, incorporate that size into the packet
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN + packet->param2;
|
||||
break;
|
||||
|
||||
case SHA_MODE_READ_CONTEXT:
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN;
|
||||
break;
|
||||
|
||||
case SHA_MODE_WRITE_CONTEXT:
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN + write_context_size;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Sign method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atSign(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_SIGN;
|
||||
packet->txsize = SIGN_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand UpdateExtra method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atUpdateExtra(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_UPDATE_EXTRA;
|
||||
packet->txsize = UPDATE_COUNT;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand ECDSA Verify method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atVerify(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_VERIFY;
|
||||
|
||||
// variable packet size based on mode
|
||||
switch (packet->param1 & VERIFY_MODE_MASK)
|
||||
{
|
||||
case VERIFY_MODE_STORED:
|
||||
packet->txsize = VERIFY_256_STORED_COUNT;
|
||||
break;
|
||||
|
||||
case VERIFY_MODE_VALIDATE_EXTERNAL:
|
||||
packet->txsize = VERIFY_256_EXTERNAL_COUNT;
|
||||
break;
|
||||
|
||||
case VERIFY_MODE_EXTERNAL:
|
||||
packet->txsize = VERIFY_256_EXTERNAL_COUNT;
|
||||
break;
|
||||
|
||||
case VERIFY_MODE_VALIDATE:
|
||||
case VERIFY_MODE_INVALIDATE:
|
||||
packet->txsize = VERIFY_256_VALIDATE_COUNT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand Write method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \param[in] has_mac Flag to indicate whether a mac is present or not
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atWrite(ATCACommand ca_cmd, ATCAPacket *packet, bool has_mac)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_WRITE;
|
||||
|
||||
packet->txsize = 7;
|
||||
if (packet->param1 & ATCA_ZONE_READWRITE_32)
|
||||
{
|
||||
packet->txsize += ATCA_BLOCK_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize += ATCA_WORD_SIZE;
|
||||
}
|
||||
if (has_mac)
|
||||
{
|
||||
packet->txsize += WRITE_MAC_SIZE;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand AES method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atAES(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_AES;
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN;
|
||||
|
||||
if ((packet->param1 & AES_MODE_OP_MASK) == AES_MODE_GFM)
|
||||
{
|
||||
packet->txsize += ATCA_AES_GFM_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
packet->txsize += AES_DATA_SIZE;
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief ATCACommand AES method
|
||||
* \param[in] ca_cmd instance
|
||||
* \param[in] packet pointer to the packet containing the command being built
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atSelfTest(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_SELFTEST;
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN;
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** \brief ATCACommand KDF method
|
||||
* \param[in] ca_cmd Instance
|
||||
* \param[in] packet Pointer to the packet containing the command being
|
||||
* built.
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atKDF(ATCACommand ca_cmd, ATCAPacket *packet)
|
||||
{
|
||||
// Set the opcode & parameters
|
||||
packet->opcode = ATCA_KDF;
|
||||
|
||||
// Set TX size
|
||||
if ((packet->param1 & KDF_MODE_ALG_MASK) == KDF_MODE_ALG_AES)
|
||||
{
|
||||
// AES algorithm has a fixed message size
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN + KDF_DETAILS_SIZE + AES_DATA_SIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// All other algorithms encode message size in the last byte of details
|
||||
packet->txsize = ATCA_CMD_SIZE_MIN + KDF_DETAILS_SIZE + packet->data[3];
|
||||
}
|
||||
atCalcCrc(packet);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Initializer for ATCACommand
|
||||
* \param[in] device_type Specifies which set of commands and execution times
|
||||
* should be associated with this command object.
|
||||
* \param[in] ca_cmd Pre-allocated command structure to initialize.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS initATCACommand(ATCADeviceType device_type, ATCACommand ca_cmd)
|
||||
{
|
||||
if (ca_cmd == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
ca_cmd->dt = device_type;
|
||||
ca_cmd->clock_divider = 0;
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef ATCA_NO_HEAP
|
||||
/** \brief constructor for ATCACommand
|
||||
* \param[in] device_type Specifies which set of commands and execution times
|
||||
* should be associated with this command object.
|
||||
* \return Initialized object on success. NULL on failure.
|
||||
*/
|
||||
ATCACommand newATCACommand(ATCADeviceType device_type)
|
||||
{
|
||||
ATCACommand ca_cmd;
|
||||
ATCA_STATUS status;
|
||||
|
||||
ca_cmd = (ATCACommand)malloc(sizeof(*ca_cmd));
|
||||
status = initATCACommand(device_type, ca_cmd);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
free(ca_cmd);
|
||||
ca_cmd = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ca_cmd;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef ATCA_NO_HEAP
|
||||
/** \brief ATCACommand destructor
|
||||
* \param[in] ca_cmd instance of a command object
|
||||
*/
|
||||
void deleteATCACommand(ATCACommand *ca_cmd)
|
||||
{
|
||||
if (ca_cmd == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
free(*ca_cmd);
|
||||
*ca_cmd = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Calculates CRC over the given raw data and returns the CRC in
|
||||
* little-endian byte order.
|
||||
*
|
||||
* \param[in] length Size of data not including the CRC byte positions
|
||||
* \param[in] data Pointer to the data over which to compute the CRC
|
||||
* \param[out] crc_le Pointer to the place where the two-bytes of CRC will be
|
||||
* returned in little-endian byte order.
|
||||
*/
|
||||
void atCRC(size_t length, const uint8_t *data, uint8_t *crc_le)
|
||||
{
|
||||
size_t counter;
|
||||
uint16_t crc_register = 0;
|
||||
uint16_t polynom = 0x8005;
|
||||
uint8_t shift_register;
|
||||
uint8_t data_bit, crc_bit;
|
||||
|
||||
for (counter = 0; counter < length; counter++)
|
||||
{
|
||||
for (shift_register = 0x01; shift_register > 0x00; shift_register <<= 1)
|
||||
{
|
||||
data_bit = (data[counter] & shift_register) ? 1 : 0;
|
||||
crc_bit = crc_register >> 15;
|
||||
crc_register <<= 1;
|
||||
if (data_bit != crc_bit)
|
||||
{
|
||||
crc_register ^= polynom;
|
||||
}
|
||||
}
|
||||
}
|
||||
crc_le[0] = (uint8_t)(crc_register & 0x00FF);
|
||||
crc_le[1] = (uint8_t)(crc_register >> 8);
|
||||
}
|
||||
|
||||
|
||||
/** \brief This function calculates CRC and adds it to the correct offset in the packet data
|
||||
* \param[in] packet Packet to calculate CRC data for
|
||||
*/
|
||||
|
||||
void atCalcCrc(ATCAPacket *packet)
|
||||
{
|
||||
uint8_t length, *crc;
|
||||
|
||||
packet->param2 = ATCA_UINT16_HOST_TO_LE(packet->param2);
|
||||
|
||||
length = packet->txsize - ATCA_CRC_SIZE;
|
||||
// computer pointer to CRC in the packet
|
||||
crc = &(packet->txsize) + length;
|
||||
|
||||
// stuff CRC into packet
|
||||
atCRC(length, &(packet->txsize), crc);
|
||||
}
|
||||
|
||||
|
||||
/** \brief This function checks the consistency of a response.
|
||||
* \param[in] response pointer to response
|
||||
* \return ATCA_SUCCESS on success, otherwise ATCA_RX_CRC_ERROR
|
||||
*/
|
||||
|
||||
ATCA_STATUS atCheckCrc(const uint8_t *response)
|
||||
{
|
||||
uint8_t crc[ATCA_CRC_SIZE];
|
||||
uint8_t count = response[ATCA_COUNT_IDX];
|
||||
|
||||
count -= ATCA_CRC_SIZE;
|
||||
atCRC(count, response, crc);
|
||||
|
||||
return (crc[0] == response[count] && crc[1] == response[count + 1]) ? ATCA_SUCCESS : ATCA_RX_CRC_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/** \brief determines if a given device type is a SHA device or a superset of a SHA device
|
||||
* \param[in] device_type Type of device to check for family type
|
||||
* \return boolean indicating whether the given device is a SHA family device.
|
||||
*/
|
||||
|
||||
bool atIsSHAFamily(ATCADeviceType device_type)
|
||||
{
|
||||
switch (device_type)
|
||||
{
|
||||
case ATSHA204A:
|
||||
case ATECC108A:
|
||||
case ATECC508A:
|
||||
case ATECC608A:
|
||||
return true;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief determines if a given device type is an ECC device or a superset of a ECC device
|
||||
* \param[in] device_type Type of device to check for family type
|
||||
* \return boolean indicating whether the given device is an ECC family device.
|
||||
*/
|
||||
bool atIsECCFamily(ATCADeviceType device_type)
|
||||
{
|
||||
switch (device_type)
|
||||
{
|
||||
case ATECC108A:
|
||||
case ATECC508A:
|
||||
case ATECC608A:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief checks for basic error frame in data
|
||||
* \param[in] data pointer to received data - expected to be in the form of a CA device response frame
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS isATCAError(uint8_t *data)
|
||||
{
|
||||
if (data[0] == 0x04) // error packets are always 4 bytes long
|
||||
{
|
||||
switch (data[1])
|
||||
{
|
||||
case 0x00: //No Error
|
||||
return ATCA_SUCCESS;
|
||||
case 0x01: // checkmac or verify failed
|
||||
return ATCA_CHECKMAC_VERIFY_FAILED;
|
||||
break;
|
||||
case 0x03: // command received byte length, opcode or parameter was illegal
|
||||
return ATCA_PARSE_ERROR;
|
||||
break;
|
||||
case 0x05: // computation error during ECC processing causing invalid results
|
||||
return ATCA_STATUS_ECC;
|
||||
break;
|
||||
case 0x07: // chip is in self test failure mode
|
||||
return ATCA_STATUS_SELFTEST_ERROR;
|
||||
break;
|
||||
case 0x08: //random number generator health test error
|
||||
return ATCA_HEALTH_TEST_ERROR;
|
||||
case 0x0f: // chip can't execute the command
|
||||
return ATCA_EXECUTION_ERROR;
|
||||
break;
|
||||
case 0x11: // chip was successfully woken up
|
||||
return ATCA_WAKE_SUCCESS;
|
||||
break;
|
||||
case 0xff: // bad crc found (command not properly received by device) or other comm error
|
||||
return ATCA_STATUS_CRC;
|
||||
break;
|
||||
default:
|
||||
return ATCA_GEN_FAIL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,765 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Microchip Crypto Auth device command object - this is a command builder only, it does
|
||||
* not send the command. The result of a command method is a fully formed packet, ready to send
|
||||
* to the ATCAIFace object to dispatch.
|
||||
*
|
||||
* This command object supports the ATSHA and ATECC device family.
|
||||
* The command list is a superset of all device commands for this family. The command object
|
||||
* differentiates the packet contents based on specific device type within the family.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCA_COMMAND_H
|
||||
#define ATCA_COMMAND_H
|
||||
|
||||
#include "atca_compiler.h"
|
||||
#include "atca_status.h"
|
||||
#include "atca_devtypes.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup command ATCACommand (atca_)
|
||||
\brief CryptoAuthLib command builder object, ATCACommand. Member functions for the ATCACommand object.
|
||||
@{ */
|
||||
|
||||
/** \brief atca_command is the C object backing ATCACommand.
|
||||
*/
|
||||
struct atca_command
|
||||
{
|
||||
ATCADeviceType dt;
|
||||
uint8_t clock_divider;
|
||||
uint16_t execution_time_msec;
|
||||
};
|
||||
|
||||
/*--- ATCACommand ---------*/
|
||||
typedef struct atca_command* ATCACommand;
|
||||
|
||||
ATCA_STATUS initATCACommand(ATCADeviceType device_type, ATCACommand ca_cmd);
|
||||
ATCACommand newATCACommand(ATCADeviceType device_type);
|
||||
void deleteATCACommand(ATCACommand *ca_cmd);
|
||||
|
||||
/* add ATCACommand declarations here
|
||||
*
|
||||
* since these are still C functions, not classes, naming is an important
|
||||
* consideration to keep the namespace from colliding with other 3rd party
|
||||
* libraries or even ourselves/ASF.
|
||||
*
|
||||
* Basic conventions:
|
||||
* all methods start with the prefix 'at'
|
||||
* all method names must be unique, obviously
|
||||
* all method implementations should be proceeded by their Doxygen comment header
|
||||
*
|
||||
**/
|
||||
|
||||
|
||||
// this is the ATCACommand parameter structure. The caller to the command method must
|
||||
// initialize param1, param2 and data if appropriate. The command method will fill in the rest
|
||||
// and initialize the packet so it's ready to send via the ATCAIFace.
|
||||
// this particular structure mimics the ATSHA and ATECC family device's command structures
|
||||
|
||||
// Note: pack @ 2 is required, @ 1 causes word alignment crash (though it should not), a known bug in GCC.
|
||||
// @2, the wire still has the intended byte alignment with arm-eabi. this is likely the least portable part of atca
|
||||
|
||||
|
||||
#ifdef ATCA_NO_PRAGMA_PACK
|
||||
typedef struct __attribute__ ((packed))
|
||||
#else
|
||||
#pragma pack( push, ATCAPacket, 2 )
|
||||
typedef struct
|
||||
#endif
|
||||
/** \brief an ATCA packet structure. This is a superset of the packet transmitted on the wire. It's also
|
||||
* used as a buffer for receiving the response
|
||||
*/
|
||||
{
|
||||
|
||||
// used for transmit/send
|
||||
uint8_t _reserved; // used by HAL layer as needed (I/O tokens, Word address values)
|
||||
|
||||
//--- start of packet i/o frame----
|
||||
uint8_t txsize;
|
||||
uint8_t opcode;
|
||||
uint8_t param1; // often same as mode
|
||||
uint16_t param2;
|
||||
uint8_t data[192]; // includes 2-byte CRC. data size is determined by largest possible data section of any
|
||||
// command + crc (see: x08 verify data1 + data2 + data3 + data4)
|
||||
// this is an explicit design trade-off (space) resulting in simplicity in use
|
||||
// and implementation
|
||||
//--- end of packet i/o frame
|
||||
|
||||
// used for receive
|
||||
uint8_t execTime; // execution time of command by opcode
|
||||
|
||||
// structure should be packed since it will be transmitted over the wire
|
||||
// this method varies by compiler. As new compilers are supported, add their structure packing method here
|
||||
|
||||
} ATCAPacket;
|
||||
|
||||
#ifndef ATCA_NO_PRAGMA_PACK
|
||||
#pragma pack( pop, ATCAPacket)
|
||||
#endif
|
||||
|
||||
|
||||
ATCA_STATUS atCheckMAC(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atCounter(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atDeriveKey(ATCACommand ca_cmd, ATCAPacket *packet, bool has_mac);
|
||||
ATCA_STATUS atECDH(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atGenDig(ATCACommand ca_cmd, ATCAPacket *packet, bool is_no_mac_key);
|
||||
ATCA_STATUS atGenKey(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atHMAC(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atInfo(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atLock(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atMAC(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atNonce(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atPause(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atPrivWrite(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atRandom(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atRead(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atSecureBoot(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atSHA(ATCACommand ca_cmd, ATCAPacket *packet, uint16_t write_context_size);
|
||||
ATCA_STATUS atSign(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atUpdateExtra(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atVerify(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atWrite(ATCACommand ca_cmd, ATCAPacket *packet, bool has_mac);
|
||||
ATCA_STATUS atAES(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atSelfTest(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
ATCA_STATUS atKDF(ATCACommand ca_cmd, ATCAPacket *packet);
|
||||
|
||||
bool atIsSHAFamily(ATCADeviceType device_type);
|
||||
bool atIsECCFamily(ATCADeviceType device_type);
|
||||
ATCA_STATUS isATCAError(uint8_t *data);
|
||||
|
||||
|
||||
// command helpers
|
||||
void atCRC(size_t length, const uint8_t *data, uint8_t *crc_le);
|
||||
void atCalcCrc(ATCAPacket *pkt);
|
||||
ATCA_STATUS atCheckCrc(const uint8_t *response);
|
||||
|
||||
|
||||
/* command definitions */
|
||||
|
||||
//! minimum number of bytes in command (from count byte to second CRC byte)
|
||||
#define ATCA_CMD_SIZE_MIN ((uint8_t)7)
|
||||
//! maximum size of command packet (Verify)
|
||||
#define ATCA_CMD_SIZE_MAX ((uint8_t)4 * 36 + 7)
|
||||
//! status byte for success
|
||||
#define CMD_STATUS_SUCCESS ((uint8_t)0x00)
|
||||
//! status byte after wake-up
|
||||
#define CMD_STATUS_WAKEUP ((uint8_t)0x11)
|
||||
//! command parse error
|
||||
#define CMD_STATUS_BYTE_PARSE ((uint8_t)0x03)
|
||||
//! command ECC error
|
||||
#define CMD_STATUS_BYTE_ECC ((uint8_t)0x05)
|
||||
//! command execution error
|
||||
#define CMD_STATUS_BYTE_EXEC ((uint8_t)0x0F)
|
||||
//! communication error
|
||||
#define CMD_STATUS_BYTE_COMM ((uint8_t)0xFF)
|
||||
|
||||
/** \name Opcodes for Crypto Authentication device commands
|
||||
@{ */
|
||||
#define ATCA_CHECKMAC ((uint8_t)0x28) //!< CheckMac command op-code
|
||||
#define ATCA_DERIVE_KEY ((uint8_t)0x1C) //!< DeriveKey command op-code
|
||||
#define ATCA_INFO ((uint8_t)0x30) //!< Info command op-code
|
||||
#define ATCA_GENDIG ((uint8_t)0x15) //!< GenDig command op-code
|
||||
#define ATCA_GENKEY ((uint8_t)0x40) //!< GenKey command op-code
|
||||
#define ATCA_HMAC ((uint8_t)0x11) //!< HMAC command op-code
|
||||
#define ATCA_LOCK ((uint8_t)0x17) //!< Lock command op-code
|
||||
#define ATCA_MAC ((uint8_t)0x08) //!< MAC command op-code
|
||||
#define ATCA_NONCE ((uint8_t)0x16) //!< Nonce command op-code
|
||||
#define ATCA_PAUSE ((uint8_t)0x01) //!< Pause command op-code
|
||||
#define ATCA_PRIVWRITE ((uint8_t)0x46) //!< PrivWrite command op-code
|
||||
#define ATCA_RANDOM ((uint8_t)0x1B) //!< Random command op-code
|
||||
#define ATCA_READ ((uint8_t)0x02) //!< Read command op-code
|
||||
#define ATCA_SIGN ((uint8_t)0x41) //!< Sign command op-code
|
||||
#define ATCA_UPDATE_EXTRA ((uint8_t)0x20) //!< UpdateExtra command op-code
|
||||
#define ATCA_VERIFY ((uint8_t)0x45) //!< GenKey command op-code
|
||||
#define ATCA_WRITE ((uint8_t)0x12) //!< Write command op-code
|
||||
#define ATCA_ECDH ((uint8_t)0x43) //!< ECDH command op-code
|
||||
#define ATCA_COUNTER ((uint8_t)0x24) //!< Counter command op-code
|
||||
#define ATCA_SHA ((uint8_t)0x47) //!< SHA command op-code
|
||||
#define ATCA_AES ((uint8_t)0x51) //!< AES command op-code
|
||||
#define ATCA_KDF ((uint8_t)0x56) //!< KDF command op-code
|
||||
#define ATCA_SECUREBOOT ((uint8_t)0x80) //!< Secure Boot command op-code
|
||||
#define ATCA_SELFTEST ((uint8_t)0x77) //!< Self test command op-code
|
||||
|
||||
|
||||
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
/** \name Definitions of Data and Packet Sizes
|
||||
@{ */
|
||||
#define ATCA_BLOCK_SIZE (32) //!< size of a block
|
||||
#define ATCA_WORD_SIZE (4) //!< size of a word
|
||||
#define ATCA_PUB_KEY_PAD (4) //!< size of the public key pad
|
||||
#define ATCA_SERIAL_NUM_SIZE (9) //!< number of bytes in the device serial number
|
||||
#define ATCA_RSP_SIZE_VAL ((uint8_t)7) //!< size of response packet containing four bytes of data
|
||||
#define ATCA_KEY_COUNT (16) //!< number of keys
|
||||
#define ATCA_ECC_CONFIG_SIZE (128) //!< size of configuration zone
|
||||
#define ATCA_SHA_CONFIG_SIZE (88) //!< size of configuration zone
|
||||
#define ATCA_OTP_SIZE (64) //!< size of OTP zone
|
||||
#define ATCA_DATA_SIZE (ATCA_KEY_COUNT * ATCA_KEY_SIZE) //!< size of data zone
|
||||
#define ATCA_AES_GFM_SIZE ATCA_BLOCK_SIZE //!< size of GFM data
|
||||
|
||||
#define ATCA_CHIPMODE_OFFSET (19) //!< ChipMode byte offset within the configuration zone
|
||||
#define ATCA_CHIPMODE_I2C_ADDRESS_FLAG ((uint8_t)0x01) //!< ChipMode I2C Address in UserExtraAdd flag
|
||||
#define ATCA_CHIPMODE_TTL_ENABLE_FLAG ((uint8_t)0x02) //!< ChipMode TTLenable flag
|
||||
#define ATCA_CHIPMODE_WATCHDOG_MASK ((uint8_t)0x04) //!< ChipMode watchdog duration mask
|
||||
#define ATCA_CHIPMODE_WATCHDOG_SHORT ((uint8_t)0x00) //!< ChipMode short watchdog (~1.3s)
|
||||
#define ATCA_CHIPMODE_WATCHDOG_LONG ((uint8_t)0x04) //!< ChipMode long watchdog (~13s)
|
||||
#define ATCA_CHIPMODE_CLOCK_DIV_MASK ((uint8_t)0xF8) //!< ChipMode clock divider mask
|
||||
#define ATCA_CHIPMODE_CLOCK_DIV_M0 ((uint8_t)0x00) //!< ChipMode clock divider M0
|
||||
#define ATCA_CHIPMODE_CLOCK_DIV_M1 ((uint8_t)0x28) //!< ChipMode clock divider M1
|
||||
#define ATCA_CHIPMODE_CLOCK_DIV_M2 ((uint8_t)0x68) //!< ChipMode clock divider M2
|
||||
|
||||
#define ATCA_COUNT_SIZE ((uint8_t)1) //!< Number of bytes in the command packet Count
|
||||
#define ATCA_CRC_SIZE ((uint8_t)2) //!< Number of bytes in the command packet CRC
|
||||
#define ATCA_PACKET_OVERHEAD (ATCA_COUNT_SIZE + ATCA_CRC_SIZE) //!< Number of bytes in the command packet
|
||||
|
||||
#define ATCA_PUB_KEY_SIZE (64) //!< size of a p256 public key
|
||||
#define ATCA_PRIV_KEY_SIZE (32) //!< size of a p256 private key
|
||||
#define ATCA_SIG_SIZE (64) //!< size of a p256 signature
|
||||
#define ATCA_KEY_SIZE (32) //!< size of a symmetric SHA key
|
||||
#define RSA2048_KEY_SIZE (256) //!< size of a RSA private key
|
||||
|
||||
#define ATCA_RSP_SIZE_MIN ((uint8_t)4) //!< minimum number of bytes in response
|
||||
#define ATCA_RSP_SIZE_4 ((uint8_t)7) //!< size of response packet containing 4 bytes data
|
||||
#define ATCA_RSP_SIZE_72 ((uint8_t)75) //!< size of response packet containing 64 bytes data
|
||||
#define ATCA_RSP_SIZE_64 ((uint8_t)67) //!< size of response packet containing 64 bytes data
|
||||
#define ATCA_RSP_SIZE_32 ((uint8_t)35) //!< size of response packet containing 32 bytes data
|
||||
#define ATCA_RSP_SIZE_16 ((uint8_t)19) //!< size of response packet containing 16 bytes data
|
||||
#define ATCA_RSP_SIZE_MAX ((uint8_t)75) //!< maximum size of response packet (GenKey and Verify command)
|
||||
|
||||
#define OUTNONCE_SIZE (32) //!< Size of the OutNonce response expected from several commands
|
||||
|
||||
/** \name Definitions for Command Parameter Ranges
|
||||
@{ */
|
||||
#define ATCA_KEY_ID_MAX ((uint8_t)15) //!< maximum value for key id
|
||||
#define ATCA_OTP_BLOCK_MAX ((uint8_t)1) //!< maximum value for OTP block
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for Indexes Common to All Commands
|
||||
@{ */
|
||||
#define ATCA_COUNT_IDX (0) //!< command packet index for count
|
||||
#define ATCA_OPCODE_IDX (1) //!< command packet index for op-code
|
||||
#define ATCA_PARAM1_IDX (2) //!< command packet index for first parameter
|
||||
#define ATCA_PARAM2_IDX (3) //!< command packet index for second parameter
|
||||
#define ATCA_DATA_IDX (5) //!< command packet index for data load
|
||||
#define ATCA_RSP_DATA_IDX (1) //!< buffer index of data in response
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for Zone and Address Parameters
|
||||
@{ */
|
||||
#define ATCA_ZONE_CONFIG ((uint8_t)0x00) //!< Configuration zone
|
||||
#define ATCA_ZONE_OTP ((uint8_t)0x01) //!< OTP (One Time Programming) zone
|
||||
#define ATCA_ZONE_DATA ((uint8_t)0x02) //!< Data zone
|
||||
#define ATCA_ZONE_MASK ((uint8_t)0x03) //!< Zone mask
|
||||
#define ATCA_ZONE_ENCRYPTED ((uint8_t)0x40) //!< Zone bit 6 set: Write is encrypted with an unlocked data zone.
|
||||
#define ATCA_ZONE_READWRITE_32 ((uint8_t)0x80) //!< Zone bit 7 set: Access 32 bytes, otherwise 4 bytes.
|
||||
#define ATCA_ADDRESS_MASK_CONFIG (0x001F) //!< Address bits 5 to 7 are 0 for Configuration zone.
|
||||
#define ATCA_ADDRESS_MASK_OTP (0x000F) //!< Address bits 4 to 7 are 0 for OTP zone.
|
||||
#define ATCA_ADDRESS_MASK (0x007F) //!< Address bit 7 to 15 are always 0.
|
||||
#define ATCA_TEMPKEY_KEYID (0xFFFF) //!< KeyID when referencing TempKey
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for Key types
|
||||
@{ */
|
||||
#define ATCA_B283_KEY_TYPE 0 //!< B283 NIST ECC key
|
||||
#define ATCA_K283_KEY_TYPE 1 //!< K283 NIST ECC key
|
||||
#define ATCA_P256_KEY_TYPE 4 //!< P256 NIST ECC key
|
||||
#define ATCA_AES_KEY_TYPE 6 //!< AES-128 Key
|
||||
#define ATCA_SHA_KEY_TYPE 7 //!< SHA key or other data
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the AES Command
|
||||
@{ */
|
||||
#define AES_MODE_IDX ATCA_PARAM1_IDX //!< AES command index for mode
|
||||
#define AES_KEYID_IDX ATCA_PARAM2_IDX //!< AES command index for key id
|
||||
#define AES_INPUT_IDX ATCA_DATA_IDX //!< AES command index for input data
|
||||
#define AES_COUNT (23) //!< AES command packet size
|
||||
#define AES_MODE_MASK ((uint8_t)0xC7) //!< AES mode bits 3 to 5 are 0
|
||||
#define AES_MODE_KEY_BLOCK_MASK ((uint8_t)0xC0) //!< AES mode mask for key block field
|
||||
#define AES_MODE_OP_MASK ((uint8_t)0x07) //!< AES mode operation mask
|
||||
#define AES_MODE_ENCRYPT ((uint8_t)0x00) //!< AES mode: Encrypt
|
||||
#define AES_MODE_DECRYPT ((uint8_t)0x01) //!< AES mode: Decrypt
|
||||
#define AES_MODE_GFM ((uint8_t)0x03) //!< AES mode: GFM calculation
|
||||
#define AES_MODE_KEY_BLOCK_POS (6) //!< Bit shift for key block in mode
|
||||
#define AES_DATA_SIZE (16) //!< size of AES encrypt/decrypt data
|
||||
#define AES_RSP_SIZE ATCA_RSP_SIZE_16 //!< AES command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the CheckMac Command
|
||||
@{ */
|
||||
#define CHECKMAC_MODE_IDX ATCA_PARAM1_IDX //!< CheckMAC command index for mode
|
||||
#define CHECKMAC_KEYID_IDX ATCA_PARAM2_IDX //!< CheckMAC command index for key identifier
|
||||
#define CHECKMAC_CLIENT_CHALLENGE_IDX ATCA_DATA_IDX //!< CheckMAC command index for client challenge
|
||||
#define CHECKMAC_CLIENT_RESPONSE_IDX (37) //!< CheckMAC command index for client response
|
||||
#define CHECKMAC_DATA_IDX (69) //!< CheckMAC command index for other data
|
||||
#define CHECKMAC_COUNT (84) //!< CheckMAC command packet size
|
||||
#define CHECKMAC_MODE_CHALLENGE ((uint8_t)0x00) //!< CheckMAC mode 0: first SHA block from key id
|
||||
#define CHECKMAC_MODE_BLOCK2_TEMPKEY ((uint8_t)0x01) //!< CheckMAC mode bit 0: second SHA block from TempKey
|
||||
#define CHECKMAC_MODE_BLOCK1_TEMPKEY ((uint8_t)0x02) //!< CheckMAC mode bit 1: first SHA block from TempKey
|
||||
#define CHECKMAC_MODE_SOURCE_FLAG_MATCH ((uint8_t)0x04) //!< CheckMAC mode bit 2: match TempKey.SourceFlag
|
||||
#define CHECKMAC_MODE_INCLUDE_OTP_64 ((uint8_t)0x20) //!< CheckMAC mode bit 5: include first 64 OTP bits
|
||||
#define CHECKMAC_MODE_MASK ((uint8_t)0x27) //!< CheckMAC mode bits 3, 4, 6, and 7 are 0.
|
||||
#define CHECKMAC_CLIENT_CHALLENGE_SIZE (32) //!< CheckMAC size of client challenge
|
||||
#define CHECKMAC_CLIENT_RESPONSE_SIZE (32) //!< CheckMAC size of client response
|
||||
#define CHECKMAC_OTHER_DATA_SIZE (13) //!< CheckMAC size of "other data"
|
||||
#define CHECKMAC_CLIENT_COMMAND_SIZE (4) //!< CheckMAC size of client command header size inside "other data"
|
||||
#define CHECKMAC_CMD_MATCH (0) //!< CheckMAC return value when there is a match
|
||||
#define CHECKMAC_CMD_MISMATCH (1) //!< CheckMAC return value when there is a mismatch
|
||||
#define CHECKMAC_RSP_SIZE ATCA_RSP_SIZE_MIN //!< CheckMAC response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Counter command
|
||||
@{ */
|
||||
#define COUNTER_COUNT ATCA_CMD_SIZE_MIN
|
||||
#define COUNTER_MODE_IDX ATCA_PARAM1_IDX //!< Counter command index for mode
|
||||
#define COUNTER_KEYID_IDX ATCA_PARAM2_IDX //!< Counter command index for key id
|
||||
#define COUNTER_MODE_MASK ((uint8_t)0x01) //!< Counter mode bits 1 to 7 are 0
|
||||
#define COUNTER_MAX_VALUE ((uint32_t)2097151) //!< Counter maximum value of the counter
|
||||
#define COUNTER_MODE_READ ((uint8_t)0x00) //!< Counter command mode for reading
|
||||
#define COUNTER_MODE_INCREMENT ((uint8_t)0x01) //!< Counter command mode for incrementing
|
||||
#define COUNTER_RSP_SIZE ATCA_RSP_SIZE_4 //!< Counter command response packet size
|
||||
#define COUNTER_SIZE ATCA_RSP_SIZE_MIN //!< Counter size in binary
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the DeriveKey Command
|
||||
@{ */
|
||||
#define DERIVE_KEY_RANDOM_IDX ATCA_PARAM1_IDX //!< DeriveKey command index for random bit
|
||||
#define DERIVE_KEY_TARGETKEY_IDX ATCA_PARAM2_IDX //!< DeriveKey command index for target slot
|
||||
#define DERIVE_KEY_MAC_IDX ATCA_DATA_IDX //!< DeriveKey command index for optional MAC
|
||||
#define DERIVE_KEY_COUNT_SMALL ATCA_CMD_SIZE_MIN //!< DeriveKey command packet size without MAC
|
||||
#define DERIVE_KEY_MODE ((uint8_t)0x04) //!< DeriveKey command mode set to 4 as in datasheet
|
||||
#define DERIVE_KEY_COUNT_LARGE (39) //!< DeriveKey command packet size with MAC
|
||||
#define DERIVE_KEY_RANDOM_FLAG ((uint8_t)4) //!< DeriveKey 1. parameter; has to match TempKey.SourceFlag
|
||||
#define DERIVE_KEY_MAC_SIZE (32) //!< DeriveKey MAC size
|
||||
#define DERIVE_KEY_RSP_SIZE ATCA_RSP_SIZE_MIN //!< DeriveKey response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the ECDH Command
|
||||
@{ */
|
||||
#define ECDH_PREFIX_MODE ((uint8_t)0x00)
|
||||
#define ECDH_COUNT (ATCA_CMD_SIZE_MIN + ATCA_PUB_KEY_SIZE)
|
||||
#define ECDH_MODE_SOURCE_MASK ((uint8_t)0x01)
|
||||
#define ECDH_MODE_SOURCE_EEPROM_SLOT ((uint8_t)0x00)
|
||||
#define ECDH_MODE_SOURCE_TEMPKEY ((uint8_t)0x01)
|
||||
#define ECDH_MODE_OUTPUT_MASK ((uint8_t)0x02)
|
||||
#define ECDH_MODE_OUTPUT_CLEAR ((uint8_t)0x00)
|
||||
#define ECDH_MODE_OUTPUT_ENC ((uint8_t)0x02)
|
||||
#define ECDH_MODE_COPY_MASK ((uint8_t)0x0C)
|
||||
#define ECDH_MODE_COPY_COMPATIBLE ((uint8_t)0x00)
|
||||
#define ECDH_MODE_COPY_EEPROM_SLOT ((uint8_t)0x04)
|
||||
#define ECDH_MODE_COPY_TEMP_KEY ((uint8_t)0x08)
|
||||
#define ECDH_MODE_COPY_OUTPUT_BUFFER ((uint8_t)0x0C)
|
||||
#define ECDH_KEY_SIZE ATCA_BLOCK_SIZE //!< ECDH output data size
|
||||
#define ECDH_RSP_SIZE ATCA_RSP_SIZE_64 //!< ECDH command packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the GenDig Command
|
||||
@{ */
|
||||
#define GENDIG_ZONE_IDX ATCA_PARAM1_IDX //!< GenDig command index for zone
|
||||
#define GENDIG_KEYID_IDX ATCA_PARAM2_IDX //!< GenDig command index for key id
|
||||
#define GENDIG_DATA_IDX ATCA_DATA_IDX //!< GenDig command index for optional data
|
||||
#define GENDIG_COUNT ATCA_CMD_SIZE_MIN //!< GenDig command packet size without "other data"
|
||||
#define GENDIG_ZONE_CONFIG ((uint8_t)0) //!< GenDig zone id config. Use KeyID to specify any of the four 256-bit blocks of the Configuration zone.
|
||||
#define GENDIG_ZONE_OTP ((uint8_t)1) //!< GenDig zone id OTP. Use KeyID to specify either the first or second 256-bit block of the OTP zone.
|
||||
#define GENDIG_ZONE_DATA ((uint8_t)2) //!< GenDig zone id data. Use KeyID to specify a slot in the Data zone or a transport key in the hardware array.
|
||||
#define GENDIG_ZONE_SHARED_NONCE ((uint8_t)3) //!< GenDig zone id shared nonce. KeyID specifies the location of the input value in the message generation.
|
||||
#define GENDIG_ZONE_COUNTER ((uint8_t)4) //!< GenDig zone id counter. KeyID specifies the monotonic counter ID to be included in the message generation.
|
||||
#define GENDIG_ZONE_KEY_CONFIG ((uint8_t)5) //!< GenDig zone id key config. KeyID specifies the slot for which the configuration information is to be included in the message generation.
|
||||
#define GENDIG_RSP_SIZE ATCA_RSP_SIZE_MIN //!< GenDig command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the GenKey Command
|
||||
@{ */
|
||||
#define GENKEY_MODE_IDX ATCA_PARAM1_IDX //!< GenKey command index for mode
|
||||
#define GENKEY_KEYID_IDX ATCA_PARAM2_IDX //!< GenKey command index for key id
|
||||
#define GENKEY_DATA_IDX (5) //!< GenKey command index for other data
|
||||
#define GENKEY_COUNT ATCA_CMD_SIZE_MIN //!< GenKey command packet size without "other data"
|
||||
#define GENKEY_COUNT_DATA (10) //!< GenKey command packet size with "other data"
|
||||
#define GENKEY_OTHER_DATA_SIZE (3) //!< GenKey size of "other data"
|
||||
#define GENKEY_MODE_MASK ((uint8_t)0x1C) //!< GenKey mode bits 0 to 1 and 5 to 7 are 0
|
||||
#define GENKEY_MODE_PRIVATE ((uint8_t)0x04) //!< GenKey mode: private key generation
|
||||
#define GENKEY_MODE_PUBLIC ((uint8_t)0x00) //!< GenKey mode: public key calculation
|
||||
#define GENKEY_MODE_DIGEST ((uint8_t)0x08) //!< GenKey mode: PubKey digest will be created after the public key is calculated
|
||||
#define GENKEY_MODE_PUBKEY_DIGEST ((uint8_t)0x10) //!< GenKey mode: Calculate PubKey digest on the public key in KeyId
|
||||
#define GENKEY_PRIVATE_TO_TEMPKEY ((uint16_t)0xFFFF) //!< GenKey Create private key and store to tempkey (608 only)
|
||||
#define GENKEY_RSP_SIZE_SHORT ATCA_RSP_SIZE_MIN //!< GenKey response packet size in Digest mode
|
||||
#define GENKEY_RSP_SIZE_LONG ATCA_RSP_SIZE_64 //!< GenKey response packet size when returning a public key
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the HMAC Command
|
||||
@{ */
|
||||
#define HMAC_MODE_IDX ATCA_PARAM1_IDX //!< HMAC command index for mode
|
||||
#define HMAC_KEYID_IDX ATCA_PARAM2_IDX //!< HMAC command index for key id
|
||||
#define HMAC_COUNT ATCA_CMD_SIZE_MIN //!< HMAC command packet size
|
||||
#define HMAC_MODE_FLAG_TK_RAND ((uint8_t)0x00) //!< HMAC mode bit 2: The value of this bit must match the value in TempKey.SourceFlag or the command will return an error.
|
||||
#define HMAC_MODE_FLAG_TK_NORAND ((uint8_t)0x04) //!< HMAC mode bit 2: The value of this bit must match the value in TempKey.SourceFlag or the command will return an error.
|
||||
#define HMAC_MODE_FLAG_OTP88 ((uint8_t)0x10) //!< HMAC mode bit 4: Include the first 88 OTP bits (OTP[0] through OTP[10]) in the message.; otherwise, the corresponding message bits are set to zero. Not applicable for ATECC508A.
|
||||
#define HMAC_MODE_FLAG_OTP64 ((uint8_t)0x20) //!< HMAC mode bit 5: Include the first 64 OTP bits (OTP[0] through OTP[7]) in the message.; otherwise, the corresponding message bits are set to zero. If Mode[4] is set, the value of this mode bit is ignored. Not applicable for ATECC508A.
|
||||
#define HMAC_MODE_FLAG_FULLSN ((uint8_t)0x40) //!< HMAC mode bit 6: If set, include the 48 bits SN[2:3] and SN[4:7] in the message.; otherwise, the corresponding message bits are set to zero.
|
||||
#define HMAC_MODE_MASK ((uint8_t)0x74) //!< HMAC mode bits 0, 1, 3, and 7 are 0.
|
||||
#define HMAC_DIGEST_SIZE (32) //!< HMAC size of digest response
|
||||
#define HMAC_RSP_SIZE ATCA_RSP_SIZE_32 //!< HMAC command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Info Command
|
||||
@{ */
|
||||
#define INFO_PARAM1_IDX ATCA_PARAM1_IDX //!< Info command index for 1. parameter
|
||||
#define INFO_PARAM2_IDX ATCA_PARAM2_IDX //!< Info command index for 2. parameter
|
||||
#define INFO_COUNT ATCA_CMD_SIZE_MIN //!< Info command packet size
|
||||
#define INFO_MODE_REVISION ((uint8_t)0x00) //!< Info mode Revision
|
||||
#define INFO_MODE_KEY_VALID ((uint8_t)0x01) //!< Info mode KeyValid
|
||||
#define INFO_MODE_STATE ((uint8_t)0x02) //!< Info mode State
|
||||
#define INFO_MODE_GPIO ((uint8_t)0x03) //!< Info mode GPIO
|
||||
#define INFO_MODE_VOL_KEY_PERMIT ((uint8_t)0x04) //!< Info mode GPIO
|
||||
#define INFO_MODE_MAX ((uint8_t)0x03) //!< Info mode maximum value
|
||||
#define INFO_NO_STATE ((uint8_t)0x00) //!< Info mode is not the state mode.
|
||||
#define INFO_OUTPUT_STATE_MASK ((uint8_t)0x01) //!< Info output state mask
|
||||
#define INFO_DRIVER_STATE_MASK ((uint8_t)0x02) //!< Info driver state mask
|
||||
#define INFO_PARAM2_SET_LATCH_STATE ((uint16_t)0x0002) //!< Info param2 to set the persistent latch state.
|
||||
#define INFO_PARAM2_LATCH_SET ((uint16_t)0x0001) //!< Info param2 to set the persistent latch
|
||||
#define INFO_PARAM2_LATCH_CLEAR ((uint16_t)0x0000) //!< Info param2 to clear the persistent latch
|
||||
#define INFO_SIZE ((uint8_t)0x04) //!< Info return size
|
||||
#define INFO_RSP_SIZE ATCA_RSP_SIZE_VAL //!< Info command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the KDF Command
|
||||
@{ */
|
||||
#define KDF_MODE_IDX ATCA_PARAM1_IDX //!< KDF command index for mode
|
||||
#define KDF_KEYID_IDX ATCA_PARAM2_IDX //!< KDF command index for key id
|
||||
#define KDF_DETAILS_IDX ATCA_DATA_IDX //!< KDF command index for details
|
||||
#define KDF_DETAILS_SIZE 4 //!< KDF details (param3) size
|
||||
#define KDF_MESSAGE_IDX (ATCA_DATA_IDX + KDF_DETAILS_SIZE)
|
||||
|
||||
#define KDF_MODE_SOURCE_MASK ((uint8_t)0x03) //!< KDF mode source key mask
|
||||
#define KDF_MODE_SOURCE_TEMPKEY ((uint8_t)0x00) //!< KDF mode source key in TempKey
|
||||
#define KDF_MODE_SOURCE_TEMPKEY_UP ((uint8_t)0x01) //!< KDF mode source key in upper TempKey
|
||||
#define KDF_MODE_SOURCE_SLOT ((uint8_t)0x02) //!< KDF mode source key in a slot
|
||||
#define KDF_MODE_SOURCE_ALTKEYBUF ((uint8_t)0x03) //!< KDF mode source key in alternate key buffer
|
||||
|
||||
#define KDF_MODE_TARGET_MASK ((uint8_t)0x1C) //!< KDF mode target key mask
|
||||
#define KDF_MODE_TARGET_TEMPKEY ((uint8_t)0x00) //!< KDF mode target key in TempKey
|
||||
#define KDF_MODE_TARGET_TEMPKEY_UP ((uint8_t)0x04) //!< KDF mode target key in upper TempKey
|
||||
#define KDF_MODE_TARGET_SLOT ((uint8_t)0x08) //!< KDF mode target key in slot
|
||||
#define KDF_MODE_TARGET_ALTKEYBUF ((uint8_t)0x0C) //!< KDF mode target key in alternate key buffer
|
||||
#define KDF_MODE_TARGET_OUTPUT ((uint8_t)0x10) //!< KDF mode target key in output buffer
|
||||
#define KDF_MODE_TARGET_OUTPUT_ENC ((uint8_t)0x14) //!< KDF mode target key encrypted in output buffer
|
||||
|
||||
#define KDF_MODE_ALG_MASK ((uint8_t)0x60) //!< KDF mode algorithm mask
|
||||
#define KDF_MODE_ALG_PRF ((uint8_t)0x00) //!< KDF mode PRF algorithm
|
||||
#define KDF_MODE_ALG_AES ((uint8_t)0x20) //!< KDF mode AES algorithm
|
||||
#define KDF_MODE_ALG_HKDF ((uint8_t)0x40) //!< KDF mode HKDF algorithm
|
||||
|
||||
#define KDF_DETAILS_PRF_KEY_LEN_MASK ((uint32_t)0x00000003) //!< KDF details for PRF, source key length mask
|
||||
#define KDF_DETAILS_PRF_KEY_LEN_16 ((uint32_t)0x00000000) //!< KDF details for PRF, source key length is 16 bytes
|
||||
#define KDF_DETAILS_PRF_KEY_LEN_32 ((uint32_t)0x00000001) //!< KDF details for PRF, source key length is 32 bytes
|
||||
#define KDF_DETAILS_PRF_KEY_LEN_48 ((uint32_t)0x00000002) //!< KDF details for PRF, source key length is 48 bytes
|
||||
#define KDF_DETAILS_PRF_KEY_LEN_64 ((uint32_t)0x00000003) //!< KDF details for PRF, source key length is 64 bytes
|
||||
|
||||
#define KDF_DETAILS_PRF_TARGET_LEN_MASK ((uint32_t)0x00000100) //!< KDF details for PRF, target length mask
|
||||
#define KDF_DETAILS_PRF_TARGET_LEN_32 ((uint32_t)0x00000000) //!< KDF details for PRF, target length is 32 bytes
|
||||
#define KDF_DETAILS_PRF_TARGET_LEN_64 ((uint32_t)0x00000100) //!< KDF details for PRF, target length is 64 bytes
|
||||
|
||||
#define KDF_DETAILS_PRF_AEAD_MASK ((uint32_t)0x00000600) //!< KDF details for PRF, AEAD processing mask
|
||||
#define KDF_DETAILS_PRF_AEAD_MODE0 ((uint32_t)0x00000000) //!< KDF details for PRF, AEAD no processing
|
||||
#define KDF_DETAILS_PRF_AEAD_MODE1 ((uint32_t)0x00000200) //!< KDF details for PRF, AEAD First 32 go to target, second 32 go to output buffer
|
||||
|
||||
#define KDF_DETAILS_AES_KEY_LOC_MASK ((uint32_t)0x00000003) //!< KDF details for AES, key location mask
|
||||
|
||||
#define KDF_DETAILS_HKDF_MSG_LOC_MASK ((uint32_t)0x00000003) //!< KDF details for HKDF, message location mask
|
||||
#define KDF_DETAILS_HKDF_MSG_LOC_SLOT ((uint32_t)0x00000000) //!< KDF details for HKDF, message location in slot
|
||||
#define KDF_DETAILS_HKDF_MSG_LOC_TEMPKEY ((uint32_t)0x00000001) //!< KDF details for HKDF, message location in TempKey
|
||||
#define KDF_DETAILS_HKDF_MSG_LOC_INPUT ((uint32_t)0x00000002) //!< KDF details for HKDF, message location in input parameter
|
||||
#define KDF_DETAILS_HKDF_MSG_LOC_IV ((uint32_t)0x00000003) //!< KDF details for HKDF, message location is a special IV function
|
||||
#define KDF_DETAILS_HKDF_ZERO_KEY ((uint32_t)0x00000004) //!< KDF details for HKDF, key is 32 bytes of zero
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Lock Command
|
||||
@{ */
|
||||
#define LOCK_ZONE_IDX ATCA_PARAM1_IDX //!< Lock command index for zone
|
||||
#define LOCK_SUMMARY_IDX ATCA_PARAM2_IDX //!< Lock command index for summary
|
||||
#define LOCK_COUNT ATCA_CMD_SIZE_MIN //!< Lock command packet size
|
||||
#define LOCK_ZONE_CONFIG ((uint8_t)0x00) //!< Lock zone is Config
|
||||
#define LOCK_ZONE_DATA ((uint8_t)0x01) //!< Lock zone is OTP or Data
|
||||
#define LOCK_ZONE_DATA_SLOT ((uint8_t)0x02) //!< Lock slot of Data
|
||||
#define LOCK_ZONE_NO_CRC ((uint8_t)0x80) //!< Lock command: Ignore summary.
|
||||
#define LOCK_ZONE_MASK (0xBF) //!< Lock parameter 1 bits 6 are 0.
|
||||
#define ATCA_UNLOCKED (0x55) //!< Value indicating an unlocked zone
|
||||
#define ATCA_LOCKED (0x00) //!< Value indicating a locked zone
|
||||
#define LOCK_RSP_SIZE ATCA_RSP_SIZE_MIN //!< Lock command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the MAC Command
|
||||
@{ */
|
||||
#define MAC_MODE_IDX ATCA_PARAM1_IDX //!< MAC command index for mode
|
||||
#define MAC_KEYID_IDX ATCA_PARAM2_IDX //!< MAC command index for key id
|
||||
#define MAC_CHALLENGE_IDX ATCA_DATA_IDX //!< MAC command index for optional challenge
|
||||
#define MAC_COUNT_SHORT ATCA_CMD_SIZE_MIN //!< MAC command packet size without challenge
|
||||
#define MAC_COUNT_LONG (39) //!< MAC command packet size with challenge
|
||||
#define MAC_MODE_CHALLENGE ((uint8_t)0x00) //!< MAC mode 0: first SHA block from data slot
|
||||
#define MAC_MODE_BLOCK2_TEMPKEY ((uint8_t)0x01) //!< MAC mode bit 0: second SHA block from TempKey
|
||||
#define MAC_MODE_BLOCK1_TEMPKEY ((uint8_t)0x02) //!< MAC mode bit 1: first SHA block from TempKey
|
||||
#define MAC_MODE_SOURCE_FLAG_MATCH ((uint8_t)0x04) //!< MAC mode bit 2: match TempKey.SourceFlag
|
||||
#define MAC_MODE_PTNONCE_TEMPKEY ((uint8_t)0x06) //!< MAC mode bit 0: second SHA block from TempKey
|
||||
#define MAC_MODE_PASSTHROUGH ((uint8_t)0x07) //!< MAC mode bit 0-2: pass-through mode
|
||||
#define MAC_MODE_INCLUDE_OTP_88 ((uint8_t)0x10) //!< MAC mode bit 4: include first 88 OTP bits
|
||||
#define MAC_MODE_INCLUDE_OTP_64 ((uint8_t)0x20) //!< MAC mode bit 5: include first 64 OTP bits
|
||||
#define MAC_MODE_INCLUDE_SN ((uint8_t)0x40) //!< MAC mode bit 6: include serial number
|
||||
#define MAC_CHALLENGE_SIZE (32) //!< MAC size of challenge
|
||||
#define MAC_SIZE (32) //!< MAC size of response
|
||||
#define MAC_MODE_MASK ((uint8_t)0x77) //!< MAC mode bits 3 and 7 are 0.
|
||||
#define MAC_RSP_SIZE ATCA_RSP_SIZE_32 //!< MAC command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Nonce Command
|
||||
@{ */
|
||||
#define NONCE_MODE_IDX ATCA_PARAM1_IDX //!< Nonce command index for mode
|
||||
#define NONCE_PARAM2_IDX ATCA_PARAM2_IDX //!< Nonce command index for 2. parameter
|
||||
#define NONCE_INPUT_IDX ATCA_DATA_IDX //!< Nonce command index for input data
|
||||
#define NONCE_COUNT_SHORT (ATCA_CMD_SIZE_MIN + 20) //!< Nonce command packet size for 20 bytes of NumIn
|
||||
#define NONCE_COUNT_LONG (ATCA_CMD_SIZE_MIN + 32) //!< Nonce command packet size for 32 bytes of NumIn
|
||||
#define NONCE_COUNT_LONG_64 (ATCA_CMD_SIZE_MIN + 64) //!< Nonce command packet size for 64 bytes of NumIn
|
||||
#define NONCE_MODE_MASK ((uint8_t)0x03) //!< Nonce mode bits 2 to 7 are 0.
|
||||
#define NONCE_MODE_SEED_UPDATE ((uint8_t)0x00) //!< Nonce mode: update seed
|
||||
#define NONCE_MODE_NO_SEED_UPDATE ((uint8_t)0x01) //!< Nonce mode: do not update seed
|
||||
#define NONCE_MODE_INVALID ((uint8_t)0x02) //!< Nonce mode 2 is invalid.
|
||||
#define NONCE_MODE_PASSTHROUGH ((uint8_t)0x03) //!< Nonce mode: pass-through
|
||||
|
||||
#define NONCE_MODE_INPUT_LEN_MASK ((uint8_t)0x20) //!< Nonce mode: input size mask
|
||||
#define NONCE_MODE_INPUT_LEN_32 ((uint8_t)0x00) //!< Nonce mode: input size is 32 bytes
|
||||
#define NONCE_MODE_INPUT_LEN_64 ((uint8_t)0x20) //!< Nonce mode: input size is 64 bytes
|
||||
|
||||
#define NONCE_MODE_TARGET_MASK ((uint8_t)0xC0) //!< Nonce mode: target mask
|
||||
#define NONCE_MODE_TARGET_TEMPKEY ((uint8_t)0x00) //!< Nonce mode: target is TempKey
|
||||
#define NONCE_MODE_TARGET_MSGDIGBUF ((uint8_t)0x40) //!< Nonce mode: target is Message Digest Buffer
|
||||
#define NONCE_MODE_TARGET_ALTKEYBUF ((uint8_t)0x80) //!< Nonce mode: target is Alternate Key Buffer
|
||||
|
||||
#define NONCE_ZERO_CALC_MASK ((uint16_t)0x8000) //!< Nonce zero (param2): calculation mode mask
|
||||
#define NONCE_ZERO_CALC_RANDOM ((uint16_t)0x0000) //!< Nonce zero (param2): calculation mode random, use RNG in calculation and return RNG output
|
||||
#define NONCE_ZERO_CALC_TEMPKEY ((uint16_t)0x8000) //!< Nonce zero (param2): calculation mode TempKey, use TempKey in calculation and return new TempKey value
|
||||
|
||||
#define NONCE_NUMIN_SIZE (20) //!< Nonce NumIn size for random modes
|
||||
#define NONCE_NUMIN_SIZE_PASSTHROUGH (32) //!< Nonce NumIn size for 32-byte pass-through mode
|
||||
|
||||
#define NONCE_RSP_SIZE_SHORT ATCA_RSP_SIZE_MIN //!< Nonce command response packet size with no output
|
||||
#define NONCE_RSP_SIZE_LONG ATCA_RSP_SIZE_32 //!< Nonce command response packet size with output
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Pause Command
|
||||
@{ */
|
||||
#define PAUSE_SELECT_IDX ATCA_PARAM1_IDX //!< Pause command index for Selector
|
||||
#define PAUSE_PARAM2_IDX ATCA_PARAM2_IDX //!< Pause command index for 2. parameter
|
||||
#define PAUSE_COUNT ATCA_CMD_SIZE_MIN //!< Pause command packet size
|
||||
#define PAUSE_RSP_SIZE ATCA_RSP_SIZE_MIN //!< Pause command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the PrivWrite Command
|
||||
@{ */
|
||||
#define PRIVWRITE_ZONE_IDX ATCA_PARAM1_IDX //!< PrivWrite command index for zone
|
||||
#define PRIVWRITE_KEYID_IDX ATCA_PARAM2_IDX //!< PrivWrite command index for KeyID
|
||||
#define PRIVWRITE_VALUE_IDX ( 5) //!< PrivWrite command index for value
|
||||
#define PRIVWRITE_MAC_IDX (41) //!< PrivWrite command index for MAC
|
||||
#define PRIVWRITE_COUNT (75) //!< PrivWrite command packet size
|
||||
#define PRIVWRITE_ZONE_MASK ((uint8_t)0x40) //!< PrivWrite zone bits 0 to 5 and 7 are 0.
|
||||
#define PRIVWRITE_MODE_ENCRYPT ((uint8_t)0x40) //!< PrivWrite mode: encrypted
|
||||
#define PRIVWRITE_RSP_SIZE ATCA_RSP_SIZE_MIN //!< PrivWrite command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Random Command
|
||||
@{ */
|
||||
#define RANDOM_MODE_IDX ATCA_PARAM1_IDX //!< Random command index for mode
|
||||
#define RANDOM_PARAM2_IDX ATCA_PARAM2_IDX //!< Random command index for 2. parameter
|
||||
#define RANDOM_COUNT ATCA_CMD_SIZE_MIN //!< Random command packet size
|
||||
#define RANDOM_SEED_UPDATE ((uint8_t)0x00) //!< Random mode for automatic seed update
|
||||
#define RANDOM_NO_SEED_UPDATE ((uint8_t)0x01) //!< Random mode for no seed update
|
||||
#define RANDOM_NUM_SIZE ((uint8_t)32) //!< Number of bytes in the data packet of a random command
|
||||
#define RANDOM_RSP_SIZE ATCA_RSP_SIZE_32 //!< Random command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Read Command
|
||||
@{ */
|
||||
#define READ_ZONE_IDX ATCA_PARAM1_IDX //!< Read command index for zone
|
||||
#define READ_ADDR_IDX ATCA_PARAM2_IDX //!< Read command index for address
|
||||
#define READ_COUNT ATCA_CMD_SIZE_MIN //!< Read command packet size
|
||||
#define READ_ZONE_MASK ((uint8_t)0x83) //!< Read zone bits 2 to 6 are 0.
|
||||
#define READ_4_RSP_SIZE ATCA_RSP_SIZE_VAL //!< Read command response packet size when reading 4 bytes
|
||||
#define READ_32_RSP_SIZE ATCA_RSP_SIZE_32 //!< Read command response packet size when reading 32 bytes
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the SecureBoot Command
|
||||
@{ */
|
||||
#define SECUREBOOT_MODE_IDX ATCA_PARAM1_IDX //!< SecureBoot command index for mode
|
||||
#define SECUREBOOT_DIGEST_SIZE (32) //!< SecureBoot digest input size
|
||||
#define SECUREBOOT_SIGNATURE_SIZE (64) //!< SecureBoot signature input size
|
||||
#define SECUREBOOT_COUNT_DIG (ATCA_CMD_SIZE_MIN + SECUREBOOT_DIGEST_SIZE) //!< SecureBoot command packet size for just a digest
|
||||
#define SECUREBOOT_COUNT_DIG_SIG (ATCA_CMD_SIZE_MIN + SECUREBOOT_DIGEST_SIZE + SECUREBOOT_SIGNATURE_SIZE) //!< SecureBoot command packet size for a digest and signature
|
||||
#define SECUREBOOT_MAC_SIZE (32) //!< SecureBoot MAC output size
|
||||
#define SECUREBOOT_RSP_SIZE_NO_MAC ATCA_RSP_SIZE_MIN //!< SecureBoot response packet size for no MAC
|
||||
#define SECUREBOOT_RSP_SIZE_MAC (ATCA_PACKET_OVERHEAD + SECUREBOOT_MAC_SIZE) //!< SecureBoot response packet size with MAC
|
||||
|
||||
#define SECUREBOOT_MODE_MASK ((uint8_t)0x07) //!< SecureBoot mode mask
|
||||
#define SECUREBOOT_MODE_FULL ((uint8_t)0x05) //!< SecureBoot mode Full
|
||||
#define SECUREBOOT_MODE_FULL_STORE ((uint8_t)0x06) //!< SecureBoot mode FullStore
|
||||
#define SECUREBOOT_MODE_FULL_COPY ((uint8_t)0x07) //!< SecureBoot mode FullCopy
|
||||
#define SECUREBOOT_MODE_PROHIBIT_FLAG ((uint8_t)0x40) //!< SecureBoot mode flag to prohibit SecureBoot until next power cycle
|
||||
#define SECUREBOOT_MODE_ENC_MAC_FLAG ((uint8_t)0x80) //!< SecureBoot mode flag for encrypted digest and returning validating MAC
|
||||
|
||||
#define SECUREBOOTCONFIG_OFFSET (70) //!< SecureBootConfig byte offset into the configuration zone
|
||||
#define SECUREBOOTCONFIG_MODE_MASK ((uint16_t)0x0003) //!< Mask for SecureBootMode field in SecureBootConfig value
|
||||
#define SECUREBOOTCONFIG_MODE_DISABLED ((uint16_t)0x0000) //!< Disabled SecureBootMode in SecureBootConfig value
|
||||
#define SECUREBOOTCONFIG_MODE_FULL_BOTH ((uint16_t)0x0001) //!< Both digest and signature always required SecureBootMode in SecureBootConfig value
|
||||
#define SECUREBOOTCONFIG_MODE_FULL_SIG ((uint16_t)0x0002) //!< Signature stored SecureBootMode in SecureBootConfig value
|
||||
#define SECUREBOOTCONFIG_MODE_FULL_DIG ((uint16_t)0x0003) //!< Digest stored SecureBootMode in SecureBootConfig value
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the SelfTest Command
|
||||
@{ */
|
||||
#define SELFTEST_MODE_IDX ATCA_PARAM1_IDX //!< SelfTest command index for mode
|
||||
#define SELFTEST_COUNT ATCA_CMD_SIZE_MIN //!< SelfTest command packet size
|
||||
#define SELFTEST_MODE_RNG ((uint8_t)0x01) //!< SelfTest mode RNG DRBG function
|
||||
#define SELFTEST_MODE_ECDSA_SIGN_VERIFY ((uint8_t)0x02) //!< SelfTest mode ECDSA verify function
|
||||
#define SELFTEST_MODE_ECDH ((uint8_t)0x08) //!< SelfTest mode ECDH function
|
||||
#define SELFTEST_MODE_AES ((uint8_t)0x10) //!< SelfTest mode AES encrypt function
|
||||
#define SELFTEST_MODE_SHA ((uint8_t)0x20) //!< SelfTest mode SHA function
|
||||
#define SELFTEST_MODE_ALL ((uint8_t)0x3B) //!< SelfTest mode all algorithms
|
||||
#define SELFTEST_RSP_SIZE ATCA_RSP_SIZE_MIN //!< SelfTest command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the SHA Command
|
||||
@{ */
|
||||
#define SHA_COUNT_SHORT ATCA_CMD_SIZE_MIN
|
||||
#define SHA_COUNT_LONG ATCA_CMD_SIZE_MIN //!< Just a starting size
|
||||
#define ATCA_SHA_DIGEST_SIZE (32)
|
||||
#define SHA_DATA_MAX (64)
|
||||
#define ATCA_SHA256_BLOCK_SIZE (64)
|
||||
#define SHA_CONTEXT_MAX_SIZE (99)
|
||||
|
||||
#define SHA_MODE_MASK ((uint8_t)0x07) //!< Mask the bit 0-2
|
||||
#define SHA_MODE_SHA256_START ((uint8_t)0x00) //!< Initialization, does not accept a message
|
||||
#define SHA_MODE_SHA256_UPDATE ((uint8_t)0x01) //!< Add 64 bytes in the meesage to the SHA context
|
||||
#define SHA_MODE_SHA256_END ((uint8_t)0x02) //!< Complete the calculation and return the digest
|
||||
#define SHA_MODE_SHA256_PUBLIC ((uint8_t)0x03) //!< Add 64 byte ECC public key in the slot to the SHA context
|
||||
#define SHA_MODE_HMAC_START ((uint8_t)0x04) //!< Initialization, HMAC calculation
|
||||
#define SHA_MODE_HMAC_UPDATE ((uint8_t)0x01) //!< Add 64 bytes in the meesage to the SHA context
|
||||
#define SHA_MODE_HMAC_END ((uint8_t)0x05) //!< Complete the HMAC computation and return digest
|
||||
#define SHA_MODE_608_HMAC_END ((uint8_t)0x02) //!< Complete the HMAC computation and return digest... Different command on 608
|
||||
#define SHA_MODE_READ_CONTEXT ((uint8_t)0x06) //!< Read current SHA-256 context out of the device
|
||||
#define SHA_MODE_WRITE_CONTEXT ((uint8_t)0x07) //!< Restore a SHA-256 context into the device
|
||||
#define SHA_MODE_TARGET_MASK ((uint8_t)0xC0) //!< Resulting digest target location mask
|
||||
#define SHA_MODE_TARGET_TEMPKEY ((uint8_t)0x00) //!< Place resulting digest both in Output buffer and TempKey
|
||||
#define SHA_MODE_TARGET_MSGDIGBUF ((uint8_t)0x40) //!< Place resulting digest both in Output buffer and Message Digest Buffer
|
||||
#define SHA_MODE_TARGET_OUT_ONLY ((uint8_t)0xC0) //!< Place resulting digest both in Output buffer ONLY
|
||||
|
||||
#define SHA_RSP_SIZE ATCA_RSP_SIZE_32 //!< SHA command response packet size
|
||||
#define SHA_RSP_SIZE_SHORT ATCA_RSP_SIZE_MIN //!< SHA command response packet size only status code
|
||||
#define SHA_RSP_SIZE_LONG ATCA_RSP_SIZE_32 //!< SHA command response packet size
|
||||
/** @} */
|
||||
|
||||
/** @} *//** \name Definitions for the Sign Command
|
||||
@{ */
|
||||
#define SIGN_MODE_IDX ATCA_PARAM1_IDX //!< Sign command index for mode
|
||||
#define SIGN_KEYID_IDX ATCA_PARAM2_IDX //!< Sign command index for key id
|
||||
#define SIGN_COUNT ATCA_CMD_SIZE_MIN //!< Sign command packet size
|
||||
#define SIGN_MODE_MASK ((uint8_t)0xE1) //!< Sign mode bits 1 to 4 are 0
|
||||
#define SIGN_MODE_INTERNAL ((uint8_t)0x00) //!< Sign mode 0: internal
|
||||
#define SIGN_MODE_INVALIDATE ((uint8_t)0x01) //!< Sign mode bit 1: Signature will be used for Verify(Invalidate)
|
||||
#define SIGN_MODE_INCLUDE_SN ((uint8_t)0x40) //!< Sign mode bit 6: include serial number
|
||||
#define SIGN_MODE_EXTERNAL ((uint8_t)0x80) //!< Sign mode bit 7: external
|
||||
#define SIGN_MODE_SOURCE_MASK ((uint8_t)0x20) //!< Sign mode message source mask
|
||||
#define SIGN_MODE_SOURCE_TEMPKEY ((uint8_t)0x00) //!< Sign mode message source is TempKey
|
||||
#define SIGN_MODE_SOURCE_MSGDIGBUF ((uint8_t)0x20) //!< Sign mode message source is the Message Digest Buffer
|
||||
#define SIGN_RSP_SIZE ATCA_RSP_SIZE_MAX //!< Sign command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the UpdateExtra Command
|
||||
@{ */
|
||||
#define UPDATE_MODE_IDX ATCA_PARAM1_IDX //!< UpdateExtra command index for mode
|
||||
#define UPDATE_VALUE_IDX ATCA_PARAM2_IDX //!< UpdateExtra command index for new value
|
||||
#define UPDATE_COUNT ATCA_CMD_SIZE_MIN //!< UpdateExtra command packet size
|
||||
#define UPDATE_MODE_USER_EXTRA ((uint8_t)0x00) //!< UpdateExtra mode update UserExtra (config byte 84)
|
||||
#define UPDATE_MODE_SELECTOR ((uint8_t)0x01) //!< UpdateExtra mode update Selector (config byte 85)
|
||||
#define UPDATE_MODE_USER_EXTRA_ADD UPDATE_MODE_SELECTOR //!< UpdateExtra mode update UserExtraAdd (config byte 85)
|
||||
#define UPDATE_MODE_DEC_COUNTER ((uint8_t)0x02) //!< UpdateExtra mode: decrement counter
|
||||
#define UPDATE_RSP_SIZE ATCA_RSP_SIZE_MIN //!< UpdateExtra command response packet size
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Verify Command
|
||||
@{ */
|
||||
#define VERIFY_MODE_IDX ATCA_PARAM1_IDX //!< Verify command index for mode
|
||||
#define VERIFY_KEYID_IDX ATCA_PARAM2_IDX //!< Verify command index for key id
|
||||
#define VERIFY_DATA_IDX ( 5) //!< Verify command index for data
|
||||
#define VERIFY_256_STORED_COUNT ( 71) //!< Verify command packet size for 256-bit key in stored mode
|
||||
#define VERIFY_283_STORED_COUNT ( 79) //!< Verify command packet size for 283-bit key in stored mode
|
||||
#define VERIFY_256_VALIDATE_COUNT ( 90) //!< Verify command packet size for 256-bit key in validate mode
|
||||
#define VERIFY_283_VALIDATE_COUNT ( 98) //!< Verify command packet size for 283-bit key in validate mode
|
||||
#define VERIFY_256_EXTERNAL_COUNT (135) //!< Verify command packet size for 256-bit key in external mode
|
||||
#define VERIFY_283_EXTERNAL_COUNT (151) //!< Verify command packet size for 283-bit key in external mode
|
||||
#define VERIFY_256_KEY_SIZE ( 64) //!< Verify key size for 256-bit key
|
||||
#define VERIFY_283_KEY_SIZE ( 72) //!< Verify key size for 283-bit key
|
||||
#define VERIFY_256_SIGNATURE_SIZE ( 64) //!< Verify signature size for 256-bit key
|
||||
#define VERIFY_283_SIGNATURE_SIZE ( 72) //!< Verify signature size for 283-bit key
|
||||
#define VERIFY_OTHER_DATA_SIZE ( 19) //!< Verify size of "other data"
|
||||
#define VERIFY_MODE_MASK ((uint8_t)0x03) //!< Verify mode bits 2 to 7 are 0
|
||||
#define VERIFY_MODE_STORED ((uint8_t)0x00) //!< Verify mode: stored
|
||||
#define VERIFY_MODE_VALIDATE_EXTERNAL ((uint8_t)0x01) //!< Verify mode: validate external
|
||||
#define VERIFY_MODE_EXTERNAL ((uint8_t)0x02) //!< Verify mode: external
|
||||
#define VERIFY_MODE_VALIDATE ((uint8_t)0x03) //!< Verify mode: validate
|
||||
#define VERIFY_MODE_INVALIDATE ((uint8_t)0x07) //!< Verify mode: invalidate
|
||||
#define VERIFY_MODE_SOURCE_MASK ((uint8_t)0x20) //!< Verify mode message source mask
|
||||
#define VERIFY_MODE_SOURCE_TEMPKEY ((uint8_t)0x00) //!< Verify mode message source is TempKey
|
||||
#define VERIFY_MODE_SOURCE_MSGDIGBUF ((uint8_t)0x20) //!< Verify mode message source is the Message Digest Buffer
|
||||
#define VERIFY_MODE_MAC_FLAG ((uint8_t)0x80) //!< Verify mode: MAC
|
||||
#define VERIFY_KEY_B283 ((uint16_t)0x0000) //!< Verify key type: B283
|
||||
#define VERIFY_KEY_K283 ((uint16_t)0x0001) //!< Verify key type: K283
|
||||
#define VERIFY_KEY_P256 ((uint16_t)0x0004) //!< Verify key type: P256
|
||||
#define VERIFY_RSP_SIZE ATCA_RSP_SIZE_MIN //!< Verify command response packet size
|
||||
#define VERIFY_RSP_SIZE_MAC ATCA_RSP_SIZE_32 //!< Verify command response packet size with validating MAC
|
||||
/** @} */
|
||||
|
||||
/** \name Definitions for the Write Command
|
||||
@{ */
|
||||
#define WRITE_ZONE_IDX ATCA_PARAM1_IDX //!< Write command index for zone
|
||||
#define WRITE_ADDR_IDX ATCA_PARAM2_IDX //!< Write command index for address
|
||||
#define WRITE_VALUE_IDX ATCA_DATA_IDX //!< Write command index for data
|
||||
#define WRITE_MAC_VS_IDX ( 9) //!< Write command index for MAC following short data
|
||||
#define WRITE_MAC_VL_IDX (37) //!< Write command index for MAC following long data
|
||||
#define WRITE_MAC_SIZE (32) //!< Write MAC size
|
||||
#define WRITE_ZONE_MASK ((uint8_t)0xC3) //!< Write zone bits 2 to 5 are 0.
|
||||
#define WRITE_ZONE_WITH_MAC ((uint8_t)0x40) //!< Write zone bit 6: write encrypted with MAC
|
||||
#define WRITE_ZONE_OTP ((uint8_t)1) //!< Write zone id OTP
|
||||
#define WRITE_ZONE_DATA ((uint8_t)2) //!< Write zone id data
|
||||
#define WRITE_RSP_SIZE ATCA_RSP_SIZE_MIN //!< Write command response packet size
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLiub is meant to be portable across architectures, even
|
||||
* non-Microchip architectures and compiler environments. This file is
|
||||
* for isolating compiler specific macros.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCA_COMPILER_H_
|
||||
#define ATCA_COMPILER_H_
|
||||
|
||||
#if defined(__clang__)
|
||||
/* Clang/LLVM. ---------------------------------------------- */
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap16(x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap16(x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) (x)
|
||||
#else
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) __builtin_bswap64(x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) __builtin_bswap64(x)
|
||||
#endif
|
||||
|
||||
#elif defined(__ICC) || defined(__INTEL_COMPILER)
|
||||
/* Intel ICC/ICPC. ------------------------------------------ */
|
||||
|
||||
#elif defined(__GNUC__) || defined(__GNUG__)
|
||||
/* GNU GCC/G++. --------------------------------------------- */
|
||||
#if defined(__AVR32__)
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap_16(x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap_16(x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap_32(x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) (x)
|
||||
#define ATCA_NO_PRAGMA_PACK
|
||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) __builtin_bswap16(x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) __builtin_bswap16(x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) (x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) (x)
|
||||
#else
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) __builtin_bswap32(x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) __builtin_bswap64(x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) __builtin_bswap64(x)
|
||||
#endif
|
||||
|
||||
#elif defined(__HP_cc) || defined(__HP_aCC)
|
||||
/* Hewlett-Packard C/aC++. ---------------------------------- */
|
||||
|
||||
#elif defined(__IBMC__) || defined(__IBMCPP__)
|
||||
/* IBM XL C/C++. -------------------------------------------- */
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
/* Microsoft Visual Studio. --------------------------------- */
|
||||
// MSVC is usually always little-endian architecture
|
||||
#include <stdlib.h>
|
||||
#define ATCA_UINT16_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT16_LE_TO_HOST(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_LE(x) (x)
|
||||
#define ATCA_UINT32_HOST_TO_BE(x) _byteswap_ulong(x)
|
||||
#define ATCA_UINT32_BE_TO_HOST(x) _byteswap_ulong(x)
|
||||
#define ATCA_UINT64_HOST_TO_BE(x) _byteswap_uint64(x)
|
||||
#define ATCA_UINT64_BE_TO_HOST(x) _byteswap_uint64(x)
|
||||
#define strtok_r strtok_s
|
||||
|
||||
#elif defined(__PGI)
|
||||
/* Portland Group PGCC/PGCPP. ------------------------------- */
|
||||
|
||||
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||
/* Oracle Solaris Studio. ----------------------------------- */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* ATCA_COMPILER_H_ */
|
||||
@@ -0,0 +1,174 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Microchip CryptoAuth device object
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "atca_device.h"
|
||||
|
||||
/** \defgroup device ATCADevice (atca_)
|
||||
* \brief ATCADevice object - composite of command and interface objects
|
||||
@{ */
|
||||
|
||||
|
||||
#ifndef ATCA_NO_HEAP
|
||||
/** \brief constructor for a Microchip CryptoAuth device
|
||||
* \param[in] cfg Interface configuration object
|
||||
* \return Reference to a new ATCADevice on success. NULL on failure.
|
||||
*/
|
||||
ATCADevice newATCADevice(ATCAIfaceCfg *cfg)
|
||||
{
|
||||
ATCADevice ca_dev = NULL;
|
||||
ATCA_STATUS status;
|
||||
|
||||
if (cfg == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca_dev = (ATCADevice)malloc(sizeof(*ca_dev));
|
||||
if (ca_dev == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca_dev->mCommands = (ATCACommand)malloc(sizeof(*(ca_dev->mCommands)));
|
||||
if (ca_dev->mCommands == NULL)
|
||||
{
|
||||
free(ca_dev);
|
||||
ca_dev = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ca_dev->mIface = (ATCAIface)malloc(sizeof(*(ca_dev->mIface)));
|
||||
if (ca_dev->mIface == NULL)
|
||||
{
|
||||
free(ca_dev->mCommands);
|
||||
free(ca_dev);
|
||||
ca_dev = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = initATCADevice(cfg, ca_dev);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
free(ca_dev->mIface);
|
||||
free(ca_dev->mCommands);
|
||||
free(ca_dev);
|
||||
ca_dev = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ca_dev;
|
||||
}
|
||||
|
||||
/** \brief destructor for a device NULLs reference after object is freed
|
||||
* \param[in] ca_dev pointer to a reference to a device
|
||||
*/
|
||||
void deleteATCADevice(ATCADevice *ca_dev)
|
||||
{
|
||||
if (ca_dev == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
releaseATCADevice(*ca_dev);
|
||||
deleteATCACommand(&(*ca_dev)->mCommands);
|
||||
// Free iface manually as we don't want to call releaseATCAIface twice
|
||||
if ((*ca_dev)->mIface)
|
||||
{
|
||||
free((*ca_dev)->mIface);
|
||||
(*ca_dev)->mIface = NULL;
|
||||
}
|
||||
|
||||
free(*ca_dev);
|
||||
*ca_dev = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Initializer for an Microchip CryptoAuth device
|
||||
* \param[in] cfg pointer to an interface configuration object
|
||||
* \param[inout] ca_dev As input, pre-allocated structure to be initialized.
|
||||
* mCommands and mIface members should point to existing
|
||||
* structures to be initialized.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS initATCADevice(ATCAIfaceCfg *cfg, ATCADevice ca_dev)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
if (cfg == NULL || ca_dev == NULL || ca_dev->mCommands == NULL || ca_dev->mIface == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
status = initATCACommand(cfg->devtype, ca_dev->mCommands);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = initATCAIface(cfg, ca_dev->mIface);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief returns a reference to the ATCACommand object for the device
|
||||
* \param[in] dev reference to a device
|
||||
* \return reference to the ATCACommand object for the device
|
||||
*/
|
||||
ATCACommand atGetCommands(ATCADevice dev)
|
||||
{
|
||||
return dev->mCommands;
|
||||
}
|
||||
|
||||
/** \brief returns a reference to the ATCAIface interface object for the device
|
||||
* \param[in] dev reference to a device
|
||||
* \return reference to the ATCAIface object for the device
|
||||
*/
|
||||
ATCAIface atGetIFace(ATCADevice dev)
|
||||
{
|
||||
return dev->mIface;
|
||||
}
|
||||
|
||||
/** \brief Release any resources associated with the device.
|
||||
* \param[in] ca_dev Device to release
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS releaseATCADevice(ATCADevice ca_dev)
|
||||
{
|
||||
if (ca_dev == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
return releaseATCAIface(ca_dev->mIface);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Microchip Crypto Auth device object
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCA_DEVICE_H
|
||||
#define ATCA_DEVICE_H
|
||||
|
||||
#include "atca_command.h"
|
||||
#include "atca_iface.h"
|
||||
/** \defgroup device ATCADevice (atca_)
|
||||
@{ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \brief atca_device is the C object backing ATCADevice. See the
|
||||
* atca_device.h file for details on the ATCADevice methods.
|
||||
*/
|
||||
struct atca_device
|
||||
{
|
||||
ATCACommand mCommands; //!< Command set for a given CryptoAuth device
|
||||
ATCAIface mIface; //!< Physical interface
|
||||
};
|
||||
|
||||
typedef struct atca_device * ATCADevice;
|
||||
|
||||
ATCA_STATUS initATCADevice(ATCAIfaceCfg* cfg, ATCADevice cadev);
|
||||
ATCADevice newATCADevice(ATCAIfaceCfg *cfg);
|
||||
ATCA_STATUS releaseATCADevice(ATCADevice ca_dev);
|
||||
void deleteATCADevice(ATCADevice *ca_dev);
|
||||
|
||||
ATCACommand atGetCommands(ATCADevice dev);
|
||||
ATCAIface atGetIFace(ATCADevice dev);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Microchip Crypto Auth
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCA_DEVTYPES_H_
|
||||
#define ATCA_DEVTYPES_H_
|
||||
|
||||
/** \defgroup device ATCADevice (atca_)
|
||||
@{ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief The supported Device type in Cryptoauthlib library */
|
||||
typedef enum
|
||||
{
|
||||
ATSHA204A,
|
||||
ATECC108A,
|
||||
ATECC508A,
|
||||
ATECC608A,
|
||||
ATCA_DEV_UNKNOWN = 0x20
|
||||
} ATCADeviceType;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif /* ATCA_DEVTYPES_H_ */
|
||||
@@ -0,0 +1,372 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Implements an execution handler that executes a given command on a
|
||||
* device and returns the results.
|
||||
*
|
||||
* This implementation wraps Polling and No polling (simple wait) schemes into
|
||||
* a single method and use it across the library. Polling is used by default,
|
||||
* however, by defining the ATCA_NO_POLL symbol the code will instead wait an
|
||||
* estimated max execution time before requesting the result.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "atca_command.h"
|
||||
#include "atca_device.h"
|
||||
#include "atca_execution.h"
|
||||
#include "atca_devtypes.h"
|
||||
#include "hal/atca_hal.h"
|
||||
|
||||
#ifndef ATCA_POLLING_INIT_TIME_MSEC
|
||||
#define ATCA_POLLING_INIT_TIME_MSEC 1
|
||||
#endif
|
||||
|
||||
#ifndef ATCA_POLLING_FREQUENCY_TIME_MSEC
|
||||
#define ATCA_POLLING_FREQUENCY_TIME_MSEC 2
|
||||
#endif
|
||||
|
||||
#ifndef ATCA_POLLING_MAX_TIME_MSEC
|
||||
#define ATCA_POLLING_MAX_TIME_MSEC 2500
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_NO_POLL
|
||||
// *INDENT-OFF* - Preserve time formatting from the code formatter
|
||||
/*Execution times for ATSHA204A supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_204[] = {
|
||||
{ ATCA_CHECKMAC, 38},
|
||||
{ ATCA_DERIVE_KEY, 62},
|
||||
{ ATCA_GENDIG, 43},
|
||||
{ ATCA_HMAC, 69},
|
||||
{ ATCA_INFO, 2},
|
||||
{ ATCA_LOCK, 24},
|
||||
{ ATCA_MAC, 35},
|
||||
{ ATCA_NONCE, 60},
|
||||
{ ATCA_PAUSE, 2},
|
||||
{ ATCA_RANDOM, 50},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SHA, 22},
|
||||
{ ATCA_UPDATE_EXTRA, 12},
|
||||
{ ATCA_WRITE, 42}
|
||||
};
|
||||
|
||||
/*Execution times for ATECC108A supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_108[] = {
|
||||
{ ATCA_CHECKMAC, 13},
|
||||
{ ATCA_COUNTER, 20},
|
||||
{ ATCA_DERIVE_KEY, 50},
|
||||
{ ATCA_GENDIG, 11},
|
||||
{ ATCA_GENKEY, 115},
|
||||
{ ATCA_HMAC, 23},
|
||||
{ ATCA_INFO, 2},
|
||||
{ ATCA_LOCK, 32},
|
||||
{ ATCA_MAC, 14},
|
||||
{ ATCA_NONCE, 29},
|
||||
{ ATCA_PAUSE, 3},
|
||||
{ ATCA_PRIVWRITE, 48},
|
||||
{ ATCA_RANDOM, 23},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SHA, 9},
|
||||
{ ATCA_SIGN, 60},
|
||||
{ ATCA_UPDATE_EXTRA, 10},
|
||||
{ ATCA_VERIFY, 72},
|
||||
{ ATCA_WRITE, 26}
|
||||
};
|
||||
|
||||
/*Execution times for ATECC508A supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_508[] = {
|
||||
{ ATCA_CHECKMAC, 13},
|
||||
{ ATCA_COUNTER, 20},
|
||||
{ ATCA_DERIVE_KEY, 50},
|
||||
{ ATCA_ECDH, 58},
|
||||
{ ATCA_GENDIG, 11},
|
||||
{ ATCA_GENKEY, 115},
|
||||
{ ATCA_HMAC, 23},
|
||||
{ ATCA_INFO, 2},
|
||||
{ ATCA_LOCK, 32},
|
||||
{ ATCA_MAC, 14},
|
||||
{ ATCA_NONCE, 29},
|
||||
{ ATCA_PAUSE, 3},
|
||||
{ ATCA_PRIVWRITE, 48},
|
||||
{ ATCA_RANDOM, 23},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SHA, 9},
|
||||
{ ATCA_SIGN, 60},
|
||||
{ ATCA_UPDATE_EXTRA, 10},
|
||||
{ ATCA_VERIFY, 72},
|
||||
{ ATCA_WRITE, 26}
|
||||
};
|
||||
|
||||
/*Execution times for ATECC608A-M0 supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_608_m0[] = {
|
||||
{ ATCA_AES, 27},
|
||||
{ ATCA_CHECKMAC, 40},
|
||||
{ ATCA_COUNTER, 25},
|
||||
{ ATCA_DERIVE_KEY, 50},
|
||||
{ ATCA_ECDH, 75},
|
||||
{ ATCA_GENDIG, 25},
|
||||
{ ATCA_GENKEY, 115},
|
||||
{ ATCA_INFO, 5},
|
||||
{ ATCA_KDF, 165},
|
||||
{ ATCA_LOCK, 35},
|
||||
{ ATCA_MAC, 55},
|
||||
{ ATCA_NONCE, 20},
|
||||
{ ATCA_PRIVWRITE, 50},
|
||||
{ ATCA_RANDOM, 23},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SECUREBOOT, 80},
|
||||
{ ATCA_SELFTEST, 250},
|
||||
{ ATCA_SHA, 36},
|
||||
{ ATCA_SIGN, 115},
|
||||
{ ATCA_UPDATE_EXTRA, 10},
|
||||
{ ATCA_VERIFY, 105},
|
||||
{ ATCA_WRITE, 45}
|
||||
};
|
||||
|
||||
/*Execution times for ATECC608A-M1 supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_608_m1[] = {
|
||||
{ ATCA_AES, 27},
|
||||
{ ATCA_CHECKMAC, 40},
|
||||
{ ATCA_COUNTER, 25},
|
||||
{ ATCA_DERIVE_KEY, 50},
|
||||
{ ATCA_ECDH, 172},
|
||||
{ ATCA_GENDIG, 35},
|
||||
{ ATCA_GENKEY, 215},
|
||||
{ ATCA_INFO, 5},
|
||||
{ ATCA_KDF, 165},
|
||||
{ ATCA_LOCK, 35},
|
||||
{ ATCA_MAC, 55},
|
||||
{ ATCA_NONCE, 20},
|
||||
{ ATCA_PRIVWRITE, 50},
|
||||
{ ATCA_RANDOM, 23},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SECUREBOOT, 160},
|
||||
{ ATCA_SELFTEST, 625},
|
||||
{ ATCA_SHA, 42},
|
||||
{ ATCA_SIGN, 220},
|
||||
{ ATCA_UPDATE_EXTRA, 10},
|
||||
{ ATCA_VERIFY, 295},
|
||||
{ ATCA_WRITE, 45}
|
||||
};
|
||||
|
||||
/*Execution times for ATECC608A-M2 supported commands...*/
|
||||
static const device_execution_time_t device_execution_time_608_m2[] = {
|
||||
{ ATCA_AES, 27},
|
||||
{ ATCA_CHECKMAC, 40},
|
||||
{ ATCA_COUNTER, 25},
|
||||
{ ATCA_DERIVE_KEY, 50},
|
||||
{ ATCA_ECDH, 531},
|
||||
{ ATCA_GENDIG, 35},
|
||||
{ ATCA_GENKEY, 653},
|
||||
{ ATCA_INFO, 5},
|
||||
{ ATCA_KDF, 165},
|
||||
{ ATCA_LOCK, 35},
|
||||
{ ATCA_MAC, 55},
|
||||
{ ATCA_NONCE, 20},
|
||||
{ ATCA_PRIVWRITE, 50},
|
||||
{ ATCA_RANDOM, 23},
|
||||
{ ATCA_READ, 5},
|
||||
{ ATCA_SECUREBOOT, 480},
|
||||
{ ATCA_SELFTEST, 2324},
|
||||
{ ATCA_SHA, 75},
|
||||
{ ATCA_SIGN, 665},
|
||||
{ ATCA_UPDATE_EXTRA, 10},
|
||||
{ ATCA_VERIFY, 1085},
|
||||
{ ATCA_WRITE, 45}
|
||||
};
|
||||
// *INDENT-ON*
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_NO_POLL
|
||||
/** \brief return the typical execution time for the given command
|
||||
* \param[in] opcode Opcode value of the command
|
||||
* \param[in] ca_cmd Command object for which the execution times are associated
|
||||
* \return ATCA_SUCCESS
|
||||
*/
|
||||
ATCA_STATUS atGetExecTime(uint8_t opcode, ATCACommand ca_cmd)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
const device_execution_time_t *execution_times;
|
||||
uint8_t i, no_of_commands;
|
||||
|
||||
|
||||
switch (ca_cmd->dt)
|
||||
{
|
||||
case ATSHA204A:
|
||||
execution_times = device_execution_time_204;
|
||||
no_of_commands = sizeof(device_execution_time_204) / sizeof(device_execution_time_t);
|
||||
break;
|
||||
|
||||
case ATECC108A:
|
||||
execution_times = device_execution_time_108;
|
||||
no_of_commands = sizeof(device_execution_time_108) / sizeof(device_execution_time_t);
|
||||
break;
|
||||
|
||||
case ATECC508A:
|
||||
execution_times = device_execution_time_508;
|
||||
no_of_commands = sizeof(device_execution_time_508) / sizeof(device_execution_time_t);
|
||||
break;
|
||||
|
||||
case ATECC608A:
|
||||
if (ca_cmd->clock_divider == ATCA_CHIPMODE_CLOCK_DIV_M1)
|
||||
{
|
||||
execution_times = device_execution_time_608_m1;
|
||||
no_of_commands = sizeof(device_execution_time_608_m1) / sizeof(device_execution_time_t);
|
||||
}
|
||||
else if (ca_cmd->clock_divider == ATCA_CHIPMODE_CLOCK_DIV_M2)
|
||||
{
|
||||
execution_times = device_execution_time_608_m2;
|
||||
no_of_commands = sizeof(device_execution_time_608_m2) / sizeof(device_execution_time_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume default M0 clock divider
|
||||
execution_times = device_execution_time_608_m0;
|
||||
no_of_commands = sizeof(device_execution_time_608_m0) / sizeof(device_execution_time_t);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
no_of_commands = 0;
|
||||
execution_times = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
ca_cmd->execution_time_msec = ATCA_UNSUPPORTED_CMD;
|
||||
|
||||
for (i = 0; i < no_of_commands; i++)
|
||||
{
|
||||
if (execution_times[i].opcode == opcode)
|
||||
{
|
||||
ca_cmd->execution_time_msec = execution_times[i].execution_time_msec;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ca_cmd->execution_time_msec == ATCA_UNSUPPORTED_CMD)
|
||||
{
|
||||
status = ATCA_BAD_OPCODE;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Wakes up device, sends the packet, waits for command completion,
|
||||
* receives response, and puts the device into the idle state.
|
||||
*
|
||||
* \param[inout] packet As input, the packet to be sent. As output, the
|
||||
* data buffer in the packet structure will contain the
|
||||
* response.
|
||||
* \param[in] device CryptoAuthentication device to send the command to.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atca_execute_command(ATCAPacket* packet, ATCADevice device)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint32_t execution_or_wait_time;
|
||||
uint32_t max_delay_count;
|
||||
uint16_t rxsize;
|
||||
|
||||
do
|
||||
{
|
||||
#ifdef ATCA_NO_POLL
|
||||
if ((status = atGetExecTime(packet->opcode, device->mCommands)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
execution_or_wait_time = device->mCommands->execution_time_msec;
|
||||
max_delay_count = 0;
|
||||
#else
|
||||
execution_or_wait_time = ATCA_POLLING_INIT_TIME_MSEC;
|
||||
max_delay_count = ATCA_POLLING_MAX_TIME_MSEC / ATCA_POLLING_FREQUENCY_TIME_MSEC;
|
||||
#endif
|
||||
|
||||
if ((status = atwake(device->mIface)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// send the command
|
||||
if ((status = atsend(device->mIface, (uint8_t*)packet, packet->txsize)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Delay for execution time or initial wait before polling
|
||||
atca_delay_ms(execution_or_wait_time);
|
||||
|
||||
do
|
||||
{
|
||||
memset(packet->data, 0, sizeof(packet->data));
|
||||
// receive the response
|
||||
rxsize = sizeof(packet->data);
|
||||
if ((status = atreceive(device->mIface, packet->data, &rxsize)) == ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef ATCA_NO_POLL
|
||||
// delay for polling frequency time
|
||||
atca_delay_ms(ATCA_POLLING_FREQUENCY_TIME_MSEC);
|
||||
#endif
|
||||
}
|
||||
while (max_delay_count-- > 0);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Check response size
|
||||
if (rxsize < 4)
|
||||
{
|
||||
if (rxsize > 0)
|
||||
{
|
||||
status = ATCA_RX_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATCA_RX_NO_RESPONSE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atCheckCrc(packet->data)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = isATCAError(packet->data)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
atidle(device->mIface);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Defines an execution handler that executes a given command on a
|
||||
* device and returns the results.
|
||||
*
|
||||
* The basic flow is to wake the device, send the command, wait/poll for
|
||||
* completion, and finally receives the response from the device and does
|
||||
* basic checks before returning to caller.
|
||||
*
|
||||
* This handler supports the ATSHA and ATECC device family.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCA_EXECUTION_H
|
||||
#define ATCA_EXECUTION_H
|
||||
|
||||
#include "atca_status.h"
|
||||
#include "atca_command.h"
|
||||
#include "atca_device.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define ATCA_UNSUPPORTED_CMD ((uint16_t)0xFFFF)
|
||||
|
||||
#ifdef ATCA_NO_POLL
|
||||
/** \brief Structure to hold the device execution time and the opcode for the
|
||||
* corresponding command
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t opcode;
|
||||
uint16_t execution_time_msec;
|
||||
}device_execution_time_t;
|
||||
|
||||
ATCA_STATUS atGetExecTime(uint8_t opcode, ATCACommand ca_cmd);
|
||||
#endif
|
||||
|
||||
ATCA_STATUS atca_execute_command(ATCAPacket* packet, ATCADevice device);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Microchip CryptoAuthLib hardware interface object
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "atca_iface.h"
|
||||
#include "hal/atca_hal.h"
|
||||
|
||||
/** \defgroup interface ATCAIface (atca_)
|
||||
* \brief Abstract interface to all CryptoAuth device types. This interface
|
||||
* connects to the HAL implementation and abstracts the physical details of the
|
||||
* device communication from all the upper layers of CryptoAuthLib
|
||||
@{ */
|
||||
|
||||
|
||||
#ifndef ATCA_POST_DELAY_MSEC
|
||||
/* \brief How long to wait after an initial wake failure for the POSt to
|
||||
* complete.
|
||||
* If Power-on self test (POST) is enabled, the self test will run on waking
|
||||
* from sleep or during power-on, which delays the wake reply.
|
||||
*/
|
||||
#define ATCA_POST_DELAY_MSEC 25
|
||||
#endif
|
||||
|
||||
ATCA_STATUS _atinit(ATCAIface ca_iface, ATCAHAL_t *hal);
|
||||
|
||||
/** \brief Initializer for ATCAIface objects
|
||||
* \param[in] cfg Logical configuration for the interface
|
||||
* \param[in] ca_iface Interface structure to initialize.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS initATCAIface(ATCAIfaceCfg *cfg, ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
if (cfg == NULL || ca_iface == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
ca_iface->mType = cfg->iface_type;
|
||||
ca_iface->mIfaceCFG = cfg;
|
||||
|
||||
status = atinit(ca_iface);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
#ifndef ATCA_NO_HEAP
|
||||
/** \brief Constructor for ATCAIface objects
|
||||
* \param[in] cfg Logical configuration for the interface
|
||||
* \return New interface instance on success. NULL on failure.
|
||||
*/
|
||||
ATCAIface newATCAIface(ATCAIfaceCfg *cfg)
|
||||
{
|
||||
ATCAIface ca_iface;
|
||||
ATCA_STATUS status;
|
||||
|
||||
ca_iface = (ATCAIface)malloc(sizeof(struct atca_iface));
|
||||
status = initATCAIface(cfg, ca_iface);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
free(ca_iface);
|
||||
ca_iface = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ca_iface;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** \brief Performs the HAL initialization by calling intermediate HAL wrapper
|
||||
* function. If using the basic API, the atcab_init() function should
|
||||
* be called instead.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atinit(ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_COMM_FAIL;
|
||||
ATCAHAL_t hal;
|
||||
|
||||
_atinit(ca_iface, &hal);
|
||||
|
||||
status = ca_iface->atinit(&hal, ca_iface->mIfaceCFG);
|
||||
if (status == ATCA_SUCCESS)
|
||||
{
|
||||
ca_iface->hal_data = hal.hal_data;
|
||||
|
||||
// Perform the post init
|
||||
status = ca_iface->atpostinit(ca_iface);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Sends the data to the device by calling intermediate HAL wrapper
|
||||
* function.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \param[in] txdata Data to be transmitted to the device.
|
||||
* \param[in] txlength Number of bytes to be transmitted to the device.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atsend(ATCAIface ca_iface, uint8_t *txdata, int txlength)
|
||||
{
|
||||
return ca_iface->atsend(ca_iface, txdata, txlength);
|
||||
}
|
||||
|
||||
/**\brief Receives data from the device by calling intermediate HAL wrapper
|
||||
* function.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \param[out] rxdata Data received will be returned here.
|
||||
* \param[inout] rxlength As input, the size of the rxdata buffer.
|
||||
* As output, the number of bytes received.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atreceive(ATCAIface ca_iface, uint8_t *rxdata, uint16_t *rxlength)
|
||||
{
|
||||
return ca_iface->atreceive(ca_iface, rxdata, rxlength);
|
||||
}
|
||||
|
||||
/** \brief Wakes up the device by calling intermediate HAL wrapper function.
|
||||
* If using the basic API, the atcab_wakeup() function should be used
|
||||
* instead.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atwake(ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS status = ca_iface->atwake(ca_iface);
|
||||
|
||||
if (status == ATCA_WAKE_FAILED)
|
||||
{
|
||||
// The device might be performing a POST. Wait for it to complete
|
||||
// and try again.
|
||||
atca_delay_ms(ATCA_POST_DELAY_MSEC);
|
||||
|
||||
status = ca_iface->atwake(ca_iface);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Puts the device into idle state by calling intermediate HAL wrapper
|
||||
* function. If using the basic API, the atcab_idle() function should
|
||||
* be used instead.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atidle(ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
status = ca_iface->atidle(ca_iface);
|
||||
atca_delay_ms(1);
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Puts the device into sleep state by calling intermediate HAL wrapper
|
||||
* function. If using the basic API, the atcab_sleep() function should
|
||||
* be used instead.
|
||||
* \param[in] ca_iface Device to interact with.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atsleep(ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
status = ca_iface->atsleep(ca_iface);
|
||||
atca_delay_ms(1);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns the logical interface configuration for the device.
|
||||
* \param[in] ca_iface Device interface.
|
||||
* \return Logical interface configuration.
|
||||
*/
|
||||
ATCAIfaceCfg * atgetifacecfg(ATCAIface ca_iface)
|
||||
{
|
||||
return ca_iface->mIfaceCFG;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Returns the HAL data pointer for the device.
|
||||
* \param[in] ca_iface Device interface.
|
||||
* \return HAL data pointer.
|
||||
*/
|
||||
void* atgetifacehaldat(ATCAIface ca_iface)
|
||||
{
|
||||
return ca_iface->hal_data;
|
||||
}
|
||||
|
||||
/** \brief Instruct the HAL driver to release any resources associated with
|
||||
* this interface.
|
||||
* \param[in] ca_iface Device interface.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS releaseATCAIface(ATCAIface ca_iface)
|
||||
{
|
||||
ATCA_STATUS ret = ATCA_BAD_PARAM;
|
||||
|
||||
if (ca_iface)
|
||||
{
|
||||
ret = hal_iface_release(ca_iface->mType, ca_iface->hal_data);
|
||||
ca_iface->hal_data = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifndef ATCA_NO_HEAP
|
||||
/** \brief Instruct the HAL driver to release any resources associated with
|
||||
* this interface, then delete the object.
|
||||
* \param[in] ca_iface Device interface.
|
||||
*/
|
||||
void deleteATCAIface(ATCAIface *ca_iface)
|
||||
{
|
||||
if (ca_iface == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
releaseATCAIface(*ca_iface);
|
||||
free(*ca_iface);
|
||||
*ca_iface = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ATCA_STATUS _atinit(ATCAIface ca_iface, ATCAHAL_t *hal)
|
||||
{
|
||||
// get method mapping to HAL methods for this interface
|
||||
hal_iface_init(ca_iface->mIfaceCFG, hal);
|
||||
ca_iface->atinit = hal->halinit;
|
||||
ca_iface->atpostinit = hal->halpostinit;
|
||||
ca_iface->atsend = hal->halsend;
|
||||
ca_iface->atreceive = hal->halreceive;
|
||||
ca_iface->atwake = hal->halwake;
|
||||
ca_iface->atsleep = hal->halsleep;
|
||||
ca_iface->atidle = hal->halidle;
|
||||
ca_iface->hal_data = hal->hal_data;
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
/** @} */
|
||||
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Microchip Crypto Auth hardware interface object
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCA_IFACE_H
|
||||
#define ATCA_IFACE_H
|
||||
|
||||
/** \defgroup interface ATCAIface (atca_)
|
||||
* \brief Abstract interface to all CryptoAuth device types. This interface
|
||||
* connects to the HAL implementation and abstracts the physical details of the
|
||||
* device communication from all the upper layers of CryptoAuthLib
|
||||
@{ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "atca_command.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATCA_I2C_IFACE,
|
||||
ATCA_SWI_IFACE,
|
||||
ATCA_UART_IFACE,
|
||||
ATCA_SPI_IFACE,
|
||||
ATCA_HID_IFACE,
|
||||
ATCA_CUSTOM_IFACE,
|
||||
// additional physical interface types here
|
||||
ATCA_UNKNOWN_IFACE,
|
||||
} ATCAIfaceType;
|
||||
|
||||
|
||||
/*The types are used within the kit protocol to identify the correct interface*/
|
||||
typedef enum
|
||||
{ ATCA_KIT_AUTO_IFACE, //Selects the first device if the Kit interface is not defined
|
||||
ATCA_KIT_I2C_IFACE,
|
||||
ATCA_KIT_SWI_IFACE,
|
||||
ATCA_KIT_UNKNOWN_IFACE,
|
||||
} ATCAKitType;
|
||||
|
||||
|
||||
|
||||
/* ATCAIfaceCfg is a mediator object between a completely abstract notion of a
|
||||
physical interface and an actual physical interface.
|
||||
|
||||
The main purpose of it is to keep hardware specifics from bleeding into the
|
||||
higher levels - hardware specifics could include things like framework
|
||||
specific items (ASF SERCOM) vs a non-Microchip I2C library constant that
|
||||
defines an I2C port. But I2C has roughly the same parameters regardless of
|
||||
architecture and framework.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
||||
ATCAIfaceType iface_type; // active iface - how to interpret the union below
|
||||
ATCADeviceType devtype; // explicit device type
|
||||
|
||||
union // each instance of an iface cfg defines a single type of interface
|
||||
{
|
||||
struct ATCAI2C
|
||||
{
|
||||
uint8_t slave_address; // 8-bit slave address
|
||||
uint8_t bus; // logical i2c bus number, 0-based - HAL will map this to a pin pair for SDA SCL
|
||||
uint32_t baud; // typically 400000
|
||||
} atcai2c;
|
||||
|
||||
struct ATCASWI
|
||||
{
|
||||
uint8_t bus; // logical SWI bus - HAL will map this to a pin or uart port
|
||||
} atcaswi;
|
||||
|
||||
struct ATCAUART
|
||||
{
|
||||
int port; // logic port number
|
||||
uint32_t baud; // typically 115200
|
||||
uint8_t wordsize; // usually 8
|
||||
uint8_t parity; // 0 == even, 1 == odd, 2 == none
|
||||
uint8_t stopbits; // 0,1,2
|
||||
} atcauart;
|
||||
|
||||
struct ATCAHID
|
||||
{
|
||||
int idx; // HID enumeration index
|
||||
ATCAKitType dev_interface; // Kit interface type
|
||||
uint8_t dev_identity; // I2C address for the I2C interface device or the bus number for the SWI interface device.
|
||||
uint32_t vid; // Vendor ID of kit (0x03EB for CK101)
|
||||
uint32_t pid; // Product ID of kit (0x2312 for CK101)
|
||||
uint32_t packetsize; // Size of the USB packet
|
||||
} atcahid;
|
||||
|
||||
struct ATCACUSTOM
|
||||
{
|
||||
ATCA_STATUS (*halinit)(void *hal, void *cfg);
|
||||
ATCA_STATUS (*halpostinit)(void *iface);
|
||||
ATCA_STATUS (*halsend)(void *iface, uint8_t *txdata, int txlength);
|
||||
ATCA_STATUS (*halreceive)(void *iface, uint8_t* rxdata, uint16_t* rxlength);
|
||||
ATCA_STATUS (*halwake)(void *iface);
|
||||
ATCA_STATUS (*halidle)(void *iface);
|
||||
ATCA_STATUS (*halsleep)(void *iface);
|
||||
ATCA_STATUS (*halrelease)(void* hal_data);
|
||||
} atcacustom;
|
||||
|
||||
};
|
||||
|
||||
uint16_t wake_delay; // microseconds of tWHI + tWLO which varies based on chip type
|
||||
int rx_retries; // the number of retries to attempt for receiving bytes
|
||||
void * cfg_data; // opaque data used by HAL in device discovery
|
||||
} ATCAIfaceCfg;
|
||||
typedef struct atca_iface * ATCAIface;
|
||||
|
||||
|
||||
/** \brief atca_iface is the C object backing ATCAIface. See the atca_iface.h file for
|
||||
* details on the ATCAIface methods
|
||||
*/
|
||||
|
||||
struct atca_iface
|
||||
{
|
||||
ATCAIfaceType mType;
|
||||
ATCAIfaceCfg *mIfaceCFG; // points to previous defined/given Cfg object, caller manages this
|
||||
|
||||
ATCA_STATUS (*atinit)(void *hal, ATCAIfaceCfg *);
|
||||
ATCA_STATUS (*atpostinit)(ATCAIface hal);
|
||||
ATCA_STATUS (*atsend)(ATCAIface hal, uint8_t *txdata, int txlength);
|
||||
ATCA_STATUS (*atreceive)(ATCAIface hal, uint8_t *rxdata, uint16_t *rxlength);
|
||||
ATCA_STATUS (*atwake)(ATCAIface hal);
|
||||
ATCA_STATUS (*atidle)(ATCAIface hal);
|
||||
ATCA_STATUS (*atsleep)(ATCAIface hal);
|
||||
|
||||
// treat as private
|
||||
void *hal_data; // generic pointer used by HAL to point to architecture specific structure
|
||||
// no ATCA object should touch this except HAL, HAL manages this pointer and memory it points to
|
||||
};
|
||||
|
||||
ATCA_STATUS initATCAIface(ATCAIfaceCfg *cfg, ATCAIface ca_iface);
|
||||
ATCAIface newATCAIface(ATCAIfaceCfg *cfg);
|
||||
ATCA_STATUS releaseATCAIface(ATCAIface ca_iface);
|
||||
void deleteATCAIface(ATCAIface *ca_iface);
|
||||
|
||||
// IFace methods
|
||||
ATCA_STATUS atinit(ATCAIface ca_iface);
|
||||
ATCA_STATUS atpostinit(ATCAIface ca_iface);
|
||||
ATCA_STATUS atsend(ATCAIface ca_iface, uint8_t *txdata, int txlength);
|
||||
ATCA_STATUS atreceive(ATCAIface ca_iface, uint8_t *rxdata, uint16_t *rxlength);
|
||||
ATCA_STATUS atwake(ATCAIface ca_iface);
|
||||
ATCA_STATUS atidle(ATCAIface ca_iface);
|
||||
ATCA_STATUS atsleep(ATCAIface ca_iface);
|
||||
|
||||
// accessors
|
||||
ATCAIfaceCfg * atgetifacecfg(ATCAIface ca_iface);
|
||||
void* atgetifacehaldat(ATCAIface ca_iface);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/** @} */
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Microchip Crypto Auth status codes
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ATCA_STATUS_H
|
||||
#define _ATCA_STATUS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "atca_bool.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* all status codes for the ATCA lib are defined here */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ATCA_SUCCESS = 0x00, //!< Function succeeded.
|
||||
ATCA_CONFIG_ZONE_LOCKED = 0x01,
|
||||
ATCA_DATA_ZONE_LOCKED = 0x02,
|
||||
ATCA_WAKE_FAILED = 0xD0, //!< response status byte indicates CheckMac failure (status byte = 0x01)
|
||||
ATCA_CHECKMAC_VERIFY_FAILED = 0xD1, //!< response status byte indicates CheckMac failure (status byte = 0x01)
|
||||
ATCA_PARSE_ERROR = 0xD2, //!< response status byte indicates parsing error (status byte = 0x03)
|
||||
ATCA_STATUS_CRC = 0xD4, //!< response status byte indicates DEVICE did not receive data properly (status byte = 0xFF)
|
||||
ATCA_STATUS_UNKNOWN = 0xD5, //!< response status byte is unknown
|
||||
ATCA_STATUS_ECC = 0xD6, //!< response status byte is ECC fault (status byte = 0x05)
|
||||
ATCA_STATUS_SELFTEST_ERROR = 0xD7, //!< response status byte is Self Test Error, chip in failure mode (status byte = 0x07)
|
||||
ATCA_FUNC_FAIL = 0xE0, //!< Function could not execute due to incorrect condition / state.
|
||||
ATCA_GEN_FAIL = 0xE1, //!< unspecified error
|
||||
ATCA_BAD_PARAM = 0xE2, //!< bad argument (out of range, null pointer, etc.)
|
||||
ATCA_INVALID_ID = 0xE3, //!< invalid device id, id not set
|
||||
ATCA_INVALID_SIZE = 0xE4, //!< Count value is out of range or greater than buffer size.
|
||||
ATCA_RX_CRC_ERROR = 0xE5, //!< CRC error in data received from device
|
||||
ATCA_RX_FAIL = 0xE6, //!< Timed out while waiting for response. Number of bytes received is > 0.
|
||||
ATCA_RX_NO_RESPONSE = 0xE7, //!< Not an error while the Command layer is polling for a command response.
|
||||
ATCA_RESYNC_WITH_WAKEUP = 0xE8, //!< Re-synchronization succeeded, but only after generating a Wake-up
|
||||
ATCA_PARITY_ERROR = 0xE9, //!< for protocols needing parity
|
||||
ATCA_TX_TIMEOUT = 0xEA, //!< for Microchip PHY protocol, timeout on transmission waiting for master
|
||||
ATCA_RX_TIMEOUT = 0xEB, //!< for Microchip PHY protocol, timeout on receipt waiting for master
|
||||
ATCA_TOO_MANY_COMM_RETRIES = 0xEC, //!< Device did not respond too many times during a transmission. Could indicate no device present.
|
||||
ATCA_SMALL_BUFFER = 0xED, //!< Supplied buffer is too small for data required
|
||||
ATCA_COMM_FAIL = 0xF0, //!< Communication with device failed. Same as in hardware dependent modules.
|
||||
ATCA_TIMEOUT = 0xF1, //!< Timed out while waiting for response. Number of bytes received is 0.
|
||||
ATCA_BAD_OPCODE = 0xF2, //!< opcode is not supported by the device
|
||||
ATCA_WAKE_SUCCESS = 0xF3, //!< received proper wake token
|
||||
ATCA_EXECUTION_ERROR = 0xF4, //!< chip was in a state where it could not execute the command, response status byte indicates command execution error (status byte = 0x0F)
|
||||
ATCA_UNIMPLEMENTED = 0xF5, //!< Function or some element of it hasn't been implemented yet
|
||||
ATCA_ASSERT_FAILURE = 0xF6, //!< Code failed run-time consistency check
|
||||
ATCA_TX_FAIL = 0xF7, //!< Failed to write
|
||||
ATCA_NOT_LOCKED = 0xF8, //!< required zone was not locked
|
||||
ATCA_NO_DEVICES = 0xF9, //!< For protocols that support device discovery (kit protocol), no devices were found
|
||||
ATCA_HEALTH_TEST_ERROR = 0xFA, //!< random number generator health test error
|
||||
ATCA_ALLOC_FAILURE = 0xFB, //!< Couldn't allocate required memory
|
||||
} ATCA_STATUS;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Microchip CryptoAuth Library Version
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _ATCA_VERSION_H
|
||||
#define _ATCA_VERSION_H
|
||||
|
||||
// Version format yyyymmdd
|
||||
#define ATCA_LIBRARY_VERSION "20191122"
|
||||
|
||||
#endif /* _ATCA_VERSION_H */
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Declarations common to all atcacert code.
|
||||
*
|
||||
* These are common definitions used by all the atcacert code.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCACERT_H
|
||||
#define ATCACERT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
#ifndef FALSE
|
||||
#define FALSE (0)
|
||||
#endif
|
||||
#ifndef TRUE
|
||||
#define TRUE (1)
|
||||
#endif
|
||||
|
||||
#define ATCACERT_E_SUCCESS 0 //!< Operation completed successfully.
|
||||
#define ATCACERT_E_ERROR 1 //!< General error.
|
||||
#define ATCACERT_E_BAD_PARAMS 2 //!< Invalid/bad parameter passed to function.
|
||||
#define ATCACERT_E_BUFFER_TOO_SMALL 3 //!< Supplied buffer for output is too small to hold the result.
|
||||
#define ATCACERT_E_DECODING_ERROR 4 //!< Data being decoded/parsed has an invalid format.
|
||||
#define ATCACERT_E_INVALID_DATE 5 //!< Date is invalid.
|
||||
#define ATCACERT_E_UNIMPLEMENTED 6 //!< Function is unimplemented for the current configuration.
|
||||
#define ATCACERT_E_UNEXPECTED_ELEM_SIZE 7 //!< A certificate element size was not what was expected.
|
||||
#define ATCACERT_E_ELEM_MISSING 8 //!< The certificate element isn't defined for the certificate definition.
|
||||
#define ATCACERT_E_ELEM_OUT_OF_BOUNDS 9 //!< Certificate element is out of bounds for the given certificate.
|
||||
#define ATCACERT_E_BAD_CERT 10 //!< Certificate structure is bad in some way.
|
||||
#define ATCACERT_E_WRONG_CERT_DEF 11
|
||||
#define ATCACERT_E_VERIFY_FAILED 12 //!< Certificate or challenge/response verification failed.
|
||||
#define ATCACERT_E_INVALID_TRANSFORM 13 //!< Invalid transform passed to function.
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
@@ -0,0 +1,366 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Client side cert i/o methods. These declarations deal with the client-side, the node being authenticated,
|
||||
* of the authentication process. It is assumed the client has an ECC CryptoAuthentication device
|
||||
* (e.g. ATECC508A) and the certificates are stored on that device.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "atcacert_client.h"
|
||||
#include "atcacert_pem.h"
|
||||
#include "cryptoauthlib.h"
|
||||
#include "basic/atca_basic.h"
|
||||
|
||||
// Perform floor integer division (-1 / 2 == -1) instead of truncate towards zero (-1 / 2 == 0)
|
||||
static int floor_div(int a, int b)
|
||||
{
|
||||
int d = a / b;
|
||||
int r = a % b;
|
||||
|
||||
return r ? (d - ((a < 0) ^ (b < 0))) : d;
|
||||
}
|
||||
|
||||
int atcacert_get_response(uint8_t device_private_key_slot,
|
||||
const uint8_t challenge[32],
|
||||
uint8_t response[64])
|
||||
{
|
||||
if (device_private_key_slot > 15 || challenge == NULL || response == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
return atcab_sign(device_private_key_slot, challenge, response);
|
||||
}
|
||||
|
||||
int atcacert_read_device_loc(const atcacert_device_loc_t* device_loc,
|
||||
uint8_t* data)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if (device_loc->zone == DEVZONE_DATA && device_loc->is_genkey)
|
||||
{
|
||||
uint8_t public_key[ATCA_PUB_KEY_SIZE];
|
||||
if (device_loc->offset + device_loc->count > sizeof(public_key))
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcab_get_pubkey(device_loc->slot, public_key);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
memcpy(data, &public_key[device_loc->offset], device_loc->count);
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t count = device_loc->count;
|
||||
size_t zone_size;
|
||||
ret = atcab_get_zone_size(device_loc->zone, device_loc->slot, &zone_size);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
if (device_loc->offset + device_loc->count > (uint16_t)zone_size)
|
||||
{
|
||||
if (device_loc->offset > zone_size)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
count = zone_size - device_loc->offset;
|
||||
}
|
||||
|
||||
ret = atcab_read_bytes_zone(
|
||||
device_loc->zone,
|
||||
device_loc->slot,
|
||||
device_loc->offset,
|
||||
data,
|
||||
count);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_read_cert(const atcacert_def_t* cert_def,
|
||||
const uint8_t ca_public_key[64],
|
||||
uint8_t* cert,
|
||||
size_t* cert_size)
|
||||
{
|
||||
int ret = 0;
|
||||
atcacert_device_loc_t device_locs[16];
|
||||
size_t device_locs_count = 0;
|
||||
size_t i = 0;
|
||||
atcacert_build_state_t build_state;
|
||||
|
||||
if (cert_def == NULL || cert == NULL || cert_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcacert_get_device_locs(
|
||||
cert_def,
|
||||
device_locs,
|
||||
&device_locs_count,
|
||||
sizeof(device_locs) / sizeof(device_locs[0]),
|
||||
ATCA_BLOCK_SIZE);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcacert_cert_build_start(&build_state, cert_def, cert, cert_size, ca_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < device_locs_count; i++)
|
||||
{
|
||||
static uint8_t data[416];
|
||||
ret = atcacert_read_device_loc(&device_locs[i], data);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcacert_cert_build_process(&build_state, &device_locs[i], data);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = atcacert_cert_build_finish(&build_state);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_write_cert(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size)
|
||||
{
|
||||
int ret = 0;
|
||||
atcacert_device_loc_t device_locs[16];
|
||||
size_t device_locs_count = 0;
|
||||
size_t i = 0;
|
||||
|
||||
if (cert_def == NULL || cert == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcacert_get_device_locs(
|
||||
cert_def,
|
||||
device_locs,
|
||||
&device_locs_count,
|
||||
sizeof(device_locs) / sizeof(device_locs[0]),
|
||||
ATCA_BLOCK_SIZE);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (i = 0; i < device_locs_count; i++)
|
||||
{
|
||||
int end_block;
|
||||
int start_block;
|
||||
static uint8_t data[416];
|
||||
int block;
|
||||
|
||||
if (device_locs[i].zone == DEVZONE_CONFIG)
|
||||
{
|
||||
continue; // Cert data isn't written to the config zone, only read
|
||||
}
|
||||
if (device_locs[i].zone == DEVZONE_DATA && device_locs[i].is_genkey)
|
||||
{
|
||||
continue; // Public key is generated not written
|
||||
|
||||
}
|
||||
ret = atcacert_get_device_data(cert_def, cert, cert_size, &device_locs[i], data);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
start_block = device_locs[i].offset / ATCA_BLOCK_SIZE;
|
||||
end_block = floor_div((int)(device_locs[i].offset + device_locs[i].count) - 1, ATCA_BLOCK_SIZE);
|
||||
for (block = start_block; block <= end_block; block++)
|
||||
{
|
||||
ret = atcab_write_zone(
|
||||
device_locs[i].zone,
|
||||
device_locs[i].slot,
|
||||
(uint8_t)block,
|
||||
0,
|
||||
&data[(block - start_block) * ATCA_BLOCK_SIZE],
|
||||
ATCA_BLOCK_SIZE);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_create_csr_pem(const atcacert_def_t* csr_def, char* csr, size_t* csr_size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
size_t csr_max_size;
|
||||
size_t csr_der_size;
|
||||
|
||||
// Check the pointers
|
||||
if (csr_def == NULL || csr == NULL || csr_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
csr_max_size = *csr_size;
|
||||
*csr_size = 0;
|
||||
|
||||
// Create DER CSR
|
||||
csr_der_size = csr_max_size;
|
||||
status = atcacert_create_csr(csr_def, (uint8_t*)csr, &csr_der_size);
|
||||
if (status != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Move the DER CSR to the end of the buffer, so we can encode it into
|
||||
// PEM in place.
|
||||
memmove(csr + (csr_max_size - csr_der_size), csr, csr_der_size);
|
||||
|
||||
*csr_size = csr_max_size;
|
||||
status = atcacert_encode_pem_csr((uint8_t*)(csr + (csr_max_size - csr_der_size)), csr_der_size, csr, csr_size);
|
||||
if (status != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_create_csr(const atcacert_def_t* csr_def, uint8_t* csr, size_t* csr_size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t pub_key[ATCA_PUB_KEY_SIZE] = { 0 };
|
||||
uint8_t sig[ATCA_SIG_SIZE] = { 0 };
|
||||
const atcacert_device_loc_t* pub_dev_loc = NULL;
|
||||
const atcacert_cert_loc_t* pub_loc = NULL;
|
||||
uint16_t key_slot = 0;
|
||||
uint16_t priv_key_slot = 0;
|
||||
uint8_t tbs_digest[ATCA_BLOCK_SIZE] = { 0 };
|
||||
size_t csr_max_size = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the pointers
|
||||
if (csr_def == NULL || csr == NULL || csr == NULL || csr_size == NULL)
|
||||
{
|
||||
status = ATCACERT_E_BAD_PARAMS;
|
||||
BREAK(status, "Null input parameter");
|
||||
}
|
||||
// Check the csr buffer size
|
||||
if (*csr_size < csr_def->cert_template_size)
|
||||
{
|
||||
status = ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
BREAK(status, "CSR buffer size too small");
|
||||
}
|
||||
// Copy the CSR template into the CSR that will be returned
|
||||
memcpy(csr, csr_def->cert_template, csr_def->cert_template_size);
|
||||
csr_max_size = *csr_size;
|
||||
*csr_size = csr_def->cert_template_size;
|
||||
|
||||
// Get a few elements from the csr_def structure
|
||||
pub_loc = &(csr_def->std_cert_elements[STDCERT_PUBLIC_KEY]);
|
||||
pub_dev_loc = &(csr_def->public_key_dev_loc);
|
||||
key_slot = pub_dev_loc->slot;
|
||||
priv_key_slot = csr_def->private_key_slot;
|
||||
|
||||
// Get the public key from the device
|
||||
if (pub_dev_loc->is_genkey)
|
||||
{
|
||||
// Calculate the public key from the private key
|
||||
status = atcab_get_pubkey(key_slot, pub_key);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Could not generate public key");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the public key from a slot
|
||||
status = atcab_read_pubkey(key_slot, pub_key);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Could not read public key");
|
||||
}
|
||||
}
|
||||
// Insert the public key into the CSR template
|
||||
status = atcacert_set_cert_element(csr_def, pub_loc, csr, *csr_size, pub_key, ATCA_PUB_KEY_SIZE);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Setting CSR public key failed");
|
||||
}
|
||||
|
||||
// Get the CSR TBS digest
|
||||
status = atcacert_get_tbs_digest(csr_def, csr, *csr_size, tbs_digest);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Get TBS digest failed");
|
||||
}
|
||||
|
||||
// Sign the TBS digest
|
||||
status = atcab_sign(priv_key_slot, tbs_digest, sig);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Signing CSR failed");
|
||||
}
|
||||
|
||||
// Insert the signature into the CSR template
|
||||
status = atcacert_set_signature(csr_def, csr, csr_size, csr_max_size, sig);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Setting CSR signature failed");
|
||||
}
|
||||
|
||||
// The exact size of the csr cannot be determined until after adding the signature
|
||||
// it is returned in the csr_size parameter. (*csr_size = *csr_size;)
|
||||
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Client side cert i/o methods. These declarations deal with the client-side, the node being authenticated,
|
||||
* of the authentication process. It is assumed the client has an ECC CryptoAuthentication device
|
||||
* (e.g. ATECC508A) and the certificates are stored on that device.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCACERT_CLIENT_H
|
||||
#define ATCACERT_CLIENT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "atcacert_def.h"
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/** \brief Read the data from a device location.
|
||||
*
|
||||
* \param[in] device_loc Device location to read data from.
|
||||
* \param[out] data Data read is returned here.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_read_device_loc(const atcacert_device_loc_t* device_loc,
|
||||
uint8_t* data);
|
||||
|
||||
/**
|
||||
* \brief Reads the certificate specified by the certificate definition from the
|
||||
* ATECC508A device.
|
||||
*
|
||||
* This process involves reading the dynamic cert data from the device and combining it
|
||||
* with the template found in the certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition describing where to find the dynamic
|
||||
* certificate information on the device and how to incorporate it
|
||||
* into the template.
|
||||
* \param[in] ca_public_key The ECC P256 public key of the certificate authority that signed
|
||||
* this certificate. Formatted as the 32 byte X and Y integers
|
||||
* concatenated together (64 bytes total). Set to NULL if the
|
||||
* authority key id is not needed, set properly in the cert_def
|
||||
* template, or stored on the device as specifed in the
|
||||
* cert_def cert_elements.
|
||||
* \param[out] cert Buffer to received the certificate.
|
||||
* \param[inout] cert_size As input, the size of the cert buffer in bytes.
|
||||
* As output, the size of the certificate returned in cert in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_read_cert(const atcacert_def_t* cert_def,
|
||||
const uint8_t ca_public_key[64],
|
||||
uint8_t* cert,
|
||||
size_t* cert_size);
|
||||
|
||||
/**
|
||||
* \brief Take a full certificate and write it to the ATECC508A device according to the
|
||||
* certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition describing where the dynamic certificate
|
||||
* information is and how to store it on the device.
|
||||
* \param[in] cert Full certificate to be stored.
|
||||
* \param[in] cert_size Size of the full certificate in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_write_cert(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size);
|
||||
|
||||
/**
|
||||
* \brief Creates a CSR specified by the CSR definition from the ATECC508A device.
|
||||
* This process involves reading the dynamic CSR data from the device and combining it
|
||||
* with the template found in the CSR definition, then signing it. Return the CSR int der format
|
||||
* \param[in] csr_def CSR definition describing where to find the dynamic CSR information
|
||||
* on the device and how to incorporate it into the template.
|
||||
* \param[out] csr Buffer to receive the CSR.
|
||||
* \param[inout] csr_size As input, the size of the CSR buffer in bytes.
|
||||
* As output, the size of the CSR returned in cert in bytes.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_create_csr(const atcacert_def_t* csr_def, uint8_t* csr, size_t* csr_size);
|
||||
|
||||
/**
|
||||
* \brief Creates a CSR specified by the CSR definition from the ATECC508A device.
|
||||
* This process involves reading the dynamic CSR data from the device and combining it
|
||||
* with the template found in the CSR definition, then signing it. Return the CSR int der format
|
||||
* \param[in] csr_def CSR definition describing where to find the dynamic CSR information
|
||||
* on the device and how to incorporate it into the template.
|
||||
* \param[out] csr Buffer to received the CSR formatted as PEM.
|
||||
* \param[inout] csr_size As input, the size of the CSR buffer in bytes.
|
||||
* As output, the size of the CSR as PEM returned in cert in bytes.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_create_csr_pem(const atcacert_def_t* csr_def, char* csr, size_t* csr_size);
|
||||
|
||||
/**
|
||||
* \brief Calculates the response to a challenge sent from the host.
|
||||
*
|
||||
* The challenge-response protocol is an ECDSA Sign and Verify. This performs the ECDSA Sign on the
|
||||
* challenge and returns the signature as the response.
|
||||
*
|
||||
* \param[in] device_private_key_slot Slot number for the device's private key. This must be the
|
||||
* same slot used to generate the public key included in the
|
||||
* device's certificate.
|
||||
* \param[in] challenge Challenge to generate the response for. Must be 32 bytes.
|
||||
* \param[out] response Response will be returned in this buffer. 64 bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_response(uint8_t device_private_key_slot,
|
||||
const uint8_t challenge[32],
|
||||
uint8_t response[64]);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Declarations for date handling with regard to certificates.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCACERT_DATE_H
|
||||
#define ATCACERT_DATE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "atcacert.h"
|
||||
|
||||
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* Holds a broken-down date in UTC. Mimics atcacert_tm_utc_t from time.h.
|
||||
*/
|
||||
typedef struct atcacert_tm_utc_s
|
||||
{
|
||||
int tm_sec; // 0 to 59
|
||||
int tm_min; // 0 to 59
|
||||
int tm_hour; // 0 to 23
|
||||
int tm_mday; // 1 to 31
|
||||
int tm_mon; // 0 to 11
|
||||
int tm_year; // years since 1900
|
||||
} atcacert_tm_utc_t;
|
||||
|
||||
/**
|
||||
* Date formats.
|
||||
*/
|
||||
typedef enum atcacert_date_format_e
|
||||
{
|
||||
DATEFMT_ISO8601_SEP, //!< ISO8601 full date YYYY-MM-DDThh:mm:ssZ
|
||||
DATEFMT_RFC5280_UTC, //!< RFC 5280 (X.509) 4.1.2.5.1 UTCTime format YYMMDDhhmmssZ
|
||||
DATEFMT_POSIX_UINT32_BE, //!< POSIX (aka UNIX) date format. Seconds since Jan 1, 1970. 32 bit unsigned integer, big endian.
|
||||
DATEFMT_POSIX_UINT32_LE, //!< POSIX (aka UNIX) date format. Seconds since Jan 1, 1970. 32 bit unsigned integer, little endian.
|
||||
DATEFMT_RFC5280_GEN //!< RFC 5280 (X.509) 4.1.2.5.2 GeneralizedTime format YYYYMMDDhhmmssZ
|
||||
} atcacert_date_format_t;
|
||||
|
||||
#define DATEFMT_ISO8601_SEP_SIZE (20)
|
||||
#define DATEFMT_RFC5280_UTC_SIZE (13)
|
||||
#define DATEFMT_POSIX_UINT32_BE_SIZE (4)
|
||||
#define DATEFMT_POSIX_UINT32_LE_SIZE (4)
|
||||
#define DATEFMT_RFC5280_GEN_SIZE (15)
|
||||
#define DATEFMT_MAX_SIZE DATEFMT_ISO8601_SEP_SIZE
|
||||
#define ATCACERT_DATE_FORMAT_SIZES_COUNT 5
|
||||
|
||||
extern const size_t ATCACERT_DATE_FORMAT_SIZES[ATCACERT_DATE_FORMAT_SIZES_COUNT];
|
||||
|
||||
/**
|
||||
* \brief Format a timestamp according to the format type.
|
||||
*
|
||||
* \param[in] format Format to use.
|
||||
* \param[in] timestamp Timestamp to format.
|
||||
* \param[out] formatted_date Formatted date will be returned in this buffer.
|
||||
* \param[inout] formatted_date_size As input, the size of the formatted_date buffer.
|
||||
* As output, the size of the returned formatted_date.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_date_enc(atcacert_date_format_t format,
|
||||
const atcacert_tm_utc_t* timestamp,
|
||||
uint8_t* formatted_date,
|
||||
size_t* formatted_date_size);
|
||||
|
||||
/**
|
||||
* \brief Parse a formatted timestamp according to the specified format.
|
||||
*
|
||||
* \param[in] format Format to parse the formatted date as.
|
||||
* \param[in] formatted_date Formatted date to be parsed.
|
||||
* \param[in] formatted_date_size Size of the formatted date in bytes.
|
||||
* \param[out] timestamp Parsed timestamp is returned here.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_date_dec(atcacert_date_format_t format,
|
||||
const uint8_t* formatted_date,
|
||||
size_t formatted_date_size,
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
/**
|
||||
* \brief Encode the issue and expire dates in the format used by the compressed certificate.
|
||||
*
|
||||
* \param[in] issue_date Issue date to encode. Note that minutes and seconds will be ignored.
|
||||
* \param[in] expire_years Expire date is expressed as a number of years past the issue date.
|
||||
* 0 should be used if there is no expire date.
|
||||
* \param[out] enc_dates Encoded dates for use in the compressed certificate is returned here.
|
||||
* 3 bytes.
|
||||
*
|
||||
* \return 0 on success
|
||||
*/
|
||||
int atcacert_date_enc_compcert(const atcacert_tm_utc_t * issue_date,
|
||||
uint8_t expire_years,
|
||||
uint8_t enc_dates[3]);
|
||||
|
||||
/**
|
||||
* \brief Decode the issue and expire dates from the format used by the compressed certificate.
|
||||
*
|
||||
* \param[in] enc_dates Encoded date from the compressed certificate. 3 bytes.
|
||||
* \param[in] expire_date_format Expire date format. Only used to determine max date when no
|
||||
* expiration date is specified by the encoded date.
|
||||
* \param[out] issue_date Decoded issue date is returned here.
|
||||
* \param[out] expire_date Decoded expire date is returned here. If there is no
|
||||
* expiration date, the expire date will be set to a maximum
|
||||
* value for the given expire_date_format.
|
||||
*
|
||||
* \return 0 on success
|
||||
*/
|
||||
int atcacert_date_dec_compcert(const uint8_t enc_dates[3],
|
||||
atcacert_date_format_t expire_date_format,
|
||||
atcacert_tm_utc_t* issue_date,
|
||||
atcacert_tm_utc_t* expire_date);
|
||||
|
||||
/**
|
||||
* \brief Return the maximum date available for the given format.
|
||||
*
|
||||
* \param[in] format Format to get the max date for.
|
||||
* \param[out] timestamp Max date is returned here.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_date_get_max_date(atcacert_date_format_t format, atcacert_tm_utc_t* timestamp);
|
||||
|
||||
int atcacert_date_enc_iso8601_sep(const atcacert_tm_utc_t * timestamp,
|
||||
uint8_t formatted_date[DATEFMT_ISO8601_SEP_SIZE]);
|
||||
|
||||
int atcacert_date_dec_iso8601_sep(const uint8_t formatted_date[DATEFMT_ISO8601_SEP_SIZE],
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
int atcacert_date_enc_rfc5280_utc(const atcacert_tm_utc_t * timestamp,
|
||||
uint8_t formatted_date[DATEFMT_RFC5280_UTC_SIZE]);
|
||||
|
||||
int atcacert_date_dec_rfc5280_utc(const uint8_t formatted_date[DATEFMT_RFC5280_UTC_SIZE],
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
int atcacert_date_enc_rfc5280_gen(const atcacert_tm_utc_t * timestamp,
|
||||
uint8_t formatted_date[DATEFMT_RFC5280_GEN_SIZE]);
|
||||
|
||||
int atcacert_date_dec_rfc5280_gen(const uint8_t formatted_date[DATEFMT_RFC5280_GEN_SIZE],
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
int atcacert_date_enc_posix_uint32_be(const atcacert_tm_utc_t * timestamp,
|
||||
uint8_t formatted_date[DATEFMT_POSIX_UINT32_BE_SIZE]);
|
||||
|
||||
int atcacert_date_dec_posix_uint32_be(const uint8_t formatted_date[DATEFMT_POSIX_UINT32_BE_SIZE],
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
int atcacert_date_enc_posix_uint32_le(const atcacert_tm_utc_t * timestamp,
|
||||
uint8_t formatted_date[DATEFMT_POSIX_UINT32_LE_SIZE]);
|
||||
|
||||
int atcacert_date_dec_posix_uint32_le(const uint8_t formatted_date[DATEFMT_POSIX_UINT32_LE_SIZE],
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,825 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Declarations for certificates related to ECC CryptoAuthentication devices.
|
||||
* These are the definitions required to define a certificate and its various
|
||||
* elements with regards to the CryptoAuthentication ECC devices.
|
||||
*
|
||||
* Only the dynamic elements of a certificate (the parts of the certificate
|
||||
* that change from device to device) are stored on the ATECC device. The
|
||||
* definitions here describe the form of the certificate, and where the
|
||||
* dynamic elements can be found both on the ATECC device itself and in the
|
||||
* certificate template.
|
||||
*
|
||||
* This also defines utility functions for working with the certificates and their definitions.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCACERT_DEF_H
|
||||
#define ATCACERT_DEF_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "atca_compiler.h"
|
||||
#include "atcacert.h"
|
||||
#include "atcacert_date.h"
|
||||
#include "basic/atca_helpers.h"
|
||||
|
||||
#define ATCA_MAX_TRANSFORMS 2
|
||||
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* Types of certificates.
|
||||
*/
|
||||
typedef enum atcacert_cert_type_e
|
||||
{
|
||||
CERTTYPE_X509, //!< Standard X509 certificate
|
||||
CERTTYPE_CUSTOM //!< Custom format
|
||||
} atcacert_cert_type_t;
|
||||
|
||||
/**
|
||||
* Sources for the certificate serial number.
|
||||
*/
|
||||
typedef enum atcacert_cert_sn_src_e
|
||||
{
|
||||
SNSRC_STORED = 0x0, //!< Cert serial is stored on the device.
|
||||
SNSRC_STORED_DYNAMIC = 0x7, //!< Cert serial is stored on the device with the first byte being the DER size (X509 certs only).
|
||||
SNSRC_DEVICE_SN = 0x8, //!< Cert serial number is 0x40(MSB) + 9-byte device serial number. Only applies to device certificates.
|
||||
SNSRC_SIGNER_ID = 0x9, //!< Cert serial number is 0x40(MSB) + 2-byte signer ID. Only applies to signer certificates.
|
||||
SNSRC_PUB_KEY_HASH = 0xA, //!< Cert serial number is the SHA256(Subject public key + Encoded dates), with uppermost 2 bits set to 01.
|
||||
SNSRC_DEVICE_SN_HASH = 0xB, //!< Cert serial number is the SHA256(Device SN + Encoded dates), with uppermost 2 bits set to 01. Only applies to device certificates.
|
||||
SNSRC_PUB_KEY_HASH_POS = 0xC, //!< Depreciated, don't use. Cert serial number is the SHA256(Subject public key + Encoded dates), with MSBit set to 0 to ensure it's positive.
|
||||
SNSRC_DEVICE_SN_HASH_POS = 0xD, //!< Depreciated, don't use. Cert serial number is the SHA256(Device SN + Encoded dates), with MSBit set to 0 to ensure it's positive. Only applies to device certificates.
|
||||
SNSRC_PUB_KEY_HASH_RAW = 0xE, //!< Depreciated, don't use. Cert serial number is the SHA256(Subject public key + Encoded dates).
|
||||
SNSRC_DEVICE_SN_HASH_RAW = 0xF //!< Depreciated, don't use. Cert serial number is the SHA256(Device SN + Encoded dates). Only applies to device certificates.
|
||||
} atcacert_cert_sn_src_t;
|
||||
|
||||
/**
|
||||
* ATECC device zones. The values match the Zone Encodings as specified in the datasheet.
|
||||
*/
|
||||
typedef enum atcacert_device_zone_e
|
||||
{
|
||||
DEVZONE_CONFIG = 0x00, //!< Configuration zone.
|
||||
DEVZONE_OTP = 0x01, //!< One Time Programmable zone.
|
||||
DEVZONE_DATA = 0x02, //!< Data zone (slots).
|
||||
DEVZONE_NONE = 0x07 //!< Special value used to indicate there is no device location.
|
||||
} atcacert_device_zone_t;
|
||||
|
||||
/** \brief How to transform the data from the device to the certificate.
|
||||
*/
|
||||
typedef enum atcacert_transform_e
|
||||
{
|
||||
TF_NONE, //!< No transform, data is used byte for byte
|
||||
TF_REVERSE, //!< Reverse the bytes (e.g. change endianness)
|
||||
TF_BIN2HEX_UC, //!< Convert raw binary into ASCII hex, uppercase
|
||||
TF_BIN2HEX_LC, //!< Convert raw binary into ASCII hex, lowercase
|
||||
TF_HEX2BIN_UC, //!< Convert ASCII hex, uppercase to binary
|
||||
TF_HEX2BIN_LC, //!< Convert ASCII hex, lowercase to binary
|
||||
TF_BIN2HEX_SPACE_UC, //!< Convert raw binary into ASCII hex, uppercase space between bytes
|
||||
TF_BIN2HEX_SPACE_LC, //!< Convert raw binary into ASCII hex, lowercase space between bytes
|
||||
TF_HEX2BIN_SPACE_UC, //!< Convert ASCII hex, uppercase with spaces between bytes to binary
|
||||
TF_HEX2BIN_SPACE_LC, //!< Convert ASCII hex, lowercase with spaces between bytes to binary
|
||||
} atcacert_transform_t;
|
||||
|
||||
/**
|
||||
* Standard dynamic certificate elements.
|
||||
*/
|
||||
typedef enum atcacert_std_cert_element_e
|
||||
{
|
||||
STDCERT_PUBLIC_KEY,
|
||||
STDCERT_SIGNATURE,
|
||||
STDCERT_ISSUE_DATE,
|
||||
STDCERT_EXPIRE_DATE,
|
||||
STDCERT_SIGNER_ID,
|
||||
STDCERT_CERT_SN,
|
||||
STDCERT_AUTH_KEY_ID,
|
||||
STDCERT_SUBJ_KEY_ID,
|
||||
STDCERT_NUM_ELEMENTS //!< Special item to give the number of elements in this enum
|
||||
} atcacert_std_cert_element_t;
|
||||
|
||||
// Some of these structures may need to be byte-accurate
|
||||
#ifndef ATCA_NO_PRAGMA_PACK
|
||||
#pragma pack(push, 1)
|
||||
#define ATCA_PACKED
|
||||
#else
|
||||
#define ATCA_PACKED __attribute__ ((packed))
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Defines a chunk of data in an ATECC device.
|
||||
*/
|
||||
typedef struct ATCA_PACKED atcacert_device_loc_s
|
||||
{
|
||||
atcacert_device_zone_t zone; //!< Zone in the device.
|
||||
uint8_t slot; //!< Slot within the data zone. Only applies if zone is DEVZONE_DATA.
|
||||
uint8_t is_genkey; //!< If true, use GenKey command to get the contents instead of Read.
|
||||
uint16_t offset; //!< Byte offset in the zone.
|
||||
uint16_t count; //!< Byte count.
|
||||
} atcacert_device_loc_t;
|
||||
|
||||
/**
|
||||
* Defines a chunk of data in a certificate template.
|
||||
*/
|
||||
typedef struct ATCA_PACKED atcacert_cert_loc_s
|
||||
{
|
||||
uint16_t offset; //!< Byte offset in the certificate template.
|
||||
uint16_t count; //!< Byte count. Set to 0 if it doesn't exist.
|
||||
} atcacert_cert_loc_t;
|
||||
|
||||
/**
|
||||
* Defines a generic dynamic element for a certificate including the device and template locations.
|
||||
*/
|
||||
typedef struct ATCA_PACKED atcacert_cert_element_s
|
||||
{
|
||||
char id[25]; //!< ID identifying this element.
|
||||
atcacert_device_loc_t device_loc; //!< Location in the device for the element.
|
||||
atcacert_cert_loc_t cert_loc; //!< Location in the certificate template for the element.
|
||||
atcacert_transform_t transforms[ATCA_MAX_TRANSFORMS]; //!< List of transforms from device to cert for this element.
|
||||
} atcacert_cert_element_t;
|
||||
|
||||
/**
|
||||
* Defines a certificate and all the pieces to work with it.
|
||||
*
|
||||
* If any of the standard certificate elements (std_cert_elements) are not a part of the certificate
|
||||
* definition, set their count to 0 to indicate their absence.
|
||||
*/
|
||||
typedef struct ATCA_PACKED atcacert_def_s
|
||||
{
|
||||
atcacert_cert_type_t type; //!< Certificate type.
|
||||
uint8_t template_id; //!< ID for the this certificate definition (4-bit value).
|
||||
uint8_t chain_id; //!< ID for the certificate chain this definition is a part of (4-bit value).
|
||||
uint8_t private_key_slot; //!< If this is a device certificate template, this is the device slot for the device private key.
|
||||
atcacert_cert_sn_src_t sn_source; //!< Where the certificate serial number comes from (4-bit value).
|
||||
atcacert_device_loc_t cert_sn_dev_loc; //!< Only applies when sn_source is SNSRC_STORED or SNSRC_STORED_DYNAMIC. Describes where to get the certificate serial number on the device.
|
||||
atcacert_date_format_t issue_date_format; //!< Format of the issue date in the certificate.
|
||||
atcacert_date_format_t expire_date_format; //!< format of the expire date in the certificate.
|
||||
atcacert_cert_loc_t tbs_cert_loc; //!< Location in the certificate for the TBS (to be signed) portion.
|
||||
uint8_t expire_years; //!< Number of years the certificate is valid for (5-bit value). 0 means no expiration.
|
||||
atcacert_device_loc_t public_key_dev_loc; //!< Where on the device the public key can be found.
|
||||
atcacert_device_loc_t comp_cert_dev_loc; //!< Where on the device the compressed cert can be found.
|
||||
atcacert_cert_loc_t std_cert_elements[STDCERT_NUM_ELEMENTS]; //!< Where in the certificate template the standard cert elements are inserted.
|
||||
const atcacert_cert_element_t* cert_elements; //!< Additional certificate elements outside of the standard certificate contents.
|
||||
uint8_t cert_elements_count; //!< Number of additional certificate elements in cert_elements.
|
||||
const uint8_t* cert_template; //!< Pointer to the actual certificate template data.
|
||||
uint16_t cert_template_size; //!< Size of the certificate template in cert_template in bytes.
|
||||
const struct atcacert_def_s* ca_cert_def; //!< Certificate definition of the CA certificate
|
||||
} atcacert_def_t;
|
||||
|
||||
/**
|
||||
* Tracks the state of a certificate as it's being rebuilt from device information.
|
||||
*/
|
||||
|
||||
typedef struct ATCA_PACKED atcacert_build_state_s
|
||||
{
|
||||
const atcacert_def_t* cert_def; //!< Certificate definition for the certificate being rebuilt.
|
||||
uint8_t* cert; //!< Buffer to contain the rebuilt certificate.
|
||||
size_t* cert_size; //!< Current size of the certificate in bytes.
|
||||
size_t max_cert_size; //!< Max size of the cert buffer in bytes.
|
||||
uint8_t is_device_sn; //!< Indicates the structure contains the device SN.
|
||||
uint8_t device_sn[9]; //!< Storage for the device SN, when it's found.
|
||||
} atcacert_build_state_t;
|
||||
|
||||
#ifndef ATCA_NO_PRAGMA_PACK
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Add all the device locations required to rebuild the specified certificate (cert_def) to
|
||||
* a device locations list.
|
||||
*
|
||||
* The block_size parameter will adjust all added device locations to have a offset and count that
|
||||
* aligns with that block size. This allows one to generate a list of device locations that matches
|
||||
* specific read or write semantics (e.g. 4 byte or 32 byte reads).
|
||||
*
|
||||
* \param[in] cert_def Certificate definition containing all the device locations
|
||||
* to add to the list.
|
||||
* \param[inout] device_locs List of device locations to add to.
|
||||
* \param[inout] device_locs_count As input, existing size of the device locations list.
|
||||
* As output, the new size of the device locations list.
|
||||
* \param[in] device_locs_max_count Maximum number of elements device_locs can hold.
|
||||
* \param[in] block_size Block size to align all offsets and counts to when adding
|
||||
* device locations.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_device_locs(const atcacert_def_t* cert_def,
|
||||
atcacert_device_loc_t* device_locs,
|
||||
size_t* device_locs_count,
|
||||
size_t device_locs_max_count,
|
||||
size_t block_size);
|
||||
|
||||
/**
|
||||
* \brief Starts the certificate rebuilding process.
|
||||
*
|
||||
* \param[out] build_state Structure is initialized to start the certificate building process.
|
||||
* Will be passed to the other certificate building functions.
|
||||
* \param[in] cert_def Certificate definition for the certificate being built.
|
||||
* \param[in] cert Buffer to contain the rebuilt certificate.
|
||||
* \param[in] cert_size As input, the size of the cert buffer in bytes. This value will be
|
||||
* adjusted to the current/final size of the certificate through the
|
||||
* building process.
|
||||
* \param[in] ca_public_key ECC P256 public key of the certificate authority (issuer) for the
|
||||
* certificate being built. Set to NULL if the authority key id is
|
||||
* not needed, set properly in the cert_def template, or stored on the
|
||||
* device as specified in the cert_def cert_elements.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_cert_build_start(atcacert_build_state_t* build_state,
|
||||
const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t* cert_size,
|
||||
const uint8_t ca_public_key[64]);
|
||||
|
||||
/**
|
||||
* \brief Process information read from the ATECC device. If it contains information for the
|
||||
* certificate, it will be incorporated into the certificate.
|
||||
*
|
||||
* \param[in] build_state Current certificate building state.
|
||||
* \param[in] device_loc Device location structure describing where on the device the following
|
||||
* data came from.
|
||||
* \param[in] device_data Actual data from the device. It should represent the offset and byte
|
||||
* count specified in the device_loc parameter.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_cert_build_process(atcacert_build_state_t* build_state,
|
||||
const atcacert_device_loc_t* device_loc,
|
||||
const uint8_t* device_data);
|
||||
|
||||
/**
|
||||
* \brief Completes any final certificate processing required after all data from the device has
|
||||
* been incorporated.
|
||||
*
|
||||
* The final certificate and its size in bytes are contained in the cert and cert_size elements
|
||||
* of the build_state structure. This will be the same buffers as supplied to the
|
||||
* atcacert_cert_build_start function at the beginning of the certificate rebuilding process.
|
||||
*
|
||||
* \param[in] build_state Current certificate build state.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_cert_build_finish(atcacert_build_state_t* build_state);
|
||||
|
||||
/**
|
||||
* \brief Gets the dynamic data that would be saved to the specified device location. This
|
||||
* function is primarily used to break down a full certificate into the dynamic components
|
||||
* to be saved to a device.
|
||||
*
|
||||
* The atcacert_add_device_locs function can be used to generate a list of device locations a
|
||||
* particular certificate definition requires.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate we're getting data from.
|
||||
* \param[in] cert Certificate to get the device data from.
|
||||
* \param[in] cert_size Size of the certificate in bytes.
|
||||
* \param[in] device_loc Device location to request data for.
|
||||
* \param[out] device_data Buffer that represents the device data in device_loc. Required to be
|
||||
* at least device_loc.count in size.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_device_data(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const atcacert_device_loc_t* device_loc,
|
||||
uint8_t* device_data);
|
||||
|
||||
/**
|
||||
* \brief Sets the subject public key and subject key ID in a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] subj_public_key Subject public key as X and Y integers concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_subj_public_key(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t subj_public_key[64]);
|
||||
|
||||
/**
|
||||
* \brief Gets the subject public key from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] subj_public_key Subject public key is returned in this buffer. Formatted at X and Y
|
||||
* integers concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_subj_public_key(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t subj_public_key[64]);
|
||||
|
||||
/**
|
||||
* \brief Gets the subject key ID from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] subj_key_id Subject key ID is returned in this buffer. 20 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_subj_key_id(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t subj_key_id[20]);
|
||||
|
||||
/**
|
||||
* \brief Sets the signature in a certificate. This may alter the size of the X.509 certificates.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[inout] cert_size As input, size of the certificate (cert) in bytes.
|
||||
* As output, the new size of the certificate.
|
||||
* \param[in] max_cert_size Maximum size of the cert buffer.
|
||||
* \param[in] signature Signature as R and S integers concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_signature(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t* cert_size,
|
||||
size_t max_cert_size,
|
||||
const uint8_t signature[64]);
|
||||
|
||||
/**
|
||||
* \brief Gets the signature from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] signature Signature is returned in this buffer. Formatted at R and S integers
|
||||
* concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_signature(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t signature[64]);
|
||||
|
||||
/**
|
||||
* \brief Sets the issue date (notBefore) in a certificate. Will be formatted according to the date
|
||||
* format specified in the certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] timestamp Issue date.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_issue_date(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const atcacert_tm_utc_t* timestamp);
|
||||
|
||||
/**
|
||||
* \brief Gets the issue date from a certificate. Will be parsed according to the date format
|
||||
* specified in the certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] timestamp Issue date is returned in this structure.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_issue_date(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
/**
|
||||
* \brief Sets the expire date (notAfter) in a certificate. Will be formatted according to the date
|
||||
* format specified in the certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] timestamp Expire date.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_expire_date(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const atcacert_tm_utc_t* timestamp);
|
||||
|
||||
/**
|
||||
* \brief Gets the expire date from a certificate. Will be parsed according to the date format
|
||||
* specified in the certificate definition.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] timestamp Expire date is returned in this structure.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_expire_date(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
atcacert_tm_utc_t* timestamp);
|
||||
|
||||
/**
|
||||
* \brief Sets the signer ID in a certificate. Will be formatted as 4 upper-case hex digits.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] signer_id Signer ID.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_signer_id(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t signer_id[2]);
|
||||
|
||||
/**
|
||||
* \brief Gets the signer ID from a certificate. Will be parsed as 4 upper-case hex digits.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] signer_id Signer ID will be returned in this buffer. 2 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_signer_id(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t signer_id[2]);
|
||||
|
||||
/**
|
||||
* \brief Sets the certificate serial number in a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[inout] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] max_cert_size Maximum size of the cert buffer.
|
||||
* \param[in] cert_sn Certificate serial number.
|
||||
* \param[in] cert_sn_size Size of the certificate serial number in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_cert_sn(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t* cert_size,
|
||||
size_t max_cert_size,
|
||||
const uint8_t* cert_sn,
|
||||
size_t cert_sn_size);
|
||||
|
||||
/**
|
||||
* \brief Sets the certificate serial number by generating it from other information in the
|
||||
* certificate using the scheme specified by sn_source in cert_def. See the
|
||||
*
|
||||
* This method requires certain elements in the certificate be set properly as they're used for
|
||||
* generating the serial number. See atcacert_cert_sn_src_t for what elements should be set in the
|
||||
* certificate beforehand. If the sn_source is set to SNSRC_STORED or SNSRC_STORED_DYNAMIC, the
|
||||
* function will return ATCACERT_E_SUCCESS without making any changes to the certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] device_sn Device serial number, only used if required by the sn_source scheme.
|
||||
* Can be set to NULL, if not required.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_gen_cert_sn(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t device_sn[9]);
|
||||
|
||||
/**
|
||||
* \brief Gets the certificate serial number from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] cert_sn Certificate SN will be returned in this buffer.
|
||||
* \param[inout] cert_sn_size As input, the size of the cert_sn buffer.
|
||||
* As output, the size of the certificate SN (cert_sn) in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_cert_sn(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
uint8_t* cert_sn,
|
||||
size_t* cert_sn_size);
|
||||
|
||||
/**
|
||||
* \brief Sets the authority key ID in a certificate. Note that this takes the actual public key
|
||||
* creates a key ID from it.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] auth_public_key Authority public key as X and Y integers concatenated together.
|
||||
* 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_auth_key_id(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t auth_public_key[64]);
|
||||
|
||||
/**
|
||||
* \brief Sets the authority key ID in a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] auth_key_id Authority key ID. Same size as defined in the cert_def.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_auth_key_id_raw(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t* auth_key_id);
|
||||
|
||||
/**
|
||||
* \brief Gets the authority key ID from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] auth_key_id Authority key ID is returned in this buffer. 20 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_auth_key_id(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t auth_key_id[20]);
|
||||
|
||||
/**
|
||||
* \brief Sets the signature, issue date, expire date, and signer ID found in the compressed
|
||||
* certificate. This also checks fields common between the cert_def and the compressed
|
||||
* certificate to make sure they match.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[inout] cert_size As input, size of the certificate (cert) in bytes.
|
||||
* As output, the new size of the certificate.
|
||||
* \param[in] max_cert_size Maximum size of the cert buffer.
|
||||
* \param[in] comp_cert Compressed certificate. 72 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success. ATCACERT_E_WRONG_CERT_DEF if the template ID, chain ID, and/or SN source
|
||||
* don't match between the cert_def and the compressed certificate.
|
||||
*/
|
||||
int atcacert_set_comp_cert(const atcacert_def_t* cert_def,
|
||||
uint8_t* cert,
|
||||
size_t* cert_size,
|
||||
size_t max_cert_size,
|
||||
const uint8_t comp_cert[72]);
|
||||
|
||||
/**
|
||||
* \brief Generate the compressed certificate for the given certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to generate the compressed certificate for.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] comp_cert Compressed certificate is returned in this buffer. 72 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_comp_cert(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t comp_cert[72]);
|
||||
|
||||
/**
|
||||
* \brief Get a pointer to the TBS data in a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get the TBS data pointer for.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] tbs Pointer to a const pointer that will be set the start of the TBS data.
|
||||
* \param[out] tbs_size Size of the TBS data will be returned here.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_tbs(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t** tbs,
|
||||
size_t* tbs_size);
|
||||
|
||||
/**
|
||||
* \brief Get the SHA256 digest of certificate's TBS data.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert Certificate to get the TBS data pointer for.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] tbs_digest TBS data digest will be returned here. 32 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_tbs_digest(const atcacert_def_t * cert_def,
|
||||
const uint8_t * cert,
|
||||
size_t cert_size,
|
||||
uint8_t tbs_digest[32]);
|
||||
|
||||
/**
|
||||
* \brief Sets an element in a certificate. The data_size must match the size in cert_loc.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert_loc Certificate location for this element.
|
||||
* \param[inout] cert Certificate to update.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] data Element data to insert into the certificate. Buffer must contain
|
||||
* cert_loc.count bytes to be copied into the certificate.
|
||||
* \param[in] data_size Size of the data in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_set_cert_element(const atcacert_def_t* cert_def,
|
||||
const atcacert_cert_loc_t* cert_loc,
|
||||
uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t* data,
|
||||
size_t data_size);
|
||||
|
||||
/**
|
||||
* \brief Gets an element from a certificate.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition for the certificate.
|
||||
* \param[in] cert_loc Certificate location for this element.
|
||||
* \param[in] cert Certificate to get element from.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[out] data Element data will be returned in this buffer. This buffer must be large
|
||||
* enough to hold cert_loc.count bytes.
|
||||
* \param[in] data_size Expected size of the cert element data.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_cert_element(const atcacert_def_t* cert_def,
|
||||
const atcacert_cert_loc_t* cert_loc,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
uint8_t* data,
|
||||
size_t data_size);
|
||||
|
||||
|
||||
// Below are utility functions for dealing with various bits for data conversion and wrangling
|
||||
|
||||
/**
|
||||
* \brief Calculates the key ID for a given public ECC P256 key.
|
||||
*
|
||||
* Uses method 1 for calculating the keyIdentifier as specified by RFC 5280, section 4.2.1.2:
|
||||
* (1) The keyIdentifier is composed of the 160-bit SHA-1 hash of the
|
||||
* value of the BIT STRING subjectPublicKey (excluding the tag,
|
||||
* length, and number of unused bits).
|
||||
*
|
||||
* \param[in] public_key ECC P256 public key to calculate key key ID for. Formatted as the X and
|
||||
* Y integers concatenated together. 64 bytes.
|
||||
* \param[in] key_id Calculated key ID will be returned in this buffer. 20 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_get_key_id(const uint8_t public_key[64], uint8_t key_id[20]);
|
||||
|
||||
/**
|
||||
* \brief Merge a new device location into a list of device locations. If the new location overlaps
|
||||
* with an existing location, the existing one will be modified to encompass both. Otherwise
|
||||
* the new location is appended to the end of the list.
|
||||
*
|
||||
* The block_size parameter will adjust all added device locations to have an offset and count that
|
||||
* aligns with that block size. This allows one to generate a list of device locations that matches
|
||||
* specific read/write semantics (e.g. 4 byte or 32 byte reads). Note that this block_size only
|
||||
* applies to the device_loc being added. Existing device locations in the list won't be modified
|
||||
* to match the block size.
|
||||
*
|
||||
* \param[inout] device_locs Existing device location list to merge the new device
|
||||
* location into.
|
||||
* \param[inout] device_locs_count As input, the existing number of items in the device_locs
|
||||
* list. As output, the new size of the device_locs list.
|
||||
* \param[in] device_locs_max_count Maximum number of items the device_locs list can hold.
|
||||
* \param[in] device_loc New device location to be merged into the device_locs list.
|
||||
* \param[in] block_size Block size to align all offsets and counts to when adding
|
||||
* device location.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_merge_device_loc(atcacert_device_loc_t* device_locs,
|
||||
size_t* device_locs_count,
|
||||
size_t device_locs_max_count,
|
||||
const atcacert_device_loc_t* device_loc,
|
||||
size_t block_size);
|
||||
|
||||
/** \brief Determines if the two device locations overlap.
|
||||
* \param[in] device_loc1 First device location to check.
|
||||
* \param[in] device_loc2 Second device location o check.
|
||||
* \return 0 (false) if they don't overlap, non-zero if the do overlap.
|
||||
*/
|
||||
int atcacert_is_device_loc_overlap(const atcacert_device_loc_t* device_loc1,
|
||||
const atcacert_device_loc_t* device_loc2);
|
||||
|
||||
/**
|
||||
* \brief Takes a raw P256 ECC public key and converts it to the padded version used by ATECC
|
||||
* devices. Input and output buffers can point to the same location to do an in-place
|
||||
* transform.
|
||||
*
|
||||
* \param[in] raw_key Public key as X and Y integers concatenated together. 64 bytes.
|
||||
* \param[out] padded_key Padded key is returned in this buffer. X and Y integers are padded
|
||||
* with 4 bytes of 0 in the MSB. 72 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
void atcacert_public_key_add_padding(const uint8_t raw_key[64], uint8_t padded_key[72]);
|
||||
|
||||
/**
|
||||
* \brief Takes a padded public key used by ATECC devices and converts it to a raw P256 ECC public
|
||||
* key. Input and output buffers can point to the same location to do an in-place transform.
|
||||
*
|
||||
* \param[out] padded_key X and Y integers are padded with 4 bytes of 0 in the MSB. 72 bytes.
|
||||
* \param[in] raw_key Raw key is returned in this buffer. Public key as X and Y integers
|
||||
* concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
void atcacert_public_key_remove_padding(const uint8_t padded_key[72], uint8_t raw_key[64]);
|
||||
|
||||
/**
|
||||
* \brief Apply the specified transform to the specified data.
|
||||
*
|
||||
* \param[in] transform Transform to be performed.
|
||||
* \param[in] data Input data to be transformed.
|
||||
* \param[in] data_size Size of the input data in bytes.
|
||||
* \param[out] destination Destination buffer to hold the transformed data.
|
||||
* \param[inout] destination_size As input, the size of the destination buffer.
|
||||
* As output the size of the transformed data.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_transform_data(atcacert_transform_t transform,
|
||||
const uint8_t* data,
|
||||
size_t data_size,
|
||||
uint8_t* destination,
|
||||
size_t* destination_size);
|
||||
|
||||
/** \brief Return the maximum possible certificate size in bytes for a given
|
||||
* cert def. Certificate can be variable size, so this gives an
|
||||
* appropriate buffer size when reading the certificates.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition to find a max size for.
|
||||
* \param[out] max_cert_size Maximum certificate size will be returned here in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_max_cert_size(const atcacert_def_t* cert_def,
|
||||
size_t* max_cert_size);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,562 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief functions required to work with DER encoded data related to X.509 certificates.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "atcacert_der.h"
|
||||
#include <string.h>
|
||||
|
||||
int atcacert_der_enc_length(uint32_t length, uint8_t* der_length, size_t* der_length_size)
|
||||
{
|
||||
size_t der_length_size_calc = 0;
|
||||
int exp = sizeof(length) - 1;
|
||||
|
||||
if (der_length_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (length < 0x80)
|
||||
{
|
||||
// The length can take the short form with only one byte
|
||||
der_length_size_calc = 1;
|
||||
exp = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Length is long-form, encoded as a multi-byte big-endian unsigned integer
|
||||
|
||||
// Find first non-zero octet
|
||||
while (length / ((uint32_t)1 << (8 * exp)) == 0)
|
||||
{
|
||||
exp--;
|
||||
}
|
||||
|
||||
der_length_size_calc = 2 + exp;
|
||||
}
|
||||
|
||||
if (der_length != NULL && *der_length_size < der_length_size_calc)
|
||||
{
|
||||
*der_length_size = der_length_size_calc;
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*der_length_size = der_length_size_calc;
|
||||
|
||||
if (der_length == NULL)
|
||||
{
|
||||
return ATCACERT_E_SUCCESS; // Caller is only requesting the size
|
||||
|
||||
}
|
||||
// Encode length in big-endian format
|
||||
for (; exp >= 0; exp--)
|
||||
{
|
||||
der_length[der_length_size_calc - 1 - exp] = (uint8_t)((length >> (exp * 8)) & 0xFF);
|
||||
}
|
||||
|
||||
if (der_length_size_calc > 1)
|
||||
{
|
||||
der_length[0] = 0x80 | (uint8_t)(der_length_size_calc - 1); // Set number of bytes octet with long-form flag
|
||||
|
||||
}
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_der_dec_length(const uint8_t* der_length, size_t* der_length_size, uint32_t* length)
|
||||
{
|
||||
if (der_length == NULL || der_length_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (*der_length_size < 1)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR;
|
||||
}
|
||||
|
||||
if (der_length[0] & 0x80)
|
||||
{
|
||||
// Long form
|
||||
size_t num_bytes = der_length[0] & 0x7F;
|
||||
size_t i;
|
||||
if (*der_length_size < num_bytes + 1)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Invalid DER length format, not enough data.
|
||||
}
|
||||
if (num_bytes == 0)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Invalid DER length format, indefinite length not supported.
|
||||
}
|
||||
if (num_bytes > sizeof(*length))
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Can't parse DER length format, larger than length.
|
||||
|
||||
}
|
||||
if (length != NULL)
|
||||
{
|
||||
// Decode integer in big-endian format
|
||||
*length = 0;
|
||||
for (i = 1; i <= num_bytes; i++)
|
||||
{
|
||||
*length += der_length[i] * ((uint32_t)1 << (8 * (num_bytes - i)));
|
||||
}
|
||||
}
|
||||
*der_length_size = num_bytes + 1; // Return the actual number of bytes the DER length encoding used.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (length != NULL)
|
||||
{
|
||||
*length = der_length[0];
|
||||
}
|
||||
*der_length_size = 1; // Return the actual number of bytes the DER length encoding used.
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_der_adjust_length(uint8_t* der_length, size_t* der_length_size, int delta_length, uint32_t* new_length)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t new_der_len_size = 0;
|
||||
uint32_t old_len = 0;
|
||||
uint32_t new_len = 0;
|
||||
uint8_t new_der_length[5];
|
||||
|
||||
ret = atcacert_der_dec_length(der_length, der_length_size, &old_len);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (delta_length < 0 && (size_t)(-delta_length) > old_len)
|
||||
{
|
||||
return ATCACERT_E_ERROR;
|
||||
}
|
||||
new_len = old_len + delta_length;
|
||||
|
||||
if (new_length != NULL)
|
||||
{
|
||||
*new_length = new_len;
|
||||
}
|
||||
|
||||
new_der_len_size = sizeof(new_der_length);
|
||||
ret = atcacert_der_enc_length(new_len, new_der_length, &new_der_len_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (*der_length_size != new_der_len_size)
|
||||
{
|
||||
return ATCACERT_E_BAD_CERT;
|
||||
}
|
||||
|
||||
memcpy(der_length, new_der_length, new_der_len_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int atcacert_der_enc_integer(const uint8_t* int_data,
|
||||
size_t int_data_size,
|
||||
uint8_t is_unsigned,
|
||||
uint8_t* der_int,
|
||||
size_t* der_int_size)
|
||||
{
|
||||
uint8_t der_length[5];
|
||||
size_t der_length_size = sizeof(der_length);
|
||||
size_t der_int_size_calc = 0;
|
||||
size_t trim = 0;
|
||||
size_t pad = 0;
|
||||
int ret;
|
||||
|
||||
if (int_data == NULL || der_int_size == NULL || int_data_size <= 0)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (!(is_unsigned && (int_data[0] & 0x80)))
|
||||
{
|
||||
// This is not an unsigned value that needs a padding byte, trim any unnecessary bytes.
|
||||
// Trim a byte when the upper 9 bits are all 0s or all 1s.
|
||||
while (
|
||||
(int_data_size - trim >= 2) && (
|
||||
((int_data[trim] == 0x00) && ((int_data[trim + 1] & 0x80) == 0)) ||
|
||||
((int_data[trim] == 0xFF) && ((int_data[trim + 1] & 0x80) != 0))))
|
||||
{
|
||||
trim++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Will be adding extra byte for unsigned padding so it's not interpreted as negative
|
||||
pad = 1;
|
||||
}
|
||||
|
||||
ret = atcacert_der_enc_length((uint32_t)(int_data_size + pad - trim), der_length, &der_length_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
der_int_size_calc = 1 + der_length_size + int_data_size + pad - trim;
|
||||
|
||||
if (der_int != NULL && der_int_size_calc > *der_int_size)
|
||||
{
|
||||
*der_int_size = der_int_size_calc;
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*der_int_size = der_int_size_calc;
|
||||
|
||||
if (der_int == NULL)
|
||||
{
|
||||
return ATCACERT_E_SUCCESS; // Caller just wanted the size of the encoded integer
|
||||
|
||||
}
|
||||
der_int[0] = 0x02; // Integer tag
|
||||
memcpy(&der_int[1], der_length, der_length_size); // Integer length
|
||||
if (pad)
|
||||
{
|
||||
der_int[der_length_size + 1] = 0; // Unsigned integer value requires padding byte so it's not interpreted as negative
|
||||
}
|
||||
memcpy(&der_int[der_length_size + 1 + pad], &int_data[trim], int_data_size - trim); // Integer value
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_der_dec_integer(const uint8_t* der_int,
|
||||
size_t* der_int_size,
|
||||
uint8_t* int_data,
|
||||
size_t* int_data_size)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t der_length_size = 0;
|
||||
uint32_t int_data_size_calc = 0;
|
||||
|
||||
if (der_int == NULL || der_int_size == NULL || (int_data != NULL && int_data_size == NULL))
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (*der_int_size < 1)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data to decode
|
||||
|
||||
}
|
||||
if (der_int[0] != 0x02)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Not an integer tag
|
||||
|
||||
}
|
||||
der_length_size = *der_int_size - 1;
|
||||
ret = atcacert_der_dec_length(&der_int[1], &der_length_size, &int_data_size_calc);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (*der_int_size < (1 + der_length_size + int_data_size_calc))
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Invalid DER integer, not enough data.
|
||||
|
||||
}
|
||||
*der_int_size = (1 + der_length_size + int_data_size_calc);
|
||||
|
||||
if (int_data == NULL && int_data_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_SUCCESS; // Caller doesn't want the actual data, just the der_int_size
|
||||
|
||||
}
|
||||
if (int_data != NULL && *int_data_size < int_data_size_calc)
|
||||
{
|
||||
*int_data_size = int_data_size_calc;
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*int_data_size = int_data_size_calc;
|
||||
|
||||
if (int_data == NULL)
|
||||
{
|
||||
return ATCACERT_E_SUCCESS; // Caller doesn't want the actual data, just the int_data_size
|
||||
|
||||
}
|
||||
memcpy(int_data, &der_int[1 + der_length_size], int_data_size_calc);
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_der_enc_ecdsa_sig_value(const uint8_t raw_sig[64],
|
||||
uint8_t* der_sig,
|
||||
size_t* der_sig_size)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t r_size = 0;
|
||||
size_t s_size = 0;
|
||||
size_t der_sig_size_calc = 0;
|
||||
|
||||
if (raw_sig == NULL || der_sig_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
// Find size of the DER encoded R integer
|
||||
ret = atcacert_der_enc_integer(&raw_sig[0], 32, TRUE, NULL, &r_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Find size of the DER encoded S integer
|
||||
ret = atcacert_der_enc_integer(&raw_sig[32], 32, TRUE, NULL, &s_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This calculation assumes all DER lengths are a single byte, which is fine for 32 byte
|
||||
// R and S integers.
|
||||
der_sig_size_calc = 5 + r_size + s_size;
|
||||
|
||||
if (der_sig != NULL && *der_sig_size < der_sig_size_calc)
|
||||
{
|
||||
*der_sig_size = der_sig_size_calc;
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
*der_sig_size = der_sig_size_calc;
|
||||
|
||||
if (der_sig == NULL)
|
||||
{
|
||||
return ATCACERT_E_SUCCESS; // Caller just wanted the encoded size
|
||||
|
||||
}
|
||||
der_sig[0] = 0x03; // signatureValue bit string tag
|
||||
der_sig[1] = (uint8_t)(der_sig_size_calc - 2); // signatureValue bit string length
|
||||
der_sig[2] = 0x00; // signatureValue bit string spare bits
|
||||
|
||||
// signatureValue bit string value is the DER encoding of ECDSA-Sig-Value
|
||||
der_sig[3] = 0x30; // sequence tag
|
||||
der_sig[4] = (uint8_t)(der_sig_size_calc - 5); // sequence length
|
||||
|
||||
// Add R integer
|
||||
ret = atcacert_der_enc_integer(&raw_sig[0], 32, TRUE, &der_sig[5], &r_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Add S integer
|
||||
ret = atcacert_der_enc_integer(&raw_sig[32], 32, TRUE, &der_sig[5 + r_size], &s_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_der_dec_ecdsa_sig_value(const uint8_t* der_sig,
|
||||
size_t* der_sig_size,
|
||||
uint8_t raw_sig[64])
|
||||
{
|
||||
int ret = 0;
|
||||
size_t curr_idx = 0;
|
||||
size_t dec_size = 0;
|
||||
uint32_t bs_length = 0;
|
||||
uint32_t seq_length = 0;
|
||||
size_t r_size = 0;
|
||||
size_t s_size = 0;
|
||||
uint8_t int_data[33];
|
||||
size_t int_data_size = 0;
|
||||
|
||||
if (der_sig == NULL || der_sig_size == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
if (*der_sig_size < 1)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data to decode
|
||||
|
||||
}
|
||||
// signatureValue bit string tag
|
||||
curr_idx = 0;
|
||||
if (der_sig[curr_idx] != 0x03)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Unexpected tag value
|
||||
}
|
||||
curr_idx++;
|
||||
|
||||
// signatureValue bit string length
|
||||
dec_size = *der_sig_size - curr_idx;
|
||||
ret = atcacert_der_dec_length(&der_sig[curr_idx], &dec_size, &bs_length);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret; // Failed to decode length
|
||||
}
|
||||
curr_idx += dec_size;
|
||||
if (curr_idx + bs_length > *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Not enough data in buffer to decode the rest
|
||||
|
||||
}
|
||||
// signatureValue bit string spare bits
|
||||
if (curr_idx >= *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data left
|
||||
}
|
||||
if (der_sig[curr_idx] != 0x00)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Unexpected spare bits value
|
||||
}
|
||||
curr_idx++;
|
||||
|
||||
// signatureValue bit string value is the DER encoding of ECDSA-Sig-Value
|
||||
|
||||
// sequence tag
|
||||
if (curr_idx >= *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data left
|
||||
}
|
||||
if (der_sig[curr_idx] != 0x30)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Unexpected tag value
|
||||
}
|
||||
curr_idx++;
|
||||
|
||||
// sequence length
|
||||
if (curr_idx >= *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data left
|
||||
}
|
||||
dec_size = *der_sig_size - curr_idx;
|
||||
ret = atcacert_der_dec_length(&der_sig[curr_idx], &dec_size, &seq_length);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret; // Failed to decode length
|
||||
}
|
||||
curr_idx += dec_size;
|
||||
if (curr_idx + seq_length > *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Not enough data in buffer to decode the rest
|
||||
|
||||
}
|
||||
// R integer
|
||||
if (curr_idx >= *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data left
|
||||
}
|
||||
r_size = *der_sig_size - curr_idx;
|
||||
int_data_size = sizeof(int_data);
|
||||
ret = atcacert_der_dec_integer(&der_sig[curr_idx], &r_size, int_data, &int_data_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret; // Failed to decode length
|
||||
}
|
||||
curr_idx += r_size;
|
||||
|
||||
if (raw_sig != NULL)
|
||||
{
|
||||
memset(raw_sig, 0, 64); // Zero out the raw sig as the decoded integers may not touch all bytes
|
||||
|
||||
}
|
||||
if (int_data_size <= 32)
|
||||
{
|
||||
if (raw_sig != NULL)
|
||||
{
|
||||
memcpy(&raw_sig[32 - int_data_size], &int_data[0], int_data_size);
|
||||
}
|
||||
}
|
||||
else if (int_data_size == 33)
|
||||
{
|
||||
if (int_data[0] != 0x00)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // R integer is too large
|
||||
}
|
||||
// DER integer was 0-padded to keep it positive
|
||||
if (raw_sig != NULL)
|
||||
{
|
||||
memcpy(&raw_sig[0], &int_data[1], 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // R integer is too large
|
||||
|
||||
}
|
||||
// S integer
|
||||
if (curr_idx >= *der_sig_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // No data left
|
||||
}
|
||||
s_size = *der_sig_size - curr_idx;
|
||||
int_data_size = sizeof(int_data);
|
||||
ret = atcacert_der_dec_integer(&der_sig[curr_idx], &s_size, int_data, &int_data_size);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret; // Failed to decode length
|
||||
}
|
||||
curr_idx += s_size;
|
||||
|
||||
if (int_data_size <= 32)
|
||||
{
|
||||
if (raw_sig != NULL)
|
||||
{
|
||||
memcpy(&raw_sig[64 - int_data_size], &int_data[0], int_data_size);
|
||||
}
|
||||
}
|
||||
else if (int_data_size == 33)
|
||||
{
|
||||
if (int_data[0] != 0x00)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // S integer is too large
|
||||
}
|
||||
// DER integer was 0-padded to keep it positive
|
||||
if (raw_sig != NULL)
|
||||
{
|
||||
memcpy(&raw_sig[32], &int_data[1], 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // S integer is too large
|
||||
|
||||
}
|
||||
if (seq_length != r_size + s_size)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Unexpected extra data in sequence
|
||||
|
||||
}
|
||||
if (bs_length != r_size + s_size + 3)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Unexpected extra data in bit string
|
||||
|
||||
}
|
||||
*der_sig_size = curr_idx;
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief function declarations required to work with DER encoded data related to X.509 certificates.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ATCACERT_DER_H
|
||||
#define ATCACERT_DER_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "atcacert.h"
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* \brief Encode a length in DER format.
|
||||
*
|
||||
* X.690 (http://www.itu.int/rec/T-REC-X.690/en) section 8.1.3, for encoding
|
||||
*
|
||||
* \param[in] length Length to be encoded.
|
||||
* \param[out] der_length DER encoded length will returned in this buffer.
|
||||
* \param[inout] der_length_size As input, size of der_length buffer in bytes.
|
||||
* As output, the size of the DER length encoding in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_enc_length(uint32_t length, uint8_t* der_length, size_t* der_length_size);
|
||||
|
||||
/**
|
||||
* \brief Decode a DER format length.
|
||||
*
|
||||
* X.690 (http://www.itu.int/rec/T-REC-X.690/en) section 8.1.3, for encoding
|
||||
*
|
||||
* \param[in] der_length DER encoded length.
|
||||
* \param[inout] der_length_size As input, the size of the der_length buffer in bytes.
|
||||
* As output, the size of the DER encoded length that was decoded.
|
||||
* \param[out] length Decoded length is returned here.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_dec_length(const uint8_t* der_length, size_t* der_length_size, uint32_t* length);
|
||||
|
||||
int atcacert_der_adjust_length(uint8_t* der_length, size_t* der_length_size, int delta_length, uint32_t* new_length);
|
||||
|
||||
/**
|
||||
* \brief Encode an ASN.1 integer in DER format, including tag and length fields.
|
||||
*
|
||||
* X.680 (http://www.itu.int/rec/T-REC-X.680/en) section 19.8, for tag value
|
||||
* X.690 (http://www.itu.int/rec/T-REC-X.690/en) section 8.3, for encoding
|
||||
*
|
||||
* \param[in] int_data Raw integer in big-endian format.
|
||||
* \param[in] int_data_size Size of the raw integer in bytes.
|
||||
* \param[in] is_unsigned Indicate whether the input integer should be treated as unsigned.
|
||||
* \param[out] der_int DER encoded integer is returned in this buffer.
|
||||
* \param[inout] der_int_size As input, the size of the der_int buffer in bytes.
|
||||
* As output, the size of the DER integer returned in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_enc_integer(const uint8_t* int_data,
|
||||
size_t int_data_size,
|
||||
uint8_t is_unsigned,
|
||||
uint8_t* der_int,
|
||||
size_t* der_int_size);
|
||||
|
||||
/**
|
||||
* \brief Decode an ASN.1 DER encoded integer.
|
||||
*
|
||||
* X.680 (http://www.itu.int/rec/T-REC-X.680/en) section 19.8, for tag value
|
||||
* X.690 (http://www.itu.int/rec/T-REC-X.690/en) section 8.3, for encoding
|
||||
*
|
||||
* \param[in] der_int DER encoded ASN.1 integer, including the tag and length fields.
|
||||
* \param[inout] der_int_size As input, the size of the der_int buffer in bytes.
|
||||
* As output, the size of the DER integer decoded in bytes.
|
||||
* \param[out] int_data Decode integer is returned in this buffer in a signed big-endian
|
||||
* format.
|
||||
* \param[inout] int_data_size As input, the size of int_data in bytes.
|
||||
* As output, the size of the decoded integer in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_dec_integer(const uint8_t* der_int,
|
||||
size_t* der_int_size,
|
||||
uint8_t* int_data,
|
||||
size_t* int_data_size);
|
||||
|
||||
/**
|
||||
* \brief Formats a raw ECDSA P256 signature in the DER encoding found in X.509 certificates.
|
||||
*
|
||||
* This will return the DER encoding of the signatureValue field as found in an X.509 certificate
|
||||
* (RFC 5280). This include the tag, length, and value. The value of the signatureValue is the DER
|
||||
* encoding of the ECDSA-Sig-Value as specified by RFC 5480 and SECG SEC1.
|
||||
*
|
||||
* \param[in] raw_sig P256 ECDSA signature to be formatted. Input format is R and S
|
||||
* integers concatenated together. 64 bytes.
|
||||
* \param[out] der_sig X.509 format signature (TLV of signatureValue) will be returned in
|
||||
* this buffer.
|
||||
* \param[inout] der_sig_size As input, the size of the x509_sig buffer in bytes.
|
||||
* As output, the size of the returned X.509 signature in bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_enc_ecdsa_sig_value(const uint8_t raw_sig[64],
|
||||
uint8_t* der_sig,
|
||||
size_t* der_sig_size);
|
||||
|
||||
/**
|
||||
* \brief Parses an ECDSA P256 signature in the DER encoding as found in X.509 certificates.
|
||||
*
|
||||
* This will parse the DER encoding of the signatureValue field as found in an X.509 certificate
|
||||
* (RFC 5280). x509_sig should include the tag, length, and value. The value of the signatureValue
|
||||
* is the DER encoding of the ECDSA-Sig-Value as specified by RFC 5480 and SECG SEC1.
|
||||
*
|
||||
* \param[in] der_sig X.509 format signature (TLV of signatureValue) to be parsed.
|
||||
* \param[inout] der_sig_size As input, size of the der_sig buffer in bytes.
|
||||
* As output, size of the DER x.509 signature parsed from the buffer.
|
||||
* \param[out] raw_sig Parsed P256 ECDSA signature will be returned in this buffer.
|
||||
* Formatted as R and S integers concatenated together. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_der_dec_ecdsa_sig_value(const uint8_t * der_sig,
|
||||
size_t * der_sig_size,
|
||||
uint8_t raw_sig[64]);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief host side methods using CryptoAuth hardware
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert_host_hw.h"
|
||||
#include "basic/atca_basic.h"
|
||||
#include "crypto/atca_crypto_sw_sha2.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int atcacert_verify_cert_hw(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t ca_public_key[64])
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t tbs_digest[32];
|
||||
uint8_t signature[64];
|
||||
bool is_verified = false;
|
||||
|
||||
if (cert_def == NULL || ca_public_key == NULL || cert == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcacert_get_tbs_digest(cert_def, cert, cert_size, tbs_digest);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcacert_get_signature(cert_def, cert, cert_size, signature);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcab_verify_extern(tbs_digest, signature, ca_public_key, &is_verified);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return is_verified ? ATCACERT_E_SUCCESS : ATCACERT_E_VERIFY_FAILED;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int atcacert_gen_challenge_hw(uint8_t challenge[32])
|
||||
{
|
||||
if (challenge == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
return atcab_random(challenge);
|
||||
}
|
||||
|
||||
|
||||
int atcacert_verify_response_hw(const uint8_t device_public_key[64],
|
||||
const uint8_t challenge[32],
|
||||
const uint8_t response[64])
|
||||
{
|
||||
int ret = 0;
|
||||
bool is_verified = false;
|
||||
|
||||
if (device_public_key == NULL || challenge == NULL || response == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcab_verify_extern(challenge, response, device_public_key, &is_verified);
|
||||
if (ret != ATCA_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return is_verified ? ATCACERT_E_SUCCESS : ATCACERT_E_VERIFY_FAILED;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief host side methods using CryptoAuth hardware
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef ATCACERT_HOST_HA_H
|
||||
#define ATCACERT_HOST_HA_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "atcacert_def.h"
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* \brief Verify a certificate against its certificate authority's public key using the host's ATECC
|
||||
* device for crypto functions.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition describing how to extract the TBS and signature
|
||||
* components from the certificate specified.
|
||||
* \param[in] cert Certificate to verify.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] ca_public_key The ECC P256 public key of the certificate authority that signed this
|
||||
* certificate. Formatted as the 32 byte X and Y integers concatenated
|
||||
* together (64 bytes total).
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS if the verify succeeds, ATCACERT_VERIFY_FAILED or ATCA_EXECUTION_ERROR if it fails to
|
||||
* verify. ATCA_EXECUTION_ERROR may occur when the public key is invalid and doesn't fall
|
||||
* on the P256 curve.
|
||||
*/
|
||||
int atcacert_verify_cert_hw(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t ca_public_key[64]);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Generate a random challenge to be sent to the client using the RNG on the host's ATECC
|
||||
* device.
|
||||
*
|
||||
* \param[out] challenge Random challenge is return here. 32 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_gen_challenge_hw(uint8_t challenge[32]);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Verify a client's response to a challenge using the host's ATECC device for crypto
|
||||
* functions.
|
||||
*
|
||||
* The challenge-response protocol is an ECDSA Sign and Verify. This performs an ECDSA verify on the
|
||||
* response returned by the client, verifying the client has the private key counter-part to the
|
||||
* public key returned in its certificate.
|
||||
*
|
||||
* \param[in] device_public_key Device public key as read from its certificate. Formatted as the X
|
||||
* and Y integers concatenated together. 64 bytes.
|
||||
* \param[in] challenge Challenge that was sent to the client. 32 bytes.
|
||||
* \param[in] response Response returned from the client to be verified. 64 bytes.
|
||||
*
|
||||
* \return ATCACERT_E_SUCCESS if the verify succeeds, ATCACERT_VERIFY_FAILED or ATCA_EXECUTION_ERROR if it fails to
|
||||
* verify. ATCA_EXECUTION_ERROR may occur when the public key is invalid and doesn't fall
|
||||
* on the P256 curve.
|
||||
*/
|
||||
int atcacert_verify_response_hw(const uint8_t device_public_key[64],
|
||||
const uint8_t challenge[32],
|
||||
const uint8_t response[64]);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief host side methods using software implementations
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atcacert_host_sw.h"
|
||||
#include "crypto/atca_crypto_sw_sha2.h"
|
||||
#include "crypto/atca_crypto_sw_ecdsa.h"
|
||||
#include "crypto/atca_crypto_sw_rand.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int atcacert_verify_cert_sw(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t ca_public_key[64])
|
||||
{
|
||||
int ret = 0;
|
||||
uint8_t tbs_digest[32];
|
||||
uint8_t signature[64];
|
||||
|
||||
if (cert_def == NULL || ca_public_key == NULL || cert == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
ret = atcacert_get_tbs_digest(cert_def, cert, cert_size, tbs_digest);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcacert_get_signature(cert_def, cert, cert_size, signature);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = atcac_sw_ecdsa_verify_p256(tbs_digest, signature, ca_public_key);
|
||||
if (ret != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int atcacert_gen_challenge_sw(uint8_t challenge[32])
|
||||
{
|
||||
if (challenge == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
return atcac_sw_random(challenge, 32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int atcacert_verify_response_sw(const uint8_t device_public_key[64],
|
||||
const uint8_t challenge[32],
|
||||
const uint8_t response[64])
|
||||
{
|
||||
if (device_public_key == NULL || challenge == NULL || response == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
return atcac_sw_ecdsa_verify_p256(challenge, response, device_public_key);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Host side methods using software implementations. host-side, the one authenticating
|
||||
* a client, of the authentication process. Crypto functions are performed using a software library.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCACERT_HOST_SOFT_H
|
||||
#define ATCACERT_HOST_SOFT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "atcacert_def.h"
|
||||
|
||||
// Inform function naming when compiling in C++
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup atcacert_ Certificate manipulation methods (atcacert_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide convenient ways to perform certification I/O with
|
||||
* CryptoAuth chips and perform certificate manipulation in memory
|
||||
*
|
||||
@{ */
|
||||
|
||||
/**
|
||||
* \brief Verify a certificate against its certificate authority's public key using software crypto
|
||||
* functions.The function is currently not implemented.
|
||||
*
|
||||
* \param[in] cert_def Certificate definition describing how to extract the TBS and signature
|
||||
* components from the certificate specified.
|
||||
* \param[in] cert Certificate to verify.
|
||||
* \param[in] cert_size Size of the certificate (cert) in bytes.
|
||||
* \param[in] ca_public_key The ECC P256 public key of the certificate authority that signed this
|
||||
* certificate. Formatted as the 32 byte X and Y integers concatenated
|
||||
* together (64 bytes total).
|
||||
*
|
||||
* \return ATCA_UNIMPLEMENTED , as the function is currently not implemented.
|
||||
*/
|
||||
int atcacert_verify_cert_sw(const atcacert_def_t* cert_def,
|
||||
const uint8_t* cert,
|
||||
size_t cert_size,
|
||||
const uint8_t ca_public_key[64]);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Generate a random challenge to be sent to the client using a software PRNG.The function is currently not implemented.
|
||||
*
|
||||
* \param[out] challenge Random challenge is return here. 32 bytes.
|
||||
*
|
||||
* \return ATCA_UNIMPLEMENTED , as the function is currently not implemented.
|
||||
*/
|
||||
int atcacert_gen_challenge_sw(uint8_t challenge[32]);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief Verify a client's response to a challenge using software crypto functions.The function is currently not implemented.
|
||||
*
|
||||
* The challenge-response protocol is an ECDSA Sign and Verify. This performs an ECDSA verify on the
|
||||
* response returned by the client, verifying the client has the private key counter-part to the
|
||||
* public key returned in its certificate.
|
||||
*
|
||||
* \param[in] device_public_key Device public key as read from its certificate. Formatted as the X
|
||||
* and Y integers concatenated together. 64 bytes.
|
||||
* \param[in] challenge Challenge that was sent to the client. 32 bytes.
|
||||
* \param[in] response Response returned from the client to be verified. 64 bytes.
|
||||
*
|
||||
* \return ATCA_UNIMPLEMENTED , as the function is currently not implemented.
|
||||
*/
|
||||
int atcacert_verify_response_sw(const uint8_t device_public_key[64],
|
||||
const uint8_t challenge[32],
|
||||
const uint8_t response[64]);
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,165 @@
|
||||
#include "atcacert.h"
|
||||
#include "atcacert_pem.h"
|
||||
#include "../basic/atca_helpers.h"
|
||||
|
||||
int atcacert_encode_pem(const uint8_t* der,
|
||||
size_t der_size,
|
||||
char* pem,
|
||||
size_t* pem_size,
|
||||
const char* header,
|
||||
const char* footer)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
size_t max_pem_size;
|
||||
size_t header_size;
|
||||
size_t footer_size;
|
||||
size_t b64_size;
|
||||
size_t pem_index = 0;
|
||||
|
||||
if (der == NULL || pem == NULL || pem_size == NULL || header == NULL || footer == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
max_pem_size = *pem_size;
|
||||
*pem_size = 0; // Default to 0
|
||||
|
||||
// Add header
|
||||
header_size = strlen(header);
|
||||
if (pem_index + header_size + 2 > max_pem_size)
|
||||
{
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
memcpy(&pem[pem_index], header, header_size);
|
||||
pem_index += header_size;
|
||||
memcpy(&pem[pem_index], "\r\n", 2);
|
||||
pem_index += 2;
|
||||
|
||||
// Add base64 encoded DER data with \r\n every 64 characters
|
||||
b64_size = max_pem_size - pem_index;
|
||||
status = atcab_base64encode(der, der_size, &pem[pem_index], &b64_size);
|
||||
if (status != ATCACERT_E_SUCCESS)
|
||||
{
|
||||
if (status == ATCA_SMALL_BUFFER)
|
||||
{
|
||||
status = ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
pem_index += b64_size;
|
||||
|
||||
// Add \r\n after data
|
||||
footer_size = strlen(footer);
|
||||
if (pem_index + 2 + footer_size + 2 + 1 > max_pem_size)
|
||||
{
|
||||
return ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
memcpy(&pem[pem_index], "\r\n", 2);
|
||||
pem_index += 2;
|
||||
|
||||
// Add footer
|
||||
memcpy(&pem[pem_index], footer, footer_size);
|
||||
pem_index += footer_size;
|
||||
memcpy(&pem[pem_index], "\r\n", 2);
|
||||
pem_index += 2;
|
||||
|
||||
pem[pem_index] = 0; // Terminating null, not included in size
|
||||
|
||||
// Set output size
|
||||
*pem_size = pem_index;
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_decode_pem(const char* pem,
|
||||
size_t pem_size,
|
||||
uint8_t* der,
|
||||
size_t* der_size,
|
||||
const char* header,
|
||||
const char* footer)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
const char* header_pos = NULL;
|
||||
const char* data_pos = NULL;
|
||||
const char* footer_pos = NULL;
|
||||
|
||||
if (pem == NULL || der == NULL || der_size == NULL || header == NULL || footer == NULL)
|
||||
{
|
||||
return ATCACERT_E_BAD_PARAMS;
|
||||
}
|
||||
|
||||
// Find the position of the header
|
||||
header_pos = strstr(pem, header);
|
||||
if (header_pos == NULL)
|
||||
{
|
||||
return ATCACERT_E_DECODING_ERROR; // Couldn't find header
|
||||
}
|
||||
|
||||
// Data should be right after the header. Not accounting for new lines as
|
||||
// the base64 decode should skip over those.
|
||||
data_pos = header_pos + strlen(header);
|
||||
|
||||
// Find footer
|
||||
footer_pos = strstr(pem, footer);
|
||||
if (footer_pos == NULL || footer_pos < data_pos)
|
||||
{
|
||||
// Couldn't find footer or found it before the data
|
||||
return ATCACERT_E_DECODING_ERROR;
|
||||
}
|
||||
|
||||
// Decode data
|
||||
status = atcab_base64decode(data_pos, footer_pos - data_pos, der, der_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
if (status == ATCA_SMALL_BUFFER)
|
||||
{
|
||||
status = ATCACERT_E_BUFFER_TOO_SMALL;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCACERT_E_SUCCESS;
|
||||
}
|
||||
|
||||
int atcacert_encode_pem_cert(const uint8_t* der_cert, size_t der_cert_size, char* pem_cert, size_t* pem_cert_size)
|
||||
{
|
||||
return atcacert_encode_pem(
|
||||
der_cert,
|
||||
der_cert_size,
|
||||
pem_cert,
|
||||
pem_cert_size,
|
||||
PEM_CERT_BEGIN,
|
||||
PEM_CERT_END);
|
||||
}
|
||||
|
||||
int atcacert_encode_pem_csr(const uint8_t* der_csr, size_t der_csr_size, char* pem_csr, size_t* pem_csr_size)
|
||||
{
|
||||
return atcacert_encode_pem(
|
||||
der_csr,
|
||||
der_csr_size,
|
||||
pem_csr,
|
||||
pem_csr_size,
|
||||
PEM_CSR_BEGIN,
|
||||
PEM_CSR_END);
|
||||
}
|
||||
|
||||
int atcacert_decode_pem_cert(const char* pem_cert, size_t pem_cert_size, uint8_t* der_cert, size_t* der_cert_size)
|
||||
{
|
||||
return atcacert_decode_pem(
|
||||
pem_cert,
|
||||
pem_cert_size,
|
||||
der_cert,
|
||||
der_cert_size,
|
||||
PEM_CERT_BEGIN,
|
||||
PEM_CERT_END);
|
||||
}
|
||||
|
||||
int atcacert_decode_pem_csr(const char* pem_csr, size_t pem_csr_size, uint8_t* der_csr, size_t* der_csr_size)
|
||||
{
|
||||
return atcacert_decode_pem(
|
||||
pem_csr,
|
||||
pem_csr_size,
|
||||
der_csr,
|
||||
der_csr_size,
|
||||
PEM_CSR_BEGIN,
|
||||
PEM_CSR_END);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Functions for converting between DER and PEM formats.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef ATCACERT_PEM_H
|
||||
#define ATCACERT_PEM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define PEM_CERT_BEGIN "-----BEGIN CERTIFICATE-----"
|
||||
#define PEM_CERT_END "-----END CERTIFICATE-----"
|
||||
#define PEM_CSR_BEGIN "-----BEGIN CERTIFICATE REQUEST-----"
|
||||
#define PEM_CSR_END "-----END CERTIFICATE REQUEST-----"
|
||||
|
||||
/**
|
||||
* \brief Encode a DER data in PEM format.
|
||||
* \param[in] der DER data to be encoded as PEM.
|
||||
* \param[out] der_size DER data size in bytes.
|
||||
* \param[out] pem PEM encoded data is returned here.
|
||||
* \param[inout] pem_size As input, the size of the pem buffer.
|
||||
* As output, the size of the PEM data.
|
||||
* \param[in] header Header to place at the beginning of the PEM data.
|
||||
* \param[in] footer Footer to place at the end of the PEM data.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_encode_pem(const uint8_t* der,
|
||||
size_t der_size,
|
||||
char* pem,
|
||||
size_t* pem_size,
|
||||
const char* header,
|
||||
const char* footer);
|
||||
|
||||
/**
|
||||
* \brief Decode PEM data into DER format.
|
||||
* \param[in] pem PEM data to decode to DER.
|
||||
* \param[in] pem_size PEM data size in bytes.
|
||||
* \param[out] der DER data is returned here.
|
||||
* \param[inout] der_size As input, the size of the der buffer.
|
||||
* As output, the size of the DER data.
|
||||
* \param[in] header Header to find the beginning of the PEM data.
|
||||
* \param[in] footer Footer to find the end of the PEM data.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_decode_pem(const char* pem,
|
||||
size_t pem_size,
|
||||
uint8_t* der,
|
||||
size_t* der_size,
|
||||
const char* header,
|
||||
const char* footer);
|
||||
|
||||
/**
|
||||
* \brief Encode a DER certificate in PEM format.
|
||||
* \param[in] der_cert DER certificate to be encoded as PEM.
|
||||
* \param[out] der_cert_size DER certificate size in bytes.
|
||||
* \param[out] pem_cert PEM encoded certificate is returned here.
|
||||
* \param[inout] pem_cert_size As input, the size of the pem_cert buffer.
|
||||
* As output, the size of the PEM certificate.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_encode_pem_cert(const uint8_t* der_cert, size_t der_cert_size, char* pem_cert, size_t* pem_cert_size);
|
||||
|
||||
/**
|
||||
* \brief Decode a PEM certificate into DER format.
|
||||
* \param[in] pem_cert PEM certificate to decode to DER.
|
||||
* \param[in] pem_cert_size PEM certificate size in bytes.
|
||||
* \param[out] der_cert DER certificate is returned here.
|
||||
* \param[inout] der_cert_size As input, the size of the der_cert buffer.
|
||||
* As output, the size of the DER certificate.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_decode_pem_cert(const char* pem_cert, size_t pem_cert_size, uint8_t* der_cert, size_t* der_cert_size);
|
||||
|
||||
/**
|
||||
* \brief Encode a DER CSR in PEM format.
|
||||
* \param[in] der_csr DER CSR to be encoded as PEM.
|
||||
* \param[out] der_csr_size DER CSR size in bytes.
|
||||
* \param[out] pem_csr PEM encoded CSR is returned here.
|
||||
* \param[inout] pem_csr_size As input, the size of the pem_csr buffer.
|
||||
* As output, the size of the PEM CSR.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_encode_pem_csr(const uint8_t* der_csr, size_t der_csr_size, char* pem_csr, size_t* pem_csr_size);
|
||||
|
||||
/**
|
||||
* \brief Extract the CSR certificate bytes from a PEM encoded CSR certificate
|
||||
* \param[in] pem_csr PEM CSR to decode to DER.
|
||||
* \param[in] pem_csr_size PEM CSR size in bytes.
|
||||
* \param[out] der_csr DER CSR is returned here.
|
||||
* \param[inout] der_csr_size As input, the size of the der_csr buffer.
|
||||
* As output, the size of the DER CSR.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
int atcacert_decode_pem_csr(const char* pem_csr, size_t pem_csr_size, uint8_t* der_csr, size_t* der_csr_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
basic directory - Purpose
|
||||
=========================
|
||||
The purpose of this directory is to contain the files implementing the APIs for
|
||||
a basic interface to the core CryptoAuthLib library.
|
||||
|
||||
High-level functions like these make it very convenient to use the library when
|
||||
standard configurations and defaults are in play. They are the easiest to use
|
||||
when developing examples or trying to understand the "flow" of an
|
||||
authentication operation without getting overwhelmed by the details.
|
||||
|
||||
This makes simple jobs easy and if you need more sophistication and power, you
|
||||
can employ the full power of the CryptoAuthLib object model.
|
||||
|
||||
See the Doxygen documentation in cryptoauthlib/docs for details on the API of
|
||||
the Basic commands.
|
||||
@@ -0,0 +1,429 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods. These methods provide a simpler way
|
||||
* to access the core crypto methods.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_version.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
#if defined(_MSC_VER)
|
||||
#pragma message("Warning : Using a constant host nonce with atcab_read_enc, atcab_write_enc, etcc., can allow spoofing of a device by replaying previously recorded messages")
|
||||
#else
|
||||
#warning "Using a constant host nonce with atcab_read_enc, atcab_write_enc, etcc., can allow spoofing of a device by replaying previously recorded messages"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char atca_version[] = ATCA_LIBRARY_VERSION;
|
||||
ATCADevice _gDevice = NULL;
|
||||
#ifdef ATCA_NO_HEAP
|
||||
struct atca_command g_atcab_command;
|
||||
struct atca_iface g_atcab_iface;
|
||||
struct atca_device g_atcab_device;
|
||||
#endif
|
||||
#define MAX_BUSES 4
|
||||
|
||||
/** \brief basic API methods are all prefixed with atcab_ (CryptoAuthLib Basic)
|
||||
* the fundamental premise of the basic API is it is based on a single interface
|
||||
* instance and that instance is global, so all basic API commands assume that
|
||||
* one global device is the one to operate on.
|
||||
*/
|
||||
|
||||
/** \brief returns a version string for the CryptoAuthLib release.
|
||||
* The format of the version string returned is "yyyymmdd"
|
||||
* \param[out] ver_str ptr to space to receive version string
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_version(char *ver_str)
|
||||
{
|
||||
strcpy(ver_str, atca_version);
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Creates a global ATCADevice object used by Basic API.
|
||||
* \param[in] cfg Logical interface configuration. Some predefined
|
||||
* configurations can be found in atca_cfgs.h
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_init(ATCAIfaceCfg *cfg)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// If a device has already been initialized, release it
|
||||
if (_gDevice)
|
||||
{
|
||||
atcab_release();
|
||||
}
|
||||
|
||||
#ifdef ATCA_NO_HEAP
|
||||
g_atcab_device.mCommands = &g_atcab_command;
|
||||
g_atcab_device.mIface = &g_atcab_iface;
|
||||
status = initATCADevice(cfg, &g_atcab_device);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
_gDevice = &g_atcab_device;
|
||||
#else
|
||||
_gDevice = newATCADevice(cfg);
|
||||
if (_gDevice == NULL)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (cfg->devtype == ATECC608A)
|
||||
{
|
||||
if ((status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, ATCA_CHIPMODE_OFFSET, &_gDevice->mCommands->clock_divider, 1)) != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
_gDevice->mCommands->clock_divider &= ATCA_CHIPMODE_CLOCK_DIV_MASK;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Initialize the global ATCADevice object to point to one of your
|
||||
* choosing for use with all the atcab_ basic API.
|
||||
* \param[in] ca_device ATCADevice instance to use as the global Basic API
|
||||
* crypto device instance
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_init_device(ATCADevice ca_device)
|
||||
{
|
||||
if (ca_device == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (atGetCommands(ca_device) == NULL || atGetIFace(ca_device) == NULL)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
|
||||
// if there's already a device created, release it
|
||||
if (_gDevice)
|
||||
{
|
||||
atcab_release();
|
||||
}
|
||||
|
||||
_gDevice = ca_device;
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief release (free) the global ATCADevice instance.
|
||||
* This must be called in order to release or free up the interface.
|
||||
* \return Returns ATCA_SUCCESS .
|
||||
*/
|
||||
ATCA_STATUS atcab_release(void)
|
||||
{
|
||||
#ifdef ATCA_NO_HEAP
|
||||
ATCA_STATUS status = releaseATCADevice(_gDevice);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
_gDevice = NULL;
|
||||
#else
|
||||
deleteATCADevice(&_gDevice);
|
||||
#endif
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Get the global device object.
|
||||
* \return instance of global ATCADevice
|
||||
*/
|
||||
ATCADevice atcab_get_device(void)
|
||||
{
|
||||
return _gDevice;
|
||||
}
|
||||
|
||||
/** \brief Get the current device type.
|
||||
* \return Device type if basic api is initialized or ATCA_DEV_UNKNOWN.
|
||||
*/
|
||||
ATCADeviceType atcab_get_device_type(void)
|
||||
{
|
||||
if (_gDevice)
|
||||
{
|
||||
return _gDevice->mIface->mIfaceCFG->devtype;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_DEV_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief wakeup the CryptoAuth device
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_wakeup(void)
|
||||
{
|
||||
if (_gDevice == NULL)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
|
||||
return atwake(_gDevice->mIface);
|
||||
}
|
||||
|
||||
/** \brief idle the CryptoAuth device
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_idle(void)
|
||||
{
|
||||
if (_gDevice == NULL)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
|
||||
return atidle(_gDevice->mIface);
|
||||
}
|
||||
|
||||
/** \brief invoke sleep on the CryptoAuth device
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sleep(void)
|
||||
{
|
||||
if (_gDevice == NULL)
|
||||
{
|
||||
return ATCA_GEN_FAIL;
|
||||
}
|
||||
|
||||
return atsleep(_gDevice->mIface);
|
||||
}
|
||||
|
||||
|
||||
/** \brief auto discovery of crypto auth devices
|
||||
*
|
||||
* Calls interface discovery functions and fills in cfg_array up to the maximum
|
||||
* number of configurations either found or the size of the array. The cfg_array
|
||||
* can have a mixture of interface types (ie: some I2C, some SWI or UART) depending upon
|
||||
* which interfaces you've enabled
|
||||
*
|
||||
* \param[out] cfg_array ptr to an array of interface configs
|
||||
* \param[in] max_ifaces maximum size of cfg_array
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
|
||||
ATCA_STATUS atcab_cfg_discover(ATCAIfaceCfg cfg_array[], int max_ifaces)
|
||||
{
|
||||
int iface_num = 0;
|
||||
int found = 0;
|
||||
int i = 0;
|
||||
|
||||
// this cumulatively gathers all the interfaces enabled by #defines
|
||||
|
||||
#ifdef ATCA_HAL_I2C
|
||||
int i2c_buses[MAX_BUSES];
|
||||
memset(i2c_buses, -1, sizeof(i2c_buses));
|
||||
hal_i2c_discover_buses(i2c_buses, MAX_BUSES);
|
||||
|
||||
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
|
||||
{
|
||||
if (i2c_buses[i] != -1)
|
||||
{
|
||||
hal_i2c_discover_devices(i2c_buses[i], &cfg_array[iface_num], &found);
|
||||
iface_num += found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_HAL_SWI
|
||||
int swi_buses[MAX_BUSES];
|
||||
memset(swi_buses, -1, sizeof(swi_buses));
|
||||
hal_swi_discover_buses(swi_buses, MAX_BUSES);
|
||||
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
|
||||
{
|
||||
if (swi_buses[i] != -1)
|
||||
{
|
||||
hal_swi_discover_devices(swi_buses[i], &cfg_array[iface_num], &found);
|
||||
iface_num += found;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_HAL_UART
|
||||
int uart_buses[MAX_BUSES];
|
||||
memset(uart_buses, -1, sizeof(uart_buses));
|
||||
hal_uart_discover_buses(uart_buses, MAX_BUSES);
|
||||
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
|
||||
{
|
||||
if (uart_buses[i] != -1)
|
||||
{
|
||||
hal_uart_discover_devices(uart_buses[i], &cfg_array[iface_num], &found);
|
||||
iface_num += found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_HAL_KIT_CDC
|
||||
int cdc_buses[MAX_BUSES];
|
||||
memset(cdc_buses, -1, sizeof(cdc_buses));
|
||||
hal_kit_cdc_discover_buses(cdc_buses, MAX_BUSES);
|
||||
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
|
||||
{
|
||||
if (cdc_buses[i] != -1)
|
||||
{
|
||||
hal_kit_cdc_discover_devices(cdc_buses[i], &cfg_array[iface_num++], &found);
|
||||
iface_num += found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ATCA_HAL_KIT_HID
|
||||
int hid_buses[MAX_BUSES];
|
||||
memset(hid_buses, -1, sizeof(hid_buses));
|
||||
hal_kit_hid_discover_buses(hid_buses, MAX_BUSES);
|
||||
for (i = 0; i < MAX_BUSES && iface_num < max_ifaces; i++)
|
||||
{
|
||||
if (hid_buses[i] != -1)
|
||||
{
|
||||
hal_kit_hid_discover_devices(hid_buses[i], &cfg_array[iface_num++], &found);
|
||||
iface_num += found;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief common cleanup code which idles the device after any operation
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS _atcab_exit(void)
|
||||
{
|
||||
return atcab_idle();
|
||||
}
|
||||
|
||||
/** \brief Compute the address given the zone, slot, block, and offset
|
||||
* \param[in] zone Zone to get address from. Config(0), OTP(1), or
|
||||
* Data(2) which requires a slot.
|
||||
* \param[in] slot Slot Id number for data zone and zero for other zones.
|
||||
* \param[in] block Block number within the data or configuration or OTP zone .
|
||||
* \param[in] offset Offset Number within the block of data or configuration or OTP zone.
|
||||
* \param[out] addr Pointer to the address of data or configuration or OTP zone.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_get_addr(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, uint16_t* addr)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t mem_zone = zone & 0x03;
|
||||
|
||||
if (addr == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if ((mem_zone != ATCA_ZONE_CONFIG) && (mem_zone != ATCA_ZONE_DATA) && (mem_zone != ATCA_ZONE_OTP))
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
do
|
||||
{
|
||||
// Initialize the addr to 00
|
||||
*addr = 0;
|
||||
// Mask the offset
|
||||
offset = offset & (uint8_t)0x07;
|
||||
if ((mem_zone == ATCA_ZONE_CONFIG) || (mem_zone == ATCA_ZONE_OTP))
|
||||
{
|
||||
*addr = block << 3;
|
||||
*addr |= offset;
|
||||
}
|
||||
else // ATCA_ZONE_DATA
|
||||
{
|
||||
*addr = slot << 3;
|
||||
*addr |= offset;
|
||||
*addr |= block << 8;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Gets the size of the specified zone in bytes.
|
||||
*
|
||||
* \param[in] zone Zone to get size information from. Config(0), OTP(1), or
|
||||
* Data(2) which requires a slot.
|
||||
* \param[in] slot If zone is Data(2), the slot to query for size.
|
||||
* \param[out] size Zone size is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_get_zone_size(uint8_t zone, uint16_t slot, size_t* size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
if (size == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (_gDevice->mIface->mIfaceCFG->devtype == ATSHA204A)
|
||||
{
|
||||
switch (zone)
|
||||
{
|
||||
case ATCA_ZONE_CONFIG: *size = 88; break;
|
||||
case ATCA_ZONE_OTP: *size = 64; break;
|
||||
case ATCA_ZONE_DATA: *size = 32; break;
|
||||
default: status = ATCA_BAD_PARAM; break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (zone)
|
||||
{
|
||||
case ATCA_ZONE_CONFIG: *size = 128; break;
|
||||
case ATCA_ZONE_OTP: *size = 64; break;
|
||||
case ATCA_ZONE_DATA:
|
||||
if (slot < 8)
|
||||
{
|
||||
*size = 36;
|
||||
}
|
||||
else if (slot == 8)
|
||||
{
|
||||
*size = 416;
|
||||
}
|
||||
else if (slot < 16)
|
||||
{
|
||||
*size = 72;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
}
|
||||
break;
|
||||
default: status = ATCA_BAD_PARAM; break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,275 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods - a simple crypto authentication API.
|
||||
* These methods manage a global ATCADevice object behind the scenes. They also
|
||||
* manage the wake/idle state transitions so callers don't need to.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "cryptoauthlib.h"
|
||||
#include "crypto/atca_crypto_sw_sha2.h"
|
||||
|
||||
#ifndef ATCA_BASIC_H_
|
||||
#define ATCA_BASIC_H_
|
||||
|
||||
/** \defgroup atcab_ Basic Crypto API methods (atcab_)
|
||||
*
|
||||
* \brief
|
||||
* These methods provide the most convenient, simple API to CryptoAuth chips
|
||||
*
|
||||
@{ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLOCK_NUMBER(a) (a / 32)
|
||||
#define WORD_OFFSET(a) ((a % 32) / 4)
|
||||
|
||||
#define ATCA_AES_GCM_IV_STD_LENGTH 12
|
||||
|
||||
extern ATCADevice _gDevice;
|
||||
|
||||
// Basic global methods
|
||||
ATCA_STATUS atcab_version(char *ver_str);
|
||||
ATCA_STATUS atcab_init(ATCAIfaceCfg *cfg);
|
||||
ATCA_STATUS atcab_init_device(ATCADevice ca_device);
|
||||
ATCA_STATUS atcab_release(void);
|
||||
ATCADevice atcab_get_device(void);
|
||||
ATCADeviceType atcab_get_device_type(void);
|
||||
ATCA_STATUS _atcab_exit(void);
|
||||
ATCA_STATUS atcab_wakeup(void);
|
||||
ATCA_STATUS atcab_idle(void);
|
||||
ATCA_STATUS atcab_sleep(void);
|
||||
ATCA_STATUS atcab_cfg_discover(ATCAIfaceCfg cfg_array[], int max);
|
||||
ATCA_STATUS atcab_get_addr(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, uint16_t* addr);
|
||||
ATCA_STATUS atcab_get_zone_size(uint8_t zone, uint16_t slot, size_t* size);
|
||||
|
||||
// AES command functions
|
||||
ATCA_STATUS atcab_aes(uint8_t mode, uint16_t key_id, const uint8_t* aes_in, uint8_t* aes_out);
|
||||
ATCA_STATUS atcab_aes_encrypt(uint16_t key_id, uint8_t key_block, const uint8_t* plaintext, uint8_t* ciphertext);
|
||||
ATCA_STATUS atcab_aes_decrypt(uint16_t key_id, uint8_t key_block, const uint8_t* ciphertext, uint8_t* plaintext);
|
||||
ATCA_STATUS atcab_aes_gfm(const uint8_t* h, const uint8_t* input, uint8_t* output);
|
||||
|
||||
typedef struct atca_aes_cbc_ctx
|
||||
{
|
||||
uint16_t key_id; //!< Key location. Can either be a slot number or ATCA_TEMPKEY_KEYID for TempKey.
|
||||
uint8_t key_block; //!< Index of the 16-byte block to use within the key location for the actual key.
|
||||
uint8_t ciphertext[AES_DATA_SIZE]; //!< Ciphertext from last operation.
|
||||
} atca_aes_cbc_ctx_t;
|
||||
|
||||
ATCA_STATUS atcab_aes_cbc_init(atca_aes_cbc_ctx_t* ctx, uint16_t key_id, uint8_t key_block, const uint8_t* iv);
|
||||
ATCA_STATUS atcab_aes_cbc_encrypt_block(atca_aes_cbc_ctx_t* ctx, const uint8_t* plaintext, uint8_t* ciphertext);
|
||||
ATCA_STATUS atcab_aes_cbc_decrypt_block(atca_aes_cbc_ctx_t* ctx, const uint8_t* ciphertext, uint8_t* plaintext);
|
||||
|
||||
typedef struct atca_aes_cmac_ctx
|
||||
{
|
||||
atca_aes_cbc_ctx_t cbc_ctx; //!< CBC context
|
||||
uint32_t block_size; //!< Number of bytes in current block.
|
||||
uint8_t block[AES_DATA_SIZE]; //!< Unprocessed message storage.
|
||||
} atca_aes_cmac_ctx_t;
|
||||
|
||||
ATCA_STATUS atcab_aes_cmac_init(atca_aes_cmac_ctx_t* ctx, uint16_t key_id, uint8_t key_block);
|
||||
ATCA_STATUS atcab_aes_cmac_update(atca_aes_cmac_ctx_t* ctx, const uint8_t* data, uint32_t data_size);
|
||||
ATCA_STATUS atcab_aes_cmac_finish(atca_aes_cmac_ctx_t* ctx, uint8_t* cmac, uint32_t cmac_size);
|
||||
|
||||
typedef struct atca_aes_ctr_ctx
|
||||
{
|
||||
uint16_t key_id; //!< Key location. Can either be a slot number or ATCA_TEMPKEY_KEYID for TempKey.
|
||||
uint8_t key_block; //!< Index of the 16-byte block to use within the key location for the actual key.
|
||||
uint8_t cb[AES_DATA_SIZE]; //!< Counter block, comprises of nonce + count value (16 bytes).
|
||||
uint8_t counter_size; //!< Size of counter in the initialization vector.
|
||||
}atca_aes_ctr_ctx_t;
|
||||
|
||||
ATCA_STATUS atcab_aes_ctr_init(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t key_block, uint8_t counter_size, const uint8_t* iv);
|
||||
ATCA_STATUS atcab_aes_ctr_init_rand(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t key_block, uint8_t counter_size, uint8_t* iv);
|
||||
ATCA_STATUS atcab_aes_ctr_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* input, uint8_t* output);
|
||||
ATCA_STATUS atcab_aes_ctr_encrypt_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* plaintext, uint8_t* ciphertext);
|
||||
ATCA_STATUS atcab_aes_ctr_decrypt_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* ciphertext, uint8_t* plaintext);
|
||||
ATCA_STATUS atcab_aes_ctr_increment(atca_aes_ctr_ctx_t* ctx);
|
||||
|
||||
// CheckMAC command functions
|
||||
ATCA_STATUS atcab_checkmac(uint8_t mode, uint16_t key_id, const uint8_t *challenge, const uint8_t *response, const uint8_t *other_data);
|
||||
|
||||
// Counter command functions
|
||||
ATCA_STATUS atcab_counter(uint8_t mode, uint16_t counter_id, uint32_t* counter_value);
|
||||
ATCA_STATUS atcab_counter_increment(uint16_t counter_id, uint32_t* counter_value);
|
||||
ATCA_STATUS atcab_counter_read(uint16_t counter_id, uint32_t* counter_value);
|
||||
|
||||
// DeriveKey command functions
|
||||
ATCA_STATUS atcab_derivekey(uint8_t mode, uint16_t key_id, const uint8_t* mac);
|
||||
|
||||
// ECDH command functions
|
||||
ATCA_STATUS atcab_ecdh_base(uint8_t mode, uint16_t key_id, const uint8_t* public_key, uint8_t* pms, uint8_t* out_nonce);
|
||||
ATCA_STATUS atcab_ecdh(uint16_t key_id, const uint8_t* public_key, uint8_t* pms);
|
||||
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id);
|
||||
#else
|
||||
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE]);
|
||||
#endif
|
||||
|
||||
ATCA_STATUS atcab_ecdh_ioenc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key);
|
||||
ATCA_STATUS atcab_ecdh_tempkey(const uint8_t* public_key, uint8_t* pms);
|
||||
ATCA_STATUS atcab_ecdh_tempkey_ioenc(const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key);
|
||||
|
||||
// GenDig command functions
|
||||
ATCA_STATUS atcab_gendig(uint8_t zone, uint16_t key_id, const uint8_t *other_data, uint8_t other_data_size);
|
||||
|
||||
// GenKey command functions
|
||||
ATCA_STATUS atcab_genkey_base(uint8_t mode, uint16_t key_id, const uint8_t* other_data, uint8_t* public_key);
|
||||
ATCA_STATUS atcab_genkey(uint16_t key_id, uint8_t* public_key);
|
||||
ATCA_STATUS atcab_get_pubkey(uint16_t key_id, uint8_t* public_key);
|
||||
|
||||
// HMAC command functions
|
||||
ATCA_STATUS atcab_hmac(uint8_t mode, uint16_t key_id, uint8_t* digest);
|
||||
|
||||
// Info command functions
|
||||
ATCA_STATUS atcab_info_base(uint8_t mode, uint16_t param2, uint8_t* out_data);
|
||||
ATCA_STATUS atcab_info(uint8_t* revision);
|
||||
ATCA_STATUS atcab_info_set_latch(bool state);
|
||||
ATCA_STATUS atcab_info_get_latch(bool* state);
|
||||
|
||||
// KDF command functions
|
||||
ATCA_STATUS atcab_kdf(uint8_t mode, uint16_t key_id, const uint32_t details, const uint8_t* message, uint8_t* out_data, uint8_t* out_nonce);
|
||||
|
||||
// Lock command functions
|
||||
ATCA_STATUS atcab_lock(uint8_t mode, uint16_t summary_crc);
|
||||
ATCA_STATUS atcab_lock_config_zone(void);
|
||||
ATCA_STATUS atcab_lock_config_zone_crc(uint16_t summary_crc);
|
||||
ATCA_STATUS atcab_lock_data_zone(void);
|
||||
ATCA_STATUS atcab_lock_data_zone_crc(uint16_t summary_crc);
|
||||
ATCA_STATUS atcab_lock_data_slot(uint16_t slot);
|
||||
|
||||
// MAC command functions
|
||||
ATCA_STATUS atcab_mac(uint8_t mode, uint16_t key_id, const uint8_t* challenge, uint8_t* digest);
|
||||
|
||||
// Nonce command functions
|
||||
ATCA_STATUS atcab_nonce_base(uint8_t mode, uint16_t zero, const uint8_t *num_in, uint8_t* rand_out);
|
||||
ATCA_STATUS atcab_nonce(const uint8_t *num_in);
|
||||
ATCA_STATUS atcab_nonce_load(uint8_t target, const uint8_t *num_in, uint16_t num_in_size);
|
||||
ATCA_STATUS atcab_nonce_rand(const uint8_t *num_in, uint8_t* rand_out);
|
||||
ATCA_STATUS atcab_challenge(const uint8_t *num_in);
|
||||
ATCA_STATUS atcab_challenge_seed_update(const uint8_t *num_in, uint8_t* rand_out);
|
||||
|
||||
// PrivWrite command functions
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32]);
|
||||
#else
|
||||
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32], const uint8_t num_in[NONCE_NUMIN_SIZE]);
|
||||
#endif
|
||||
|
||||
// Random command functions
|
||||
ATCA_STATUS atcab_random(uint8_t* rand_out);
|
||||
|
||||
// Read command functions
|
||||
ATCA_STATUS atcab_read_zone(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, uint8_t *data, uint8_t len);
|
||||
ATCA_STATUS atcab_is_locked(uint8_t zone, bool *is_locked);
|
||||
ATCA_STATUS atcab_is_slot_locked(uint16_t slot, bool *is_locked);
|
||||
ATCA_STATUS atcab_read_bytes_zone(uint8_t zone, uint16_t slot, size_t offset, uint8_t *data, size_t length);
|
||||
ATCA_STATUS atcab_read_serial_number(uint8_t* serial_number);
|
||||
ATCA_STATUS atcab_read_pubkey(uint16_t slot, uint8_t *public_key);
|
||||
ATCA_STATUS atcab_read_sig(uint16_t slot, uint8_t *sig);
|
||||
ATCA_STATUS atcab_read_config_zone(uint8_t* config_data);
|
||||
ATCA_STATUS atcab_cmp_config_zone(uint8_t* config_data, bool* same_config);
|
||||
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_read_enc(uint16_t key_id, uint8_t block, uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id);
|
||||
#else
|
||||
ATCA_STATUS atcab_read_enc(uint16_t key_id, uint8_t block, uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE]);
|
||||
#endif
|
||||
|
||||
// SecureBoot command functions
|
||||
ATCA_STATUS atcab_secureboot(uint8_t mode, uint16_t param2, const uint8_t* digest, const uint8_t* signature, uint8_t* mac);
|
||||
ATCA_STATUS atcab_secureboot_mac(uint8_t mode, const uint8_t* digest, const uint8_t* signature, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified);
|
||||
|
||||
// SelfTest command functions
|
||||
ATCA_STATUS atcab_selftest(uint8_t mode, uint16_t param2, uint8_t* result);
|
||||
|
||||
// SHA command functions
|
||||
typedef struct atca_sha256_ctx
|
||||
{
|
||||
uint32_t total_msg_size; //!< Total number of message bytes processed
|
||||
uint32_t block_size; //!< Number of bytes in current block
|
||||
uint8_t block[ATCA_SHA256_BLOCK_SIZE * 2]; //!< Unprocessed message storage
|
||||
} atca_sha256_ctx_t;
|
||||
|
||||
typedef atca_sha256_ctx_t atca_hmac_sha256_ctx_t;
|
||||
|
||||
ATCA_STATUS atcab_sha_base(uint8_t mode, uint16_t length, const uint8_t* data_in, uint8_t* data_out, uint16_t* data_out_size);
|
||||
ATCA_STATUS atcab_sha_start(void);
|
||||
ATCA_STATUS atcab_sha_update(const uint8_t* message);
|
||||
ATCA_STATUS atcab_sha_end(uint8_t *digest, uint16_t length, const uint8_t *message);
|
||||
ATCA_STATUS atcab_sha_read_context(uint8_t* context, uint16_t* context_size);
|
||||
ATCA_STATUS atcab_sha_write_context(const uint8_t* context, uint16_t context_size);
|
||||
ATCA_STATUS atcab_sha(uint16_t length, const uint8_t *message, uint8_t *digest);
|
||||
ATCA_STATUS atcab_hw_sha2_256(const uint8_t * data, size_t data_size, uint8_t* digest);
|
||||
ATCA_STATUS atcab_hw_sha2_256_init(atca_sha256_ctx_t* ctx);
|
||||
ATCA_STATUS atcab_hw_sha2_256_update(atca_sha256_ctx_t* ctx, const uint8_t* data, size_t data_size);
|
||||
ATCA_STATUS atcab_hw_sha2_256_finish(atca_sha256_ctx_t* ctx, uint8_t* digest);
|
||||
ATCA_STATUS atcab_sha_hmac_init(atca_hmac_sha256_ctx_t* ctx, uint16_t key_slot);
|
||||
ATCA_STATUS atcab_sha_hmac_update(atca_hmac_sha256_ctx_t* ctx, const uint8_t* data, size_t data_size);
|
||||
ATCA_STATUS atcab_sha_hmac_finish(atca_hmac_sha256_ctx_t* ctx, uint8_t* digest, uint8_t target);
|
||||
ATCA_STATUS atcab_sha_hmac(const uint8_t * data, size_t data_size, uint16_t key_slot, uint8_t* digest, uint8_t target);
|
||||
|
||||
// Sign command functions
|
||||
ATCA_STATUS atcab_sign_base(uint8_t mode, uint16_t key_id, uint8_t *signature);
|
||||
ATCA_STATUS atcab_sign(uint16_t key_id, const uint8_t *msg, uint8_t *signature);
|
||||
ATCA_STATUS atcab_sign_internal(uint16_t key_id, bool is_invalidate, bool is_full_sn, uint8_t *signature);
|
||||
|
||||
// UpdateExtra command functions
|
||||
ATCA_STATUS atcab_updateextra(uint8_t mode, uint16_t new_value);
|
||||
|
||||
// Verify command functions
|
||||
ATCA_STATUS atcab_verify(uint8_t mode, uint16_t key_id, const uint8_t* signature, const uint8_t* public_key, const uint8_t* other_data, uint8_t* mac);
|
||||
ATCA_STATUS atcab_verify_extern(const uint8_t *message, const uint8_t *signature, const uint8_t *public_key, bool *is_verified);
|
||||
ATCA_STATUS atcab_verify_extern_mac(const uint8_t *message, const uint8_t* signature, const uint8_t* public_key, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified);
|
||||
ATCA_STATUS atcab_verify_stored(const uint8_t *message, const uint8_t *signature, uint16_t key_id, bool *is_verified);
|
||||
ATCA_STATUS atcab_verify_stored_mac(const uint8_t *message, const uint8_t *signature, uint16_t key_id, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified);
|
||||
|
||||
ATCA_STATUS atcab_verify_validate(uint16_t key_id, const uint8_t *signature, const uint8_t *other_data, bool *is_verified);
|
||||
ATCA_STATUS atcab_verify_invalidate(uint16_t key_id, const uint8_t *signature, const uint8_t *other_data, bool *is_verified);
|
||||
|
||||
// Write command functions
|
||||
ATCA_STATUS atcab_write(uint8_t zone, uint16_t address, const uint8_t *value, const uint8_t *mac);
|
||||
ATCA_STATUS atcab_write_zone(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, const uint8_t *data, uint8_t len);
|
||||
ATCA_STATUS atcab_write_bytes_zone(uint8_t zone, uint16_t slot, size_t offset_bytes, const uint8_t *data, size_t length);
|
||||
ATCA_STATUS atcab_write_pubkey(uint16_t slot, const uint8_t *public_key);
|
||||
ATCA_STATUS atcab_write_config_zone(const uint8_t* config_data);
|
||||
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_write_enc(uint16_t key_id, uint8_t block, const uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id);
|
||||
#else
|
||||
ATCA_STATUS atcab_write_enc(uint16_t key_id, uint8_t block, const uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE]);
|
||||
#endif
|
||||
|
||||
ATCA_STATUS atcab_write_config_counter(uint16_t counter_id, uint32_t counter_value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif /* ATCA_BASIC_H_ */
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for AES command.
|
||||
*
|
||||
* The AES command supports 128-bit AES encryption or decryption of small
|
||||
* messages or data packets in ECB mode. Also can perform GFM (Galois Field
|
||||
* Multiply) calculation in support of AES-GCM.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
|
||||
/** \brief Compute the AES-128 encrypt, decrypt, or GFM calculation.
|
||||
* \param[in] mode The mode for the AES command.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] aes_in Input data to the AES command (16 bytes).
|
||||
* \param[out] aes_out Output data from the AES command is returned here (16
|
||||
* bytes).
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes(uint8_t mode, uint16_t key_id, const uint8_t* aes_in, uint8_t* aes_out)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
if (aes_in == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
// build a AES command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
if (AES_MODE_GFM == (mode & AES_MODE_GFM))
|
||||
{
|
||||
memcpy(packet.data, aes_in, ATCA_AES_GFM_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(packet.data, aes_in, AES_DATA_SIZE);
|
||||
}
|
||||
|
||||
if ((status = atAES(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (aes_out && packet.data[ATCA_COUNT_IDX] >= (3 + AES_DATA_SIZE))
|
||||
{
|
||||
// The AES command return a 16 byte data.
|
||||
memcpy(aes_out, &packet.data[ATCA_RSP_DATA_IDX], AES_DATA_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Perform an AES-128 encrypt operation with a key in the device.
|
||||
*
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] plaintext Input plaintext to be encrypted (16 bytes).
|
||||
* \param[out] ciphertext Output ciphertext is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_encrypt(uint16_t key_id, uint8_t key_block, const uint8_t* plaintext, uint8_t* ciphertext)
|
||||
{
|
||||
uint8_t mode;
|
||||
|
||||
mode = AES_MODE_ENCRYPT | (AES_MODE_KEY_BLOCK_MASK & (key_block << AES_MODE_KEY_BLOCK_POS));
|
||||
return atcab_aes(mode, key_id, plaintext, ciphertext);
|
||||
}
|
||||
|
||||
/** \brief Perform an AES-128 decrypt operation with a key in the device.
|
||||
*
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] ciphertext Input ciphertext to be decrypted (16 bytes).
|
||||
* \param[out] plaintext Output plaintext is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_decrypt(uint16_t key_id, uint8_t key_block, const uint8_t* ciphertext, uint8_t* plaintext)
|
||||
{
|
||||
uint8_t mode;
|
||||
|
||||
mode = AES_MODE_DECRYPT | (AES_MODE_KEY_BLOCK_MASK & (key_block << AES_MODE_KEY_BLOCK_POS));
|
||||
return atcab_aes(mode, key_id, ciphertext, plaintext);
|
||||
}
|
||||
|
||||
/** \brief Perform a Galois Field Multiply (GFM) operation.
|
||||
*
|
||||
* \param[in] h First input value (16 bytes).
|
||||
* \param[in] input Second input value (16 bytes).
|
||||
* \param[out] output GFM result is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gfm(const uint8_t* h, const uint8_t* input, uint8_t* output)
|
||||
{
|
||||
uint8_t aes_in[AES_DATA_SIZE * 2];
|
||||
|
||||
memcpy(aes_in, h, AES_DATA_SIZE);
|
||||
memcpy(aes_in + AES_DATA_SIZE, input, AES_DATA_SIZE);
|
||||
// KeyID is ignored for GFM mode
|
||||
return atcab_aes(AES_MODE_GFM, 0x0000, aes_in, output);
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for AES CBC mode.
|
||||
*
|
||||
* The AES command supports 128-bit AES encryption or decryption of small
|
||||
* messages or data packets in ECB mode. Also can perform GFM (Galois Field
|
||||
* Multiply) calculation in support of AES-GCM.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
/** \brief Initialize context for AES CBC operation.
|
||||
*
|
||||
* \param[in] ctx AES CBC context to be initialized
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] iv Initialization vector (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cbc_init(atca_aes_cbc_ctx_t* ctx, uint16_t key_id, uint8_t key_block, const uint8_t* iv)
|
||||
{
|
||||
if (ctx == NULL || iv == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->key_id = key_id;
|
||||
ctx->key_block = key_block;
|
||||
memcpy(ctx->ciphertext, iv, sizeof(ctx->ciphertext));
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Encrypt a block of data using CBC mode and a key within the
|
||||
* ATECC608A. atcab_aes_cbc_init() should be called before the
|
||||
* first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES CBC context.
|
||||
* \param[in] plaintext Plaintext to be encrypted (16 bytes).
|
||||
* \param[out] ciphertext Encrypted data is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cbc_encrypt_block(atca_aes_cbc_ctx_t* ctx, const uint8_t* plaintext, uint8_t* ciphertext)
|
||||
{
|
||||
uint8_t input[AES_DATA_SIZE];
|
||||
int i;
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
if (ctx == NULL || plaintext == NULL || ciphertext == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// XOR plaintext with previous block's ciphertext to get input value to block encrypt
|
||||
for (i = 0; i < AES_DATA_SIZE; i++)
|
||||
{
|
||||
input[i] = plaintext[i] ^ ctx->ciphertext[i];
|
||||
}
|
||||
|
||||
// Block encrypt of input data
|
||||
status = atcab_aes_encrypt(ctx->key_id, ctx->key_block, input, ciphertext);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Save copy of ciphertext for next block operation
|
||||
memcpy(ctx->ciphertext, ciphertext, AES_DATA_SIZE);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Decrypt a block of data using CBC mode and a key within the
|
||||
* ATECC608A. atcab_aes_cbc_init() should be called before the
|
||||
* first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES CBC context.
|
||||
* \param[in] ciphertext Ciphertext to be decrypted (16 bytes).
|
||||
* \param[out] plaintext Decrypted data is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cbc_decrypt_block(atca_aes_cbc_ctx_t* ctx, const uint8_t* ciphertext, uint8_t* plaintext)
|
||||
{
|
||||
uint8_t output[AES_DATA_SIZE];
|
||||
int i;
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
if (ctx == NULL || ciphertext == NULL || plaintext == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Block decrypt of ciphertext
|
||||
status = atcab_aes_decrypt(ctx->key_id, ctx->key_block, ciphertext, output);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// XOR output with previous block's ciphertext to get plaintext
|
||||
for (i = 0; i < AES_DATA_SIZE; i++)
|
||||
{
|
||||
plaintext[i] = output[i] ^ ctx->ciphertext[i];
|
||||
}
|
||||
|
||||
// Save copy of ciphertext for next block operation
|
||||
memcpy(ctx->ciphertext, ciphertext, AES_DATA_SIZE);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for AES CBC_MAC mode.
|
||||
*
|
||||
* The AES command supports 128-bit AES encryption or decryption of small
|
||||
* messages or data packets in ECB mode. Also can perform GFM (Galois Field
|
||||
* Multiply) calculation in support of AES-GCM.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#ifdef _WIN32
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
static const uint8_t g_aes_zero_block[AES_DATA_SIZE] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/** \brief Initialize a CMAC calculation using an AES-128 key in the ATECC608A.
|
||||
*
|
||||
* \param[in] ctx AES-128 CMAC context.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cmac_init(atca_aes_cmac_ctx_t* ctx, uint16_t key_id, uint8_t key_block)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
// IV for CMAC CBC calculations is all zeros
|
||||
return atcab_aes_cbc_init(&ctx->cbc_ctx, key_id, key_block, g_aes_zero_block);
|
||||
}
|
||||
|
||||
/** \brief Add data to an initialized CMAC calculation.
|
||||
*
|
||||
* \param[in] ctx AES-128 CMAC context.
|
||||
* \param[in] data Data to be added.
|
||||
* \param[in] data_size Size of the data to be added in bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cmac_update(atca_aes_cmac_ctx_t* ctx, const uint8_t* data, uint32_t data_size)
|
||||
{
|
||||
uint32_t rem_size = AES_DATA_SIZE - ctx->block_size;
|
||||
uint32_t copy_size = data_size > rem_size ? rem_size : data_size;
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t ciphertext[AES_DATA_SIZE];
|
||||
uint32_t block_count;
|
||||
uint32_t i;
|
||||
|
||||
if (ctx == NULL || (data == NULL && data_size > 0))
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
memcpy(&ctx->block[ctx->block_size], data, copy_size);
|
||||
|
||||
if (ctx->block_size + data_size < AES_DATA_SIZE + 1)
|
||||
{
|
||||
// The last block of a CMAC operation is handled specially, so we don't
|
||||
// process a complete block unless we know there's data afterwards.
|
||||
ctx->block_size += data_size;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
// Process the current block
|
||||
status = atcab_aes_cbc_encrypt_block(&ctx->cbc_ctx, ctx->block, ciphertext);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Process any additional blocks
|
||||
data_size -= copy_size; // Adjust to the remaining message bytes
|
||||
block_count = data_size / AES_DATA_SIZE;
|
||||
if (block_count > 0 && data_size % AES_DATA_SIZE == 0)
|
||||
{
|
||||
block_count--; // Don't process last block because it may need special handling
|
||||
}
|
||||
for (i = 0; i < block_count; i++)
|
||||
{
|
||||
status = atcab_aes_cbc_encrypt_block(&ctx->cbc_ctx, &data[copy_size + i * AES_DATA_SIZE], ciphertext);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
data_size -= AES_DATA_SIZE;
|
||||
}
|
||||
|
||||
// Save any remaining data
|
||||
ctx->block_size = data_size;
|
||||
memcpy(ctx->block, &data[copy_size + block_count * AES_DATA_SIZE], ctx->block_size);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Left shift an MSB buffer by 1 bit.
|
||||
*
|
||||
* \param[inout] data Data to left shift.
|
||||
* \param[in] data_size Size of data in bytes.
|
||||
*/
|
||||
static void left_shift_one(uint8_t* data, size_t data_size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < data_size; i++)
|
||||
{
|
||||
data[i] = data[i] << 1;
|
||||
if (i + 1 < data_size && data[i + 1] & 0x80)
|
||||
{
|
||||
data[i] |= 0x01; // Next byte has a bit that needs to be shifted into this one
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Finish a CMAC operation returning the CMAC value.
|
||||
*
|
||||
* \param[in] ctx AES-128 CMAC context.
|
||||
* \param[out] cmac CMAC is returned here.
|
||||
* \param[in] cmac_size Size of CMAC requested in bytes (max 16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_cmac_finish(atca_aes_cmac_ctx_t* ctx, uint8_t* cmac, uint32_t cmac_size)
|
||||
{
|
||||
uint32_t i;
|
||||
uint8_t subkey[AES_DATA_SIZE];
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
bool is_msb_one;
|
||||
uint8_t cmac_full[AES_DATA_SIZE];
|
||||
|
||||
if (ctx == NULL || cmac == NULL || cmac_size > AES_DATA_SIZE)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Calculate L as AES Encrypt of an all zero block
|
||||
status = atcab_aes_encrypt(ctx->cbc_ctx.key_id, ctx->cbc_ctx.key_block, g_aes_zero_block, subkey);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Calculate subkey 1
|
||||
is_msb_one = (subkey[0] & 0x80);
|
||||
left_shift_one(subkey, sizeof(subkey)); // L << 1
|
||||
if (is_msb_one)
|
||||
{
|
||||
subkey[AES_DATA_SIZE - 1] ^= 0x87; // (L << 1) XOR R128
|
||||
}
|
||||
|
||||
if (ctx->block_size != AES_DATA_SIZE)
|
||||
{
|
||||
// Data is not a complete block, we calculate subkey 2
|
||||
is_msb_one = (subkey[0] & 0x80);
|
||||
left_shift_one(subkey, sizeof(subkey)); // K1 << 1
|
||||
if (is_msb_one)
|
||||
{
|
||||
subkey[AES_DATA_SIZE - 1] ^= 0x87; // (K1 << 1) XOR R128
|
||||
}
|
||||
|
||||
// Pad out an incomplete block starting with a 1 bit, followed by zeros
|
||||
for (i = 0; i < AES_DATA_SIZE - ctx->block_size; i++)
|
||||
{
|
||||
ctx->block[ctx->block_size + i] = (i == 0 ? 0x80 : 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
// XOR last block with subkey
|
||||
for (i = 0; i < AES_DATA_SIZE; i++)
|
||||
{
|
||||
ctx->block[i] ^= subkey[i];
|
||||
}
|
||||
|
||||
// Process last block
|
||||
status = atcab_aes_cbc_encrypt_block(&ctx->cbc_ctx, ctx->block, cmac_full);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
memcpy(cmac, cmac_full, cmac_size);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for AES CTR mode.
|
||||
*
|
||||
* The AES command supports 128-bit AES encryption or decryption of small
|
||||
* messages or data packets in ECB mode. Also can perform GFM (Galois Field
|
||||
* Multiply) calculation in support of AES-GCM.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "basic/atca_basic.h"
|
||||
|
||||
/** \brief Initialize context for AES CTR operation with an existing IV, which
|
||||
* is common when start a decrypt operation.
|
||||
*
|
||||
* The IV is a combination of nonce (left-field) and big-endian counter
|
||||
* (right-field). The counter_size field sets the size of the counter and the
|
||||
* remaining bytes are assumed to be the nonce.
|
||||
*
|
||||
* \param[in] ctx AES CTR context to be initialized.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] counter_size Size of counter in IV in bytes. 4 bytes is a
|
||||
* common size.
|
||||
* \param[in] iv Initialization vector (concatenation of nonce and
|
||||
* counter) 16 bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_init(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t key_block, uint8_t counter_size, const uint8_t* iv)
|
||||
{
|
||||
if (ctx == NULL || iv == NULL || counter_size > AES_DATA_SIZE)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->key_id = key_id;
|
||||
ctx->key_block = key_block;
|
||||
ctx->counter_size = counter_size;
|
||||
memcpy(ctx->cb, iv, AES_DATA_SIZE);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Initialize context for AES CTR operation with a random nonce and
|
||||
* counter set to 0 as the IV, which is common when starting an
|
||||
* encrypt operation.
|
||||
*
|
||||
* The IV is a combination of nonce (left-field) and big-endian counter
|
||||
* (right-field). The counter_size field sets the size of the counter and the
|
||||
* remaining bytes are assumed to be the nonce.
|
||||
*
|
||||
* \param[in] ctx AES CTR context to be initialized.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] counter_size Size of counter in IV in bytes. 4 bytes is a
|
||||
* common size.
|
||||
* \param[out] iv Initialization vector (concatenation of nonce and
|
||||
* counter) is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_init_rand(atca_aes_ctr_ctx_t* ctx, uint16_t key_id, uint8_t key_block, uint8_t counter_size, uint8_t* iv)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t nonce_size;
|
||||
|
||||
if (ctx == NULL || iv == NULL || counter_size > AES_DATA_SIZE)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
ctx->key_id = key_id;
|
||||
ctx->key_block = key_block;
|
||||
ctx->counter_size = counter_size;
|
||||
|
||||
// Generate random nonce
|
||||
nonce_size = AES_DATA_SIZE - ctx->counter_size;
|
||||
if (nonce_size != 0)
|
||||
{
|
||||
uint8_t random_nonce[32];
|
||||
status = atcab_random(random_nonce);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
memcpy(iv, random_nonce, nonce_size);
|
||||
}
|
||||
memcpy(ctx->cb, iv, AES_DATA_SIZE);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Increments AES CTR counter value.
|
||||
*
|
||||
* \param[in,out] ctx AES CTR context
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_increment(atca_aes_ctr_ctx_t* ctx)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (ctx == NULL || ctx->counter_size > AES_DATA_SIZE)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Increment the big-endian counter value
|
||||
for (i = 0; i < ctx->counter_size; i++)
|
||||
{
|
||||
// Counter is right-aligned in buffer
|
||||
if (++(ctx->cb[AES_DATA_SIZE - i - 1]) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= ctx->counter_size)
|
||||
{
|
||||
// Counter overflowed
|
||||
memset(&ctx->cb[AES_DATA_SIZE - ctx->counter_size], 0, ctx->counter_size);
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Process a block of data using CTR mode and a key within the
|
||||
* ATECC608A device. atcab_aes_ctr_init() or atcab_aes_ctr_init_rand()
|
||||
* should be called before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES CTR context structure.
|
||||
* \param[in] input Input data to be processed (16 bytes).
|
||||
* \param[out] output Output data is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, ATCA_INVALID_SIZE on counter overflow,
|
||||
* otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* input, uint8_t* output)
|
||||
{
|
||||
uint8_t i;
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t encrypted_counter[AES_DATA_SIZE];
|
||||
|
||||
if (ctx == NULL || input == NULL || output == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Block encrypt of counter block (128 bits)
|
||||
status = atcab_aes_encrypt(ctx->key_id, ctx->key_block, ctx->cb, encrypted_counter);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// XOR output of AES encrypt with input to get output
|
||||
for (i = 0; i < AES_DATA_SIZE; i++)
|
||||
{
|
||||
output[i] = encrypted_counter[i] ^ input[i];
|
||||
}
|
||||
|
||||
status = atcab_aes_ctr_increment(ctx);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Encrypt a block of data using CTR mode and a key within the
|
||||
* ATECC608A device. atcab_aes_ctr_init() or atcab_aes_ctr_init_rand()
|
||||
* should be called before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES CTR context structure.
|
||||
* \param[in] plaintext Plaintext to be encrypted (16 bytes).
|
||||
* \param[out] ciphertext Encrypted data is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, ATCA_INVALID_SIZE on counter overflow,
|
||||
* otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_encrypt_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* plaintext, uint8_t* ciphertext)
|
||||
{
|
||||
return atcab_aes_ctr_block(ctx, plaintext, ciphertext);
|
||||
}
|
||||
|
||||
/** \brief Decrypt a block of data using CTR mode and a key within the
|
||||
* ATECC608A device. atcab_aes_ctr_init() or atcab_aes_ctr_init_rand()
|
||||
* should be called before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES CTR context structure.
|
||||
* \param[in] ciphertext Ciphertext to be decrypted (16 bytes).
|
||||
* \param[out] plaintext Decrypted data is returned here (16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, ATCA_INVALID_SIZE on counter overflow,
|
||||
* otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_ctr_decrypt_block(atca_aes_ctr_ctx_t* ctx, const uint8_t* ciphertext, uint8_t* plaintext)
|
||||
{
|
||||
return atcab_aes_ctr_block(ctx, ciphertext, plaintext);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,583 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for AES GCM mode.
|
||||
*
|
||||
* The AES command supports 128-bit AES encryption or decryption of small
|
||||
* messages or data packets in ECB mode. Also can perform GFM (Galois Field
|
||||
* Multiply) calculation in support of AES-GCM.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic_aes_gcm.h"
|
||||
#include "atca_compiler.h"
|
||||
|
||||
/** \ingroup atcab_
|
||||
* @{
|
||||
*/
|
||||
|
||||
const char* atca_basic_aes_gcm_version = "1.0";
|
||||
|
||||
/** \brief Performs running GHASH calculations using the current hash value,
|
||||
* hash subkey, and data received. In case of partial blocks, the last
|
||||
* block is padded with zeros to get the output.
|
||||
*
|
||||
* \param[in] h Subkey to use in GHASH calculations.
|
||||
* \param[in] data Input data to hash.
|
||||
* \param[in] data_size Data size in bytes.
|
||||
* \param[in,out] y As input, current hash value. As output, the new
|
||||
* hash output.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS atcab_aes_ghash(const uint8_t* h, const uint8_t* data, size_t data_size, uint8_t* y)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t pad_bytes[AES_DATA_SIZE];
|
||||
size_t xor_index;
|
||||
|
||||
if (h == NULL || data == NULL || y == NULL)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
if (data_size == 0)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
while (data_size / AES_DATA_SIZE)
|
||||
{
|
||||
for (xor_index = 0; xor_index < AES_DATA_SIZE; xor_index++)
|
||||
{
|
||||
y[xor_index] ^= *data++;
|
||||
}
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gfm(h, y, y)))
|
||||
{
|
||||
RETURN(status, "GHASH GFM (full block) failed");
|
||||
}
|
||||
|
||||
data_size -= AES_DATA_SIZE;
|
||||
}
|
||||
|
||||
if (data_size)
|
||||
{
|
||||
memcpy(pad_bytes, data, data_size);
|
||||
memset(&pad_bytes[data_size], 0, sizeof(pad_bytes) - data_size);
|
||||
|
||||
for (xor_index = 0; xor_index < AES_DATA_SIZE; xor_index++)
|
||||
{
|
||||
y[xor_index] ^= pad_bytes[xor_index];
|
||||
}
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gfm(h, y, y)))
|
||||
{
|
||||
RETURN(status, "GHASH GFM (partial block) failed");
|
||||
}
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Increments AES GCM counter value.
|
||||
*
|
||||
* \param[in,out] cb AES GCM counter block to be incremented
|
||||
* (16 bytes).
|
||||
* \param[in] counter_size Counter size in bytes. Should be 4 for GCM.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS atcab_aes_gcm_increment(uint8_t* cb, size_t counter_size)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (cb == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Not converting to uint32_t and incrementing as there may be alignment
|
||||
// issues with the cb buffer
|
||||
|
||||
// Increment the big-endian counter value
|
||||
for (i = 0; i < counter_size; i++)
|
||||
{
|
||||
// Counter is right-aligned in buffer
|
||||
if (++(cb[AES_DATA_SIZE - i - 1]) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= counter_size)
|
||||
{
|
||||
// Counter overflowed
|
||||
memset(&cb[AES_DATA_SIZE - counter_size], 0, counter_size);
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Initialize context for AES GCM operation with an existing IV, which
|
||||
* is common when starting a decrypt operation.
|
||||
*
|
||||
* \param[in] ctx AES GCM context to be initialized.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the key
|
||||
* location for the actual key.
|
||||
* \param[in] iv Initialization vector.
|
||||
* \param[in] iv_size Size of IV in bytes. Standard is 12 bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_init(atca_aes_gcm_ctx_t* ctx, uint16_t key_id, uint8_t key_block, const uint8_t* iv, size_t iv_size)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t ghash_data[AES_DATA_SIZE];
|
||||
uint32_t length;
|
||||
|
||||
if (ctx == NULL || iv == NULL || iv_size == 0)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "GCM init failed; Either null pointer or 0 iv_size");
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
|
||||
//Calculate H = CIPHK(0^128)
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_encrypt(key_id, key_block, ctx->h, ctx->h)))
|
||||
{
|
||||
RETURN(status, "GCM - H failed");
|
||||
}
|
||||
|
||||
//Calculate J0
|
||||
if (iv_size == ATCA_AES_GCM_IV_STD_LENGTH)
|
||||
{
|
||||
//J0 = IV || 0^31 ||1.
|
||||
memcpy(ctx->j0, iv, iv_size);
|
||||
ctx->j0[AES_DATA_SIZE - 1] = 0x01;
|
||||
}
|
||||
else
|
||||
{
|
||||
//J0=GHASH(H, IV||0^(s+64)||[len(IV)]64)
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, iv, iv_size, ctx->j0)))
|
||||
{
|
||||
RETURN(status, "GCM - J0 (IV) failed");
|
||||
}
|
||||
|
||||
memset(ghash_data, 0, AES_DATA_SIZE);
|
||||
length = ATCA_UINT32_HOST_TO_BE((uint32_t)(iv_size * 8));
|
||||
memcpy(&ghash_data[12], &length, sizeof(length));
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ghash_data, sizeof(ghash_data), ctx->j0)))
|
||||
{
|
||||
RETURN(status, "GCM - J0 (IV Size) failed");
|
||||
}
|
||||
}
|
||||
|
||||
ctx->key_id = key_id;
|
||||
ctx->key_block = key_block;
|
||||
memcpy(ctx->cb, ctx->j0, AES_DATA_SIZE);
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_increment(ctx->cb, 4)))
|
||||
{
|
||||
RETURN(status, "GCM CTR increment failed");
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Initialize context for AES GCM operation with a IV composed of a
|
||||
* random and optional fixed(free) field, which is common when
|
||||
* starting an encrypt operation.
|
||||
*
|
||||
* \param[in] ctx AES CTR context to be initialized.
|
||||
* \param[in] key_id Key location. Can either be a slot number or
|
||||
* ATCA_TEMPKEY_KEYID for TempKey.
|
||||
* \param[in] key_block Index of the 16-byte block to use within the
|
||||
* key location for the actual key.
|
||||
* \param[in] rand_size Size of the random field in bytes. Minimum and
|
||||
* recommended size is 12 bytes. Max is 32 bytes.
|
||||
* \param[in] free_field Fixed data to include in the IV after the
|
||||
* random field. Can be NULL if not used.
|
||||
* \param[in] free_field_size Size of the free field in bytes.
|
||||
* \param[out] iv Initialization vector is returned here. Its
|
||||
* size will be rand_size and free_field_size
|
||||
* combined.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_init_rand(atca_aes_gcm_ctx_t* ctx, uint16_t key_id, uint8_t key_block, size_t rand_size,
|
||||
const uint8_t* free_field, size_t free_field_size, uint8_t* iv)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t random[RANDOM_NUM_SIZE];
|
||||
|
||||
if (ctx == NULL || iv == NULL || (free_field_size > 0 && free_field == NULL))
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
// 800-38D 8.2.2 specifies a minimum rand_field size of 12 bytes (96 bits)
|
||||
if (rand_size < 12 || rand_size > RANDOM_NUM_SIZE)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Bad rand_size");
|
||||
}
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_random(random)))
|
||||
{
|
||||
RETURN(status, "GCM init rand - Random Generation failed");
|
||||
}
|
||||
memcpy(iv, random, rand_size);
|
||||
memcpy(&iv[rand_size], free_field, free_field_size);
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_init(ctx, key_id, key_block, iv, rand_size + free_field_size)))
|
||||
{
|
||||
RETURN(status, "GCM init failed");
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Process Additional Authenticated Data (AAD) using GCM mode and a
|
||||
* key within the ATECC608A device.
|
||||
*
|
||||
* This can be called multiple times. atcab_aes_gcm_init() or
|
||||
* atcab_aes_gcm_init_rand() should be called before the first use of this
|
||||
* function. When there is AAD to include, this should be called before
|
||||
* atcab_aes_gcm_encrypt_update() or atcab_aes_gcm_decrypt_update().
|
||||
*
|
||||
* \param[in] ctx AES GCM context
|
||||
* \param[in] aad Additional authenticated data to be added
|
||||
* \param[in] aad_size Size of aad in bytes
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_aad_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* aad, uint32_t aad_size)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint32_t block_count;
|
||||
uint32_t rem_size;
|
||||
uint32_t copy_size;
|
||||
|
||||
if (ctx == NULL || (aad_size > 0 && aad == NULL))
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
|
||||
if (aad_size == 0)
|
||||
{
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
rem_size = AES_DATA_SIZE - (uint32_t)ctx->partial_aad_size;
|
||||
copy_size = aad_size > rem_size ? rem_size : aad_size;
|
||||
|
||||
// Copy data into current block
|
||||
memcpy(&ctx->partial_aad[ctx->partial_aad_size], aad, copy_size);
|
||||
|
||||
if (ctx->partial_aad_size + aad_size < AES_DATA_SIZE)
|
||||
{
|
||||
// Not enough data to finish off the current block
|
||||
ctx->partial_aad_size += aad_size;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
// Process the current block
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ctx->partial_aad, AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (AAD) failed");
|
||||
}
|
||||
|
||||
// Process any additional blocks
|
||||
aad_size -= copy_size; // Adjust to the remaining aad bytes
|
||||
block_count = aad_size / AES_DATA_SIZE;
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, &aad[copy_size], block_count * AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (AAD) failed");
|
||||
}
|
||||
|
||||
// Save any remaining data
|
||||
ctx->aad_size += (block_count + 1) * AES_DATA_SIZE;
|
||||
ctx->partial_aad_size = aad_size % AES_DATA_SIZE;
|
||||
memcpy(ctx->partial_aad, &aad[copy_size + block_count * AES_DATA_SIZE], ctx->partial_aad_size);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Process data using GCM mode and a key within the ATECC608A device.
|
||||
* atcab_aes_gcm_init() or atcab_aes_gcm_init_rand() should be called
|
||||
* before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[in] input Data to be processed.
|
||||
* \param[in] input_size Size of input in bytes.
|
||||
* \param[out] output Output data is returned here.
|
||||
* \param[in] is_encrypt Encrypt operation if true, otherwise decrypt.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS atcab_aes_gcm_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* input, uint32_t input_size,
|
||||
uint8_t* output, bool is_encrypt)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint32_t data_idx;
|
||||
uint32_t i;
|
||||
|
||||
if (ctx == NULL || (input_size > 0 && (input == NULL || output == NULL)))
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
|
||||
if (ctx->partial_aad_size > 0)
|
||||
{
|
||||
// We have a partial block of AAD that needs to be added
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ctx->partial_aad, ctx->partial_aad_size, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (AAD partial) failed");
|
||||
}
|
||||
ctx->aad_size += ctx->partial_aad_size;
|
||||
ctx->partial_aad_size = 0;
|
||||
}
|
||||
|
||||
if (input_size == 0)
|
||||
{
|
||||
// Nothing to do
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
data_idx = 0;
|
||||
while (data_idx < input_size)
|
||||
{
|
||||
if (ctx->data_size % AES_DATA_SIZE == 0)
|
||||
{
|
||||
// Need to calculate next encrypted counter block
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_encrypt(ctx->key_id, ctx->key_block, ctx->cb, ctx->enc_cb)))
|
||||
{
|
||||
RETURN(status, "AES GCM CB encrypt failed");
|
||||
}
|
||||
|
||||
// Increment counter
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_increment(ctx->cb, 4)))
|
||||
{
|
||||
RETURN(status, "AES GCM counter increment failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Process data with current encrypted counter block
|
||||
for (i = ctx->data_size % AES_DATA_SIZE; i < AES_DATA_SIZE && data_idx < input_size; i++, data_idx++)
|
||||
{
|
||||
output[data_idx] = input[data_idx] ^ ctx->enc_cb[i];
|
||||
// Save the current ciphertext block depending on whether this is an encrypt or decrypt operation
|
||||
ctx->ciphertext_block[i] = is_encrypt ? output[data_idx] : input[data_idx];
|
||||
ctx->data_size += 1;
|
||||
}
|
||||
|
||||
if (ctx->data_size % AES_DATA_SIZE == 0)
|
||||
{
|
||||
// Calculate running hash with completed block
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ctx->ciphertext_block, AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (data) failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Encrypt data using GCM mode and a key within the ATECC608A device.
|
||||
* atcab_aes_gcm_init() or atcab_aes_gcm_init_rand() should be called
|
||||
* before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[in] plaintext Plaintext to be encrypted (16 bytes).
|
||||
* \param[in] plaintext_size Size of plaintext in bytes.
|
||||
* \param[out] ciphertext Encrypted data is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_encrypt_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* plaintext, uint32_t plaintext_size, uint8_t* ciphertext)
|
||||
{
|
||||
return atcab_aes_gcm_update(ctx, plaintext, plaintext_size, ciphertext, true);
|
||||
}
|
||||
|
||||
/** \brief Complete GCM operation to generate the authentication tag.
|
||||
*
|
||||
* It calculates output block (S) by including AAD size and data size, then
|
||||
* calculates the tag. This should be called last in a encrypt/decrypt
|
||||
* operation.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[out] tag Authentication tag is returned here.
|
||||
* \param[in] tag_size Required size for the tag. Must be 12 to 16 bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
static ATCA_STATUS atcab_aes_gcm_calc_auth_tag(atca_aes_gcm_ctx_t* ctx, uint8_t* tag, size_t tag_size)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
size_t xor_index;
|
||||
uint8_t temp_data[AES_DATA_SIZE];
|
||||
uint64_t length;
|
||||
|
||||
if (ctx == NULL || tag == NULL)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
// 800-38D 5.2.1.2 specifies these tags sizes
|
||||
if (tag_size < 12 || tag_size > 16)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Invalid tag size");
|
||||
}
|
||||
|
||||
memset(temp_data, 0, AES_DATA_SIZE);
|
||||
length = ATCA_UINT64_HOST_TO_BE(((uint64_t)ctx->aad_size) * 8);
|
||||
memcpy(&temp_data[0], &length, sizeof(length));
|
||||
length = ATCA_UINT64_HOST_TO_BE(((uint64_t)ctx->data_size) * 8);
|
||||
memcpy(&temp_data[8], &length, sizeof(length));
|
||||
|
||||
//S = GHASH(H, [len(A)]64 || [len(C)]64))
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, temp_data, AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (lengths) failed");
|
||||
}
|
||||
|
||||
//T = GCTR(J0, S)
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_encrypt(ctx->key_id, ctx->key_block, ctx->j0, temp_data)))
|
||||
{
|
||||
RETURN(status, "Tag GCTR Encryption failed");
|
||||
}
|
||||
|
||||
for (xor_index = 0; xor_index < tag_size; xor_index++)
|
||||
{
|
||||
tag[xor_index] = temp_data[xor_index] ^ ctx->y[xor_index];
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Complete a GCM encrypt operation returning the authentication tag.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[out] tag Authentication tag is returned here.
|
||||
* \param[in] tag_size Tag size in bytes (12 to 16 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_encrypt_finish(atca_aes_gcm_ctx_t* ctx, uint8_t* tag, size_t tag_size)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
if (ctx == NULL)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
|
||||
if (ctx->partial_aad_size > 0)
|
||||
{
|
||||
// Incomplete AAD with no encrypted data, need to complete AAD hash
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_update(ctx, NULL, 0, NULL, true)))
|
||||
{
|
||||
RETURN(status, "GCM - S (AAD) failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Update hash with any partial block of ciphertext
|
||||
//S = GHASH(H, C || 0^u)
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ctx->ciphertext_block, ctx->data_size % AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (C - encrypt update) failed");
|
||||
}
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_calc_auth_tag(ctx, tag, tag_size)))
|
||||
{
|
||||
RETURN(status, "GCM encrypt tag calculation failed");
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Decrypt data using GCM mode and a key within the ATECC608A device.
|
||||
* atcab_aes_gcm_init() or atcab_aes_gcm_init_rand() should be called
|
||||
* before the first use of this function.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[in] ciphertext Ciphertext to be decrypted.
|
||||
* \param[in] ciphertext_size Size of ciphertext in bytes.
|
||||
* \param[out] plaintext Decrypted data is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_decrypt_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* ciphertext, uint32_t ciphertext_size, uint8_t* plaintext)
|
||||
{
|
||||
return atcab_aes_gcm_update(ctx, ciphertext, ciphertext_size, plaintext, false);
|
||||
}
|
||||
|
||||
/** \brief Complete a GCM decrypt operation verifying the authentication tag.
|
||||
*
|
||||
* \param[in] ctx AES GCM context structure.
|
||||
* \param[in] tag Expected authentication tag.
|
||||
* \param[in] tag_size Size of tag in bytes (12 to 16 bytes).
|
||||
* \param[out] is_verified Returns whether or not the tag verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_aes_gcm_decrypt_finish(atca_aes_gcm_ctx_t* ctx, const uint8_t* tag, size_t tag_size, bool* is_verified)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
uint8_t calc_tag[AES_DATA_SIZE];
|
||||
|
||||
if (ctx == NULL || is_verified == NULL)
|
||||
{
|
||||
RETURN(ATCA_BAD_PARAM, "Null pointer");
|
||||
}
|
||||
*is_verified = false;
|
||||
|
||||
if (ctx->partial_aad_size > 0)
|
||||
{
|
||||
// Incomplete AAD with no decrypted data, need to complete AAD hash
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_update(ctx, NULL, 0, NULL, false)))
|
||||
{
|
||||
RETURN(status, "GCM - S (AAD) failed");
|
||||
}
|
||||
}
|
||||
|
||||
// Update hash with any partial block of ciphertext
|
||||
//S = GHASH(H, C || 0^u)
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_ghash(ctx->h, ctx->ciphertext_block, ctx->data_size % AES_DATA_SIZE, ctx->y)))
|
||||
{
|
||||
RETURN(status, "GCM - S (C - encrypt update) failed");
|
||||
}
|
||||
|
||||
if (ATCA_SUCCESS != (status = atcab_aes_gcm_calc_auth_tag(ctx, calc_tag, tag_size)))
|
||||
{
|
||||
RETURN(status, "Tag calculation failed");
|
||||
}
|
||||
|
||||
*is_verified = (memcmp(calc_tag, tag, tag_size) == 0);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Unity tests for the cryptoauthlib AES GCM functions.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#ifndef ATCA_BASIC_AES_GCM_H_
|
||||
#define ATCA_BASIC_AES_GCM_H_
|
||||
|
||||
#include "cryptoauthlib.h"
|
||||
|
||||
/** \ingroup atcab_
|
||||
* @{
|
||||
*/
|
||||
|
||||
extern const char* atca_basic_aes_gcm_version;
|
||||
|
||||
/** Context structure for AES GCM operations.
|
||||
*/
|
||||
typedef struct atca_aes_gcm_ctx
|
||||
{
|
||||
uint16_t key_id; //!< Key location. Can either be a slot number or ATCA_TEMPKEY_KEYID for TempKey.
|
||||
uint8_t key_block; //!< Index of the 16-byte block to use within the key location for the actual key.
|
||||
uint8_t cb[AES_DATA_SIZE]; //!< Counter block, comprises of nonce + count value (16 bytes).
|
||||
uint32_t data_size; //!< Size of the data being encrypted/decrypted in bytes.
|
||||
uint32_t aad_size; //!< Size of the additional authenticated data in bytes.
|
||||
uint8_t h[AES_DATA_SIZE]; //!< Subkey for ghash functions in GCM.
|
||||
uint8_t j0[AES_DATA_SIZE]; //!< Precounter block generated from IV.
|
||||
uint8_t y[AES_DATA_SIZE]; //!< Current GHASH output
|
||||
uint8_t partial_aad[AES_DATA_SIZE]; //!< Partial blocks of data waiting to be processed
|
||||
uint32_t partial_aad_size; //!< Amount of data in the partial block buffer
|
||||
uint8_t enc_cb[AES_DATA_SIZE]; //!< Last encrypted counter block
|
||||
uint8_t ciphertext_block[AES_DATA_SIZE]; //!< Last ciphertext block
|
||||
} atca_aes_gcm_ctx_t;
|
||||
|
||||
ATCA_STATUS atcab_aes_gcm_init(atca_aes_gcm_ctx_t* ctx, uint16_t key_id, uint8_t key_block, const uint8_t* iv, size_t iv_size);
|
||||
ATCA_STATUS atcab_aes_gcm_init_rand(atca_aes_gcm_ctx_t* ctx, uint16_t key_id, uint8_t key_block, size_t rand_size,
|
||||
const uint8_t* free_field, size_t free_field_size, uint8_t* iv);
|
||||
ATCA_STATUS atcab_aes_gcm_aad_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* aad, uint32_t aad_size);
|
||||
ATCA_STATUS atcab_aes_gcm_encrypt_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* plaintext, uint32_t plaintext_size, uint8_t* ciphertext);
|
||||
ATCA_STATUS atcab_aes_gcm_encrypt_finish(atca_aes_gcm_ctx_t* ctx, uint8_t* tag, size_t tag_size);
|
||||
ATCA_STATUS atcab_aes_gcm_decrypt_update(atca_aes_gcm_ctx_t* ctx, const uint8_t* ciphertext, uint32_t ciphertext_size, uint8_t* plaintext);
|
||||
ATCA_STATUS atcab_aes_gcm_decrypt_finish(atca_aes_gcm_ctx_t* ctx, const uint8_t* tag, size_t tag_size, bool* is_verified);
|
||||
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for CheckMAC command.
|
||||
*
|
||||
* The CheckMac command calculates a MAC response that would have been
|
||||
* generated on a different CryptoAuthentication device and then compares the
|
||||
* result with input value.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Compares a MAC response with input values
|
||||
* \param[in] mode Controls which fields within the device are used in
|
||||
* the message
|
||||
* \param[in] key_id Key location in the CryptoAuth device to use for the
|
||||
* MAC
|
||||
* \param[in] challenge Challenge data (32 bytes)
|
||||
* \param[in] response MAC response data (32 bytes)
|
||||
* \param[in] other_data OtherData parameter (13 bytes)
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_checkmac(uint8_t mode, uint16_t key_id, const uint8_t *challenge, const uint8_t *response, const uint8_t *other_data)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// Verify the inputs
|
||||
if (response == NULL || other_data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (!(mode & CHECKMAC_MODE_BLOCK2_TEMPKEY) && challenge == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// build Check MAC command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
if (challenge != NULL)
|
||||
{
|
||||
memcpy(&packet.data[0], challenge, CHECKMAC_CLIENT_CHALLENGE_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
memset(&packet.data[0], 0, CHECKMAC_CLIENT_CHALLENGE_SIZE);
|
||||
}
|
||||
memcpy(&packet.data[32], response, CHECKMAC_CLIENT_RESPONSE_SIZE);
|
||||
memcpy(&packet.data[64], other_data, CHECKMAC_OTHER_DATA_SIZE);
|
||||
|
||||
if ((status = atCheckMAC(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command( (void*)&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Counter command.
|
||||
*
|
||||
* The Counter command reads or increments the binary count value for one of the
|
||||
* two monotonic counters
|
||||
*
|
||||
* \note List of devices that support this command - ATECC508A and ATECC608A.
|
||||
* There are differences in the modes that they support. Refer to device
|
||||
* datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
|
||||
/** \brief Compute the Counter functions
|
||||
* \param[in] mode the mode used for the counter
|
||||
* \param[in] counter_id The counter to be used
|
||||
* \param[out] counter_value pointer to the counter value returned from device
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS atcab_counter(uint8_t mode, uint16_t counter_id, uint32_t *counter_value)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
if (counter_id > 1)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// build a Counter command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = counter_id;
|
||||
|
||||
if ((status = atCounter(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (counter_value != NULL)
|
||||
{
|
||||
if (packet.data[ATCA_COUNT_IDX] == 7)
|
||||
{
|
||||
*counter_value = ((uint32_t)packet.data[ATCA_RSP_DATA_IDX + 0] << 0) |
|
||||
((uint32_t)packet.data[ATCA_RSP_DATA_IDX + 1] << 8) |
|
||||
((uint32_t)packet.data[ATCA_RSP_DATA_IDX + 2] << 16) |
|
||||
((uint32_t)packet.data[ATCA_RSP_DATA_IDX + 3] << 24);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATCA_RX_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Increments one of the device's monotonic counters
|
||||
* \param[in] counter_id Counter to be incremented
|
||||
* \param[out] counter_value New value of the counter is returned here. Can be
|
||||
* NULL if not needed.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_counter_increment(uint16_t counter_id, uint32_t* counter_value)
|
||||
{
|
||||
return atcab_counter(COUNTER_MODE_INCREMENT, counter_id, counter_value);
|
||||
}
|
||||
|
||||
/** \brief Read one of the device's monotonic counters
|
||||
* \param[in] counter_id Counter to be read
|
||||
* \param[out] counter_value Counter value is returned here.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_counter_read(uint16_t counter_id, uint32_t* counter_value)
|
||||
{
|
||||
return atcab_counter(COUNTER_MODE_READ, counter_id, counter_value);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for DeriveKey command.
|
||||
*
|
||||
* The DeriveKey command combines the current value of a key with the nonce
|
||||
* stored in TempKey using SHA-256 and derives a new key.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes the DeviveKey command for deriving a new key from a
|
||||
* nonce (TempKey) and an existing key.
|
||||
*
|
||||
* \param[in] mode Bit 2 must match the value in TempKey.SourceFlag
|
||||
* \param[in] target_key Key slot to be written
|
||||
* \param[in] mac Optional 32 byte MAC used to validate operation. NULL
|
||||
* if not required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_derivekey(uint8_t mode, uint16_t target_key, const uint8_t* mac)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// build a deriveKey command (pass through mode)
|
||||
packet.param1 = mode;
|
||||
packet.param2 = target_key;
|
||||
|
||||
if (mac != NULL)
|
||||
{
|
||||
memcpy(packet.data, mac, MAC_SIZE);
|
||||
}
|
||||
|
||||
if ((status = atDeriveKey(ca_cmd, &packet, mac != NULL)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for ECDH command.
|
||||
*
|
||||
* The ECDH command implements the Elliptic Curve Diffie-Hellman algorithm to
|
||||
* combine an internal private key with an external public key to calculate a
|
||||
* shared secret.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC508A, ATECC608A.
|
||||
* There are differences in the modes that they support. Refer to device
|
||||
* datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
|
||||
/** \brief Base function for generating premaster secret key using ECDH.
|
||||
* \param[in] mode Mode to be used for ECDH computation
|
||||
* \param[in] key_id Slot of key for ECDH computation
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH pre-master secret is returned here (32
|
||||
* bytes) if returned directly. Otherwise NULL.
|
||||
* \param[out] out_nonce Nonce used to encrypt pre-master secret. NULL if
|
||||
* output encryption not used.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_ecdh_base(uint8_t mode, uint16_t key_id, const uint8_t* public_key, uint8_t* pms, uint8_t* out_nonce)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// Build Command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
memcpy(packet.data, public_key, ATCA_PUB_KEY_SIZE);
|
||||
|
||||
if ((status = atECDH(_gDevice->mCommands, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (pms != NULL && packet.data[ATCA_COUNT_IDX] >= (3 + ATCA_KEY_SIZE))
|
||||
{
|
||||
memcpy(pms, &packet.data[ATCA_RSP_DATA_IDX], ATCA_KEY_SIZE);
|
||||
}
|
||||
|
||||
if (out_nonce != NULL && packet.data[ATCA_COUNT_IDX] >= (3 + ATCA_KEY_SIZE * 2))
|
||||
{
|
||||
memcpy(out_nonce, &packet.data[ATCA_RSP_DATA_IDX + ATCA_KEY_SIZE], ATCA_KEY_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief ECDH command with a private key in a slot and the premaster secret
|
||||
* is returned in the clear.
|
||||
*
|
||||
* \param[in] key_id Slot of key for ECDH computation
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH premaster secret is returned here.
|
||||
* 32 bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success
|
||||
*/
|
||||
ATCA_STATUS atcab_ecdh(uint16_t key_id, const uint8_t* public_key, uint8_t* pms)
|
||||
{
|
||||
ATCA_STATUS status;
|
||||
|
||||
status = atcab_ecdh_base(ECDH_PREFIX_MODE, key_id, public_key, pms, NULL);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief ECDH command with a private key in a slot and the premaster secret
|
||||
* is read from the next slot.
|
||||
*
|
||||
* This function only works for even numbered slots with the proper
|
||||
* configuration.
|
||||
*
|
||||
* \param[in] key_id Slot of key for ECDH computation
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH premaster secret is returned here
|
||||
* (32 bytes).
|
||||
* \param[in] read_key Read key for the premaster secret slot (key_id|1).
|
||||
* \param[in] read_key_id Read key slot for read_key.
|
||||
* \param[in] num_in 20 byte host nonce to inject into Nonce calculation
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id)
|
||||
#else
|
||||
ATCA_STATUS atcab_ecdh_enc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* read_key, uint16_t read_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE])
|
||||
#endif
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the inputs
|
||||
if (public_key == NULL || pms == NULL || read_key == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Bad input parameters");
|
||||
}
|
||||
|
||||
// Send the ECDH command with the public key provided
|
||||
if ((status = atcab_ecdh(key_id, public_key, NULL)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "ECDH Failed");
|
||||
}
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
if ((status = atcab_read_enc(key_id | 0x0001, 0, pms, read_key, read_key_id)) != ATCA_SUCCESS)
|
||||
#else
|
||||
if ((status = atcab_read_enc(key_id | 0x0001, 0, pms, read_key, read_key_id, num_in)) != ATCA_SUCCESS)
|
||||
#endif
|
||||
{
|
||||
BREAK(status, "Encrypted read failed");
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief ECDH command with a private key in a slot and the premaster secret
|
||||
* is returned encrypted using the IO protection key.
|
||||
*
|
||||
* \param[in] key_id Slot of key for ECDH computation
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH premaster secret is returned here
|
||||
* (32 bytes).
|
||||
* \param[in] io_key IO protection key.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_ecdh_ioenc(uint16_t key_id, const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key)
|
||||
{
|
||||
uint8_t mode = ECDH_MODE_SOURCE_EEPROM_SLOT | ECDH_MODE_OUTPUT_ENC | ECDH_MODE_COPY_OUTPUT_BUFFER;
|
||||
uint8_t out_nonce[ATCA_KEY_SIZE];
|
||||
atca_io_decrypt_in_out_t io_dec_params;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// Perform ECDH operation requesting output buffer encryption
|
||||
status = atcab_ecdh_base(mode, key_id, public_key, pms, out_nonce);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Decrypt PMS
|
||||
memset(&io_dec_params, 0, sizeof(io_dec_params));
|
||||
io_dec_params.io_key = io_key;
|
||||
io_dec_params.out_nonce = out_nonce;
|
||||
io_dec_params.data = pms;
|
||||
io_dec_params.data_size = 32;
|
||||
status = atcah_io_decrypt(&io_dec_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief ECDH command with a private key in TempKey and the premaster secret
|
||||
* is returned in the clear.
|
||||
*
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH premaster secret is returned here
|
||||
* (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_ecdh_tempkey(const uint8_t* public_key, uint8_t* pms)
|
||||
{
|
||||
// Perform ECDH operation with TempKey
|
||||
uint8_t mode = ECDH_MODE_SOURCE_TEMPKEY | ECDH_MODE_COPY_OUTPUT_BUFFER;
|
||||
|
||||
return atcab_ecdh_base(mode, 0x0000, public_key, pms, NULL);
|
||||
}
|
||||
|
||||
/** \brief ECDH command with a private key in TempKey and the premaster secret
|
||||
* is returned encrypted using the IO protection key.
|
||||
*
|
||||
* \param[in] public_key Public key input to ECDH calculation. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* key.
|
||||
* \param[out] pms Computed ECDH premaster secret is returned here
|
||||
* (32 bytes).
|
||||
* \param[in] io_key IO protection key.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_ecdh_tempkey_ioenc(const uint8_t* public_key, uint8_t* pms, const uint8_t* io_key)
|
||||
{
|
||||
uint8_t mode = ECDH_MODE_SOURCE_TEMPKEY | ECDH_MODE_OUTPUT_ENC | ECDH_MODE_COPY_OUTPUT_BUFFER;
|
||||
uint8_t out_nonce[ATCA_KEY_SIZE];
|
||||
atca_io_decrypt_in_out_t io_dec_params;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// Perform ECDH operation requesting output buffer encryption
|
||||
status = atcab_ecdh_base(mode, 0x0000, public_key, pms, out_nonce);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Decrypt PMS
|
||||
memset(&io_dec_params, 0, sizeof(io_dec_params));
|
||||
io_dec_params.io_key = io_key;
|
||||
io_dec_params.out_nonce = out_nonce;
|
||||
io_dec_params.data = pms;
|
||||
io_dec_params.data_size = 32;
|
||||
status = atcah_io_decrypt(&io_dec_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for GenDig command.
|
||||
*
|
||||
* The GenDig command uses SHA-256 to combine a stored value with the contents
|
||||
* of TempKey, which must have been valid prior to the execution of this
|
||||
* command.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that
|
||||
* they support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Issues a GenDig command, which performs a SHA256 hash on the source data indicated by zone with the
|
||||
* contents of TempKey. See the CryptoAuth datasheet for your chip to see what the values of zone
|
||||
* correspond to.
|
||||
* \param[in] zone Designates the source of the data to hash with TempKey.
|
||||
* \param[in] key_id Indicates the key, OTP block, or message order for shared nonce mode.
|
||||
* \param[in] other_data Four bytes of data for SHA calculation when using a NoMac key, 32 bytes for
|
||||
* "Shared Nonce" mode, otherwise ignored (can be NULL).
|
||||
* \param[in] other_data_size Size of other_data in bytes.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_gendig(uint8_t zone, uint16_t key_id, const uint8_t *other_data, uint8_t other_data_size)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
bool is_no_mac_key = false;
|
||||
|
||||
if (other_data_size > 0 && other_data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// build gendig command
|
||||
packet.param1 = zone;
|
||||
packet.param2 = key_id;
|
||||
|
||||
if (packet.param1 == GENDIG_ZONE_SHARED_NONCE && other_data_size >= ATCA_BLOCK_SIZE)
|
||||
{
|
||||
memcpy(&packet.data[0], &other_data[0], ATCA_BLOCK_SIZE);
|
||||
}
|
||||
else if (packet.param1 == GENDIG_ZONE_DATA && other_data_size >= ATCA_WORD_SIZE)
|
||||
{
|
||||
memcpy(&packet.data[0], &other_data[0], ATCA_WORD_SIZE);
|
||||
is_no_mac_key = true;
|
||||
}
|
||||
|
||||
if ((status = atGenDig(ca_cmd, &packet, is_no_mac_key)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for GenKey command.
|
||||
*
|
||||
* The GenKey command is used for creating ECC private keys, generating ECC
|
||||
* public keys, and for digest calculations involving public keys.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC108A, ATECC508A,
|
||||
* ATECC608A. There are differences in the modes that they support. Refer
|
||||
* to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Issues GenKey command, which can generate a private key, compute a
|
||||
* public key, nd/or compute a digest of a public key.
|
||||
*
|
||||
* \param[in] mode Mode determines what operations the GenKey
|
||||
* command performs.
|
||||
* \param[in] key_id Slot to perform the GenKey command on.
|
||||
* \param[in] other_data OtherData for PubKey digest calculation. Can be set
|
||||
* to NULL otherwise.
|
||||
* \param[out] public_key If the mode indicates a public key will be
|
||||
* calculated, it will be returned here. Format will
|
||||
* be the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve. Set to NULL if public key
|
||||
* isn't required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_genkey_base(uint8_t mode, uint16_t key_id, const uint8_t* other_data, uint8_t* public_key)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// Build GenKey command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
if (other_data)
|
||||
{
|
||||
memcpy(packet.data, other_data, GENKEY_OTHER_DATA_SIZE);
|
||||
}
|
||||
|
||||
if ((status = atGenKey(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (public_key != NULL)
|
||||
{
|
||||
if (packet.data[ATCA_COUNT_IDX] == (ATCA_PUB_KEY_SIZE + ATCA_PACKET_OVERHEAD))
|
||||
{
|
||||
memcpy(public_key, &packet.data[ATCA_RSP_DATA_IDX], ATCA_PUB_KEY_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATCA_RX_FAIL;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Issues GenKey command, which generates a new random private key in
|
||||
* slot and returns the public key.
|
||||
*
|
||||
* \param[in] key_id Slot number where an ECC private key is configured.
|
||||
* Can also be ATCA_TEMPKEY_KEYID to generate a private
|
||||
* key in TempKey.
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve. Set to NULL if public key
|
||||
* isn't required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_genkey(uint16_t key_id, uint8_t *public_key)
|
||||
{
|
||||
return atcab_genkey_base(GENKEY_MODE_PRIVATE, key_id, NULL, public_key);
|
||||
}
|
||||
|
||||
/** \brief Uses GenKey command to calculate the public key from an existing
|
||||
* private key in a slot.
|
||||
*
|
||||
* \param[in] key_id Slot number of the private key.
|
||||
* \param[out] public_key Public key will be returned here. Format will be
|
||||
* the X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve. Set to NULL if public key
|
||||
* isn't required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_get_pubkey(uint16_t key_id, uint8_t *public_key)
|
||||
{
|
||||
return atcab_genkey_base(GENKEY_MODE_PUBLIC, key_id, NULL, public_key);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for HMAC command.
|
||||
*
|
||||
* The HMAC command computes an HMAC/SHA-256 digest using a key stored in the
|
||||
* device over a challenge stored in the TempKey register, and/or other
|
||||
* information stored within the device.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A, and
|
||||
* ATECC508A . There are differences in the modes that they support.
|
||||
* Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Issues a HMAC command, which computes an HMAC/SHA-256 digest of a
|
||||
* key stored in the device, a challenge, and other information on the
|
||||
* device.
|
||||
*
|
||||
* \param[in] mode Controls which fields within the device are used in the
|
||||
* message.
|
||||
* \param[in] key_id Which key is to be used to generate the response.
|
||||
* Bits 0:3 only are used to select a slot but all 16 bits
|
||||
* are used in the HMAC message.
|
||||
* \param[out] digest HMAC digest is returned in this buffer (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hmac(uint8_t mode, uint16_t key_id, uint8_t* digest)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
if (digest == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
// build HMAC command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
|
||||
if ((status = atHMAC(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet.data[ATCA_COUNT_IDX] != HMAC_DIGEST_SIZE + 3)
|
||||
{
|
||||
status = ATCA_RX_FAIL; // Unexpected response size
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(digest, &packet.data[ATCA_RSP_DATA_IDX], HMAC_DIGEST_SIZE);
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,139 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Info command.
|
||||
*
|
||||
* Info command returns a variety of static and dynamic information about the
|
||||
* device and its state. Also is used to control the GPIO pin and the persistent
|
||||
* latch.
|
||||
*
|
||||
* \note The ATSHA204A refers to this command as DevRev instead of Info,
|
||||
* however, the OpCode and operation is the same.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A & ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Issues an Info command, which return internal device information and
|
||||
* can control GPIO and the persistent latch.
|
||||
*
|
||||
* \param[in] mode Selects which mode to be used for info command.
|
||||
* \param[in] param2 Selects the particular fields for the mode.
|
||||
* \param[out] out_data Response from info command (4 bytes). Can be set to
|
||||
* NULL if not required.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_info_base(uint8_t mode, uint16_t param2, uint8_t* out_data)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// build an info command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = param2;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
if ((status = atInfo(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (out_data != NULL && packet.data[ATCA_COUNT_IDX] >= 7)
|
||||
{
|
||||
memcpy(out_data, &packet.data[ATCA_RSP_DATA_IDX], 4);
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Use the Info command to get the device revision (DevRev).
|
||||
* \param[out] revision Device revision is returned here (4 bytes).
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_info(uint8_t* revision)
|
||||
{
|
||||
if (revision == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
return atcab_info_base(INFO_MODE_REVISION, 0, revision);
|
||||
}
|
||||
|
||||
/** \brief Use the Info command to get the persistent latch current state for
|
||||
* an ATECC608A device.
|
||||
*
|
||||
* \param[out] state The state is returned here. Set (true) or Cler (false).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
|
||||
ATCA_STATUS atcab_info_get_latch(bool* state)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t out_data[4];
|
||||
|
||||
if (state == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
status = atcab_info_base(INFO_MODE_VOL_KEY_PERMIT, 0, out_data);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
*state = (out_data[0] == 1);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Use the Info command to set the persistent latch state for an
|
||||
* ATECC608A device.
|
||||
*
|
||||
* \param[out] state Persistent latch state. Set (true) or clear (false).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_info_set_latch(bool state)
|
||||
{
|
||||
uint16_t param2 = INFO_PARAM2_SET_LATCH_STATE;
|
||||
|
||||
param2 |= state ? INFO_PARAM2_LATCH_SET : INFO_PARAM2_LATCH_CLEAR;
|
||||
return atcab_info_base(INFO_MODE_VOL_KEY_PERMIT, param2, NULL);
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for KDF command.
|
||||
*
|
||||
* The KDF command implements one of a number of Key Derivation Functions (KDF).
|
||||
* Generally this function combines a source key with an input string and
|
||||
* creates a result key/digest/array. Three algorithms are currently supported:
|
||||
* PRF, HKDF and AES.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes the KDF command, which derives a new key in PRF, AES, or
|
||||
* HKDF modes.
|
||||
*
|
||||
* Generally this function combines a source key with an input string and
|
||||
* creates a result key/digest/array.
|
||||
*
|
||||
* \param[in] mode Mode determines KDF algorithm (PRF,AES,HKDF), source
|
||||
* key location, and target key locations.
|
||||
* \param[in] key_id Source and target key slots if locations are in the
|
||||
* EEPROM. Source key slot is the LSB and target key
|
||||
* slot is the MSB.
|
||||
* \param[in] details Further information about the computation, depending
|
||||
* on the algorithm (4 bytes).
|
||||
* \param[in] message Input value from system (up to 128 bytes). Actual size
|
||||
* of message is 16 bytes for AES algorithm or is encoded
|
||||
* in the MSB of the details parameter for other
|
||||
* algorithms.
|
||||
* \param[out] out_data Output of the KDF function is returned here. If the
|
||||
* result remains in the device, this can be NULL.
|
||||
* \param[out] out_nonce If the output is encrypted, a 32 byte random nonce
|
||||
* generated by the device is returned here. If output
|
||||
* encryption is not used, this can be NULL.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_kdf(uint8_t mode, uint16_t key_id, const uint32_t details, const uint8_t* message, uint8_t* out_data, uint8_t* out_nonce)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint16_t out_data_size = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (message == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Build the KDF command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
|
||||
// Add details parameter
|
||||
packet.data[0] = details;
|
||||
packet.data[1] = details >> 8;
|
||||
packet.data[2] = details >> 16;
|
||||
packet.data[3] = details >> 24;
|
||||
|
||||
// Add input message
|
||||
if ((mode & KDF_MODE_ALG_MASK) == KDF_MODE_ALG_AES)
|
||||
{
|
||||
// AES algorithm has a fixed message size
|
||||
memcpy(&packet.data[KDF_DETAILS_SIZE], message, AES_DATA_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// All other algorithms encode message size in the last byte of details
|
||||
memcpy(&packet.data[KDF_DETAILS_SIZE], message, packet.data[3]);
|
||||
}
|
||||
|
||||
// Build command
|
||||
if ((status = atKDF(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Run command
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (((mode & KDF_MODE_ALG_MASK) == KDF_MODE_ALG_PRF) && (details & KDF_DETAILS_PRF_TARGET_LEN_64))
|
||||
{
|
||||
out_data_size = 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_data_size = 32;
|
||||
}
|
||||
|
||||
// Return OutData if possible
|
||||
if (out_data != NULL && packet.data[ATCA_COUNT_IDX] >= (ATCA_PACKET_OVERHEAD + out_data_size))
|
||||
{
|
||||
memcpy(out_data, &packet.data[ATCA_RSP_DATA_IDX], out_data_size);
|
||||
}
|
||||
|
||||
// return OutNonce if possible
|
||||
if (out_nonce != NULL && packet.data[ATCA_COUNT_IDX] >= (ATCA_PACKET_OVERHEAD + out_data_size + 32))
|
||||
{
|
||||
memcpy(out_nonce, &packet.data[ATCA_RSP_DATA_IDX + out_data_size], 32);
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Lock command.
|
||||
*
|
||||
* The Lock command prevents future modifications of the Configuration zone,
|
||||
* enables configured policies for Data and OTP zones, and can render
|
||||
* individual slots read-only regardless of configuration.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief The Lock command prevents future modifications of the Configuration
|
||||
* and/or Data and OTP zones. If the device is so configured, then
|
||||
* this command can be used to lock individual data slots. This
|
||||
* command fails if the designated area is already locked.
|
||||
*
|
||||
* \param[in] mode Zone, and/or slot, and summary check (bit 7).
|
||||
* \param[in] summary_crc CRC of the config or data zones. Ignored for
|
||||
* slot locks or when mode bit 7 is set.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock(uint8_t mode, uint16_t summary_crc)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
// build command for lock zone and send
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.param1 = mode;
|
||||
packet.param2 = summary_crc;
|
||||
|
||||
do
|
||||
{
|
||||
if ((status = atLock(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Unconditionally (no CRC required) lock the config zone.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock_config_zone(void)
|
||||
{
|
||||
return atcab_lock(LOCK_ZONE_NO_CRC | LOCK_ZONE_CONFIG, 0);
|
||||
}
|
||||
|
||||
/** \brief Lock the config zone with summary CRC.
|
||||
*
|
||||
* The CRC is calculated over the entire config zone contents. 88 bytes for
|
||||
* ATSHA devices, 128 bytes for ATECC devices. Lock will fail if the provided
|
||||
* CRC doesn't match the internally calculated one.
|
||||
*
|
||||
* \param[in] summary_crc Expected CRC over the config zone.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock_config_zone_crc(uint16_t summary_crc)
|
||||
{
|
||||
return atcab_lock(LOCK_ZONE_CONFIG, summary_crc);
|
||||
}
|
||||
|
||||
/** \brief Unconditionally (no CRC required) lock the data zone (slots and OTP).
|
||||
*
|
||||
* ConfigZone must be locked and DataZone must be unlocked for the zone to be successfully locked.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock_data_zone(void)
|
||||
{
|
||||
return atcab_lock(LOCK_ZONE_NO_CRC | LOCK_ZONE_DATA, 0);
|
||||
}
|
||||
|
||||
/** \brief Lock the data zone (slots and OTP) with summary CRC.
|
||||
*
|
||||
* The CRC is calculated over the concatenated contents of all the slots and
|
||||
* OTP at the end. Private keys (KeyConfig.Private=1) are skipped. Lock will
|
||||
* fail if the provided CRC doesn't match the internally calculated one.
|
||||
*
|
||||
* \param[in] summary_crc Expected CRC over the data zone.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock_data_zone_crc(uint16_t summary_crc)
|
||||
{
|
||||
return atcab_lock(LOCK_ZONE_DATA, summary_crc);
|
||||
}
|
||||
|
||||
/** \brief Lock an individual slot in the data zone on an ATECC device. Not
|
||||
* available for ATSHA devices. Slot must be configured to be slot
|
||||
* lockable (KeyConfig.Lockable=1).
|
||||
*
|
||||
* \param[in] slot Slot to be locked in data zone.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_lock_data_slot(uint16_t slot)
|
||||
{
|
||||
return atcab_lock(((uint8_t)slot << 2) | LOCK_ZONE_DATA_SLOT, 0);
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for MAC command.
|
||||
*
|
||||
* The MAC command computes a SHA-256 digest of a key stored in the device, a
|
||||
* challenge, and other information on the device. The output of this command
|
||||
* is the digest of this message.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes MAC command, which computes a SHA-256 digest of a key
|
||||
* stored in the device, a challenge, and other information on the
|
||||
* device.
|
||||
*
|
||||
* \param[in] mode Controls which fields within the device are used in
|
||||
* the message
|
||||
* \param[in] key_id Key in the CryptoAuth device to use for the MAC
|
||||
* \param[in] challenge Challenge message (32 bytes). May be NULL if mode
|
||||
* indicates a challenge isn't required.
|
||||
* \param[out] digest MAC response is returned here (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_mac(uint8_t mode, uint16_t key_id, const uint8_t* challenge, uint8_t* digest)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
if (digest == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// build mac command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
if (!(mode & MAC_MODE_BLOCK2_TEMPKEY))
|
||||
{
|
||||
if (challenge == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
memcpy(&packet.data[0], challenge, 32); // a 32-byte challenge
|
||||
}
|
||||
|
||||
if ((status = atMAC(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(digest, &packet.data[ATCA_RSP_DATA_IDX], MAC_SIZE);
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,205 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Nonce command.
|
||||
*
|
||||
* The Nonce command generates a nonce for use by a subsequent commands of the
|
||||
* device by combining an internally generated random number with an input value
|
||||
* from the system.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes Nonce command, which loads a random or fixed nonce/data
|
||||
* into the device for use by subsequent commands.
|
||||
*
|
||||
* \param[in] mode Controls the mechanism of the internal RNG or fixed
|
||||
* write.
|
||||
* \param[in] zero Param2, normally 0, but can be used to indicate a
|
||||
* nonce calculation mode (bit 15).
|
||||
* \param[in] num_in Input value to either be included in the nonce
|
||||
* calculation in random modes (20 bytes) or to be
|
||||
* written directly (32 bytes or 64 bytes(ATECC608A))
|
||||
* in pass-through mode.
|
||||
* \param[out] rand_out If using a random mode, the internally generated
|
||||
* 32-byte random number that was used in the nonce
|
||||
* calculation is returned here. Can be NULL if not
|
||||
* needed.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_nonce_base(uint8_t mode, uint16_t zero, const uint8_t *num_in, uint8_t* rand_out)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t nonce_mode = mode & NONCE_MODE_MASK;
|
||||
|
||||
do
|
||||
{
|
||||
// build a nonce command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = zero;
|
||||
|
||||
// Copy the right amount of NumIn data
|
||||
if ((nonce_mode == NONCE_MODE_SEED_UPDATE || nonce_mode == NONCE_MODE_NO_SEED_UPDATE))
|
||||
{
|
||||
memcpy(packet.data, num_in, NONCE_NUMIN_SIZE);
|
||||
}
|
||||
else if (nonce_mode == NONCE_MODE_PASSTHROUGH)
|
||||
{
|
||||
if ((mode & NONCE_MODE_INPUT_LEN_MASK) == NONCE_MODE_INPUT_LEN_64)
|
||||
{
|
||||
memcpy(packet.data, num_in, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy(packet.data, num_in, 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if ((status = atNonce(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((rand_out != NULL) && (packet.data[ATCA_COUNT_IDX] >= 35))
|
||||
{
|
||||
memcpy(&rand_out[0], &packet.data[ATCA_RSP_DATA_IDX], 32);
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Execute a Nonce command in pass-through mode to initialize TempKey
|
||||
* to a specified value.
|
||||
*
|
||||
* \param[in] num_in Data to be loaded into TempKey (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_nonce(const uint8_t *num_in)
|
||||
{
|
||||
return atcab_nonce_base(NONCE_MODE_PASSTHROUGH, 0, num_in, NULL);
|
||||
}
|
||||
|
||||
|
||||
/** \brief Execute a Nonce command in pass-through mode to load one of the
|
||||
* device's internal buffers with a fixed value.
|
||||
*
|
||||
* For the ATECC608A, available targets are TempKey (32 or 64 bytes), Message
|
||||
* Digest Buffer (32 or 64 bytes), or the Alternate Key Buffer (32 bytes). For
|
||||
* all other devices, only TempKey (32 bytes) is available.
|
||||
*
|
||||
* \param[in] target Target device buffer to load. Can be
|
||||
* NONCE_MODE_TARGET_TEMPKEY,
|
||||
* NONCE_MODE_TARGET_MSGDIGBUF, or
|
||||
* NONCE_MODE_TARGET_ALTKEYBUF.
|
||||
* \param[in] num_in Data to load into the buffer.
|
||||
* \param[in] num_in_size Size of num_in in bytes. Can be 32 or 64 bytes
|
||||
* depending on device and target.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_nonce_load(uint8_t target, const uint8_t *num_in, uint16_t num_in_size)
|
||||
{
|
||||
uint8_t mode = NONCE_MODE_PASSTHROUGH | (NONCE_MODE_TARGET_MASK & target);
|
||||
|
||||
if (num_in_size == 32)
|
||||
{
|
||||
mode |= NONCE_MODE_INPUT_LEN_32;
|
||||
}
|
||||
else if (num_in_size == 64)
|
||||
{
|
||||
mode |= NONCE_MODE_INPUT_LEN_64;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
return atcab_nonce_base(mode, 0, num_in, NULL);
|
||||
}
|
||||
|
||||
/** \brief Execute a Nonce command to generate a random nonce combining a host
|
||||
* nonce (num_in) and a device random number.
|
||||
*
|
||||
* \param[in] num_in Host nonce to be combined with the device random
|
||||
* number (20 bytes).
|
||||
* \param[out] rand_out Internally generated 32-byte random number that was
|
||||
* used in the nonce/challenge calculation is returned
|
||||
* here. Can be NULL if not needed.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_nonce_rand(const uint8_t *num_in, uint8_t* rand_out)
|
||||
{
|
||||
return atcab_nonce_base(NONCE_MODE_SEED_UPDATE, 0, num_in, rand_out);
|
||||
}
|
||||
|
||||
/** \brief Execute a Nonce command in pass-through mode to initialize TempKey
|
||||
* to a specified value.
|
||||
*
|
||||
* \param[in] num_in Data to be loaded into TempKey (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_challenge(const uint8_t *num_in)
|
||||
{
|
||||
return atcab_nonce_base(NONCE_MODE_PASSTHROUGH, 0, num_in, NULL);
|
||||
}
|
||||
|
||||
/** \brief Execute a Nonce command to generate a random challenge combining
|
||||
* a host nonce (num_in) and a device random number.
|
||||
*
|
||||
* \param[in] num_in Host nonce to be combined with the device random
|
||||
* number (20 bytes).
|
||||
* \param[out] rand_out Internally generated 32-byte random number that was
|
||||
* used in the nonce/challenge calculation is returned
|
||||
* here. Can be NULL if not needed.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_challenge_seed_update(const uint8_t *num_in, uint8_t* rand_out)
|
||||
{
|
||||
return atcab_nonce_base(NONCE_MODE_SEED_UPDATE, 0, num_in, rand_out);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for PrivWrite command.
|
||||
*
|
||||
* The PrivWrite command is used to write externally generated ECC private keys
|
||||
* into the device.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC108A, ATECC508A, and
|
||||
* ATECC608A. There are differences in the modes that they support. Refer
|
||||
* to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
/** \brief Executes PrivWrite command, to write externally generated ECC
|
||||
* private keys into the device.
|
||||
*
|
||||
* \param[in] key_id Slot to write the external private key into.
|
||||
* \param[in] priv_key External private key (36 bytes) to be written.
|
||||
* The first 4 bytes should be zero for P256 curve.
|
||||
* \param[in] write_key_id Write key slot. Ignored if write_key is NULL.
|
||||
* \param[in] write_key Write key (32 bytes). If NULL, perform an
|
||||
* unencrypted PrivWrite, which is only available when
|
||||
* the data zone is unlocked.
|
||||
* \param[in] num_in 20 byte host nonce to inject into Nonce calculation
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32])
|
||||
{
|
||||
uint8_t num_in[NONCE_NUMIN_SIZE] = { 0 };
|
||||
|
||||
#else
|
||||
ATCA_STATUS atcab_priv_write(uint16_t key_id, const uint8_t priv_key[36], uint16_t write_key_id, const uint8_t write_key[32], const uint8_t num_in[NONCE_NUMIN_SIZE])
|
||||
{
|
||||
#endif
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
atca_nonce_in_out_t nonce_params;
|
||||
atca_gen_dig_in_out_t gen_dig_param;
|
||||
atca_write_mac_in_out_t host_mac_param;
|
||||
atca_temp_key_t temp_key;
|
||||
uint8_t serial_num[32]; // Buffer is larger than the 9 bytes required to make reads easier
|
||||
uint8_t rand_out[RANDOM_NUM_SIZE] = { 0 };
|
||||
uint8_t cipher_text[36] = { 0 };
|
||||
uint8_t host_mac[MAC_SIZE] = { 0 };
|
||||
uint8_t other_data[4] = { 0 };
|
||||
|
||||
if (key_id > 15 || priv_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
if (write_key == NULL)
|
||||
{
|
||||
// Caller requested an unencrypted PrivWrite, which is only allowed when the data zone is unlocked
|
||||
// build an PrivWrite command
|
||||
packet.param1 = 0x00; // Mode is unencrypted write
|
||||
packet.param2 = key_id; // Key ID
|
||||
memcpy(&packet.data[0], priv_key, 36); // Private key
|
||||
memset(&packet.data[36], 0, 32); // MAC (ignored for unencrypted write)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the device SN
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 0, 0, serial_num, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Make the SN continuous by moving SN[4:8] right after SN[0:3]
|
||||
memmove(&serial_num[4], &serial_num[8], 5);
|
||||
|
||||
// Send the random Nonce command
|
||||
if ((status = atcab_nonce_rand(num_in, rand_out)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
memset(&temp_key, 0, sizeof(temp_key));
|
||||
memset(&nonce_params, 0, sizeof(nonce_params));
|
||||
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
|
||||
nonce_params.zero = 0;
|
||||
nonce_params.num_in = &num_in[0];
|
||||
nonce_params.rand_out = rand_out;
|
||||
nonce_params.temp_key = &temp_key;
|
||||
if ((status = atcah_nonce(&nonce_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Supply OtherData so GenDig behavior is the same for keys with SlotConfig.NoMac set
|
||||
other_data[0] = ATCA_GENDIG;
|
||||
other_data[1] = GENDIG_ZONE_DATA;
|
||||
other_data[2] = (uint8_t)(write_key_id);
|
||||
other_data[3] = (uint8_t)(write_key_id >> 8);
|
||||
|
||||
// Send the GenDig command
|
||||
if ((status = atcab_gendig(GENDIG_ZONE_DATA, write_key_id, other_data, sizeof(other_data))) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
// NoMac bit isn't being considered here on purpose to remove having to read SlotConfig.
|
||||
// OtherData is built to get the same result regardless of the NoMac bit.
|
||||
memset(&gen_dig_param, 0, sizeof(gen_dig_param));
|
||||
gen_dig_param.zone = GENDIG_ZONE_DATA;
|
||||
gen_dig_param.sn = serial_num;
|
||||
gen_dig_param.key_id = write_key_id;
|
||||
gen_dig_param.is_key_nomac = false;
|
||||
gen_dig_param.stored_value = write_key;
|
||||
gen_dig_param.other_data = other_data;
|
||||
gen_dig_param.temp_key = &temp_key;
|
||||
if ((status = atcah_gen_dig(&gen_dig_param)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate Auth MAC and cipher text
|
||||
memset(&host_mac_param, 0, sizeof(host_mac_param));
|
||||
host_mac_param.zone = PRIVWRITE_MODE_ENCRYPT;
|
||||
host_mac_param.key_id = key_id;
|
||||
host_mac_param.sn = serial_num;
|
||||
host_mac_param.input_data = &priv_key[0];
|
||||
host_mac_param.encrypted_data = cipher_text;
|
||||
host_mac_param.auth_mac = host_mac;
|
||||
host_mac_param.temp_key = &temp_key;
|
||||
if ((status = atcah_privwrite_auth_mac(&host_mac_param)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// build a write command for encrypted writes
|
||||
packet.param1 = PRIVWRITE_MODE_ENCRYPT; // Mode is encrypted write
|
||||
packet.param2 = key_id; // Key ID
|
||||
memcpy(&packet.data[0], cipher_text, sizeof(cipher_text));
|
||||
memcpy(&packet.data[sizeof(cipher_text)], host_mac, sizeof(host_mac));
|
||||
}
|
||||
|
||||
if ((status = atPrivWrite(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Random command.
|
||||
*
|
||||
* The Random command generates a random number for use by the system.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes Random command, which generates a 32 byte random number
|
||||
* from the CryptoAuth device.
|
||||
*
|
||||
* \param[out] rand_out 32 bytes of random data is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_random(uint8_t *rand_out)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// build an random command
|
||||
packet.param1 = RANDOM_SEED_UPDATE;
|
||||
packet.param2 = 0x0000;
|
||||
|
||||
if ((status = atRandom(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (packet.data[ATCA_COUNT_IDX] != RANDOM_RSP_SIZE)
|
||||
{
|
||||
status = ATCA_RX_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rand_out)
|
||||
{
|
||||
memcpy(rand_out, &packet.data[ATCA_RSP_DATA_IDX], RANDOM_NUM_SIZE);
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,720 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Read command.
|
||||
*
|
||||
* The Read command reads words either 4-byte words or 32-byte blocks from one
|
||||
* of the memory zones of the device. The data may optionally be encrypted
|
||||
* before being returned to the system.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
|
||||
/** \brief Executes Read command, which reads either 4 or 32 bytes of data from
|
||||
* a given slot, configuration zone, or the OTP zone.
|
||||
*
|
||||
* When reading a slot or OTP, data zone must be locked and the slot
|
||||
* configuration must not be secret for a slot to be successfully read.
|
||||
*
|
||||
* \param[in] zone Zone to be read from device. Options are
|
||||
* ATCA_ZONE_CONFIG, ATCA_ZONE_OTP, or ATCA_ZONE_DATA.
|
||||
* \param[in] slot Slot number for data zone and ignored for other zones.
|
||||
* \param[in] block 32 byte block index within the zone.
|
||||
* \param[in] offset 4 byte work index within the block. Ignored for 32 byte
|
||||
* reads.
|
||||
* \param[out] data Read data is returned here.
|
||||
* \param[in] len Length of the data to be read. Must be either 4 or 32.
|
||||
*
|
||||
* returns ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_zone(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, uint8_t *data, uint8_t len)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint16_t addr;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the input parameters
|
||||
if (data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (len != 4 && len != 32)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// The get address function checks the remaining variables
|
||||
if ((status = atcab_get_addr(zone, slot, block, offset, &addr)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// If there are 32 bytes to read, then OR the bit into the mode
|
||||
if (len == ATCA_BLOCK_SIZE)
|
||||
{
|
||||
zone = zone | ATCA_ZONE_READWRITE_32;
|
||||
}
|
||||
|
||||
// build a read command
|
||||
packet.param1 = zone;
|
||||
packet.param2 = addr;
|
||||
|
||||
if ((status = atRead(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(data, &packet.data[1], len);
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
/** \brief Executes Read command, which reads the 9 byte serial number of the
|
||||
* device from the config zone.
|
||||
*
|
||||
* \param[out] serial_number 9 byte serial number is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_serial_number(uint8_t* serial_number)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t read_buf[ATCA_BLOCK_SIZE];
|
||||
|
||||
if (!serial_number)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 0, 0, read_buf, ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
memcpy(&serial_number[0], &read_buf[0], 4);
|
||||
memcpy(&serial_number[4], &read_buf[8], 5);
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
/** \brief Executes Read command, which reads the configuration zone to see if
|
||||
* the specified slot is locked.
|
||||
*
|
||||
* \param[in] slot Slot to query for locked (slot 0-15)
|
||||
* \param[out] is_locked Lock state returned here. True if locked.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_is_slot_locked(uint16_t slot, bool *is_locked)
|
||||
{
|
||||
ATCA_STATUS ret = ATCA_GEN_FAIL;
|
||||
uint8_t data[ATCA_WORD_SIZE];
|
||||
uint16_t slot_locked;
|
||||
|
||||
do
|
||||
{
|
||||
if (slot > 15)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (is_locked == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Read the word with the lock bytes ( SlotLock[2], RFU[2] ) (config block = 2, word offset = 6)
|
||||
if ((ret = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 2 /*block*/, 6 /*offset*/, data, ATCA_WORD_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
slot_locked = ((uint16_t)data[0]) | ((uint16_t)data[1] << 8);
|
||||
*is_locked = ((slot_locked & (1 << slot)) == 0);
|
||||
}
|
||||
while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** \brief Executes Read command, which reads the configuration zone to see if
|
||||
* the specified zone is locked.
|
||||
*
|
||||
* \param[in] zone The zone to query for locked (use LOCK_ZONE_CONFIG or
|
||||
* LOCK_ZONE_DATA).
|
||||
* \param[out] is_locked Lock state returned here. True if locked.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_is_locked(uint8_t zone, bool *is_locked)
|
||||
{
|
||||
ATCA_STATUS ret = ATCA_GEN_FAIL;
|
||||
uint8_t data[ATCA_WORD_SIZE];
|
||||
|
||||
do
|
||||
{
|
||||
if (is_locked == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Read the word with the lock bytes (UserExtra, Selector, LockValue, LockConfig) (config block = 2, word offset = 5)
|
||||
if ((ret = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 2 /*block*/, 5 /*offset*/, data, ATCA_WORD_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Determine the index into the word_data based on the zone we are querying for
|
||||
switch (zone)
|
||||
{
|
||||
case LOCK_ZONE_CONFIG: *is_locked = (data[3] != 0x55); break;
|
||||
case LOCK_ZONE_DATA: *is_locked = (data[2] != 0x55); break;
|
||||
default: ret = ATCA_BAD_PARAM; break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** \brief Executes Read command on a slot configured for encrypted reads and
|
||||
* decrypts the data to return it as plaintext.
|
||||
*
|
||||
* Data zone must be locked for this command to succeed. Can only read 32 byte
|
||||
* blocks.
|
||||
*
|
||||
* \param[in] key_id The slot ID to read from.
|
||||
* \param[in] block Index of the 32 byte block within the slot to read.
|
||||
* \param[out] data Decrypted (plaintext) data from the read is returned
|
||||
* here (32 bytes).
|
||||
* \param[in] enc_key 32 byte ReadKey for the slot being read.
|
||||
* \param[in] enc_key_id KeyID of the ReadKey being used.
|
||||
* \param[in] num_in 20 byte host nonce to inject into Nonce calculation
|
||||
*
|
||||
* returns ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_read_enc(uint16_t key_id, uint8_t block, uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id)
|
||||
{
|
||||
uint8_t num_in[NONCE_NUMIN_SIZE] = { 0 };
|
||||
|
||||
#else
|
||||
ATCA_STATUS atcab_read_enc(uint16_t key_id, uint8_t block, uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE])
|
||||
{
|
||||
#endif
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t zone = ATCA_ZONE_DATA | ATCA_ZONE_READWRITE_32;
|
||||
atca_nonce_in_out_t nonce_params;
|
||||
atca_gen_dig_in_out_t gen_dig_param;
|
||||
atca_temp_key_t temp_key;
|
||||
uint8_t serial_num[32];
|
||||
uint8_t rand_out[RANDOM_NUM_SIZE] = { 0 };
|
||||
uint8_t other_data[4] = { 0 };
|
||||
int i = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Verify inputs parameters
|
||||
if (data == NULL || enc_key == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the device SN
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 0, 0, serial_num, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Make the SN continuous by moving SN[4:8] right after SN[0:3]
|
||||
memmove(&serial_num[4], &serial_num[8], 5);
|
||||
|
||||
// Send the random Nonce command
|
||||
if ((status = atcab_nonce_rand(num_in, rand_out)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Nonce failed");
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
memset(&temp_key, 0, sizeof(temp_key));
|
||||
memset(&nonce_params, 0, sizeof(nonce_params));
|
||||
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
|
||||
nonce_params.zero = 0;
|
||||
nonce_params.num_in = (uint8_t*)&num_in[0];
|
||||
nonce_params.rand_out = (uint8_t*)&rand_out;
|
||||
nonce_params.temp_key = &temp_key;
|
||||
if ((status = atcah_nonce(&nonce_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Calc TempKey failed");
|
||||
}
|
||||
|
||||
// Supply OtherData so GenDig behavior is the same for keys with SlotConfig.NoMac set
|
||||
other_data[0] = ATCA_GENDIG;
|
||||
other_data[1] = GENDIG_ZONE_DATA;
|
||||
other_data[2] = (uint8_t)(enc_key_id);
|
||||
other_data[3] = (uint8_t)(enc_key_id >> 8);
|
||||
|
||||
// Send the GenDig command
|
||||
if ((status = atcab_gendig(GENDIG_ZONE_DATA, enc_key_id, other_data, sizeof(other_data))) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "GenDig failed");
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
// NoMac bit isn't being considered here on purpose to remove having to read SlotConfig.
|
||||
// OtherData is built to get the same result regardless of the NoMac bit.
|
||||
memset(&gen_dig_param, 0, sizeof(gen_dig_param));
|
||||
gen_dig_param.key_id = enc_key_id;
|
||||
gen_dig_param.is_key_nomac = false;
|
||||
gen_dig_param.sn = serial_num;
|
||||
gen_dig_param.stored_value = enc_key;
|
||||
gen_dig_param.zone = GENDIG_ZONE_DATA;
|
||||
gen_dig_param.other_data = other_data;
|
||||
gen_dig_param.temp_key = &temp_key;
|
||||
if ((status = atcah_gen_dig(&gen_dig_param)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "");
|
||||
}
|
||||
|
||||
// Read Encrypted
|
||||
if ((status = atcab_read_zone(zone, key_id, block, 0, data, ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Read encrypted failed");
|
||||
}
|
||||
|
||||
// Decrypt
|
||||
for (i = 0; i < ATCA_BLOCK_SIZE; i++)
|
||||
{
|
||||
data[i] = data[i] ^ temp_key.value[i];
|
||||
}
|
||||
|
||||
status = ATCA_SUCCESS;
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes Read command to read the complete device configuration
|
||||
* zone.
|
||||
*
|
||||
* \param[out] config_data Configuration zone data is returned here. 88 bytes
|
||||
* for ATSHA devices, 128 bytes for ATECC devices.
|
||||
*
|
||||
* \returns ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_config_zone(uint8_t* config_data)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
|
||||
// Verify the inputs
|
||||
if (config_data == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (_gDevice->mIface->mIfaceCFG->devtype == ATSHA204A)
|
||||
{
|
||||
status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, 0x00, config_data, ATCA_SHA_CONFIG_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, 0x00, config_data, ATCA_ECC_CONFIG_SIZE);
|
||||
}
|
||||
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Compares a specified configuration zone with the configuration zone
|
||||
* currently on the device.
|
||||
*
|
||||
* This only compares the static portions of the configuration zone and skips
|
||||
* those that are unique per device (first 16 bytes) and areas that can change
|
||||
* after the configuration zone has been locked (e.g. LastKeyUse).
|
||||
*
|
||||
* \param[in] config_data Full configuration data to compare the device
|
||||
* against.
|
||||
* \param[out] same_config Result is returned here. True if the static portions
|
||||
* on the configuration zones are the same.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_cmp_config_zone(uint8_t* config_data, bool* same_config)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t device_config_data[ATCA_ECC_CONFIG_SIZE]; /** Max for all configs */
|
||||
size_t config_size = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the inputs
|
||||
if ((config_data == NULL) || (same_config == NULL))
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Invalid Parameters");
|
||||
}
|
||||
// Set the boolean to false
|
||||
*same_config = false;
|
||||
|
||||
// Read all of the configuration bytes from the device
|
||||
if ((status = atcab_read_config_zone(device_config_data)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Read config zone failed");
|
||||
}
|
||||
|
||||
/* Get the config size of the device being tested */
|
||||
if (ATCA_SUCCESS != (status = atcab_get_zone_size(ATCA_ZONE_CONFIG, 0, &config_size)))
|
||||
{
|
||||
BREAK(status, "Failed to get config zone size");
|
||||
}
|
||||
|
||||
/* Compare the lower writable bytes (16-51) */
|
||||
if (memcmp(&device_config_data[16], &config_data[16], 52 - 16))
|
||||
{
|
||||
/* Difference found */
|
||||
break;
|
||||
}
|
||||
|
||||
if (_gDevice->mIface->mIfaceCFG->devtype == ATECC608A)
|
||||
{
|
||||
/* Skip Counter[0], Counter[1], which can change during operation */
|
||||
|
||||
/* Compare UseLock through Reserved (68 --> 83) */
|
||||
if (memcmp(&device_config_data[68], &config_data[68], 84 - 68))
|
||||
{
|
||||
/* Difference found */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Skip UserExtra, UserExtraAdd, LockValue, LockConfig, and SlotLocked */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Skip the counter & LastKeyUse bytes [52-83] */
|
||||
/* Skip User Extra & Selector [84-85] */
|
||||
/* Skip all lock bytes [86-89] */
|
||||
}
|
||||
|
||||
if (90 < config_size)
|
||||
{
|
||||
/* Compare the upper writable bytes (90-config_size) */
|
||||
if (memcmp(&device_config_data[90], &config_data[90], config_size - 90))
|
||||
{
|
||||
/* Difference found */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* All Matched */
|
||||
*same_config = true;
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Executes Read command to read a 64 byte ECDSA P256 signature from a
|
||||
* slot configured for clear reads.
|
||||
*
|
||||
* \param[in] slot Slot number to read from. Only slots 8 to 15 are large
|
||||
* enough for a signature.
|
||||
* \param[out] sig Signature will be returned here (64 bytes). Format will be
|
||||
* the 32 byte R and S big-endian integers concatenated.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_sig(uint16_t slot, uint8_t* sig)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the value of the slot
|
||||
if (sig == NULL || slot < 8 || slot > 15)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Read the first block
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_DATA, slot, 0, 0, &sig[0], ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the second block
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_DATA, slot, 1, 0, &sig[ATCA_BLOCK_SIZE], ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes Read command to read an ECC P256 public key from a slot
|
||||
* configured for clear reads.
|
||||
*
|
||||
* This function assumes the public key is stored using the ECC public key
|
||||
* format specified in the datasheet.
|
||||
*
|
||||
* \param[in] slot Slot number to read from. Only slots 8 to 15 are
|
||||
* large enough for a public key.
|
||||
* \param[out] public_key Public key is returned here (64 bytes). Format will
|
||||
* be the 32 byte X and Y big-endian integers
|
||||
* concatenated.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_pubkey(uint16_t slot, uint8_t *public_key)
|
||||
{
|
||||
ATCA_STATUS ret = ATCA_GEN_FAIL;
|
||||
uint8_t read_buf[ATCA_BLOCK_SIZE];
|
||||
uint8_t block = 0;
|
||||
uint8_t offset = 0;
|
||||
uint8_t cpy_index = 0;
|
||||
uint8_t cpy_size = 0;
|
||||
uint8_t read_index = 0;
|
||||
|
||||
// Check the pointers
|
||||
if (public_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
// Check the value of the slot
|
||||
if (slot < 8 || slot > 0xF)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// The 64 byte P256 public key gets written to a 72 byte slot in the following pattern
|
||||
// | Block 1 | Block 2 | Block 3 |
|
||||
// | Pad: 4 Bytes | PubKey[0:27] | PubKey[28:31] | Pad: 4 Bytes | PubKey[32:55] | PubKey[56:63] |
|
||||
|
||||
// Read the block
|
||||
block = 0;
|
||||
if ((ret = atcab_read_zone(ATCA_ZONE_DATA, slot, block, offset, read_buf, ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy. Account for 4 byte pad
|
||||
cpy_size = ATCA_BLOCK_SIZE - ATCA_PUB_KEY_PAD;
|
||||
read_index = ATCA_PUB_KEY_PAD;
|
||||
memcpy(&public_key[cpy_index], &read_buf[read_index], cpy_size);
|
||||
cpy_index += cpy_size;
|
||||
|
||||
// Read the next block
|
||||
block = 1;
|
||||
if ((ret = atcab_read_zone(ATCA_ZONE_DATA, slot, block, offset, read_buf, ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy. First four bytes
|
||||
cpy_size = ATCA_PUB_KEY_PAD;
|
||||
read_index = 0;
|
||||
memcpy(&public_key[cpy_index], &read_buf[read_index], cpy_size);
|
||||
cpy_index += cpy_size;
|
||||
// Copy. Skip four bytes
|
||||
read_index = ATCA_PUB_KEY_PAD + ATCA_PUB_KEY_PAD;
|
||||
cpy_size = ATCA_BLOCK_SIZE - read_index;
|
||||
memcpy(&public_key[cpy_index], &read_buf[read_index], cpy_size);
|
||||
cpy_index += cpy_size;
|
||||
|
||||
// Read the next block
|
||||
block = 2;
|
||||
if ((ret = atcab_read_zone(ATCA_ZONE_DATA, slot, block, offset, read_buf, ATCA_BLOCK_SIZE)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Copy. The remaining 8 bytes
|
||||
cpy_size = ATCA_PUB_KEY_PAD + ATCA_PUB_KEY_PAD;
|
||||
read_index = 0;
|
||||
memcpy(&public_key[cpy_index], &read_buf[read_index], cpy_size);
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** \brief Used to read an arbitrary number of bytes from any zone configured
|
||||
* for clear reads.
|
||||
*
|
||||
* This function will issue the Read command as many times as is required to
|
||||
* read the requested data.
|
||||
*
|
||||
* \param[in] zone Zone to read data from. Option are ATCA_ZONE_CONFIG(0),
|
||||
* ATCA_ZONE_OTP(1), or ATCA_ZONE_DATA(2).
|
||||
* \param[in] slot Slot number to read from if zone is ATCA_ZONE_DATA(2).
|
||||
* Ignored for all other zones.
|
||||
* \param[in] offset Byte offset within the zone to read from.
|
||||
* \param[out] data Read data is returned here.
|
||||
* \param[in] length Number of bytes to read starting from the offset.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_read_bytes_zone(uint8_t zone, uint16_t slot, size_t offset, uint8_t *data, size_t length)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
size_t zone_size = 0;
|
||||
uint8_t read_buf[32];
|
||||
size_t data_idx = 0;
|
||||
size_t cur_block = 0;
|
||||
size_t cur_offset = 0;
|
||||
uint8_t read_size = ATCA_BLOCK_SIZE;
|
||||
size_t read_buf_idx = 0;
|
||||
size_t copy_length = 0;
|
||||
size_t read_offset = 0;
|
||||
|
||||
if (zone != ATCA_ZONE_CONFIG && zone != ATCA_ZONE_OTP && zone != ATCA_ZONE_DATA)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (zone == ATCA_ZONE_DATA && slot > 15)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return ATCA_SUCCESS; // Always succeed reading 0 bytes
|
||||
}
|
||||
if (data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = atcab_get_zone_size(zone, slot, &zone_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (offset + length > zone_size)
|
||||
{
|
||||
return ATCA_BAD_PARAM; // Can't read past the end of a zone
|
||||
|
||||
}
|
||||
cur_block = offset / ATCA_BLOCK_SIZE;
|
||||
|
||||
while (data_idx < length)
|
||||
{
|
||||
if (read_size == ATCA_BLOCK_SIZE && zone_size - cur_block * ATCA_BLOCK_SIZE < ATCA_BLOCK_SIZE)
|
||||
{
|
||||
// We have less than a block to read and can't read past the end of the zone, switch to word reads
|
||||
read_size = ATCA_WORD_SIZE;
|
||||
cur_offset = ((data_idx + offset) / ATCA_WORD_SIZE) % (ATCA_BLOCK_SIZE / ATCA_WORD_SIZE);
|
||||
}
|
||||
|
||||
// Read next chunk of data
|
||||
status = atcab_read_zone(
|
||||
zone,
|
||||
slot,
|
||||
(uint8_t)cur_block,
|
||||
(uint8_t)cur_offset,
|
||||
read_buf,
|
||||
read_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate where in the read buffer we need data from
|
||||
read_offset = cur_block * ATCA_BLOCK_SIZE + cur_offset * ATCA_WORD_SIZE;
|
||||
if (read_offset < offset)
|
||||
{
|
||||
read_buf_idx = offset - read_offset; // Read data starts before the requested chunk
|
||||
}
|
||||
else
|
||||
{
|
||||
read_buf_idx = 0; // Read data is within the requested chunk
|
||||
|
||||
}
|
||||
// Calculate how much data from the read buffer we want to copy
|
||||
if (length - data_idx < read_size - read_buf_idx)
|
||||
{
|
||||
copy_length = length - data_idx;
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_length = read_size - read_buf_idx;
|
||||
}
|
||||
|
||||
memcpy(&data[data_idx], &read_buf[read_buf_idx], copy_length);
|
||||
data_idx += copy_length;
|
||||
if (read_size == ATCA_BLOCK_SIZE)
|
||||
{
|
||||
cur_block += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_offset += 1;
|
||||
}
|
||||
}
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for SecureBoot command.
|
||||
*
|
||||
* The SecureBoot command provides support for secure boot of an external MCU
|
||||
* or MPU.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
/** \brief Executes Secure Boot command, which provides support for secure
|
||||
* boot of an external MCU or MPU.
|
||||
*
|
||||
* \param[in] mode Mode determines what operations the SecureBoot
|
||||
* command performs.
|
||||
* \param[in] param2 Not used, must be 0.
|
||||
* \param[in] digest Digest of the code to be verified (32 bytes).
|
||||
* \param[in] signature Signature of the code to be verified (64 bytes). Can
|
||||
* be NULL when using the FullStore mode.
|
||||
* \param[out] mac Validating MAC will be returned here (32 bytes). Can
|
||||
* be NULL if not required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_secureboot(uint8_t mode, uint16_t param2, const uint8_t* digest, const uint8_t* signature, uint8_t* mac)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
if (digest == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
packet.param1 = mode;
|
||||
packet.param2 = param2;
|
||||
|
||||
memcpy(packet.data, digest, SECUREBOOT_DIGEST_SIZE);
|
||||
|
||||
if (signature)
|
||||
{
|
||||
memcpy(&packet.data[SECUREBOOT_DIGEST_SIZE], signature, SECUREBOOT_SIGNATURE_SIZE);
|
||||
}
|
||||
|
||||
if ((status = atSecureBoot(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mac != NULL) && (packet.data[ATCA_COUNT_IDX] >= SECUREBOOT_RSP_SIZE_MAC))
|
||||
{
|
||||
memcpy(mac, &packet.data[ATCA_RSP_DATA_IDX], SECUREBOOT_MAC_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes Secure Boot command with encrypted digest and validated
|
||||
* MAC response using the IO protection key.
|
||||
*
|
||||
* \param[in] mode Mode determines what operations the SecureBoot
|
||||
* command performs.
|
||||
* \param[in] digest Digest of the code to be verified (32 bytes).
|
||||
* This is the plaintext digest (not encrypted).
|
||||
* \param[in] signature Signature of the code to be verified (64 bytes). Can
|
||||
* be NULL when using the FullStore mode.
|
||||
* \param[in] num_in Host nonce (20 bytes).
|
||||
* \param[in] io_key IO protection key (32 bytes).
|
||||
* \param[out] is_verified Verify result is returned here.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_secureboot_mac(uint8_t mode, const uint8_t* digest, const uint8_t* signature, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
atca_temp_key_t tempkey;
|
||||
atca_nonce_in_out_t nonce_params;
|
||||
atca_secureboot_enc_in_out_t sboot_enc_params;
|
||||
atca_secureboot_mac_in_out_t sboot_mac_params;
|
||||
uint8_t rand_out[RANDOM_NUM_SIZE];
|
||||
uint8_t key[ATCA_KEY_SIZE];
|
||||
uint8_t digest_enc[SECUREBOOT_DIGEST_SIZE];
|
||||
uint8_t mac[SECUREBOOT_MAC_SIZE];
|
||||
uint8_t host_mac[SECUREBOOT_MAC_SIZE];
|
||||
uint8_t buf[2];
|
||||
|
||||
do
|
||||
{
|
||||
if (is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
*is_verified = false;
|
||||
|
||||
if (digest == NULL || num_in == NULL || io_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Setup Nonce command to create nonce combining host (num_in) and
|
||||
// device (RNG) nonces
|
||||
memset(&tempkey, 0, sizeof(tempkey));
|
||||
memset(&nonce_params, 0, sizeof(nonce_params));
|
||||
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
|
||||
nonce_params.zero = 0;
|
||||
nonce_params.num_in = num_in;
|
||||
nonce_params.rand_out = rand_out;
|
||||
nonce_params.temp_key = &tempkey;
|
||||
|
||||
// Initialize TempKey with nonce
|
||||
status = atcab_nonce_base(nonce_params.mode, nonce_params.zero, nonce_params.num_in, rand_out);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate nonce (TempKey) value
|
||||
status = atcah_nonce(&nonce_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Encrypt the digest
|
||||
memset(&sboot_enc_params, 0, sizeof(sboot_enc_params));
|
||||
sboot_enc_params.digest = digest;
|
||||
sboot_enc_params.io_key = io_key;
|
||||
sboot_enc_params.temp_key = &tempkey;
|
||||
sboot_enc_params.hashed_key = key;
|
||||
sboot_enc_params.digest_enc = digest_enc;
|
||||
status = atcah_secureboot_enc(&sboot_enc_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Prepare MAC calculator
|
||||
memset(&sboot_mac_params, 0, sizeof(sboot_mac_params));
|
||||
sboot_mac_params.mode = mode | SECUREBOOT_MODE_ENC_MAC_FLAG;
|
||||
sboot_mac_params.param2 = 0;
|
||||
sboot_mac_params.hashed_key = sboot_enc_params.hashed_key;
|
||||
sboot_mac_params.digest = digest;
|
||||
sboot_mac_params.signature = signature;
|
||||
sboot_mac_params.mac = host_mac;
|
||||
|
||||
// Run the SecureBoot command
|
||||
status = atcab_secureboot(sboot_mac_params.mode, sboot_mac_params.param2, digest_enc, signature, mac);
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
// Verify failed
|
||||
*is_verified = false;
|
||||
status = ATCA_SUCCESS; // Still consider this a command success
|
||||
break;
|
||||
}
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the SecureBootConfig field out of the configuration zone, which
|
||||
// is required to properly calculate the expected MAC
|
||||
status = atcab_read_bytes_zone(ATCA_ZONE_CONFIG, 0, SECUREBOOTCONFIG_OFFSET, buf, 2);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
sboot_mac_params.secure_boot_config = (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
|
||||
|
||||
// Calculate the expected MAC
|
||||
status = atcah_secureboot_mac(&sboot_mac_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
*is_verified = (memcmp(host_mac, mac, SECUREBOOT_MAC_SIZE) == 0);
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for SelfTest command.
|
||||
*
|
||||
* The SelfTest command performs a test of one or more of the cryptographic
|
||||
* engines within the device.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC608A. Refer to device
|
||||
* datasheet for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes the SelfTest command, which performs a test of one or more
|
||||
* of the cryptographic engines within the ATECC608A chip.
|
||||
*
|
||||
* \param[in] mode Functions to test. Can be a bit field combining any
|
||||
* of the following: SELFTEST_MODE_RNG,
|
||||
* SELFTEST_MODE_ECDSA_VERIFY, SELFTEST_MODE_ECDSA_SIGN,
|
||||
* SELFTEST_MODE_ECDH, SELFTEST_MODE_AES,
|
||||
* SELFTEST_MODE_SHA, SELFTEST_MODE_ALL.
|
||||
* \param[in] param2 Currently unused, should be 0.
|
||||
* \param[out] result Results are returned here as a bit field.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_selftest(uint8_t mode, uint16_t param2, uint8_t* result)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t response = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// build a SelfTest command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = param2;
|
||||
|
||||
if ((status = atSelfTest(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = atca_execute_command(&packet, _gDevice);
|
||||
|
||||
// This command is a little awkward, because it returns its status as
|
||||
// a single byte, which can be hard to differentiate from an actual
|
||||
// error code.
|
||||
|
||||
response = packet.data[ATCA_RSP_DATA_IDX];
|
||||
|
||||
if (response & !mode)
|
||||
{
|
||||
// The response has bits set outside of the bit field requested by
|
||||
// the mode. This indicates an actual error rather than a self test
|
||||
// failure.
|
||||
return status; // Return the translated status.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Here, we have the possibility of ambiguous results, where some
|
||||
// error codes can't be differentiated from self test failures.
|
||||
// We assume self-test failures.
|
||||
if (result)
|
||||
{
|
||||
*result = response;
|
||||
}
|
||||
|
||||
// Self tests might have failed, but we returned success because
|
||||
// the results are returned in result.
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,508 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for SHA command.
|
||||
*
|
||||
* The SHA command Computes a SHA-256 or HMAC/SHA digest for general purpose
|
||||
* use by the host system.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total_msg_size; //!< Total number of message bytes processed
|
||||
uint32_t block_size; //!< Number of bytes in current block
|
||||
uint8_t block[ATCA_SHA256_BLOCK_SIZE * 2]; //!< Unprocessed message storage
|
||||
} hw_sha256_ctx;
|
||||
|
||||
/** \brief Executes SHA command, which computes a SHA-256 or HMAC/SHA-256
|
||||
* digest for general purpose use by the host system.
|
||||
*
|
||||
* Only the Start(0) and Compute(1) modes are available for ATSHA devices.
|
||||
*
|
||||
* \param[in] mode SHA command mode Start(0), Update/Compute(1),
|
||||
* End(2), Public(3), HMACstart(4), HMACend(5),
|
||||
* Read_Context(6), or Write_Context(7). Also
|
||||
* message digest target location for the
|
||||
* ATECC608A.
|
||||
* \param[in] length Number of bytes in the message parameter or
|
||||
* KeySlot for the HMAC key if Mode is
|
||||
* HMACstart(4) or Public(3).
|
||||
* \param[in] message Message bytes to be hashed or Write_Context if
|
||||
* restoring a context on the ATECC608A. Can be
|
||||
* NULL if not required by the mode.
|
||||
* \param[out] data_out Data returned by the command (digest or
|
||||
* context).
|
||||
* \param[inout] data_out_size As input, the size of the data_out buffer. As
|
||||
* output, the number of bytes returned in
|
||||
* data_out.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_base(uint8_t mode, uint16_t length, const uint8_t* message, uint8_t* data_out, uint16_t* data_out_size)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t cmd_mode = (mode & SHA_MODE_MASK);
|
||||
|
||||
if (cmd_mode != SHA_MODE_SHA256_PUBLIC && cmd_mode != SHA_MODE_HMAC_START && length > 0 && message == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM; // message data indicated, but nothing provided
|
||||
}
|
||||
if (data_out != NULL && data_out_size == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
//Build Command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = length;
|
||||
|
||||
if (cmd_mode != SHA_MODE_SHA256_PUBLIC && cmd_mode != SHA_MODE_HMAC_START)
|
||||
{
|
||||
memcpy(packet.data, message, length);
|
||||
}
|
||||
|
||||
if ((status = atSHA(ca_cmd, &packet, length)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((data_out != NULL) && (packet.data[ATCA_COUNT_IDX] > 4))
|
||||
{
|
||||
if (packet.data[ATCA_COUNT_IDX] - ATCA_PACKET_OVERHEAD > *data_out_size)
|
||||
{
|
||||
status = ATCA_SMALL_BUFFER;
|
||||
break;
|
||||
}
|
||||
*data_out_size = packet.data[ATCA_COUNT_IDX] - ATCA_PACKET_OVERHEAD;
|
||||
memcpy(data_out, &packet.data[ATCA_RSP_DATA_IDX], *data_out_size);
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to initialize SHA-256 calculation engine
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_start(void)
|
||||
{
|
||||
return atcab_sha_base(SHA_MODE_SHA256_START, 0, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to add 64 bytes of message data to the current
|
||||
* context.
|
||||
*
|
||||
* \param[in] message 64 bytes of message data to add to add to operation.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_update(const uint8_t *message)
|
||||
{
|
||||
return atcab_sha_base(SHA_MODE_SHA256_UPDATE, 64, message, NULL, NULL);
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to complete SHA-256 or HMAC/SHA-256 operation.
|
||||
*
|
||||
* \param[out] digest Digest from SHA-256 or HMAC/SHA-256 will be returned
|
||||
* here (32 bytes).
|
||||
* \param[in] length Length of any remaining data to include in hash. Max 64
|
||||
* bytes.
|
||||
* \param[in] message Remaining data to include in hash. NULL if length is 0.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_end(uint8_t *digest, uint16_t length, const uint8_t *message)
|
||||
{
|
||||
uint16_t digest_size = 32;
|
||||
|
||||
return atcab_sha_base(SHA_MODE_SHA256_END, length, message, digest, &digest_size);
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to read the SHA-256 context back. Only for
|
||||
* ATECC608A with SHA-256 contexts. HMAC not supported.
|
||||
*
|
||||
* \param[out] context Context data is returned here.
|
||||
* \param[inout] context_size As input, the size of the context buffer in
|
||||
* bytes. As output, the size of the returned
|
||||
* context data.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_read_context(uint8_t* context, uint16_t* context_size)
|
||||
{
|
||||
return atcab_sha_base(SHA_MODE_READ_CONTEXT, 0, NULL, context, context_size);
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to write (restore) a SHA-256 context into the
|
||||
* the device. Only supported for ATECC608A with SHA-256 contexts.
|
||||
*
|
||||
* \param[in] context Context data to be restored.
|
||||
* \param[in] context_size Size of the context data in bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_write_context(const uint8_t* context, uint16_t context_size)
|
||||
{
|
||||
return atcab_sha_base(SHA_MODE_WRITE_CONTEXT, context_size, context, NULL, NULL);
|
||||
}
|
||||
|
||||
/** \brief Use the SHA command to compute a SHA-256 digest.
|
||||
*
|
||||
* \param[in] length Size of message parameter in bytes.
|
||||
* \param[in] message Message data to be hashed.
|
||||
* \param[out] digest Digest is returned here (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha(uint16_t length, const uint8_t *message, uint8_t *digest)
|
||||
{
|
||||
return atcab_hw_sha2_256(message, length, digest);
|
||||
}
|
||||
|
||||
/** \brief Initialize a SHA context for performing a hardware SHA-256 operation
|
||||
* on a device. Note that only one SHA operation can be run at a time.
|
||||
*
|
||||
* \param[in] ctx SHA256 context
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hw_sha2_256_init(atca_sha256_ctx_t* ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return atcab_sha_start();
|
||||
}
|
||||
|
||||
/** \brief Add message data to a SHA context for performing a hardware SHA-256
|
||||
* operation on a device.
|
||||
*
|
||||
* \param[in] ctx SHA256 context
|
||||
* \param[in] data Message data to be added to hash.
|
||||
* \param[in] data_size Size of data in bytes.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hw_sha2_256_update(atca_sha256_ctx_t* ctx, const uint8_t* data, size_t data_size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint32_t block_count;
|
||||
uint32_t rem_size = ATCA_SHA256_BLOCK_SIZE - ctx->block_size;
|
||||
uint32_t copy_size = data_size > rem_size ? rem_size : (uint32_t)data_size;
|
||||
uint32_t i = 0;
|
||||
|
||||
// Copy data into current block
|
||||
memcpy(&ctx->block[ctx->block_size], data, copy_size);
|
||||
|
||||
if (ctx->block_size + data_size < ATCA_SHA256_BLOCK_SIZE)
|
||||
{
|
||||
// Not enough data to finish off the current block
|
||||
ctx->block_size += (uint32_t)data_size;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
// Process the current block
|
||||
status = atcab_sha_update(ctx->block);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Process any additional blocks
|
||||
data_size -= copy_size; // Adjust to the remaining message bytes
|
||||
block_count = (uint32_t)(data_size / ATCA_SHA256_BLOCK_SIZE);
|
||||
for (i = 0; i < block_count; i++)
|
||||
{
|
||||
status = atcab_sha_update(&data[copy_size + i * ATCA_SHA256_BLOCK_SIZE]);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Save any remaining data
|
||||
ctx->total_msg_size += (block_count + 1) * ATCA_SHA256_BLOCK_SIZE;
|
||||
ctx->block_size = data_size % ATCA_SHA256_BLOCK_SIZE;
|
||||
memcpy(ctx->block, &data[copy_size + block_count * ATCA_SHA256_BLOCK_SIZE], ctx->block_size);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Finish SHA-256 digest for a SHA context for performing a hardware
|
||||
* SHA-256 operation on a device.
|
||||
*
|
||||
* \param[in] ctx SHA256 context
|
||||
* \param[out] digest SHA256 digest is returned here (32 bytes)
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hw_sha2_256_finish(atca_sha256_ctx_t* ctx, uint8_t* digest)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint32_t msg_size_bits;
|
||||
uint32_t pad_zero_count;
|
||||
uint16_t digest_size;
|
||||
|
||||
if (_gDevice->mIface->mIfaceCFG->devtype == ATSHA204A)
|
||||
{
|
||||
// ATSHA204A only implements the raw 64-byte block operation, but
|
||||
// doesn't add in the final footer information. So we do that manually
|
||||
// here.
|
||||
|
||||
// Calculate the total message size in bits
|
||||
ctx->total_msg_size += ctx->block_size;
|
||||
msg_size_bits = (ctx->total_msg_size * 8);
|
||||
|
||||
// Calculate the number of padding zero bytes required between the 1 bit byte and the ATCA_SHA256_BLOCK_SIZEbit message size in bits.
|
||||
pad_zero_count = (ATCA_SHA256_BLOCK_SIZE - ((ctx->block_size + 9) % ATCA_SHA256_BLOCK_SIZE)) % ATCA_SHA256_BLOCK_SIZE;
|
||||
|
||||
// Append a single 1 bit
|
||||
ctx->block[ctx->block_size++] = 0x80;
|
||||
|
||||
// Add padding zeros plus upper 4 bytes of total message size in bits (only supporting 32bit message bit counts)
|
||||
memset(&ctx->block[ctx->block_size], 0, pad_zero_count + 4);
|
||||
ctx->block_size += pad_zero_count + 4;
|
||||
|
||||
// Add the total message size in bits to the end of the current block. Technically this is
|
||||
// supposed to be 8 bytes. This shortcut will reduce the max message size to 536,870,911 bytes.
|
||||
ctx->block[ctx->block_size++] = (uint8_t)(msg_size_bits >> 24);
|
||||
ctx->block[ctx->block_size++] = (uint8_t)(msg_size_bits >> 16);
|
||||
ctx->block[ctx->block_size++] = (uint8_t)(msg_size_bits >> 8);
|
||||
ctx->block[ctx->block_size++] = (uint8_t)(msg_size_bits >> 0);
|
||||
|
||||
digest_size = 32;
|
||||
status = atcab_sha_base(SHA_MODE_SHA256_UPDATE, ATCA_SHA256_BLOCK_SIZE, ctx->block, digest, &digest_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
if (ctx->block_size > ATCA_SHA256_BLOCK_SIZE)
|
||||
{
|
||||
digest_size = 32;
|
||||
status = atcab_sha_base(SHA_MODE_SHA256_UPDATE, ATCA_SHA256_BLOCK_SIZE, &ctx->block[ATCA_SHA256_BLOCK_SIZE], digest, &digest_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = atcab_sha_end(digest, ctx->block_size, ctx->block);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Use the SHA command to compute a SHA-256 digest.
|
||||
*
|
||||
* \param[in] data Message data to be hashed.
|
||||
* \param[in] data_size Size of data in bytes.
|
||||
* \param[out] digest Digest is returned here (32 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hw_sha2_256(const uint8_t * data, size_t data_size, uint8_t* digest)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
atca_sha256_ctx_t ctx;
|
||||
|
||||
status = atcab_hw_sha2_256_init(&ctx);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = atcab_hw_sha2_256_update(&ctx, data, data_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = atcab_hw_sha2_256_finish(&ctx, digest);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to start an HMAC/SHA-256 operation
|
||||
*
|
||||
* \param[in] ctx HMAC/SHA-256 context
|
||||
* \param[in] key_slot Slot key id to use for the HMAC calculation
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_hmac_init(atca_hmac_sha256_ctx_t* ctx, uint16_t key_slot)
|
||||
{
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
return atcab_sha_base(SHA_MODE_HMAC_START, key_slot, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to add an arbitrary amount of message data to
|
||||
* a HMAC/SHA-256 operation.
|
||||
*
|
||||
* \param[in] ctx HMAC/SHA-256 context
|
||||
* \param[in] data Message data to add
|
||||
* \param[in] data_size Size of message data in bytes
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_hmac_update(atca_hmac_sha256_ctx_t* ctx, const uint8_t* data, size_t data_size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint32_t block_count;
|
||||
uint32_t rem_size = ATCA_SHA256_BLOCK_SIZE - ctx->block_size;
|
||||
uint32_t copy_size = data_size > rem_size ? rem_size : (uint32_t)data_size;
|
||||
uint32_t i = 0;
|
||||
|
||||
// Copy data into current block
|
||||
memcpy(&ctx->block[ctx->block_size], data, copy_size);
|
||||
|
||||
if (ctx->block_size + data_size < ATCA_SHA256_BLOCK_SIZE)
|
||||
{
|
||||
// Not enough data to finish off the current block
|
||||
ctx->block_size += (uint32_t)data_size;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
// Process the current block
|
||||
status = atcab_sha_base(SHA_MODE_HMAC_UPDATE, ATCA_SHA256_BLOCK_SIZE, ctx->block, NULL, NULL);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
// Process any additional blocks
|
||||
data_size -= copy_size; // Adjust to the remaining message bytes
|
||||
block_count = (uint32_t)(data_size / ATCA_SHA256_BLOCK_SIZE);
|
||||
for (i = 0; i < block_count; i++)
|
||||
{
|
||||
status = atcab_sha_base(SHA_MODE_HMAC_UPDATE, ATCA_SHA256_BLOCK_SIZE, &data[copy_size + i * ATCA_SHA256_BLOCK_SIZE], NULL, NULL);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
// Save any remaining data
|
||||
ctx->total_msg_size += (block_count + 1) * ATCA_SHA256_BLOCK_SIZE;
|
||||
ctx->block_size = data_size % ATCA_SHA256_BLOCK_SIZE;
|
||||
memcpy(ctx->block, &data[copy_size + block_count * ATCA_SHA256_BLOCK_SIZE], ctx->block_size);
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Executes SHA command to complete a HMAC/SHA-256 operation.
|
||||
*
|
||||
* \param[in] ctx HMAC/SHA-256 context
|
||||
* \param[out] digest HMAC/SHA-256 result is returned here (32 bytes).
|
||||
* \param[in] target Where to save the digest internal to the device.
|
||||
* For ATECC608A, can be SHA_MODE_TARGET_TEMPKEY,
|
||||
* SHA_MODE_TARGET_MSGDIGBUF, or SHA_MODE_TARGET_OUT_ONLY.
|
||||
* For all other devices, SHA_MODE_TARGET_TEMPKEY is the
|
||||
* only option.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_hmac_finish(atca_hmac_sha256_ctx_t *ctx, uint8_t* digest, uint8_t target)
|
||||
{
|
||||
uint8_t mode = SHA_MODE_HMAC_END;
|
||||
uint16_t digest_size = 32;
|
||||
|
||||
if (ATECC608A == _gDevice->mIface->mIfaceCFG->devtype)
|
||||
{
|
||||
mode = SHA_MODE_608_HMAC_END;
|
||||
}
|
||||
else if (target != SHA_MODE_TARGET_TEMPKEY)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
mode |= target;
|
||||
|
||||
return atcab_sha_base(mode, ctx->block_size, ctx->block, digest, &digest_size);
|
||||
}
|
||||
|
||||
/** \brief Use the SHA command to compute an HMAC/SHA-256 operation.
|
||||
*
|
||||
* \param[in] data Message data to be hashed.
|
||||
* \param[in] data_size Size of data in bytes.
|
||||
* \param[in] key_slot Slot key id to use for the HMAC calculation
|
||||
* \param[out] digest Digest is returned here (32 bytes).
|
||||
* \param[in] target Where to save the digest internal to the device.
|
||||
* For ATECC608A, can be SHA_MODE_TARGET_TEMPKEY,
|
||||
* SHA_MODE_TARGET_MSGDIGBUF, or
|
||||
* SHA_MODE_TARGET_OUT_ONLY. For all other devices,
|
||||
* SHA_MODE_TARGET_TEMPKEY is the only option.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sha_hmac(const uint8_t * data, size_t data_size, uint16_t key_slot, uint8_t* digest, uint8_t target)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
atca_hmac_sha256_ctx_t ctx;
|
||||
|
||||
status = atcab_sha_hmac_init(&ctx, key_slot);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = atcab_sha_hmac_update(&ctx, data, data_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
status = atcab_sha_hmac_finish(&ctx, digest, target);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Sign command.
|
||||
*
|
||||
* The Sign command generates a signature using the private key in slot with
|
||||
* ECDSA algorithm.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC108A, ATECC508A, and
|
||||
* ATECC608A. There are differences in the modes that they support. Refer
|
||||
* to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes the Sign command, which generates a signature using the
|
||||
* ECDSA algorithm.
|
||||
*
|
||||
* \param[in] mode Mode determines what the source of the message to be
|
||||
* signed.
|
||||
* \param[in] key_id Private key slot used to sign the message.
|
||||
* \param[out] signature Signature is returned here. Format is R and S
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* curve.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sign_base(uint8_t mode, uint16_t key_id, uint8_t *signature)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
if (signature == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Build sign command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
if ((status = atSign(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (signature != NULL)
|
||||
{
|
||||
if (packet.data[ATCA_COUNT_IDX] == (ATCA_SIG_SIZE + ATCA_PACKET_OVERHEAD))
|
||||
{
|
||||
memcpy(signature, &packet.data[ATCA_RSP_DATA_IDX], ATCA_SIG_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ATCA_RX_FAIL;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes Sign command, to sign a 32-byte external message using the
|
||||
* private key in the specified slot. The message to be signed
|
||||
* will be loaded into the Message Digest Buffer to the
|
||||
* ATECC608A device or TempKey for other devices.
|
||||
*
|
||||
* \param[in] key_id Slot of the private key to be used to sign the
|
||||
* message.
|
||||
* \param[in] msg 32-byte message to be signed. Typically the SHA256
|
||||
* hash of the full message.
|
||||
* \param[out] signature Signature will be returned here. Format is R and S
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* curve.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sign(uint16_t key_id, const uint8_t *msg, uint8_t *signature)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t nonce_target = NONCE_MODE_TARGET_TEMPKEY;
|
||||
uint8_t sign_source = SIGN_MODE_SOURCE_TEMPKEY;
|
||||
|
||||
do
|
||||
{
|
||||
// Make sure RNG has updated its seed
|
||||
if ((status = atcab_random(NULL)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Load message into device
|
||||
if (_gDevice->mCommands->dt == ATECC608A)
|
||||
{
|
||||
// Use the Message Digest Buffer for the ATECC608A
|
||||
nonce_target = NONCE_MODE_TARGET_MSGDIGBUF;
|
||||
sign_source = SIGN_MODE_SOURCE_MSGDIGBUF;
|
||||
}
|
||||
if ((status = atcab_nonce_load(nonce_target, msg, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Sign the message
|
||||
if ((status = atcab_sign_base(SIGN_MODE_EXTERNAL | sign_source, key_id, signature)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes Sign command to sign an internally generated message.
|
||||
*
|
||||
* \param[in] key_id Slot of the private key to be used to sign the
|
||||
* message.
|
||||
* \param[in] is_invalidate Set to true if the signature will be used with
|
||||
* the Verify(Invalidate) command. false for all
|
||||
* other cases.
|
||||
* \param[in] is_full_sn Set to true if the message should incorporate
|
||||
* the device's full serial number.
|
||||
* \param[out] signature Signature is returned here. Format is R and S
|
||||
* integers in big-endian format. 64 bytes for
|
||||
* P256 curve.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_sign_internal(uint16_t key_id, bool is_invalidate, bool is_full_sn, uint8_t *signature)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t mode = SIGN_MODE_INTERNAL;
|
||||
|
||||
do
|
||||
{
|
||||
// Sign the message
|
||||
if (is_invalidate)
|
||||
{
|
||||
mode |= SIGN_MODE_INVALIDATE;
|
||||
}
|
||||
|
||||
if (is_full_sn)
|
||||
{
|
||||
mode |= SIGN_MODE_INCLUDE_SN;
|
||||
}
|
||||
|
||||
if ((status = atcab_sign_base(mode, key_id, signature)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for UpdateExtra command.
|
||||
*
|
||||
* The UpdateExtra command is used to update the values of the two extra bytes
|
||||
* within the Configuration zone after the Configuration zone has been locked.
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
|
||||
/** \brief Executes UpdateExtra command to update the values of the two
|
||||
* extra bytes within the Configuration zone (bytes 84 and 85).
|
||||
*
|
||||
* Can also be used to decrement the limited use counter associated with the
|
||||
* key in slot NewValue.
|
||||
*
|
||||
* \param[in] mode Mode determines what operations the UpdateExtra
|
||||
* command performs.
|
||||
* \param[in] new_value Value to be written.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_updateextra(uint8_t mode, uint16_t new_value)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
do
|
||||
{
|
||||
// Build command
|
||||
memset(&packet, 0, sizeof(packet));
|
||||
packet.param1 = mode;
|
||||
packet.param2 = new_value;
|
||||
|
||||
if ((status = atUpdateExtra(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Verify command.
|
||||
*
|
||||
* The Verify command takes an ECDSA [R,S] signature and verifies that it is
|
||||
* correctly generated given an input message digest and public key.
|
||||
*
|
||||
* \note List of devices that support this command - ATECC108A, ATECC508A, and
|
||||
* ATECC608A. There are differences in the modes that they support. Refer
|
||||
* to device datasheet for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
|
||||
/** \brief Executes the Verify command, which takes an ECDSA [R,S] signature
|
||||
* and verifies that it is correctly generated from a given message and
|
||||
* public key. In all cases, the signature is an input to the command.
|
||||
*
|
||||
* For the Stored, External, and ValidateExternal Modes, the contents of
|
||||
* TempKey (or Message Digest Buffer in some cases for the ATECC608A) should
|
||||
* contain the 32 byte message.
|
||||
*
|
||||
* \param[in] mode Verify command mode and options
|
||||
* \param[in] key_id Stored mode, the slot containing the public key to
|
||||
* be used for the verification.
|
||||
* ValidateExternal mode, the slot containing the
|
||||
* public key to be validated.
|
||||
* External mode, KeyID contains the curve type to be
|
||||
* used to Verify the signature.
|
||||
* Validate or Invalidate mode, the slot containing
|
||||
* the public key to be (in)validated.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] public_key If mode is External, the public key to be used for
|
||||
* verification. X and Y integers in big-endian format.
|
||||
* 64 bytes for P256 curve. NULL for all other modes.
|
||||
* \param[in] other_data If mode is Validate, the bytes used to generate the
|
||||
* message for the validation (19 bytes). NULL for all
|
||||
* other modes.
|
||||
* \param[out] mac If mode indicates a validating MAC, then the MAC will
|
||||
* will be returned here. Can be NULL otherwise.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify(uint8_t mode, uint16_t key_id, const uint8_t* signature, const uint8_t* public_key, const uint8_t* other_data, uint8_t* mac)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t verify_mode = (mode & VERIFY_MODE_MASK);
|
||||
|
||||
do
|
||||
{
|
||||
if (signature == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (verify_mode == VERIFY_MODE_EXTERNAL && public_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if ((verify_mode == VERIFY_MODE_VALIDATE || verify_mode == VERIFY_MODE_INVALIDATE) && other_data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Build the verify command
|
||||
packet.param1 = mode;
|
||||
packet.param2 = key_id;
|
||||
memcpy(&packet.data[0], signature, ATCA_SIG_SIZE);
|
||||
if (verify_mode == VERIFY_MODE_EXTERNAL)
|
||||
{
|
||||
memcpy(&packet.data[ATCA_SIG_SIZE], public_key, ATCA_PUB_KEY_SIZE);
|
||||
}
|
||||
else if (other_data)
|
||||
{
|
||||
memcpy(&packet.data[ATCA_SIG_SIZE], other_data, VERIFY_OTHER_DATA_SIZE);
|
||||
}
|
||||
|
||||
if ((status = atVerify(ca_cmd, &packet)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// The Verify command may return MAC if requested
|
||||
if ((mac != NULL) && (packet.data[ATCA_COUNT_IDX] >= (ATCA_PACKET_OVERHEAD + MAC_SIZE)))
|
||||
{
|
||||
memcpy(mac, &packet.data[ATCA_RSP_DATA_IDX], MAC_SIZE);
|
||||
}
|
||||
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command with verification MAC for the External
|
||||
* or Stored Verify modes.. This function is only available on the
|
||||
* ATECC608A.
|
||||
*
|
||||
* \param[in] mode Verify command mode. Can be VERIFY_MODE_EXTERNAL or
|
||||
* VERIFY_MODE_STORED.
|
||||
* \param[in] key_id For VERIFY_MODE_STORED mode, the slot containing the
|
||||
* public key to be used for the verification.
|
||||
* For VERIFY_MODE_EXTERNAL mode, KeyID contains the
|
||||
* curve type to be used to Verify the signature. Only
|
||||
* VERIFY_KEY_P256 supported.
|
||||
* \param[in] message 32 byte message to be verified. Typically
|
||||
* the SHA256 hash of the full message.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] public_key For VERIFY_MODE_EXTERNAL mode, the public key to be
|
||||
* used for verification. X and Y integers in
|
||||
* big-endian format. 64 bytes for P256 curve. Null for
|
||||
* VERIFY_MODE_STORED mode.
|
||||
* \param[in] num_in System nonce (32 byte) used for the verification
|
||||
* MAC.
|
||||
* \param[in] io_key IO protection key for verifying the validation MAC.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
static ATCA_STATUS atcab_verify_extern_stored_mac(
|
||||
uint8_t mode,
|
||||
uint16_t key_id,
|
||||
const uint8_t* message,
|
||||
const uint8_t* signature,
|
||||
const uint8_t* public_key,
|
||||
const uint8_t* num_in,
|
||||
const uint8_t* io_key,
|
||||
bool* is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t msg_dig_buf[64];
|
||||
atca_verify_mac_in_out_t verify_mac_params;
|
||||
uint8_t mac[SECUREBOOT_MAC_SIZE];
|
||||
uint8_t host_mac[SECUREBOOT_MAC_SIZE];
|
||||
|
||||
do
|
||||
{
|
||||
if (is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
*is_verified = false;
|
||||
if (signature == NULL || message == NULL || num_in == NULL || io_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if ((mode & VERIFY_MODE_MASK) == VERIFY_MODE_EXTERNAL && public_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM; // Only External mode requires an external public key
|
||||
|
||||
}
|
||||
// When using the message digest buffer as the message source, the
|
||||
// second 32 bytes in the buffer will be the MAC system nonce.
|
||||
memcpy(&msg_dig_buf[0], message, 32);
|
||||
memcpy(&msg_dig_buf[32], num_in, 32);
|
||||
if ((status = atcab_nonce_load(NONCE_MODE_TARGET_MSGDIGBUF, msg_dig_buf, 64)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Calculate the expected MAC
|
||||
memset(&verify_mac_params, 0, sizeof(verify_mac_params));
|
||||
verify_mac_params.mode = mode | VERIFY_MODE_SOURCE_MSGDIGBUF | VERIFY_MODE_MAC_FLAG;
|
||||
verify_mac_params.key_id = key_id;
|
||||
verify_mac_params.signature = signature;
|
||||
verify_mac_params.msg_dig_buf = msg_dig_buf;
|
||||
verify_mac_params.io_key = io_key;
|
||||
verify_mac_params.temp_key = NULL;
|
||||
verify_mac_params.sn = NULL;
|
||||
verify_mac_params.mac = host_mac;
|
||||
status = atcah_verify_mac(&verify_mac_params);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = atcab_verify(verify_mac_params.mode, verify_mac_params.key_id, signature, public_key, NULL, mac);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
status = ATCA_SUCCESS; // Verify failed, but command succeeded
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
*is_verified = (memcmp(host_mac, mac, MAC_SIZE) == 0);
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command, which verifies a signature (ECDSA
|
||||
* verify operation) with all components (message, signature, and
|
||||
* public key) supplied. The message to be signed will be loaded into
|
||||
* the Message Digest Buffer to the ATECC608A device or TempKey for
|
||||
* other devices.
|
||||
*
|
||||
* \param[in] message 32 byte message to be verified. Typically
|
||||
* the SHA256 hash of the full message.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] public_key The public key to be used for verification. X and
|
||||
* Y integers in big-endian format. 64 bytes for
|
||||
* P256 curve.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_extern(const uint8_t *message, const uint8_t *signature, const uint8_t *public_key, bool *is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t nonce_target = NONCE_MODE_TARGET_TEMPKEY;
|
||||
uint8_t verify_source = VERIFY_MODE_SOURCE_TEMPKEY;
|
||||
|
||||
if (is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
*is_verified = false;
|
||||
|
||||
if (signature == NULL || message == NULL || public_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Load message into device
|
||||
if (_gDevice->mCommands->dt == ATECC608A)
|
||||
{
|
||||
// Use the Message Digest Buffer for the ATECC608A
|
||||
nonce_target = NONCE_MODE_TARGET_MSGDIGBUF;
|
||||
verify_source = VERIFY_MODE_SOURCE_MSGDIGBUF;
|
||||
}
|
||||
if ((status = atcab_nonce_load(nonce_target, message, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = atcab_verify(VERIFY_MODE_EXTERNAL | verify_source, VERIFY_KEY_P256, signature, public_key, NULL, NULL);
|
||||
*is_verified = (status == ATCA_SUCCESS);
|
||||
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
status = ATCA_SUCCESS; // Verify failed, but command succeeded
|
||||
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command with verification MAC, which verifies a
|
||||
* signature (ECDSA verify operation) with all components (message,
|
||||
* signature, and public key) supplied. This function is only available
|
||||
* on the ATECC608A.
|
||||
*
|
||||
* \param[in] message 32 byte message to be verified. Typically
|
||||
* the SHA256 hash of the full message.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] public_key The public key to be used for verification. X and
|
||||
* Y integers in big-endian format. 64 bytes for
|
||||
* P256 curve.
|
||||
* \param[in] num_in System nonce (32 byte) used for the verification
|
||||
* MAC.
|
||||
* \param[in] io_key IO protection key for verifying the validation MAC.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_extern_mac(const uint8_t *message, const uint8_t* signature, const uint8_t* public_key, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified)
|
||||
{
|
||||
return atcab_verify_extern_stored_mac(
|
||||
VERIFY_MODE_EXTERNAL,
|
||||
VERIFY_KEY_P256,
|
||||
message,
|
||||
signature,
|
||||
public_key,
|
||||
num_in,
|
||||
io_key,
|
||||
is_verified);
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command, which verifies a signature (ECDSA
|
||||
* verify operation) with a public key stored in the device. The
|
||||
* message to be signed will be loaded into the Message Digest Buffer
|
||||
* to the ATECC608A device or TempKey for other devices.
|
||||
*
|
||||
* \param[in] message 32 byte message to be verified. Typically
|
||||
* the SHA256 hash of the full message.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] key_id Slot containing the public key to be used in the
|
||||
* verification.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_stored(const uint8_t *message, const uint8_t *signature, uint16_t key_id, bool *is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t nonce_target = NONCE_MODE_TARGET_TEMPKEY;
|
||||
uint8_t verify_source = VERIFY_MODE_SOURCE_TEMPKEY;
|
||||
|
||||
if (is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
*is_verified = false;
|
||||
|
||||
if (signature == NULL || message == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Load message into device
|
||||
if (_gDevice->mCommands->dt == ATECC608A)
|
||||
{
|
||||
// Use the Message Digest Buffer for the ATECC608A
|
||||
nonce_target = NONCE_MODE_TARGET_MSGDIGBUF;
|
||||
verify_source = VERIFY_MODE_SOURCE_MSGDIGBUF;
|
||||
}
|
||||
if ((status = atcab_nonce_load(nonce_target, message, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
status = atcab_verify(VERIFY_MODE_STORED | verify_source, key_id, signature, NULL, NULL, NULL);
|
||||
*is_verified = (status == ATCA_SUCCESS);
|
||||
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
status = ATCA_SUCCESS; // Verify failed, but command succeeded
|
||||
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command with verification MAC, which verifies a
|
||||
* signature (ECDSA verify operation) with a public key stored in the
|
||||
* device. This function is only available on the ATECC608A.
|
||||
*
|
||||
* \param[in] message 32 byte message to be verified. Typically
|
||||
* the SHA256 hash of the full message.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] key_id Slot containing the public key to be used in the
|
||||
* verification.
|
||||
* \param[in] num_in System nonce (32 byte) used for the verification
|
||||
* MAC.
|
||||
* \param[in] io_key IO protection key for verifying the validation MAC.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_stored_mac(const uint8_t *message, const uint8_t *signature, uint16_t key_id, const uint8_t* num_in, const uint8_t* io_key, bool* is_verified)
|
||||
{
|
||||
return atcab_verify_extern_stored_mac(
|
||||
VERIFY_MODE_STORED,
|
||||
key_id,
|
||||
message,
|
||||
signature,
|
||||
NULL,
|
||||
num_in,
|
||||
io_key,
|
||||
is_verified);
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command in Validate mode to validate a public
|
||||
* key stored in a slot.
|
||||
*
|
||||
* This command can only be run after GenKey has been used to create a PubKey
|
||||
* digest of the public key to be validated in TempKey (mode=0x10).
|
||||
*
|
||||
* \param[in] key_id Slot containing the public key to be validated.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] other_data 19 bytes of data used to build the verification
|
||||
* message.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* validation public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_validate(uint16_t key_id, const uint8_t *signature, const uint8_t *other_data, bool *is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
if (signature == NULL || other_data == NULL || is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
status = atcab_verify(VERIFY_MODE_VALIDATE, key_id, signature, NULL, other_data, NULL);
|
||||
*is_verified = (status == ATCA_SUCCESS);
|
||||
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
status = ATCA_SUCCESS; // Verify failed, but command succeeded
|
||||
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Verify command in Invalidate mode which invalidates a
|
||||
* previously validated public key stored in a slot.
|
||||
*
|
||||
* This command can only be run after GenKey has been used to create a PubKey
|
||||
* digest of the public key to be invalidated in TempKey (mode=0x10).
|
||||
*
|
||||
* \param[in] key_id Slot containing the public key to be invalidated.
|
||||
* \param[in] signature Signature to be verified. R and S integers in
|
||||
* big-endian format. 64 bytes for P256 curve.
|
||||
* \param[in] other_data 19 bytes of data used to build the verification
|
||||
* message.
|
||||
* \param[out] is_verified Boolean whether or not the message, signature,
|
||||
* validation public key verified.
|
||||
*
|
||||
* \return ATCA_SUCCESS on verification success or failure, because the
|
||||
* command still completed successfully.
|
||||
*/
|
||||
ATCA_STATUS atcab_verify_invalidate(uint16_t key_id, const uint8_t *signature, const uint8_t *other_data, bool *is_verified)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
|
||||
if (signature == NULL || other_data == NULL || is_verified == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
status = atcab_verify(VERIFY_MODE_INVALIDATE, key_id, signature, NULL, other_data, NULL);
|
||||
*is_verified = (status == ATCA_SUCCESS);
|
||||
|
||||
if (status == ATCA_CHECKMAC_VERIFY_FAILED)
|
||||
{
|
||||
status = ATCA_SUCCESS; // Verify failed, but command succeeded
|
||||
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,542 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief CryptoAuthLib Basic API methods for Write command.
|
||||
*
|
||||
* The Write command writes either one 4-byte word or a 32-byte block to one of
|
||||
* the EEPROM zones on the device. Depending upon the value of the WriteConfig
|
||||
* byte for a slot, the data may be required to be encrypted by the system prior
|
||||
* to being sent to the device
|
||||
*
|
||||
* \note List of devices that support this command - ATSHA204A, ATECC108A,
|
||||
* ATECC508A, and ATECC608A. There are differences in the modes that they
|
||||
* support. Refer to device datasheets for full details.
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
#include "atca_basic.h"
|
||||
#include "atca_execution.h"
|
||||
#include "host/atca_host.h"
|
||||
|
||||
|
||||
/**
|
||||
* \brief Executes the Write command, which writes either one four byte word or
|
||||
* a 32-byte block to one of the EEPROM zones on the device. Depending
|
||||
* upon the value of the WriteConfig byte for this slot, the data may be
|
||||
* required to be encrypted by the system prior to being sent to the
|
||||
* device. This command cannot be used to write slots configured as ECC
|
||||
* private keys.
|
||||
*
|
||||
* \param[in] zone Zone/Param1 for the write command.
|
||||
* \param[in] address Address/Param2 for the write command.
|
||||
* \param[in] value Plain-text data to be written or cipher-text for
|
||||
* encrypted writes. 32 or 4 bytes depending on bit 7 in the
|
||||
* zone.
|
||||
* \param[in] mac MAC required for encrypted writes (32 bytes). Set to NULL
|
||||
* if not required.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write(uint8_t zone, uint16_t address, const uint8_t *value, const uint8_t *mac)
|
||||
{
|
||||
ATCAPacket packet;
|
||||
ATCACommand ca_cmd = _gDevice->mCommands;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
if (value == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Build the write command
|
||||
packet.param1 = zone;
|
||||
packet.param2 = address;
|
||||
if (zone & ATCA_ZONE_READWRITE_32)
|
||||
{
|
||||
// 32-byte write
|
||||
memcpy(packet.data, value, 32);
|
||||
// Only 32-byte writes can have a MAC
|
||||
if (mac)
|
||||
{
|
||||
memcpy(&packet.data[32], mac, 32);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 4-byte write
|
||||
memcpy(packet.data, value, 4);
|
||||
}
|
||||
|
||||
if ((status = atWrite(ca_cmd, &packet, mac && (zone & ATCA_ZONE_READWRITE_32))) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if ((status = atca_execute_command(&packet, _gDevice)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Write command, which writes either 4 or 32 bytes of
|
||||
* data into a device zone.
|
||||
*
|
||||
* \param[in] zone Device zone to write to (0=config, 1=OTP, 2=data).
|
||||
* \param[in] slot If writing to the data zone, it is the slot to write to,
|
||||
* otherwise it should be 0.
|
||||
* \param[in] block 32-byte block to write to.
|
||||
* \param[in] offset 4-byte word within the specified block to write to. If
|
||||
* performing a 32-byte write, this should be 0.
|
||||
* \param[in] data Data to be written.
|
||||
* \param[in] len Number of bytes to be written. Must be either 4 or 32.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write_zone(uint8_t zone, uint16_t slot, uint8_t block, uint8_t offset, const uint8_t *data, uint8_t len)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint16_t addr;
|
||||
|
||||
// Check the input parameters
|
||||
if (data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (len != 4 && len != 32)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// The get address function checks the remaining variables
|
||||
if ((status = atcab_get_addr(zone, slot, block, offset, &addr)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// If there are 32 bytes to write, then xor the bit into the mode
|
||||
if (len == ATCA_BLOCK_SIZE)
|
||||
{
|
||||
zone = zone | ATCA_ZONE_READWRITE_32;
|
||||
}
|
||||
|
||||
status = atcab_write(zone, addr, data, NULL);
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Executes the Write command, which performs an encrypted write of
|
||||
* a 32 byte block into given slot.
|
||||
*
|
||||
* The function takes clear text bytes and encrypts them for writing over the
|
||||
* wire. Data zone must be locked and the slot configuration must be set to
|
||||
* encrypted write for the block to be successfully written.
|
||||
*
|
||||
* \param[in] key_id Slot ID to write to.
|
||||
* \param[in] block Index of the 32 byte block to write in the slot.
|
||||
* \param[in] data 32 bytes of clear text data to be written to the slot
|
||||
* \param[in] enc_key WriteKey to encrypt with for writing
|
||||
* \param[in] enc_key_id The KeyID of the WriteKey
|
||||
* \param[in] num_in 20 byte host nonce to inject into Nonce calculation
|
||||
*
|
||||
* returns ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
#if defined(ATCA_USE_CONSTANT_HOST_NONCE)
|
||||
ATCA_STATUS atcab_write_enc(uint16_t key_id, uint8_t block, const uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id)
|
||||
{
|
||||
uint8_t num_in[NONCE_NUMIN_SIZE] = { 0 };
|
||||
|
||||
#else
|
||||
ATCA_STATUS atcab_write_enc(uint16_t key_id, uint8_t block, const uint8_t *data, const uint8_t* enc_key, const uint16_t enc_key_id, const uint8_t num_in[NONCE_NUMIN_SIZE])
|
||||
{
|
||||
#endif
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
uint8_t zone = ATCA_ZONE_DATA | ATCA_ZONE_READWRITE_32;
|
||||
atca_nonce_in_out_t nonce_params;
|
||||
atca_gen_dig_in_out_t gen_dig_param;
|
||||
atca_write_mac_in_out_t write_mac_param;
|
||||
atca_temp_key_t temp_key;
|
||||
uint8_t serial_num[32];
|
||||
uint8_t rand_out[RANDOM_NUM_SIZE] = { 0 };
|
||||
uint8_t cipher_text[ATCA_KEY_SIZE] = { 0 };
|
||||
uint8_t mac[WRITE_MAC_SIZE] = { 0 };
|
||||
uint8_t other_data[4] = { 0 };
|
||||
uint16_t addr;
|
||||
|
||||
do
|
||||
{
|
||||
// Verify inputs parameters
|
||||
if (data == NULL || enc_key == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
// Read the device SN
|
||||
if ((status = atcab_read_zone(ATCA_ZONE_CONFIG, 0, 0, 0, serial_num, 32)) != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// Make the SN continuous by moving SN[4:8] right after SN[0:3]
|
||||
memmove(&serial_num[4], &serial_num[8], 5);
|
||||
|
||||
|
||||
// Random Nonce inputs
|
||||
memset(&temp_key, 0, sizeof(temp_key));
|
||||
memset(&nonce_params, 0, sizeof(nonce_params));
|
||||
nonce_params.mode = NONCE_MODE_SEED_UPDATE;
|
||||
nonce_params.zero = 0;
|
||||
nonce_params.num_in = (uint8_t*)&num_in[0];
|
||||
nonce_params.rand_out = (uint8_t*)&rand_out;
|
||||
nonce_params.temp_key = &temp_key;
|
||||
|
||||
// Send the random Nonce command
|
||||
if ((status = atcab_nonce_rand(num_in, rand_out)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Nonce failed");
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
if ((status = atcah_nonce(&nonce_params)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Calc TempKey failed");
|
||||
}
|
||||
|
||||
// Supply OtherData so GenDig behavior is the same for keys with SlotConfig.NoMac set
|
||||
other_data[0] = ATCA_GENDIG;
|
||||
other_data[1] = GENDIG_ZONE_DATA;
|
||||
other_data[2] = (uint8_t)(enc_key_id);
|
||||
other_data[3] = (uint8_t)(enc_key_id >> 8);
|
||||
|
||||
// Send the GenDig command
|
||||
if ((status = atcab_gendig(GENDIG_ZONE_DATA, enc_key_id, other_data, sizeof(other_data))) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "GenDig failed");
|
||||
}
|
||||
|
||||
// Calculate Tempkey
|
||||
// NoMac bit isn't being considered here on purpose to remove having to read SlotConfig.
|
||||
// OtherData is built to get the same result regardless of the NoMac bit.
|
||||
memset(&gen_dig_param, 0, sizeof(gen_dig_param));
|
||||
gen_dig_param.key_id = enc_key_id;
|
||||
gen_dig_param.is_key_nomac = false;
|
||||
gen_dig_param.sn = serial_num;
|
||||
gen_dig_param.stored_value = enc_key;
|
||||
gen_dig_param.zone = GENDIG_ZONE_DATA;
|
||||
gen_dig_param.other_data = other_data;
|
||||
gen_dig_param.temp_key = &temp_key;
|
||||
if ((status = atcah_gen_dig(&gen_dig_param)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "atcah_gen_dig() failed");
|
||||
}
|
||||
|
||||
// The get address function checks the remaining variables
|
||||
if ((status = atcab_get_addr(ATCA_ZONE_DATA, key_id, block, 0, &addr)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Get address failed");
|
||||
}
|
||||
|
||||
// Setting bit 6 to indicate input data is encrypted
|
||||
write_mac_param.zone = zone | ATCA_ZONE_ENCRYPTED;
|
||||
write_mac_param.key_id = addr;
|
||||
write_mac_param.sn = serial_num;
|
||||
write_mac_param.input_data = data;
|
||||
write_mac_param.encrypted_data = cipher_text;
|
||||
write_mac_param.auth_mac = mac;
|
||||
write_mac_param.temp_key = &temp_key;
|
||||
|
||||
if ((status = atcah_write_auth_mac(&write_mac_param)) != ATCA_SUCCESS)
|
||||
{
|
||||
BREAK(status, "Calculate Auth MAC failed");
|
||||
}
|
||||
|
||||
status = atcab_write(write_mac_param.zone, write_mac_param.key_id, write_mac_param.encrypted_data, write_mac_param.auth_mac);
|
||||
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Write command, which writes the configuration zone.
|
||||
*
|
||||
* First 16 bytes are skipped as they are not writable. LockValue and
|
||||
* LockConfig are also skipped and can only be changed via the Lock
|
||||
* command.
|
||||
*
|
||||
* This command may fail if UserExtra and/or Selector bytes have
|
||||
* already been set to non-zero values.
|
||||
*
|
||||
* \param[in] config_data Data to the config zone data. This should be 88
|
||||
* bytes for SHA devices and 128 bytes for ECC
|
||||
* devices.
|
||||
*
|
||||
* \returns ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write_config_zone(const uint8_t* config_data)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
size_t config_size = 0;
|
||||
|
||||
if (config_data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
// Get config zone size for the device
|
||||
status = atcab_get_zone_size(ATCA_ZONE_CONFIG, 0, &config_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Write config zone excluding UserExtra and Selector
|
||||
status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, &config_data[16], config_size - 16);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Write the UserExtra and Selector. This may fail if either value is already non-zero.
|
||||
status = atcab_updateextra(UPDATE_MODE_USER_EXTRA, config_data[84]);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
status = atcab_updateextra(UPDATE_MODE_SELECTOR, config_data[85]);
|
||||
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (0);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Uses the write command to write a public key to a slot in the
|
||||
* proper format.
|
||||
*
|
||||
* \param[in] slot Slot number to write. Only slots 8 to 15 are large
|
||||
* enough to store a public key.
|
||||
* \param[in] public_key Public key to write into the slot specified. X and Y
|
||||
* integers in big-endian format. 64 bytes for P256
|
||||
* curve.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write_pubkey(uint16_t slot, const uint8_t *public_key)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t public_key_formatted[ATCA_BLOCK_SIZE * 3];
|
||||
int block;
|
||||
|
||||
// Check the pointers
|
||||
if (public_key == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// The 64 byte P256 public key gets written to a 72 byte slot in the following pattern
|
||||
// | Block 1 | Block 2 | Block 3 |
|
||||
// | Pad: 4 Bytes | PubKey[0:27] | PubKey[28:31] | Pad: 4 Bytes | PubKey[32:55] | PubKey[56:63] |
|
||||
|
||||
memset(public_key_formatted, 0, sizeof(public_key_formatted));
|
||||
memcpy(&public_key_formatted[4], &public_key[0], 32); // Move X to padded position
|
||||
memcpy(&public_key_formatted[40], &public_key[32], 32); // Move Y to padded position
|
||||
|
||||
// Using this instead of atcab_write_zone_bytes, as that function doesn't work when
|
||||
// the data zone is unlocked
|
||||
for (block = 0; block < 3; block++)
|
||||
{
|
||||
status = atcab_write_zone(ATCA_ZONE_DATA, slot, block, 0, &public_key_formatted[ATCA_BLOCK_SIZE * block], ATCA_BLOCK_SIZE);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Executes the Write command, which writes data into the
|
||||
* configuration, otp, or data zones with a given byte offset and
|
||||
* length. Offset and length must be multiples of a word (4 bytes).
|
||||
*
|
||||
* Config zone must be unlocked for writes to that zone. If data zone is
|
||||
* unlocked, only 32-byte writes are allowed to slots and OTP and the offset
|
||||
* and length must be multiples of 32 or the write will fail.
|
||||
*
|
||||
* \param[in] zone Zone to write data to: ATCA_ZONE_CONFIG(0),
|
||||
* ATCA_ZONE_OTP(1), or ATCA_ZONE_DATA(2).
|
||||
* \param[in] slot If zone is ATCA_ZONE_DATA(2), the slot number to
|
||||
* write to. Ignored for all other zones.
|
||||
* \param[in] offset_bytes Byte offset within the zone to write to. Must be
|
||||
* a multiple of a word (4 bytes).
|
||||
* \param[in] data Data to be written.
|
||||
* \param[in] length Number of bytes to be written. Must be a multiple
|
||||
* of a word (4 bytes).
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write_bytes_zone(uint8_t zone, uint16_t slot, size_t offset_bytes, const uint8_t *data, size_t length)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
size_t zone_size = 0;
|
||||
size_t data_idx = 0;
|
||||
size_t cur_block = 0;
|
||||
size_t cur_word = 0;
|
||||
|
||||
if (zone != ATCA_ZONE_CONFIG && zone != ATCA_ZONE_OTP && zone != ATCA_ZONE_DATA)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (zone == ATCA_ZONE_DATA && slot > 15)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (length == 0)
|
||||
{
|
||||
return ATCA_SUCCESS; // Always succeed writing 0 bytes
|
||||
}
|
||||
if (data == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
if (offset_bytes % ATCA_WORD_SIZE != 0 || length % ATCA_WORD_SIZE != 0)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
status = atcab_get_zone_size(zone, slot, &zone_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (offset_bytes + length > zone_size)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
cur_block = offset_bytes / ATCA_BLOCK_SIZE;
|
||||
cur_word = (offset_bytes % ATCA_BLOCK_SIZE) / ATCA_WORD_SIZE;
|
||||
|
||||
while (data_idx < length)
|
||||
{
|
||||
// The last item makes sure we handle the selector, user extra, and lock bytes in the config properly
|
||||
if (cur_word == 0 && length - data_idx >= ATCA_BLOCK_SIZE && !(zone == ATCA_ZONE_CONFIG && cur_block == 2))
|
||||
{
|
||||
status = atcab_write_zone(zone, slot, (uint8_t)cur_block, 0, &data[data_idx], ATCA_BLOCK_SIZE);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
data_idx += ATCA_BLOCK_SIZE;
|
||||
cur_block += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip trying to change UserExtra, Selector, LockValue, and LockConfig which require the UpdateExtra command to change
|
||||
if (!(zone == ATCA_ZONE_CONFIG && cur_block == 2 && cur_word == 5))
|
||||
{
|
||||
status = atcab_write_zone(zone, slot, (uint8_t)cur_block, (uint8_t)cur_word, &data[data_idx], ATCA_WORD_SIZE);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
data_idx += ATCA_WORD_SIZE;
|
||||
cur_word += 1;
|
||||
if (cur_word == ATCA_BLOCK_SIZE / ATCA_WORD_SIZE)
|
||||
{
|
||||
cur_block += 1;
|
||||
cur_word = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Initialize one of the monotonic counters in device with a specific
|
||||
* value.
|
||||
*
|
||||
* The monotonic counters are stored in the configuration zone using a special
|
||||
* format. This encodes a binary count value into the 8 byte encoded value
|
||||
* required. Can only be set while the configuration zone is unlocked.
|
||||
*
|
||||
* \param[in] counter_id Counter to be written.
|
||||
* \param[in] counter_value Counter value to set.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_write_config_counter(uint16_t counter_id, uint32_t counter_value)
|
||||
{
|
||||
uint16_t lin_a, lin_b, bin_a, bin_b;
|
||||
uint8_t bytes[8];
|
||||
uint8_t idx = 0;
|
||||
ATCA_STATUS status = ATCA_GEN_FAIL;
|
||||
|
||||
if (counter_id > 1 || counter_value > COUNTER_MAX_VALUE)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
lin_a = 0xFFFF >> (counter_value % 32);
|
||||
lin_b = 0xFFFF >> ((counter_value >= 16) ? (counter_value - 16) % 32 : 0);
|
||||
bin_a = counter_value / 32;
|
||||
bin_b = (counter_value >= 16) ? ((counter_value - 16) / 32) : 0;
|
||||
|
||||
bytes[idx++] = lin_a >> 8;
|
||||
bytes[idx++] = lin_a & 0xFF;
|
||||
bytes[idx++] = lin_b >> 8;
|
||||
bytes[idx++] = lin_b & 0xFF;
|
||||
|
||||
bytes[idx++] = bin_a >> 8;
|
||||
bytes[idx++] = bin_a & 0xFF;
|
||||
bytes[idx++] = bin_b >> 8;
|
||||
bytes[idx++] = bin_b & 0xFF;
|
||||
|
||||
status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 52 + counter_id * 8, bytes, sizeof(bytes));
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -0,0 +1,857 @@
|
||||
/**
|
||||
* \file
|
||||
* \brief Helpers to support the CryptoAuthLib Basic API methods
|
||||
*
|
||||
* \copyright (c) 2015-2018 Microchip Technology Inc. and its subsidiaries.
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Subject to your compliance with these terms, you may use Microchip software
|
||||
* and any derivatives exclusively with Microchip products. It is your
|
||||
* responsibility to comply with third party license terms applicable to your
|
||||
* use of third party software (including open source software) that may
|
||||
* accompany Microchip software.
|
||||
*
|
||||
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER
|
||||
* EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE, INCLUDING ANY IMPLIED
|
||||
* WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE LIABLE FOR ANY INDIRECT,
|
||||
* SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, COST OR EXPENSE
|
||||
* OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE, HOWEVER CAUSED, EVEN IF
|
||||
* MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE
|
||||
* FORESEEABLE. TO THE FULLEST EXTENT ALLOWED BY LAW, MICROCHIP'S TOTAL
|
||||
* LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
|
||||
* THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR
|
||||
* THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "cryptoauthlib.h"
|
||||
#include "atca_helpers.h"
|
||||
|
||||
|
||||
|
||||
/* Ruleset:
|
||||
Index - Meaning
|
||||
0 - 62 Character
|
||||
1 - 63 Character
|
||||
2 - Pad Character (none if 0)
|
||||
3 - Maximum line length (no limit if 0) */
|
||||
uint8_t atcab_b64rules_default[4] = { '+', '/', '=', 64 };
|
||||
uint8_t atcab_b64rules_mime[4] = { '+', '/', '=', 76 };
|
||||
uint8_t atcab_b64rules_urlsafe[4] = { '-', '_', 0, 0 };
|
||||
|
||||
|
||||
/** \brief Convert a binary buffer to a hex string for easy reading.
|
||||
* \param[in] bin Input data to convert.
|
||||
* \param[in] bin_size Size of data to convert.
|
||||
* \param[out] hex Buffer that receives hex string.
|
||||
* \param[inout] hex_size As input, the size of the hex buffer.
|
||||
* As output, the size of the output hex.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_bin2hex(const uint8_t* bin, size_t bin_size, char* hex, size_t* hex_size)
|
||||
{
|
||||
return atcab_bin2hex_(bin, bin_size, hex, hex_size, true, true, true);
|
||||
}
|
||||
|
||||
static void uint8_to_hex(uint8_t num, char* hex_str)
|
||||
{
|
||||
uint8_t nibble = (num >> 4) & 0x0F;
|
||||
|
||||
if (nibble < 10)
|
||||
{
|
||||
*(hex_str++) = '0' + nibble;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(hex_str++) = 'A' + (nibble - 10);
|
||||
}
|
||||
nibble = num & 0x0F;
|
||||
if (nibble < 10)
|
||||
{
|
||||
*(hex_str++) = '0' + nibble;
|
||||
}
|
||||
else
|
||||
{
|
||||
*(hex_str++) = 'A' + (nibble - 10);
|
||||
}
|
||||
}
|
||||
|
||||
static void hex_to_lowercase(char *buffer, size_t length)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if ((buffer != NULL) && (length > 0))
|
||||
{
|
||||
for (index = 0; index < length; index++)
|
||||
{
|
||||
buffer[index] = tolower(buffer[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void hex_to_uppercase(char *buffer, size_t length)
|
||||
{
|
||||
size_t index;
|
||||
|
||||
if ((buffer != NULL) && (length > 0))
|
||||
{
|
||||
for (index = 0; index < length; index++)
|
||||
{
|
||||
buffer[index] = toupper(buffer[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief To reverse the input data.
|
||||
* \param[in] bin Input data to reverse.
|
||||
* \param[in] bin_size Size of data to reverse.
|
||||
* \param[out] dest Buffer to store reversed binary data.
|
||||
* \param[in] dest_size The size of the dest buffer.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_reversal(const uint8_t* bin, size_t bin_size, uint8_t* dest, size_t* dest_size)
|
||||
{
|
||||
size_t last, i;
|
||||
|
||||
// Verify the inputs
|
||||
if ((bin == NULL) || (dest == NULL))
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
if (*dest_size < bin_size)
|
||||
{
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
|
||||
last = bin_size - 1;
|
||||
|
||||
for (i = 0; i < bin_size; i++)
|
||||
{
|
||||
dest[i] = bin[last];
|
||||
last--;
|
||||
}
|
||||
*dest_size = bin_size;
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/** \brief Function that converts a binary buffer to a hex string suitable for
|
||||
* easy reading.
|
||||
* \param[in] bin Input data to convert.
|
||||
* \param[in] bin_size Size of data to convert.
|
||||
* \param[out] hex Buffer that receives hex string.
|
||||
* \param[inout] hex_size As input, the size of the hex buffer.
|
||||
* As output, the size of the output hex.
|
||||
* \param[in] is_pretty Indicates whether new lines should be
|
||||
* added for pretty printing.
|
||||
* \param[in] is_space Convert the output hex with space between it.
|
||||
* \param[in] is_upper Convert the output hex to upper case.
|
||||
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_bin2hex_(const uint8_t* bin, size_t bin_size, char* hex, size_t* hex_size, bool is_pretty, bool is_space, bool is_upper)
|
||||
{
|
||||
size_t i;
|
||||
size_t cur_hex_size = 0;
|
||||
size_t max_hex_size;
|
||||
|
||||
// Verify the inputs
|
||||
if (bin == NULL || hex == NULL || hex_size == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
max_hex_size = *hex_size;
|
||||
*hex_size = 0;
|
||||
|
||||
// Convert one byte at a time
|
||||
for (i = 0; i < bin_size; i++)
|
||||
{
|
||||
if (cur_hex_size > max_hex_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (i != 0)
|
||||
{
|
||||
if (is_pretty && (i % 16 == 0))
|
||||
{
|
||||
if (cur_hex_size + 2 > max_hex_size)
|
||||
{
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
memcpy(&hex[cur_hex_size], "\r\n", 2);
|
||||
cur_hex_size += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_space)
|
||||
{
|
||||
if (cur_hex_size + 1 > max_hex_size)
|
||||
{
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
hex[cur_hex_size] = ' ';
|
||||
cur_hex_size += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cur_hex_size + 2 > max_hex_size)
|
||||
{
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
uint8_to_hex(bin[i], &hex[cur_hex_size]);
|
||||
cur_hex_size += 2;
|
||||
}
|
||||
|
||||
if (is_upper)
|
||||
{
|
||||
hex_to_uppercase(hex, cur_hex_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
hex_to_lowercase(hex, cur_hex_size);
|
||||
}
|
||||
|
||||
*hex_size = cur_hex_size;
|
||||
if (cur_hex_size < max_hex_size)
|
||||
{
|
||||
// Since we have room add NULL as a convenience, but don't add to the
|
||||
// output size.
|
||||
hex[cur_hex_size] = 0;
|
||||
}
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
inline static uint8_t hex_digit_to_num(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return (uint8_t)(c - '0');
|
||||
}
|
||||
if (c >= 'a' && c <= 'f')
|
||||
{
|
||||
return (uint8_t)(c - 'a') + 10;
|
||||
}
|
||||
if (c >= 'A' && c <= 'F')
|
||||
{
|
||||
return (uint8_t)(c - 'A') + 10;
|
||||
}
|
||||
return 16;
|
||||
}
|
||||
|
||||
|
||||
ATCA_STATUS atcab_hex2bin_(const char* hex, size_t hex_size, uint8_t* bin, size_t* bin_size, bool is_space)
|
||||
{
|
||||
size_t hex_index;
|
||||
size_t bin_index = 0;
|
||||
bool is_upper_nibble = true;
|
||||
|
||||
for (hex_index = 0; hex_index < hex_size; hex_index++)
|
||||
{
|
||||
if (!isHexDigit(hex[hex_index]))
|
||||
{
|
||||
if (((hex_index + 1) % 3 == 0) && is_space)
|
||||
{
|
||||
if (hex[hex_index] != ' ')
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
continue; // Skip any non-hex character
|
||||
}
|
||||
if (bin_index >= *bin_size)
|
||||
{
|
||||
return ATCA_SMALL_BUFFER;
|
||||
}
|
||||
|
||||
if (is_upper_nibble)
|
||||
{
|
||||
// Upper nibble
|
||||
bin[bin_index] = hex_digit_to_num(hex[hex_index]) << 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Lower nibble
|
||||
bin[bin_index] += hex_digit_to_num(hex[hex_index]);
|
||||
bin_index++;
|
||||
}
|
||||
is_upper_nibble = !is_upper_nibble;
|
||||
}
|
||||
if (!is_upper_nibble)
|
||||
{
|
||||
// Didn't end with an even number of hex digits. Assume it was malformed.
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
*bin_size = bin_index;
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
/** \brief Function that converts a hex string to binary buffer
|
||||
* \param[in] hex Input buffer to convert
|
||||
* \param[in] hex_size Length of buffer to convert
|
||||
* \param[out] bin Buffer that receives binary
|
||||
* \param[inout] bin_size As input, the size of the bin buffer.
|
||||
* As output, the size of the bin data.
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_hex2bin(const char* hex, size_t hex_size, uint8_t* bin, size_t* bin_size)
|
||||
{
|
||||
return atcab_hex2bin_(hex, hex_size, bin, bin_size, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks to see if a character is an ASCII representation of a digit ((c ge '0') and (c le '9'))
|
||||
* \param[in] c character to check
|
||||
* \return True if the character is a digit
|
||||
*/
|
||||
bool isDigit(char c)
|
||||
{
|
||||
return (c >= '0') && (c <= '9');
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks to see if a character is whitespace
|
||||
* \param[in] c character to check
|
||||
* \return True if the character is whitespace
|
||||
*/
|
||||
bool isWhiteSpace(char c)
|
||||
{
|
||||
return (c == '\n') || (c == '\r') || (c == '\t') || (c == ' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks to see if a character is an ASCII representation of hex ((c >= 'A') and (c <= 'F')) || ((c >= 'a') and (c <= 'f'))
|
||||
* \param[in] c character to check
|
||||
* \return True if the character is a hex
|
||||
*/
|
||||
bool isAlpha(char c)
|
||||
{
|
||||
return ((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z'));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks to see if a character is an ASCII representation of hex ((c >= 'A') and (c <= 'F')) || ((c >= 'a') and (c <= 'f'))
|
||||
* \param[in] c character to check
|
||||
* \return True if the character is a hex
|
||||
*/
|
||||
bool isHexAlpha(char c)
|
||||
{
|
||||
return ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f'));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if this character is a valid hex character or if this is whitespace (The character can be
|
||||
* included in a valid hexstring).
|
||||
* \param[in] c character to check
|
||||
* \return True if the character can be included in a valid hexstring
|
||||
*/
|
||||
bool isHex(char c)
|
||||
{
|
||||
return isHexDigit(c) || isWhiteSpace(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if this character is a valid hex character.
|
||||
* \param[in] c character to check
|
||||
* \return True if the character can be included in a valid hexstring
|
||||
*/
|
||||
bool isHexDigit(char c)
|
||||
{
|
||||
return isDigit(c) || isHexAlpha(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Remove white space from a ASCII hex string.
|
||||
* \param[in] ascii_hex Initial hex string to remove white space from
|
||||
* \param[in] ascii_hex_len Length of the initial hex string
|
||||
* \param[in] packed_hex Resulting hex string without white space
|
||||
* \param[inout] packed_len In: Size to packed_hex buffer
|
||||
* Out: Number of bytes in the packed hex string
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS packHex(const char* ascii_hex, size_t ascii_hex_len, char* packed_hex, size_t* packed_len)
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t j = 0;
|
||||
|
||||
// Verify the inputs
|
||||
if ((ascii_hex == NULL) || (packed_hex == NULL) || (packed_len == NULL))
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
// Loop through each character and only add the hex characters
|
||||
for (i = 0; i < ascii_hex_len; i++)
|
||||
{
|
||||
if (isHexDigit(ascii_hex[i]))
|
||||
{
|
||||
if (j > *packed_len)
|
||||
{
|
||||
break;
|
||||
}
|
||||
packed_hex[j++] = ascii_hex[i];
|
||||
}
|
||||
}
|
||||
*packed_len = j;
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef ATCAPRINTF
|
||||
/** \brief Print each hex character in the binary buffer with spaces between bytes
|
||||
* \param[in] label label to print
|
||||
* \param[in] binary input buffer to print
|
||||
* \param[in] bin_len length of buffer to print
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_printbin_label(const char* label, uint8_t* binary, size_t bin_len)
|
||||
{
|
||||
printf("%s", label);
|
||||
return atcab_printbin(binary, bin_len, true);
|
||||
}
|
||||
|
||||
/** \brief Print each hex character in the binary buffer with spaces between bytes
|
||||
* \param[in] binary input buffer to print
|
||||
* \param[in] bin_len length of buffer to print
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_printbin_sp(uint8_t* binary, size_t bin_len)
|
||||
{
|
||||
return atcab_printbin(binary, bin_len, true);
|
||||
}
|
||||
|
||||
/** \brief Print each hex character in the binary buffer
|
||||
* \param[in] binary input buffer to print
|
||||
* \param[in] bin_len length of buffer to print
|
||||
* \param[in] add_space indicates whether spaces and returns should be added for pretty printing
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_printbin(uint8_t* binary, size_t bin_len, bool add_space)
|
||||
{
|
||||
size_t i = 0;
|
||||
size_t line_len = 16;
|
||||
|
||||
// Verify the inputs
|
||||
if (binary == NULL)
|
||||
{
|
||||
return ATCA_BAD_PARAM;
|
||||
}
|
||||
|
||||
// Set the line length
|
||||
line_len = add_space ? 16 : 32;
|
||||
|
||||
// Print the bytes
|
||||
for (i = 0; i < bin_len; i++)
|
||||
{
|
||||
// Print the byte
|
||||
if (add_space)
|
||||
{
|
||||
printf("%02X ", binary[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%02X", binary[i]);
|
||||
}
|
||||
|
||||
// Break at the line_len
|
||||
if ((i + 1) % line_len == 0)
|
||||
{
|
||||
printf("\r\n");
|
||||
}
|
||||
}
|
||||
// Print the last carriage return
|
||||
printf("\r\n");
|
||||
|
||||
return ATCA_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Base 64 Encode/Decode
|
||||
|
||||
#define B64_IS_EQUAL (uint8_t)64
|
||||
#define B64_IS_INVALID (uint8_t)0xFF
|
||||
|
||||
/**
|
||||
* \brief Returns true if this character is a valid base 64 character or if this is whitespace (A character can be
|
||||
* included in a valid base 64 string).
|
||||
* \param[in] c character to check
|
||||
* \param[in] rules base64 ruleset to use
|
||||
* \return True if the character can be included in a valid base 64 string
|
||||
*/
|
||||
bool isBase64(char c, const uint8_t * rules)
|
||||
{
|
||||
return isBase64Digit(c, rules) || isWhiteSpace(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns true if this character is a valid base 64 character.
|
||||
* \param[in] c character to check
|
||||
* \param[in] rules base64 ruleset to use
|
||||
* \return True if the character can be included in a valid base 64 string
|
||||
*/
|
||||
bool isBase64Digit(char c, const uint8_t * rules)
|
||||
{
|
||||
return isDigit(c) || isAlpha(c) || c == rules[0] || c == rules[1] || c == rules[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the base 64 index of the given character.
|
||||
* \param[in] c character to check
|
||||
* \param[in] rules base64 ruleset to use
|
||||
* \return the base 64 index of the given character
|
||||
*/
|
||||
uint8_t base64Index(char c, const uint8_t * rules)
|
||||
{
|
||||
if ((c >= 'A') && (c <= 'Z'))
|
||||
{
|
||||
return (uint8_t)(c - 'A');
|
||||
}
|
||||
if ((c >= 'a') && (c <= 'z'))
|
||||
{
|
||||
return (uint8_t)(26 + c - 'a');
|
||||
}
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
{
|
||||
return (uint8_t)(52 + c - '0');
|
||||
}
|
||||
if (c == rules[0])
|
||||
{
|
||||
return (uint8_t)62;
|
||||
}
|
||||
if (c == rules[1])
|
||||
{
|
||||
return (uint8_t)63;
|
||||
}
|
||||
if (c == rules[2])
|
||||
{
|
||||
return B64_IS_EQUAL;
|
||||
}
|
||||
return B64_IS_INVALID;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the base 64 character of the given index.
|
||||
* \param[in] id index to check
|
||||
* \param[in] rules base64 ruleset to use
|
||||
* \return the base 64 character of the given index
|
||||
*/
|
||||
char base64Char(uint8_t id, const uint8_t * rules)
|
||||
{
|
||||
if (id >= 0 && (id < 26))
|
||||
{
|
||||
return (char)('A' + id);
|
||||
}
|
||||
if ((id >= 26) && (id < 52))
|
||||
{
|
||||
return (char)('a' + id - 26);
|
||||
}
|
||||
if ((id >= 52) && (id < 62))
|
||||
{
|
||||
return (char)('0' + id - 52);
|
||||
}
|
||||
if (id == 62)
|
||||
{
|
||||
return rules[0];
|
||||
}
|
||||
if (id == 63)
|
||||
{
|
||||
return rules[1];
|
||||
}
|
||||
|
||||
if (id == B64_IS_EQUAL)
|
||||
{
|
||||
return rules[2];
|
||||
}
|
||||
return B64_IS_INVALID;
|
||||
}
|
||||
|
||||
static ATCA_STATUS atcab_base64decode_block(const uint8_t id[4], uint8_t* data, size_t* data_size, size_t data_max_size)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
size_t new_bytes = 0;
|
||||
|
||||
do
|
||||
{
|
||||
// Make sure padding characters can only be the last two
|
||||
if ((id[0] == B64_IS_EQUAL) ||
|
||||
(id[1] == B64_IS_EQUAL) ||
|
||||
(id[2] == B64_IS_EQUAL && id[3] != B64_IS_EQUAL))
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Base64 chars after end padding");
|
||||
}
|
||||
|
||||
// Make sure output buffer has enough space
|
||||
if (id[2] == B64_IS_EQUAL)
|
||||
{
|
||||
new_bytes = 1;
|
||||
}
|
||||
else if (id[3] == B64_IS_EQUAL)
|
||||
{
|
||||
new_bytes = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
new_bytes = 3;
|
||||
}
|
||||
if ((*data_size) + new_bytes > data_max_size)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "decoded buffer too small");
|
||||
}
|
||||
|
||||
// Decode into output buffer
|
||||
data[(*data_size)++] = ((id[0] << 2) | (id[1] >> 4));
|
||||
if (id[2] == B64_IS_EQUAL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
data[(*data_size)++] = ((id[1] << 4) | (id[2] >> 2));
|
||||
if (id[3] == B64_IS_EQUAL)
|
||||
{
|
||||
break;
|
||||
}
|
||||
data[(*data_size)++] = ((id[2] << 6) | id[3]);
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Decode base64 string to data with ruleset option.
|
||||
*
|
||||
* \param[in] encoded Base64 string to be decoded.
|
||||
* \param[in] encoded_size Size of the base64 string in bytes.
|
||||
* \param[out] data Decoded data will be returned here.
|
||||
* \param[inout] data_size As input, the size of the byte_array buffer.
|
||||
* As output, the length of the decoded data.
|
||||
* \param[in] rules base64 ruleset to use
|
||||
*/
|
||||
ATCA_STATUS atcab_base64decode_(const char* encoded, size_t encoded_size, uint8_t* data, size_t* data_size, const uint8_t * rules)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
uint8_t id[4];
|
||||
int id_index = 0;
|
||||
size_t enc_index = 0;
|
||||
size_t data_max_size;
|
||||
bool is_done = false;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the input parameters
|
||||
if (encoded == NULL || data == NULL || data_size == NULL || rules == NULL)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Null input parameter");
|
||||
}
|
||||
data_max_size = *data_size;
|
||||
*data_size = 0;
|
||||
|
||||
// Start decoding the input data
|
||||
for (enc_index = 0; enc_index < encoded_size; enc_index++)
|
||||
{
|
||||
if (isWhiteSpace(encoded[enc_index]))
|
||||
{
|
||||
continue; // Skip any whitespace characters
|
||||
}
|
||||
if (!isBase64Digit(encoded[enc_index], rules))
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Invalid base64 character");
|
||||
}
|
||||
if (is_done)
|
||||
{
|
||||
// We found valid base64 characters after end padding (equals)
|
||||
// characters
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Base64 chars after end padding");
|
||||
}
|
||||
id[id_index++] = base64Index(encoded[enc_index], rules);
|
||||
// Process data 4 characters at a time
|
||||
if (id_index >= 4)
|
||||
{
|
||||
id_index = 0;
|
||||
status = atcab_base64decode_block(id, data, data_size, data_max_size);
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
is_done = (id[3] == B64_IS_EQUAL);
|
||||
}
|
||||
}
|
||||
if (status != ATCA_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
if (id_index)
|
||||
{
|
||||
if (id_index < 2)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Invalid number of base64 chars");
|
||||
}
|
||||
// End of base64 string, but no padding characters
|
||||
for (; id_index < 4; id_index++)
|
||||
{
|
||||
id[id_index] = B64_IS_EQUAL;
|
||||
}
|
||||
status = atcab_base64decode_block(id, data, data_size, data_max_size);
|
||||
}
|
||||
}
|
||||
while (false);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/** \brief Encode data as base64 string with ruleset option. */
|
||||
ATCA_STATUS atcab_base64encode_(
|
||||
const uint8_t* data, /**< [in] The input byte array that will be converted to base 64 encoded characters */
|
||||
size_t data_size, /**< [in] The length of the byte array */
|
||||
char* encoded, /**< [in] The output converted to base 64 encoded characters. */
|
||||
size_t* encoded_size, /**< [inout] Input: The size of the encoded buffer, Output: The length of the encoded base 64 character string */
|
||||
const uint8_t * rules /**< [in] ruleset to use during encoding */
|
||||
)
|
||||
{
|
||||
ATCA_STATUS status = ATCA_SUCCESS;
|
||||
size_t data_idx = 0;
|
||||
size_t b64_idx = 0;
|
||||
size_t offset = 0;
|
||||
uint8_t id = 0;
|
||||
size_t b64_len;
|
||||
|
||||
do
|
||||
{
|
||||
// Check the input parameters
|
||||
if (encoded == NULL || data == NULL || encoded_size == NULL || !rules)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "Null input parameter");
|
||||
}
|
||||
|
||||
// Calculate output length for buffer size check
|
||||
b64_len = (data_size / 3 + (data_size % 3 != 0)) * 4; // ceil(size/3)*4
|
||||
if (rules[3])
|
||||
{
|
||||
// We add newlines to the output
|
||||
if (rules[3] % 4 != 0)
|
||||
{
|
||||
status = ATCA_BAD_PARAM;
|
||||
BREAK(status, "newline rules[3] must be multiple of 4");
|
||||
}
|
||||
b64_len += (b64_len / rules[3]) * 2;
|
||||
}
|
||||
b64_len += 1; // terminating null
|
||||
if (*encoded_size < b64_len)
|
||||
{
|
||||
status = ATCA_SMALL_BUFFER;
|
||||
BREAK(status, "Length of encoded buffer too small");
|
||||
}
|
||||
// Initialize the return length to 0
|
||||
*encoded_size = 0;
|
||||
|
||||
// Loop through the byte array by 3 then map to 4 base 64 encoded characters
|
||||
for (data_idx = 0; data_idx < data_size; data_idx += 3)
|
||||
{
|
||||
// Add \r\n every n bytes if specified
|
||||
if (rules[3] && data_idx > 0 && (b64_idx - offset) % rules[3] == 0)
|
||||
{
|
||||
// as soon as we do this, we introduce an offset
|
||||
encoded[b64_idx++] = '\r';
|
||||
encoded[b64_idx++] = '\n';
|
||||
offset += 2;
|
||||
}
|
||||
|
||||
id = (data[data_idx] & 0xFC) >> 2;
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
id = (data[data_idx] & 0x03) << 4;
|
||||
if (data_idx + 1 < data_size)
|
||||
{
|
||||
id |= (data[data_idx + 1] & 0xF0) >> 4;
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
id = (data[data_idx + 1] & 0x0F) << 2;
|
||||
if (data_idx + 2 < data_size)
|
||||
{
|
||||
id |= (data[data_idx + 2] & 0xC0) >> 6;
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
id = data[data_idx + 2] & 0x3F;
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
encoded[b64_idx++] = base64Char(B64_IS_EQUAL, rules);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
encoded[b64_idx++] = base64Char(id, rules);
|
||||
encoded[b64_idx++] = base64Char(B64_IS_EQUAL, rules);
|
||||
encoded[b64_idx++] = base64Char(B64_IS_EQUAL, rules);
|
||||
}
|
||||
}
|
||||
|
||||
// Strip any trailing nulls
|
||||
while (b64_idx > 1 && encoded[b64_idx - 1] == 0)
|
||||
{
|
||||
b64_idx--;
|
||||
}
|
||||
|
||||
// Null terminate end
|
||||
encoded[b64_idx++] = 0;
|
||||
|
||||
// Set the final encoded length (excluding terminating null)
|
||||
*encoded_size = b64_idx - 1;
|
||||
}
|
||||
while (false);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Encode data as base64 string
|
||||
*
|
||||
* \param[in] byte_array Data to be encode in base64.
|
||||
* \param[in] array_len Size of byte_array in bytes.
|
||||
* \param[in] encoded Base64 output is returned here.
|
||||
* \param[inout] encoded_len As input, the size of the encoded buffer.
|
||||
* As output, the length of the encoded base64
|
||||
* character string.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_base64encode(const uint8_t* byte_array, size_t array_len, char* encoded, size_t* encoded_len)
|
||||
{
|
||||
return atcab_base64encode_(byte_array, array_len, encoded, encoded_len, atcab_b64rules_default);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Decode base64 string to data
|
||||
*
|
||||
* \param[in] encoded Base64 string to be decoded.
|
||||
* \param[in] encoded_len Size of the base64 string in bytes.
|
||||
* \param[out] byte_array Decoded data will be returned here.
|
||||
* \param[inout] array_len As input, the size of the byte_array buffer.
|
||||
* As output, the length of the decoded data.
|
||||
*
|
||||
* \return ATCA_SUCCESS on success, otherwise an error code.
|
||||
*/
|
||||
ATCA_STATUS atcab_base64decode(const char* encoded, size_t encoded_len, uint8_t* byte_array, size_t* array_len)
|
||||
{
|
||||
return atcab_base64decode_(encoded, encoded_len, byte_array, array_len, atcab_b64rules_default);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user