Skip to content

Latest commit

 

History

History

PKCS #11 Test

On this page:

  1. Introduction
  2. Prerequisites For PKCS #11 Test
  3. PKCS #11 Test Configurations
  4. Source Code Organization
  5. Implement PKCS #11 Test Application
  6. Run The PKCS #11 Test
    6.1 Setup the provisioning mechanism and key function
    6.2 Compile and run the PKCS #11 test application

1. Introduction

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.

2. Prerequisites For PKCS #11 Test

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.

3. PKCS #11 Test Configurations

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.

4. Source Code Organization

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

5. Implement PKCS #11 Test Application

  1. 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.
  2. 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.
  3. 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.
  4. Implement the platform functions required by PKCS #11 tests.
  5. Enable the PKCS #11 test config, PKCS11_TEST_ENABLED, in test_execution_config.h.
  6. 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();
}

6. Run The PKCS #11 Test

6.1 Setup the provisioning mechanism and key function

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

6.2 Compile and run the PKCS #11 test application

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