添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -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)

View File

@@ -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

View File

@@ -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 Microchips 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.

View File

@@ -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")

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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).
![CryptoAuthLib Architecture](./docs/CryptoAuthLib-Architecture.png "CryptoAuthLib Architecture" )
There are three primary object types in CryptoAuthLib:
- Device (ATCADevice)
- Command (ATCACommand)
- Interface (ATCAIface)
ATCADevice is a composite object made up of ATCACommand ATCAIface.
![ATCADevice](./docs/cryptoauthlib-uml/ATCADevice.png "ATCADevice and ATCACommand object" )
![ATCAIface](./docs/cryptoauthlib-uml/ATCAIFace.png "ATCAIface object" )
![Hardware abstraction layer](./docs/cryptoauthlib-uml/ATCAHal.png "CryptoAuth hardware abstraction layer" )
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"
```

View File

@@ -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.

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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

View File

@@ -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

View File

@@ -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, &current_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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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
};

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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,
};
/** @} */

View File

@@ -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_ */

View File

@@ -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;
}
}
/** @} */

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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);
}
/** @} */

View File

@@ -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

View File

@@ -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_ */

View File

@@ -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;
}
/** @} */

View File

@@ -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

View File

@@ -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;
}
/** @} */

View File

@@ -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

View File

@@ -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

View File

@@ -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 */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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_ */

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}
/** @} */

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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