Porting the PKCS #11 Library
Amazon FreeRTOS uses the open standard PKCS #11 “CryptoKi” API as the abstraction layer for cryptographic operations, including:
-
Signing and verifying.
-
Storage and enumeration of X.509 certificates.
-
Storage and management of cryptographic keys.
For more information, see PKCS #11 Cryptographic Token Interface Base Specification.
Storing private keys in general-purpose flash memory can be convenient in evaluation and rapid prototyping scenarios. In production scenarios, to reduce the threats of data theft and device duplication, we recommend that you use dedicated cryptographic hardware. Cryptographic hardware includes components with features that prevent cryptographic secret keys from being exported. To use dedicated cryptographic hardware with Amazon FreeRTOS, you need to port the PKCS #11 API to the hardware. For information about the Amazon FreeRTOS PKCS #11 library, see Amazon FreeRTOS PKCS #11 Library in the Amazon FreeRTOS User Guide.
Prerequisites
To port the PKCS #11 library, you need the following:
-
An IDE project or
CMakeLists.txt
list file that includes vendor-supplied drivers that are suitable for sensitive data.For information about setting up a test project, see Setting Up Your Amazon FreeRTOS Source Code for Porting.
-
A validated configuration of the FreeRTOS kernel.
For information about configuring the FreeRTOS kernel for your platform, see Configuring a FreeRTOS Kernel Port.
Porting
To port the PKCS #11 library
-
Port the PKCS #11 API functions.
The PKCS #11 API is dependent on the implementation of cryptographic primitives, such as SHA256 hashing and Elliptic Curve Digital Signature Algorithm (ECDSA) signing.
The Amazon FreeRTOS implementation of PKCS #11 uses the cryptographic primitives implemented in the mbedTLS library. Amazon FreeRTOS includes a port for mbedTLS. If your target hardware offloads crypto to a separate module, or if you want to use a software implementation of the cryptographic primitives other than mbedTLS, you need to modify the existing PKCS #11 port.
-
Port the PKCS # 11 Platform Abstraction Layer (PAL) for device-specific certificate and key storage.
If you decide to use the Amazon FreeRTOS implementation of PKCS #11, little customization is required to read and write cryptographic objects to non-volatile memory (NVM), such as onboard flash memory.
Cryptographic objects should be stored in a section of NVM that is not initialized and is not erased on device reprogramming. Users of the PKCS #11 library should be able to provision devices with credentials, and then reprogram the device with a new application that accesses these credentials through the PKCS #11 interface.
PKCS #11 PAL ports must provide a location to store:
-
The device client certificate.
-
The device client private key.
-
The device client public key.
-
A trusted root CA.
-
A code-verification public key (or a certificate that contains the code-verification public key) for secure bootloader and over-the-air (OTA) updates.
-
A Just-In-Time provisioning certificate.
contains empty definitions for the PAL functions. You must provide ports for, at minimum, the functions listed in this table:<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/ports/pkcs11/iot_pkcs11_pal.cFunction Description PKCS11_PAL_SaveObject
Writes data to non-volatile storage. PKCS11_PAL_FindObject
Uses a PKCS #11 CKA_LABEL
to search for a corresponding PKCS #11 object in non-volatile storage, and returns that object’s handle, if it exists.PKCS11_PAL_GetObjectValue
Retrieves the value of an object, given the handle. PKCS11_PAL_GetObjectValueCleanup
Cleanup for the PKCS11_PAL_GetObjectValue
call. Can be used to free memory allocated in aPKCS11_PAL_GetObjectValue
call. -
-
Add support for a cryptographically random entropy source to your port:
-
If your ports use the mbedTLS library for underlying cryptographic and TLS support, and your device has a true random number generator (TRNG):
-
Implement the
mbedtls_hardware_poll()
function to seed the deterministic random bit generator (DRBG) that mbedTLS uses to produce a cryptographically random bit stream. Thembedtls_hardware_poll()
function is located in
.<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/ports/pkcs11/iot_pkcs11_pal.c
-
-
If your ports use the mbedTLS library for underlying cryptographic and TLS support, but your device does not have a TRNG:
-
Make a copy of
, and in that copy, uncomment<amazon-freertos>
/libraries/3rdparty/mbedtls/include/mbedtls/config.hMBEDTLS_ENTROPY_NV_SEED
, and comment outMBEDTLS_ENTROPY_HARDWARE_ALT
.Save the modified version of
config.h
to
. Do not overwrite the original file.<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/aws_tests/config_files/config.h -
Implement the functions
mbedtls_nv_seed_poll()
,nv_seed_read_func()
, andnv_seed_write_func()
.For information about implementing these functions, see the comments in the mbedtls/include/mbedtls/entropy_poll.h and mbedtls/include/mbedtls/config.h mbedTLS header files.
-
Important
A seed file with an NIST-approved entropy source must be supplied to the device at manufacturing time.
Note
If you are interested in the Amazon FreeRTOS Qualification Program, please read our requirements for RNG.
For more information about NIST-approved DRBGs and entropy sources, see the following NIST publications:
-
Testing
If you are using an IDE to build test projects, you need to set up your library port in the IDE project.
Setting Up the IDE Test Project
If you are using an IDE for porting and testing, you need to add some source files to the IDE test project before you can test your ported code.
Important
In the following steps, make sure that you add the source files to your IDE project from their on-disk location. Do not create duplicate copies of source files.
To set up the PKCS #11 library in the IDE project
-
Add the source file
to the<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/ports/pkcs11/iot_pkcs11_pal.caws_tests
IDE project. -
Add all of the files in the
directory and its subdirectories to the<amazon-freertos>
/libraries/abstractions/pkcs11aws_tests
IDE project. -
Add all of the files in the
directory and its subdirectories to the<amazon-freertos>
/libraries/freertos_plus/standard/pkcs11aws_tests
IDE project. These files implement wrappers for commonly grouped PKCS #11 function sets. -
Add the source file
to the<amazon-freertos>
/libraries/freertos_plus/standard/crypto/src/aws_crypto.caws_tests
IDE project. This file implements the CRYPTO abstraction wrapper for mbedTLS. -
Add all of the source and header files from
and its subdirectories to the<amazon-freertos>
/libraries/3rdparty/mbedtlsaws_tests
IDE project. -
Add
and<amazon-freertos>
/libraries/3rdparty/mbedtls/include
to the compiler’s include path.<amazon-freertos>
/libraries/abstractions/pkcs11
Configuring the CMakeLists.txt
File
If you are using CMake to build your test project, you need to define a portable layer target for the library in your CMake list file.
To define a library's portable layer target in CMakeLists.txt
, follow the
instructions in Amazon FreeRTOS Portable Layers.
The CMakeLists.txt
template list file under
includes example portable layer target definitions. You can uncomment the definition
for the library that
you are porting, and modify it to fit your platform.
<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/CMakeLists.txt
See below for an example portable layer target definition for the PKCS #11 library that uses the mbedTLS-based software implementation of PKCS #11 and supplies a port-specific PKCS #11 PAL file.
# PKCS11 afr_mcu_port(pkcs11_implementation DEPENDS AFR::pkcs11_mbedtls) target_sources( AFR::pkcs11_implementation::mcu_port INTERFACE "${
afr_ports_dir
}/pkcs11/iot_pkcs11_pal.c" )
Setting Up Your Local Testing Environment
After you set up the library in the IDE project, you need to configure some other files for testing.
To configure the source and header files for the PKCS #11 tests
-
Open
, and in the function<amazon-freertos>
/libraries/freertos_plus/standard/utils/src/iot_system_init.cSYSTEM_Init()
, comment out the lines that callBUFFERPOOL_Init()
andMQTT_AGENT_Init()
, if you have not done so already. Bufferpool and the MQTT agent are not used in this library's porting tests. When you reach the Configuring the MQTT Library for Testing section, you will be instructed to uncomment these initialization function calls for testing the MQTT library.Only uncomment calls to
SOCKETS_Init()
if you have ported the Secure Sockets library. -
Open
, and set the<amazon-freertos>
/vendors/<vendor>
/boards/<board>
/aws_tests/config_files/aws_test_runner_config.htestrunnerFULL_PKCS11_ENABLED
macro to1
to enable the PKCS #11 test.
Running the Tests
To execute the PKCS #11 tests
-
Build the test project, and then flash it to your device for execution.
-
Check the test results in the UART console.
...
Testing is complete when all tests pass.
Validation
To officially qualify a device for Amazon FreeRTOS, you need to validate the device's
ported source
code with AWS IoT Device Tester. Follow the instructions in
Using AWS IoT Device Tester for Amazon FreeRTOS in the Amazon FreeRTOS User Guide to set up Device Tester for port validation.
To test a specific library's port, the correct test group must be enabled in the
device.json
file in the Device Tester configs
folder.
After you finish porting the Amazon FreeRTOS PKCS #11 library to your device, you can start porting the TLS library. See Porting the TLS Library for instructions.