- Introduction
- Prerequisites For PKCS #11 Test
- PKCS #11 Test Configurations
- Source Code Organization
- Implement PKCS #11 Test Application
- Run The PKCS #11 Test
6.1 Setup the provisioning mechanism and key function
6.2 Compile and run the PKCS #11 test application
PKCS #11 is a standardize API to allow application software to use, create, modify and delete cryptographic objects. The benefit of PKCS #11 is that it allows the app to take advantage of offload crypto while mitigating the threats of private key cloning and theft.
To keep as lean as possible, FreeRTOS uses a subset of PKCS #11 APIs. Implementers are free to integrate more than our required subset of PKCS #11, but it is optional to do so.
The PKCS #11 API functions required by FreeRTOS are described in the following table.
FreeRTOS Library | Required PKCS #11 API Family |
---|---|
Any | Initialize, Finalize, Open/Close Session, GetSlotList, Login |
Provisioning Demo | GenerateKeyPair, CreateObject, DestroyObject, InitToken, GetTokenInfo |
TLS | Random, Sign, FindObject, GetAttributeValue |
FreeRTOS+TCP | Random, Digest |
OTA | Verify, Digest, FindObject, GetAttributeValue |
The PKCS #11 test validates the PKCS #11 subset implementation. The test directly exercises the PKCS #11 implementation on the device under testing. User runs the PKCS #11 test by running a test application. The test application is usually implemented by calling the provided PKCS #11 test routine from the main function. By passing this test, the PKCS #11 subset implementation is validated to support required PKCS #11 functions by FreeRTOS.
The PKCS #11 interface is defined in the open-standard documentation available here http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html.
The PKCS #11 tests assume the tested platform already has the following components integrated.
- The PKCS #11 APIs subset implementation
The implementation should support the APIs list in this section. - corePKCS11
The utilities in corePKCS #11 are used in PKCS #11 test. corePKCS11 library provides software based implementation. Developers can implement the required PKCS #11 APIs using hardware crypto features of their board. The PKCS #11 Test does not mandate specific implementation. - MbedTLS
MbedTLS is required to verify the result of the PKCS #11 implementation. - Unity test framework
PKCS #11 test make use of the Unity test framework. Reference the website for integration guide.
The following table lists the required test configurations for PKCS #11 tests. These test configurations need to be defined in test_param_config.h.
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 import private key. RSA and EC key import will be validated in the test if the corresponding key functions are enabled. |
PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT | The porting supports keypair generation. EC keypair generation will be validated in the test if the corresponding key functions are enabled. |
PKCS11_TEST_PREPROVISIONED_SUPPORT | The porting has pre-provisioned credentials. These test 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 the labels of the 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 1 to enable the JITP codeverify test. |
PKCS11_TEST_LABEL_CODE_VERIFICATION_KEY | The label of the code verification key used in JITP codeverify test. |
PKCS11_TEST_LABEL_JITP_CERTIFICATE | The label of the JITP certificate used in JITP codeverify test. |
PKCS11_TEST_LABEL_ROOT_CERTIFICATE | The label of the root certificate used in JITP codeverify test. |
PKCS11_TEST_RSA_CERTIFICATE | The certificate used to verify RSA preprovision mechanism. |
PKCS11_TEST_RSA_CERTIFICATE_LENGTH | The certificate length used to verify RSA preprovision mechanism. |
FreeRTOS libraries and reference integrations needs at least one of the key function and one of the key provisioning mechanism supported by the PKCS #11 APIs. The test must enable at least one of the following configurations:
- At least one of the key function configurations:
- PKCS11_TEST_RSA_KEY_SUPPORT
- PKCS11_TEST_EC_KEY_SUPPORT
- At least one of the key provisioning mechanisms:
- PKCS11_TEST_IMPORT_PRIVATE_KEY_SUPPORT
- PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT
- PKCS11_TEST_PREPROVISIONED_SUPPORT
Pre-provisioned device credential test can not be enabled with other provisioning mechanisms. It must be run in the following conditions:
- Enable PKCS11_TEST_PREPROVISIONED_SUPPORT and the other provisioning mechanisms must be disabled
- Only one of the key function, PKCS11_TEST_RSA_KEY_SUPPORT or PKCS11_TEST_EC_KEY_SUPPORT, enabled
- Setup 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 and PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS. These credentials must exist in the PKCS #11 before running the test.
- PKCS11_TEST_RSA_CERTIFICATE and PKCS11_TEST_RSA_CERTIFICATE_LENGTH must be defined before running the test to verify RSA preprovision mechanism.
You may need to run the test several times with different configurations if your implementation support pre-provisioned credentials and other provisioning mechanisms.
Note: Objects with label PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS, PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS and PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS will be destroyed during the test if any one of PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT and PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT is enabled.
The tree only lists the required files to run the PKCS #11 test.
./FreeRTOS-Libraries-Integration-Tests/
├── config_template
│ ├── test_execution_config_template.h
│ └── test_param_config_template.h
└── src
├── common
│ └── platform_function.h
├── pkcs11
│ ├── core_pkcs11_test.c
│ ├── core_pkcs11_test.h
│ ├── ecdsa_test_credentials.h
│ ├── rsa_test_credentials.h
│ └── dev_mode_key_provisioning
│ ├── dev_mode_key_provisioning.c
│ └── dev_mode_key_provisioning.h
├── qualification_test.c
└── qualification_test.h
- Add FreeRTOS-Libraries-Integration-Tests as a submodule into your project. It doesn’t matter where the submodule is placed in the project, as long as it can be built.
- Copy config_template/test_execution_config_template.h and config_template/test_param_config_template.h to a project location in the build path, and rename them to test_execution_config.h and test_param_config.h.
- Include relevant files into the build system. If using CMake, qualification_test.cmake and src/pkcs11_test.cmake can be used to include relevant files.
- Implement the platform functions required by PKCS #11 tests.
- Enable the PKCS #11 test config, PKCS11_TEST_ENABLED, in test_execution_config.h.
- Implement the main function and call the RunQualificationTest.
The following is an example test application.
#include "platform_function.h"
#include "qualification_test.h"
FRTestThreadHandle_t FRTest_ThreadCreate( FRTestThreadFunction_t threadFunc, void * pParam )
{
/* Thread create function for multithreaded test. */
}
int FRTest_ThreadTimedJoin( FRTestThreadHandle_t threadHandle, uint32_t timeoutMs )
{
/* Thread timed wait function for multithreaded test. */
}
void * FRTest_MemoryAlloc( size_t size )
{
/* Malloc function to allocate memory for test. */
}
void FRTest_MemoryFree( void * ptr )
{
/* Free function to free memory allocated by FRTest_MemoryAlloc function. */
}
void yourMainFunction( void )
{
RunQualificationTest();
}
Setup the provisioning mechanism and key function in test_param_config.h according to the device capability. The following is a sample test_param_config.h if corePKCS11 is used for the PKCS #11 implementation.
#include "core_pkcs11_config.h"
/* Setup key function. */
#define PKCS11_TEST_RSA_KEY_SUPPORT ( 1 )
#define PKCS11_TEST_EC_KEY_SUPPORT ( 1 )
/* Setup provisioning method. */
#define PKCS11_TEST_IMPORT_PRIVATE_KEY_SUPPORT ( 1 )
#define PKCS11_TEST_GENERATE_KEYPAIR_SUPPORT ( 1 )
#define PKCS11_TEST_PREPROVISIONED_SUPPORT ( 0 )
/* The device credential labels. */
#define PKCS11_TEST_LABEL_DEVICE_PRIVATE_KEY_FOR_TLS pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS
#define PKCS11_TEST_LABEL_DEVICE_PUBLIC_KEY_FOR_TLS pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS
#define PKCS11_TEST_LABEL_DEVICE_CERTIFICATE_FOR_TLS pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS
/* JITP credential labels. */
#define PKCS11_TEST_JITP_CODEVERIFY_ROOT_CERT_SUPPORTED pkcs11configJITP_CODEVERIFY_ROOT_CERT_SUPPORTED
#define PKCS11_TEST_LABEL_CODE_VERIFICATION_KEY pkcs11configLABEL_CODE_VERIFICATION_KEY
#define PKCS11_TEST_LABEL_JITP_CERTIFICATE pkcs11configLABEL_JITP_CERTIFICATE
#define PKCS11_TEST_LABEL_ROOT_CERTIFICATE pkcs11configLABEL_ROOT_CERTIFICATE
Compile and run the test application in your development environment. The following is a sample test result log:
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