Porting the corePKCS11 library
The Public Key Cryptography Standard #11 defines a platform-independent API to manage and
use cryptographic tokens. PKCS 11
FreeRTOS libraries and reference integrations use a subset of the PCKS #11 interface standard, with a focus on the operations involving asymmetric keys, random number generation, and hashing. The below table lists the use cases and required PKCS #11 APIs to support.
Use Cases | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Use Case | Required PKCS #11 API Family | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
All | Initialize, Finalize, Open/Close Session, GetSlotList, Login | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Provisioning | GenerateKeyPair, CreateObject, DestroyObject, InitToken, GetTokenInfo | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
TLS | Random, Sign, FindObject, GetAttributeValue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
FreeRTOS+TCP | Random, Digest | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
OTA | Verify, Digest, FindObject, GetAttributeValue |
When to implement a complete PKCS #11 module
Storing private keys in general-purpose flash memory can be convenient in evaluation and rapid prototyping scenarios. We recommend you use dedicated cryptographic hardware to reduce the threats of data theft and device duplication in production scenarios. Cryptographic hardware includes components with features that prevent cryptographic secret keys from being exported. To support this, you will have to implement a subset of PKCS #11 required to work with FreeRTOS libraries as defined in the above table.
When to use FreeRTOS corePKCS11
The corePKCS11 library contains a software-based implementation of the PKCS #11
interface (API) that uses the cryptographic functionality provided by
Mbed TLS
Porting corePKCS11
You will have to have implementations to read and write cryptographic objects to non-volatile memory (NVM), such as on-board flash memory. Cryptographic objects must be stored in a section of NVM that is not initialized and is not erased on device reprogramming. Users of the corePKCS11 library will provision devices with credentials, and then reprogram the device with a new application that accesses these credentials through the corePKCS11 interface. The corePKCS11 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 boot-loader and over-the-air (OTA) updates
-
A Just-In-Time provisioning certificate
Include the header file
PAL APIs | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Function | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_PAL_Initialize |
Initializes the PAL layer. Called by the corePKCS11 library at the start of its initialization sequence. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_PAL_SaveObject |
Writes data to non-volatile storage. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_PAL_FindObject |
Uses a PKCS #11 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_PAL_GetObjectValue |
Retrieves the value of an object, given the handle. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_PAL_GetObjectValueCleanup |
Cleanup for the |
Testing
If you use the FreeRTOS corePKCS11 library or implement the required subset of PKCS11 APIs, you must pass FreeRTOS PKCS11 tests. These test if the required functions for FreeRTOS libraries perform as expected.
This section also describes how you can locally run the FreeRTOS PKCS11 tests with the qualification tests.
Prerequisites
To set up the FreeRTOS PKCS11 tests, the following has to be implemented.
A supported port of PKCS11 APIs.
An implementation of FreeRTOS qualification tests platform functions which include the following:
FRTest_ThreadCreate
FRTest_ThreadTimedJoin
FRTest_MemoryAlloc
FRTest_MemoryFree
(See the
README.md
Porting tests
Add FreeRTOS-Libraries-Integration-Tests
as a submodule into your project. The submodule can be placed in any directory of the project, as long as it can be built. Copy
config_template/test_execution_config_template.h
andconfig_template/test_param_config_template.h
to a project location in the build path, and rename them totest_execution_config.h
andtest_param_config.h
.Include relevant files into the build system. If using
CMake
,qualification_test.cmake
andsrc/pkcs11_tests.cmake
can be used to include relevant files.Implement
UNITY_OUTPUT_CHAR
so that test output logs and device logs do not interleave.Integrate the MbedTLS, which verifies the cryptoki operation result.
Call
RunQualificationTest()
from the application.
Configuring tests
The PKCS11 test suite must be configured according to the PKCS11 implementation.
The following table lists the configuration required by PKCS11 tests in the
test_param_config.h
header file.
PKSC11 test configurations | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Configuration | Description | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_RSA_KEY_SUPPORT |
The porting supports RSA key functions. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_EC_KEY_SUPPORT |
The porting supports EC key functions. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_IMPORT_PRIVATE_KEY_SUPPORT |
The porting supports the import of the private key. RSA and EC key import are validated in the test if the supporting key functions are enabled. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT |
The porting supports keypair generation. EC keypair generation is validated in the test if the supporting key functions are enabled. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_PREPROVISIONED_SUPPORT |
The porting has pre-provisioned credentials.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS |
The label of the private key used in the test. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS |
The label of the public key used in the test. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS |
The label of the certificate used in the test. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_JITP_CODEVERIFY_ROOT_CERT_SUPPORTED |
The porting supports storage for JITP. Set this to 1 to enable the JITP |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_CODE_VERIFICATION_KEY |
The label of the code verification key used in JITP |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_JITP_CERTIFICATE |
The label of the JITP certificate used in JITP |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
PKCS11_TEST_LABEL_ROOT_CERTIFICATE |
The label of the root certificate used in JITP |
FreeRTOS libraries and reference integrations must support a minimum of one key function configuration like RSA or Elliptic curve keys, and one key provisioning mechanism supported by the PKCS11 APIs. The test must enable the following configurations:
At least one of the following key function configurations:
PKCS11_TEST_RSA_KEY_SUPPORT
PKCS11_TEST_EC_KEY_SUPPORT
At least one of the following key provisioning configurations:
PKCS11_TEST_IMPORT_PRIVATE_KEY_SUPPORT
PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT
PKCS11_TEST_PREPROVISIONED_SUPPORT
The pre-provisioned device credential test must run under the following conditions:
PKCS11_TEST_PREPROVISIONED_SUPPORT
must be enabled and other provisioning mechanisms disabled.Only one key function, either
PKCS11_TEST_RSA_KEY_SUPPORT
orPKCS11_TEST_EC_KEY_SUPPORT
, is enabled.Set up the pre-provisioned key labels according to your key function, including
PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS
,PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS
andPKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS
. These credentials must exist before running the test.
The test may need to run several times with different configurations, if the implementation supports pre-provisioned credentials and other provisioning mechanisms.
Note
The objects with labels PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS
,
PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS
and
PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS
are destroyed during the test
if either PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT
or
PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT
is enabled.
Running tests
This section describes how you can locally test the PKCS11 interface with the qualification tests. Alternatively, you can also use IDT to automate the execution. See AWS IoT Device Tester for FreeRTOS in the FreeRTOS User Guide for details.
The following instructions describe how to run the tests:
Open
test_execution_config.h
and define CORE_PKCS11_TEST_ENABLED to 1.Build and flash the application to your device to run. The test result are output to the serial port.
The following is an example of the output test result.
TEST(Full_PKCS11_StartFinish, PKCS11_StartFinish_FirstTest) PASS TEST(Full_PKCS11_StartFinish, PKCS11_GetFunctionList) PASS TEST(Full_PKCS11_StartFinish, PKCS11_InitializeFinalize) PASS TEST(Full_PKCS11_StartFinish, PKCS11_GetSlotList) PASS TEST(Full_PKCS11_StartFinish, PKCS11_OpenSessionCloseSession) PASS TEST(Full_PKCS11_Capabilities, PKCS11_Capabilities) PASS TEST(Full_PKCS11_NoObject, PKCS11_Digest) PASS TEST(Full_PKCS11_NoObject, PKCS11_Digest_ErrorConditions) PASS TEST(Full_PKCS11_NoObject, PKCS11_GenerateRandom) PASS TEST(Full_PKCS11_NoObject, PKCS11_GenerateRandomMultiThread) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_CreateObject) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_FindObject) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_GetAttributeValue) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_Sign) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_FindObjectMultiThread) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_GetAttributeValueMultiThread) PASS TEST(Full_PKCS11_RSA, PKCS11_RSA_DestroyObject) PASS TEST(Full_PKCS11_EC, PKCS11_EC_GenerateKeyPair) PASS TEST(Full_PKCS11_EC, PKCS11_EC_CreateObject) PASS TEST(Full_PKCS11_EC, PKCS11_EC_FindObject) PASS TEST(Full_PKCS11_EC, PKCS11_EC_GetAttributeValue) PASS TEST(Full_PKCS11_EC, PKCS11_EC_Sign) PASS TEST(Full_PKCS11_EC, PKCS11_EC_Verify) PASS TEST(Full_PKCS11_EC, PKCS11_EC_FindObjectMultiThread) PASS TEST(Full_PKCS11_EC, PKCS11_EC_GetAttributeValueMultiThread) PASS TEST(Full_PKCS11_EC, PKCS11_EC_SignVerifyMultiThread) PASS TEST(Full_PKCS11_EC, PKCS11_EC_DestroyObject) PASS ----------------------- 27 Tests 0 Failures 0 Ignored OK
Testing is complete when all tests pass.
Note
To officially qualify a device for FreeRTOS, you must validate the device's ported source code
with AWS IoT Device Tester. Follow the instructions in Using AWS IoT Device Tester for FreeRTOS in the FreeRTOS User Guide to set up AWS IoT 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 AWS IoT Device Tester
configs
folder.