FreeRTOS website now available in Simplified Chinese
Search and browse content in your preferred language. See the blog post.
New FreeRTOS Long Term Support version now available.
Receive security patches and critical bug fixes on FreeRTOS libraries for two years. See the blog post.
FreeRTOS Extended Maintenance Program (EMP) registration now open.
Providing security patches and critical bug fixes on FreeRTOS Long Term Support (LTS) versions for up to 10 additional years. See the blog post.
FreeRTOS-Plus-TCP v3.0.0 released:
We've added comprehensive unit tests and penetration and protocol testing. See the blog post.
Featured FreeRTOS IoT Integrations:
Introducing three featured integrations for more secure IoT applications. See the blog post.
PKCS #11 Functions
PKCS #11 includes many functions and supports a variety of use cases. The FreeRTOS PKCS #11 library only implements a small subset of functions for the use cases first describe. Each function is fully documented in the PKCS #11 standard. The terminology can be difficult for the first reader, so we also provide examples code below.
PKCS #11 operational functions:
C_Random. Random numbers are required by the TCP/IP stack (for example, when selecting an initial sequence number), within cryptographic algorithms, and during the TLS handshake.
C_Sign. Signing a message sent to another network node allows that node to identify the messages true origin.
C_FindObject. Finds an object managed by PKCS #11, for example the client certificate.
C_GetAttributeValue. This API gets the value of an object's attribute, for example if the object is a key type or a certificate type.
PKCS #11 administrative functions:
C_Initialize. Initializes the crypto libraries.
C_Finalize. Cleans up resources used by the crypto libraries.
C_OpenSession. Opens a session (or connection) between a software application and a particular crypto token.
C_CloseSession. Closes the session opened by C_OpenSession.
C_Login. Logs into a token.
C_GetFunctionList. Obtains a struct containing function pointers for use in calling the PKCS #11 APIs.
C_GetSlotList. Obtains the list of slots, which can be used to access any token in a slot.
Code Samples
Here are some example code snippets that showcase how one might use the PKCS #11 API.
Using C_GenerateRandom:
This code snippet shows how to use PKCS #11 to get a random number. For example, this function can be used for FreeRTOS-Plus-TCP to generate random TCP numbers.
Using C_Sign to add our private key's signature to our message:
This is a snippet from the TLS layer of our code that uses PKCS #11 for the C_Sign operation. In this example, just before we send a TLS message, we call into the PKCS #11 layer and ask it to sign our message with our private key.
static int prvPrivateKeySigningCallback( void * pvContext,
mbedtls_md_type_t xMdAlg,
const unsigned char * pucHash,
size_t xHashLen,
unsigned char* pucSig,
size_t * pxSigLen,
int ( *piRng ) ( void *, unsigned char *, size_t ),
void * pvRng )
{
CK_RV xResult = CKR_OK;
int lFinalResult = 0;
TLSContext_t * pxTLSContext = ( TLSContext_t* ) pvContext;
CK_MECHANISM xMech = { 0 };
CK_BYTE xToBeSigned[ 256 ];
CK_ULONG xToBeSignedLen = sizeof( xToBeSigned );
/* Unreferenced parameters. */
( void )( piRng );
( void )( pvRng );
( void )( xMdAlg);
/* Sanity check buffer length. */
if ( xHashLen > sizeof( xToBeSigned ) )
{
xResult = CKR_ARGUMENTS_BAD;
}
/* Format the hash data to be signed. */
if ( CKK_RSA == pxTLSContext->xKeyType )
{
xMech.mechanism = CKM_RSA_PKCS;
/* mbedTLS expects hashed data without padding, but PKCS #11 C_Sign
* function performs a hash & sign if hash algorithm is specified. This
* helper function applies padding indicating data was hashed with
* SHA-256 while still allowing pre-hashed data to be provided. */
xResult = vAppendSHA256AlgorithmIdentifierSequence( ( uint8_t * ) pucHash, xToBeSigned );
xToBeSignedLen = pkcs11RSA_SIGNATURE_INPUT_LENGTH;
}
else if ( CKK_EC == pxTLSContext->xKeyType )
{
xMech.mechanism = CKM_ECDSA;
memcpy( xToBeSigned, pucHash, xHashLen );
xToBeSignedLen = xHashLen;
}
else
{
xResult = CKR_ARGUMENTS_BAD;
}
if ( CKR_OK == xResult )
{
/* Use the PKCS#11 module to sign. */
xResult = pxTLSContext->
pxP11FunctionList->C_SignInit( pxTLSContext->xP11Session,
&xMech,
pxTLSContext->xP11PrivateKey );
}
if ( CKR_OK == xResult )
{
*pxSigLen = sizeof( xToBeSigned );
xResult = pxTLSContext->
pxP11FunctionList->C_Sign( ( CK_SESSION_HANDLE ) pxTLSContext->xP11Session,
xToBeSigned,
xToBeSignedLen,
pucSig,
( CK_ULONG_PTR ) pxSigLen );
}
if ( ( xResult == CKR_OK ) && ( CKK_EC == pxTLSContext->xKeyType ) )
{
/* PKCS #11 for P256 returns a 64-byte signature with 32 bytes for R and
* 32 bytes for S. This must be converted to an ASN.1 encoded array. */
if (*pxSigLen != pkcs11ECDSA_P256_SIGNATURE_LENGTH)
{
xResult = CKR_FUNCTION_FAILED;
}
if ( xResult == CKR_OK )
{
PKI_pkcs11SignatureTombedTLSSignature( pucSig, pxSigLen );
}
}
if ( xResult != CKR_OK )
{
TLS_PRINT( ( "ERROR: Failure in signing callback: %d \r\n", xResult ) );
lFinalResult = TLS_ERROR_SIGN;
}
return lFinalResult;
}
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.