1350 lines
39 KiB
C
Executable File
1350 lines
39 KiB
C
Executable File
/*
|
|
* Copyright 2017 Microchip Technology Incorporated and its subsidiaries.
|
|
*
|
|
* Amazon FreeRTOS PKCS#11 for Curiosity PIC32MZEF V1.0.1
|
|
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
* the Software without restriction, including without limitation the rights to
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is furnished to do
|
|
* so, subject to the following conditions:
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
* SOFTWARE
|
|
******************************************************************************
|
|
*/
|
|
|
|
|
|
/**
|
|
* @file pkcs11.c
|
|
* @brief Amazon FreeRTOS PKCS#11 implementation for software keys. This
|
|
* file deviates from the FreeRTOS style standard for some function names and
|
|
* data types in order to maintain compliance with the PKCS#11 standard.
|
|
*/
|
|
|
|
/* FreeRTOS includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "FreeRTOSIPConfig.h"
|
|
#include "task.h"
|
|
#include "aws_crypto.h"
|
|
#include "aws_pkcs11.h"
|
|
|
|
/* mbedTLS includes. */
|
|
#include "mbedtls/pk.h"
|
|
#include "mbedtls/pk_internal.h"
|
|
#include "mbedtls/x509_crt.h"
|
|
#include "mbedtls/ctr_drbg.h"
|
|
#include "mbedtls/entropy.h"
|
|
#include "mbedtls/sha256.h"
|
|
#include "mbedtls/base64.h"
|
|
#include "aws_clientcredential.h"
|
|
|
|
/* C runtime includes. */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "pkcs11_nvm.h"
|
|
#include <sys/kmem.h>
|
|
/**
|
|
* @brief File storage location definitions.
|
|
*/
|
|
#define pkcs11FILE_NAME_CLIENT_CERTIFICATE "FreeRTOS_P11_Certificate.dat"
|
|
#define pkcs11FILE_NAME_KEY "FreeRTOS_P11_Key.dat"
|
|
|
|
|
|
// TODO aa:
|
|
#define pkcs11FILE_NAME_PUBLISHER_CERTIFICATE "FreeRTOS_Publisher_Certificate.dat"
|
|
#define pkcs11FILE_NAME_PUBLISHER_KEY "FreeRTOS_Publisher_Key.dat"
|
|
|
|
|
|
// flash section where the certificates are stored
|
|
// reserve the last flash page in the upper boot alias
|
|
// keep it page aligned and size of the page size(16 KB)!
|
|
// use k1 pointers to avoid issues with reading from cache
|
|
#define PKCS11_CERTIFICATE_SECTION_START_ADDRESS (__UPPERBOOTALIASLASTPAGE_BASE)
|
|
#define PKCS11_CERTIFICATE_SECTION_SIZE (__UPPERBOOTALIASLASTPAGE_LENGTH)
|
|
|
|
// the number of the supported certificates:
|
|
// - client certificate + key
|
|
// - signing certificate + key
|
|
#define PKCS11_CERTIFICATES_NO 4
|
|
|
|
/**
|
|
* @brief Cryptoki module attribute definitions.
|
|
*/
|
|
#define pkcs11SLOT_ID 1
|
|
#define pkcs11OBJECT_HANDLE_PUBLIC_KEY 1
|
|
#define pkcs11OBJECT_HANDLE_PRIVATE_KEY 2
|
|
#define pkcs11OBJECT_HANDLE_CERTIFICATE 3
|
|
|
|
#define pkcs11SUPPORTED_KEY_BITS 2048
|
|
|
|
#define pkcs11OBJECT_CERTIFICATE_MAX_SIZE (PKCS11_CERTIFICATE_SECTION_SIZE / PKCS11_CERTIFICATES_NO - sizeof(CK_ULONG) * 2)
|
|
|
|
#define pkcs11OBJECT_FLASH_CERT_PRESENT ( 0xABCDEFuL )
|
|
|
|
typedef int( *pfnMbedTlsSign )(
|
|
void *ctx,
|
|
mbedtls_md_type_t md_alg,
|
|
const unsigned char *hash,
|
|
size_t hash_len,
|
|
unsigned char *sig,
|
|
size_t *sig_len,
|
|
int( *f_rng )( void *, unsigned char *, size_t ),
|
|
void *p_rng );
|
|
|
|
/**
|
|
* @brief Key structure.
|
|
*/
|
|
typedef struct P11Key
|
|
{
|
|
mbedtls_pk_context xMbedPkCtx;
|
|
mbedtls_x509_crt xMbedX509Cli;
|
|
mbedtls_pk_info_t xMbedPkInfo;
|
|
pfnMbedTlsSign pfnSavedMbedSign;
|
|
void *pvSavedMbedPkCtx;
|
|
} P11Key_t, * P11KeyPtr_t;
|
|
|
|
/**
|
|
* @brief Session structure.
|
|
*/
|
|
typedef struct P11Session
|
|
{
|
|
P11KeyPtr_t pxCurrentKey;
|
|
CK_ULONG ulState;
|
|
CK_BBOOL xOpened;
|
|
CK_BBOOL xFindObjectInit;
|
|
CK_BBOOL xFindObjectComplete;
|
|
CK_OBJECT_CLASS xFindObjectClass;
|
|
mbedtls_ctr_drbg_context xMbedDrbgCtx;
|
|
mbedtls_entropy_context xMbedEntropyContext;
|
|
} P11Session_t, * P11SessionPtr_t;
|
|
|
|
/**
|
|
* @brief Structure for certificates/key storage.
|
|
*/
|
|
typedef struct
|
|
{
|
|
|
|
CK_ULONG ulCertificatePresent;
|
|
CK_ULONG ulCertificateSize;
|
|
CK_CHAR cCertificateData[pkcs11OBJECT_CERTIFICATE_MAX_SIZE];
|
|
}P11CertData_t;
|
|
|
|
typedef struct
|
|
{
|
|
P11CertData_t xDeviceCertificate;
|
|
P11CertData_t xDeviceKey;
|
|
P11CertData_t xPublisherCertificate;
|
|
P11CertData_t xPublisherKey;
|
|
}P11KeyConfig_t;
|
|
|
|
int mbedtls_hardware_poll( void *data, unsigned char *output, size_t len, size_t *olen );
|
|
|
|
static void PIC32MZ_HW_TRNG_Initialize(void);
|
|
static uint64_t PIC32MZ_HW_TRNG_Get(void);
|
|
|
|
|
|
|
|
/**
|
|
* @brief Certificates/key storage in flash.
|
|
The last flash page in the upper boot alias!
|
|
*/
|
|
// const P11KeyConfig_t __attribute__((space(prog), section("PKCS11_CERTIFICATE_SECTION"), address(PKCS11_CERTIFICATE_SECTION_START_ADDRESS))) __attribute__((keep)) P11ConfigFlash;
|
|
|
|
|
|
/**
|
|
* Certificates/key save area for flash operations
|
|
*/
|
|
static P11KeyConfig_t P11ConfigSave;
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Maps an opaque caller session handle into its internal state structure.
|
|
*/
|
|
static P11SessionPtr_t prvSessionPointerFromHandle( CK_SESSION_HANDLE xSession )
|
|
{
|
|
return ( P11SessionPtr_t ) xSession; /*lint !e923 Allow casting integer type to pointer for handle. */
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Writes a file to local storage.
|
|
*/
|
|
static BaseType_t prvSaveFile( char * pcFileName,
|
|
uint8_t * pucData,
|
|
uint32_t ulDataSize )
|
|
{
|
|
uint32_t *pFlashDest, *pDataSrc;
|
|
int rowIx, nRows;
|
|
const P11CertData_t* pCertFlash;
|
|
P11CertData_t* pCertSave = 0;
|
|
CK_RV xResult = pdFALSE;
|
|
|
|
const P11KeyConfig_t* P11ConfigFlashPtr = (const P11KeyConfig_t*)KVA0_TO_KVA1(PKCS11_CERTIFICATE_SECTION_START_ADDRESS);
|
|
P11KeyConfig_t* P11ConfigSavePtr = (P11KeyConfig_t*)KVA0_TO_KVA1((uint32_t)&P11ConfigSave);
|
|
|
|
|
|
if(ulDataSize <= sizeof(pCertSave->cCertificateData))
|
|
{ // enough room to store the certificate
|
|
if(strcmp(pcFileName, pkcs11FILE_NAME_CLIENT_CERTIFICATE) == 0)
|
|
{
|
|
pCertSave = &P11ConfigSavePtr->xDeviceCertificate;
|
|
pCertFlash = &P11ConfigFlashPtr->xDeviceCertificate;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_KEY) == 0)
|
|
{
|
|
pCertSave = &P11ConfigSavePtr->xDeviceKey;
|
|
pCertFlash = &P11ConfigFlashPtr->xDeviceKey;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_PUBLISHER_CERTIFICATE) == 0)
|
|
{
|
|
pCertSave = &P11ConfigSavePtr->xPublisherCertificate;
|
|
pCertFlash = &P11ConfigFlashPtr->xPublisherCertificate;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_PUBLISHER_KEY) == 0)
|
|
{
|
|
pCertSave = &P11ConfigSavePtr->xPublisherKey;
|
|
pCertFlash = &P11ConfigFlashPtr->xPublisherKey;
|
|
}
|
|
|
|
if(pCertSave != 0)
|
|
{ // can proceed with the write
|
|
*P11ConfigSavePtr = *P11ConfigFlashPtr; // copy the (whole) existent data before erasing flash
|
|
memcpy(pCertSave->cCertificateData, pucData, ulDataSize);
|
|
pCertSave->ulCertificatePresent = pkcs11OBJECT_FLASH_CERT_PRESENT;
|
|
pCertSave->ulCertificateSize = ulDataSize;
|
|
// now update the flash
|
|
nRows = PKCS11_CERTIFICATE_SECTION_SIZE / AWS_NVM_ROW_SIZE;
|
|
pFlashDest = (uint32_t*)P11ConfigFlashPtr;
|
|
pDataSrc = (uint32_t*)P11ConfigSavePtr;
|
|
|
|
// start critical
|
|
taskENTER_CRITICAL();
|
|
AWS_UpperBootPage4ProtectionDisable();
|
|
AWS_UpperBootPage4Erase();
|
|
|
|
// start writing
|
|
for(rowIx = 0; rowIx < nRows; rowIx++)
|
|
{
|
|
AWS_UpperBootWriteRow(pFlashDest, pDataSrc);
|
|
pFlashDest += AWS_NVM_ROW_SIZE / sizeof(uint32_t);
|
|
pDataSrc += AWS_NVM_ROW_SIZE / sizeof(uint32_t);
|
|
}
|
|
|
|
AWS_UpperBootPage4ProtectionEnable();
|
|
taskEXIT_CRITICAL();
|
|
|
|
// done; verify
|
|
if(memcmp(pCertFlash, pCertSave, ulDataSize) == 0)
|
|
{
|
|
xResult = pdTRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
|
|
/**
|
|
* @brief Reads a file from local storage.
|
|
*/
|
|
|
|
|
|
// TODO: check if making this function public
|
|
// is the correct way to access the signer certificate
|
|
/*static*/ BaseType_t prvReadFile( char * pcFileName,
|
|
uint8_t ** ppucData,
|
|
uint32_t * pulDataSize )
|
|
{
|
|
CK_RV xResult = pdFALSE;
|
|
uint32_t certSize = 0;
|
|
uint8_t* pCertData = 0;
|
|
const P11CertData_t* pCertFlash = 0;
|
|
|
|
const P11KeyConfig_t* P11ConfigFlashPtr = (const P11KeyConfig_t*)KVA0_TO_KVA1(PKCS11_CERTIFICATE_SECTION_START_ADDRESS);
|
|
|
|
if(strcmp(pcFileName, pkcs11FILE_NAME_CLIENT_CERTIFICATE) == 0)
|
|
{
|
|
pCertFlash = &P11ConfigFlashPtr->xDeviceCertificate;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_KEY) == 0)
|
|
{
|
|
pCertFlash = &P11ConfigFlashPtr->xDeviceKey;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_PUBLISHER_CERTIFICATE) == 0)
|
|
{
|
|
pCertFlash = &P11ConfigFlashPtr->xPublisherCertificate;
|
|
}
|
|
else if(strcmp(pcFileName, pkcs11FILE_NAME_PUBLISHER_KEY) == 0)
|
|
{
|
|
pCertFlash = &P11ConfigFlashPtr->xPublisherKey;
|
|
}
|
|
|
|
if(pCertFlash != 0 && pCertFlash->ulCertificatePresent == pkcs11OBJECT_FLASH_CERT_PRESENT)
|
|
{
|
|
pCertData = (uint8_t*)pCertFlash->cCertificateData;
|
|
certSize = pCertFlash->ulCertificateSize;
|
|
xResult = pdTRUE;
|
|
}
|
|
|
|
*pulDataSize = certSize;
|
|
*ppucData = pCertData;
|
|
return xResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Sign a cryptographic hash with the private key.
|
|
*
|
|
* @param[in] pvContext Crypto context.
|
|
* @param[in] xMdAlg Unused.
|
|
* @param[in] pucHash Length in bytes of hash to be signed.
|
|
* @param[in] uiHashLen Byte array of hash to be signed.
|
|
* @param[out] pucSig RSA signature bytes.
|
|
* @param[in] pxSigLen Length in bytes of signature buffer.
|
|
* @param[in] piRng Unused.
|
|
* @param[in] pvRng Unused.
|
|
*
|
|
* @return Zero on success.
|
|
*/
|
|
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 ), /*lint !e955 This parameter is unused. */
|
|
void * pvRng )
|
|
{
|
|
BaseType_t xResult = 0;
|
|
P11SessionPtr_t pxSession = ( P11SessionPtr_t )pvContext;
|
|
CK_MECHANISM xMech = { 0 };
|
|
|
|
/* Unreferenced parameters. */
|
|
( void )( piRng );
|
|
( void )( pvRng );
|
|
( void )( xMdAlg );
|
|
|
|
/* Use the PKCS#11 module to sign. */
|
|
xMech.mechanism = CKM_SHA256;
|
|
|
|
xResult = ( BaseType_t )C_SignInit(
|
|
( CK_SESSION_HANDLE )pxSession,
|
|
&xMech,
|
|
( CK_OBJECT_HANDLE )pxSession->pxCurrentKey );
|
|
|
|
if( 0 == xResult )
|
|
{
|
|
xResult = ( BaseType_t )C_Sign(
|
|
( CK_SESSION_HANDLE )pxSession,
|
|
( CK_BYTE_PTR )pucHash, /*lint !e9005 The interfaces are from 3rdparty libraries, we are not suppose to change them. */
|
|
( CK_ULONG )xHashLen,
|
|
pucSig,
|
|
( CK_ULONG_PTR )pxSigLen );
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Initializes a key structure.
|
|
*/
|
|
static CK_RV prvInitializeKey( P11SessionPtr_t pxSessionObj,
|
|
const char * pcEncodedKey,
|
|
const uint32_t ulEncodedKeyLength,
|
|
const char * pcEncodedCertificate,
|
|
const uint32_t ulEncodedCertificateLength )
|
|
{
|
|
CK_RV xResult = 0;
|
|
|
|
/*
|
|
* Create the key structure, but allow an existing one to be used.
|
|
*/
|
|
|
|
if( NULL == pxSessionObj->pxCurrentKey )
|
|
{
|
|
if( NULL == ( pxSessionObj->pxCurrentKey = ( P11KeyPtr_t ) pvPortMalloc(
|
|
sizeof( P11Key_t ) ) ) ) /*lint !e9087 Allow casting void* to other types. */
|
|
{
|
|
xResult = CKR_HOST_MEMORY;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize the key field, if requested.
|
|
*/
|
|
|
|
if( ( CKR_OK == xResult ) && ( NULL != pcEncodedKey ) )
|
|
{
|
|
memset( pxSessionObj->pxCurrentKey, 0, sizeof( P11Key_t ) );
|
|
mbedtls_pk_init( &pxSessionObj->pxCurrentKey->xMbedPkCtx );
|
|
|
|
if( 0 != mbedtls_pk_parse_key(
|
|
&pxSessionObj->pxCurrentKey->xMbedPkCtx,
|
|
( const unsigned char * ) pcEncodedKey,
|
|
ulEncodedKeyLength,
|
|
NULL,
|
|
0 ) )
|
|
{
|
|
xResult = CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
/* Swap out the signing function pointer. */
|
|
memcpy(
|
|
&pxSessionObj->pxCurrentKey->xMbedPkInfo,
|
|
pxSessionObj->pxCurrentKey->xMbedPkCtx.pk_info,
|
|
sizeof( pxSessionObj->pxCurrentKey->xMbedPkInfo ) );
|
|
pxSessionObj->pxCurrentKey->pfnSavedMbedSign = pxSessionObj->pxCurrentKey->xMbedPkInfo.sign_func;
|
|
pxSessionObj->pxCurrentKey->xMbedPkInfo.sign_func = prvPrivateKeySigningCallback;
|
|
pxSessionObj->pxCurrentKey->xMbedPkCtx.pk_info = &pxSessionObj->pxCurrentKey->xMbedPkInfo;
|
|
|
|
/* Swap out the underlying internal key context. */
|
|
pxSessionObj->pxCurrentKey->pvSavedMbedPkCtx = pxSessionObj->pxCurrentKey->xMbedPkCtx.pk_ctx;
|
|
pxSessionObj->pxCurrentKey->xMbedPkCtx.pk_ctx = pxSessionObj;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Initialize the certificate field, if requested.
|
|
*/
|
|
|
|
if( ( CKR_OK == xResult ) && ( NULL != pcEncodedCertificate ) )
|
|
{
|
|
mbedtls_x509_crt_init( &pxSessionObj->pxCurrentKey->xMbedX509Cli );
|
|
|
|
if( 0 != mbedtls_x509_crt_parse(
|
|
&pxSessionObj->pxCurrentKey->xMbedX509Cli,
|
|
( const unsigned char * ) pcEncodedCertificate,
|
|
ulEncodedCertificateLength ) )
|
|
{
|
|
xResult = CKR_FUNCTION_FAILED;
|
|
}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Initializes a key structure.
|
|
*/
|
|
static CK_RV prvLoadAndInitializeDefaultCertificateAndKey( P11SessionPtr_t pxSession )
|
|
{
|
|
CK_RV xResult = 0;
|
|
uint8_t * pucCertificateData = NULL;
|
|
uint32_t ulCertificateDataLength = 0;
|
|
uint8_t * pucKeyData = NULL;
|
|
uint32_t ulKeyDataLength = 0;
|
|
|
|
/* Read the certificate from storage. */
|
|
if( pdFALSE == prvReadFile( pkcs11FILE_NAME_CLIENT_CERTIFICATE,
|
|
&pucCertificateData,
|
|
&ulCertificateDataLength ) )
|
|
{
|
|
pucCertificateData = ( uint8_t * ) clientcredentialCLIENT_CERTIFICATE_PEM;
|
|
ulCertificateDataLength = clientcredentialCLIENT_CERTIFICATE_LENGTH;
|
|
}
|
|
|
|
/* Read the private key from storage. */
|
|
if( pdFALSE == prvReadFile( pkcs11FILE_NAME_KEY,
|
|
&pucKeyData,
|
|
&ulKeyDataLength ) )
|
|
{
|
|
pucKeyData = ( uint8_t * ) clientcredentialCLIENT_PRIVATE_KEY_PEM;
|
|
ulKeyDataLength = clientcredentialCLIENT_PRIVATE_KEY_LENGTH;
|
|
}
|
|
|
|
/* Attach the certificate and key to the session. */
|
|
xResult = prvInitializeKey( pxSession,
|
|
( const char * ) pucKeyData,
|
|
ulKeyDataLength,
|
|
( const char * ) pucCertificateData,
|
|
ulCertificateDataLength );
|
|
|
|
/* Stir the random pot. */
|
|
mbedtls_entropy_update_manual( &pxSession->xMbedEntropyContext,
|
|
pucKeyData,
|
|
ulKeyDataLength );
|
|
mbedtls_entropy_update_manual( &pxSession->xMbedEntropyContext,
|
|
pucCertificateData,
|
|
ulCertificateDataLength );
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief Cleans up a key structure.
|
|
*/
|
|
static void prvFreeKey( P11KeyPtr_t pxKey )
|
|
{
|
|
if( NULL != pxKey )
|
|
{
|
|
/* Restore the internal key context. */
|
|
pxKey->xMbedPkCtx.pk_ctx = pxKey->pvSavedMbedPkCtx;
|
|
|
|
/* Clean-up. */
|
|
mbedtls_pk_free( &pxKey->xMbedPkCtx );
|
|
mbedtls_x509_crt_free( &pxKey->xMbedX509Cli );
|
|
vPortFree( pxKey );
|
|
}
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* PKCS#11 module implementation.
|
|
*/
|
|
|
|
/**
|
|
* @brief PKCS#11 interface functions implemented by this Cryptoki module.
|
|
*/
|
|
static CK_FUNCTION_LIST prvP11FunctionList =
|
|
{
|
|
{ CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR },
|
|
C_Initialize,
|
|
C_Finalize,
|
|
NULL,
|
|
C_GetFunctionList,
|
|
C_GetSlotList,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
C_OpenSession,
|
|
C_CloseSession,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
C_CreateObject,
|
|
NULL,
|
|
C_DestroyObject,
|
|
NULL,
|
|
C_GetAttributeValue,
|
|
NULL,
|
|
C_FindObjectsInit,
|
|
C_FindObjects,
|
|
C_FindObjectsFinal,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
C_SignInit,
|
|
C_Sign,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
C_VerifyInit,
|
|
C_Verify,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
C_GenerateRandom,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
* @brief Initialize the Cryptoki module for use.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pvInitArgs )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( pvInitArgs );
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Un-initialize the Cryptoki module.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_Finalize )( CK_VOID_PTR pvReserved )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( pvReserved );
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Query the list of interface function pointers.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_GetFunctionList )( CK_FUNCTION_LIST_PTR_PTR ppxFunctionList )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
*ppxFunctionList = &prvP11FunctionList;
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Query the list of slots. A single default slot is implemented.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_GetSlotList )( CK_BBOOL xTokenPresent,
|
|
CK_SLOT_ID_PTR pxSlotList,
|
|
CK_ULONG_PTR pulCount )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( xTokenPresent );
|
|
|
|
if( NULL == pxSlotList )
|
|
{
|
|
*pulCount = 1;
|
|
}
|
|
else
|
|
{
|
|
if( 0u == *pulCount )
|
|
{
|
|
return CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
|
|
pxSlotList[ 0 ] = pkcs11SLOT_ID;
|
|
*pulCount = 1;
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Start a session for a cryptographic command sequence.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_OpenSession )( CK_SLOT_ID xSlotID,
|
|
CK_FLAGS xFlags,
|
|
CK_VOID_PTR pvApplication,
|
|
CK_NOTIFY xNotify,
|
|
CK_SESSION_HANDLE_PTR pxSession )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSessionObj = NULL;
|
|
|
|
( void ) ( xSlotID );
|
|
( void ) ( pvApplication );
|
|
( void ) ( xNotify );
|
|
|
|
/*
|
|
* Make space for the context.
|
|
*/
|
|
if( NULL == ( pxSessionObj = ( P11SessionPtr_t ) pvPortMalloc( sizeof( P11Session_t ) ) ) ) /*lint !e9087 Allow casting void* to other types. */
|
|
{
|
|
xResult = CKR_HOST_MEMORY;
|
|
}
|
|
|
|
/*
|
|
* Assume that there's no performance tradeoff in loading the default key
|
|
* now, since that's the principal use case for opening a session in this
|
|
* provider anyway. This way, the private key can be used for seeding the RNG,
|
|
* especially if there's no hardware-based alternative.
|
|
*/
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
memset( pxSessionObj, 0, sizeof( P11Session_t ) );
|
|
xResult = prvLoadAndInitializeDefaultCertificateAndKey( pxSessionObj );
|
|
}
|
|
|
|
/*
|
|
* Initialize RNG.
|
|
*/
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
memset( &pxSessionObj->xMbedEntropyContext,
|
|
0,
|
|
sizeof( pxSessionObj->xMbedEntropyContext ) );
|
|
|
|
mbedtls_entropy_init( &pxSessionObj->xMbedEntropyContext );
|
|
}
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
mbedtls_ctr_drbg_init( &pxSessionObj->xMbedDrbgCtx );
|
|
|
|
if( 0 != mbedtls_ctr_drbg_seed( &pxSessionObj->xMbedDrbgCtx,
|
|
mbedtls_entropy_func,
|
|
&pxSessionObj->xMbedEntropyContext,
|
|
NULL,
|
|
0 ) )
|
|
{
|
|
xResult = CKR_FUNCTION_FAILED;
|
|
}
|
|
}
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
/*
|
|
* Assign the session.
|
|
*/
|
|
|
|
pxSessionObj->ulState =
|
|
0u != ( xFlags & CKF_RW_SESSION ) ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
|
|
pxSessionObj->xOpened = CK_TRUE;
|
|
|
|
/*
|
|
* Return the session.
|
|
*/
|
|
|
|
*pxSession = ( CK_SESSION_HANDLE ) pxSessionObj; /*lint !e923 Allow casting pointer to integer type for handle. */
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Terminate a session and release resources.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_CloseSession )( CK_SESSION_HANDLE xSession )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession );
|
|
|
|
if( NULL != pxSession )
|
|
{
|
|
/*
|
|
* Tear down the session.
|
|
*/
|
|
|
|
if( NULL != pxSession->pxCurrentKey )
|
|
{
|
|
prvFreeKey( pxSession->pxCurrentKey );
|
|
}
|
|
|
|
mbedtls_ctr_drbg_free( &pxSession->xMbedDrbgCtx );
|
|
vPortFree( pxSession );
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Provides import and storage of a single client certificate and
|
|
* associated private key.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_CreateObject )( CK_SESSION_HANDLE xSession,
|
|
CK_ATTRIBUTE_PTR pxTemplate,
|
|
CK_ULONG ulCount,
|
|
CK_OBJECT_HANDLE_PTR pxObject )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
|
|
/*
|
|
* Check parameters.
|
|
*/
|
|
|
|
if( ( 3 > ulCount ) ||
|
|
( NULL == pxTemplate ) ||
|
|
( NULL == pxObject ) )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
}
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
if( ( CKA_CLASS != pxTemplate[ 0 ].type ) ||
|
|
( sizeof( CK_OBJECT_CLASS ) != pxTemplate[ 0 ].ulValueLen ) )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Handle the object by class.
|
|
*/
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
switch( *( ( uint32_t * ) pxTemplate[ 0 ].pValue ) )
|
|
{
|
|
case CKO_CERTIFICATE:
|
|
|
|
/* Validate the attribute count for this object class. */
|
|
if( 3 != ulCount )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
break;
|
|
}
|
|
|
|
/* Validate the next attribute type. */
|
|
if( CKA_VALUE )
|
|
{
|
|
if( CKA_VALUE != pxTemplate[ 1 ].type )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if( *( ( uint32_t * ) pxTemplate[ 2 ].pValue ) == pkcs11CERTIFICATE_TYPE_USER )
|
|
{
|
|
/* Write out the client certificate. */
|
|
if( pdFALSE == prvSaveFile( pkcs11FILE_NAME_CLIENT_CERTIFICATE,
|
|
pxTemplate[ 1 ].pValue,
|
|
pxTemplate[ 1 ].ulValueLen ) )
|
|
{
|
|
xResult = CKR_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
else if( *( ( uint32_t * ) pxTemplate[ 2 ].pValue ) == pkcs11CERTIFICATE_TYPE_ROOT )
|
|
{
|
|
/* write root certificate . */
|
|
}
|
|
|
|
/* Create a certificate handle to return. */
|
|
if( CKR_OK == xResult )
|
|
{
|
|
pxObject = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
case CKO_PRIVATE_KEY:
|
|
|
|
/* Validate the attribute count for this object class. */
|
|
if( 4 != ulCount )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
break;
|
|
}
|
|
|
|
/* Find the key bytes. */
|
|
if( CKA_VALUE )
|
|
{
|
|
if( CKA_VALUE != pxTemplate[ 3 ].type )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Write out the key. */
|
|
if( pdFALSE == prvSaveFile( pkcs11FILE_NAME_KEY,
|
|
pxTemplate[ 3 ].pValue,
|
|
pxTemplate[ 3 ].ulValueLen ) )
|
|
{
|
|
xResult = CKR_DEVICE_ERROR;
|
|
break;
|
|
}
|
|
|
|
/* Create a key handle to return. */
|
|
if( CKR_OK == xResult )
|
|
{
|
|
pxObject = NULL;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Free resources attached to an object handle.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_DestroyObject )( CK_SESSION_HANDLE xSession,
|
|
CK_OBJECT_HANDLE xObject )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( xSession );
|
|
( void ) ( xObject );
|
|
|
|
/*
|
|
* This implementation uses virtual handles, and the certificate and
|
|
* private key data are attached to the session, so nothing to do here.
|
|
*/
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Query the value of the specified cryptographic object attribute.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_GetAttributeValue )( CK_SESSION_HANDLE xSession,
|
|
CK_OBJECT_HANDLE xObject,
|
|
CK_ATTRIBUTE_PTR pxTemplate,
|
|
CK_ULONG ulCount )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession );
|
|
CK_VOID_PTR pvAttr = NULL;
|
|
CK_ULONG ulAttrLength = 0;
|
|
mbedtls_pk_type_t xMbedPkType;
|
|
CK_ULONG xP11KeyType, iAttrib, xKeyBitLen;
|
|
|
|
( void ) ( xObject );
|
|
|
|
/*
|
|
* Enumerate the requested attributes.
|
|
*/
|
|
|
|
for( iAttrib = 0; iAttrib < ulCount && CKR_OK == xResult; iAttrib++ )
|
|
{
|
|
/*
|
|
* Get the attribute data and size.
|
|
*/
|
|
|
|
switch( pxTemplate[ iAttrib ].type )
|
|
{
|
|
case CKA_KEY_TYPE:
|
|
|
|
/*
|
|
* Map the private key type between APIs.
|
|
*/
|
|
xMbedPkType = mbedtls_pk_get_type( &pxSession->pxCurrentKey->xMbedPkCtx );
|
|
|
|
switch( xMbedPkType )
|
|
{
|
|
case MBEDTLS_PK_RSA:
|
|
case MBEDTLS_PK_RSA_ALT:
|
|
case MBEDTLS_PK_RSASSA_PSS:
|
|
xP11KeyType = CKK_RSA;
|
|
break;
|
|
|
|
case MBEDTLS_PK_ECKEY:
|
|
case MBEDTLS_PK_ECKEY_DH:
|
|
xP11KeyType = CKK_EC;
|
|
break;
|
|
|
|
case MBEDTLS_PK_ECDSA:
|
|
xP11KeyType = CKK_ECDSA;
|
|
break;
|
|
|
|
default:
|
|
xResult = CKR_ATTRIBUTE_VALUE_INVALID;
|
|
break;
|
|
}
|
|
|
|
ulAttrLength = sizeof( xP11KeyType );
|
|
pvAttr = &xP11KeyType;
|
|
break;
|
|
|
|
case CKA_VALUE:
|
|
|
|
/*
|
|
* Assume that the query is for the encoded client certificate.
|
|
*/
|
|
pvAttr = ( CK_VOID_PTR )pxSession->pxCurrentKey->xMbedX509Cli.raw.p; /*lint !e9005 !e9087 Allow casting other types to void*. */
|
|
ulAttrLength = pxSession->pxCurrentKey->xMbedX509Cli.raw.len;
|
|
break;
|
|
|
|
case CKA_MODULUS_BITS:
|
|
case CKA_PRIME_BITS:
|
|
|
|
/*
|
|
* Key strength size query, handled the same for RSA or ECDSA
|
|
* in this port.
|
|
*/
|
|
xKeyBitLen = mbedtls_pk_get_bitlen(
|
|
&pxSession->pxCurrentKey->xMbedPkCtx );
|
|
ulAttrLength = sizeof( xKeyBitLen );
|
|
pvAttr = &xKeyBitLen;
|
|
break;
|
|
|
|
case CKA_VENDOR_DEFINED:
|
|
|
|
/*
|
|
* Return the key context for application-layer use.
|
|
*/
|
|
ulAttrLength = sizeof( pxSession->pxCurrentKey->xMbedPkCtx );
|
|
pvAttr = &pxSession->pxCurrentKey->xMbedPkCtx;
|
|
break;
|
|
|
|
default:
|
|
xResult = CKR_ATTRIBUTE_TYPE_INVALID;
|
|
break;
|
|
}
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
/*
|
|
* Copy out the data and size.
|
|
*/
|
|
|
|
if( NULL != pxTemplate[ iAttrib ].pValue )
|
|
{
|
|
if( pxTemplate[ iAttrib ].ulValueLen < ulAttrLength )
|
|
{
|
|
xResult = CKR_BUFFER_TOO_SMALL;
|
|
}
|
|
else
|
|
{
|
|
memcpy( pxTemplate[ iAttrib ].pValue, pvAttr, ulAttrLength );
|
|
}
|
|
}
|
|
|
|
pxTemplate[ iAttrib ].ulValueLen = ulAttrLength;
|
|
}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Begin an enumeration sequence for the objects of the specified type.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsInit )( CK_SESSION_HANDLE xSession,
|
|
CK_ATTRIBUTE_PTR pxTemplate,
|
|
CK_ULONG ulCount )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession );
|
|
|
|
( void ) ( ulCount );
|
|
|
|
/*
|
|
* Allow filtering on a single object class attribute.
|
|
*/
|
|
|
|
pxSession->xFindObjectInit = CK_TRUE;
|
|
pxSession->xFindObjectComplete = CK_FALSE;
|
|
memcpy( &pxSession->xFindObjectClass,
|
|
pxTemplate[ 0 ].pValue,
|
|
sizeof( CK_OBJECT_CLASS ) );
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Query the objects of the requested type.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_FindObjects )( CK_SESSION_HANDLE xSession,
|
|
CK_OBJECT_HANDLE_PTR pxObject,
|
|
CK_ULONG ulMaxObjectCount,
|
|
CK_ULONG_PTR pulObjectCount )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
BaseType_t xDone = pdFALSE;
|
|
P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession );
|
|
|
|
/*
|
|
* Check parameters.
|
|
*/
|
|
|
|
if( ( CK_BBOOL ) CK_FALSE == pxSession->xFindObjectInit )
|
|
{
|
|
xResult = CKR_OPERATION_NOT_INITIALIZED;
|
|
xDone = pdTRUE;
|
|
}
|
|
|
|
if( ( pdFALSE == xDone ) && ( 0u == ulMaxObjectCount ) )
|
|
{
|
|
xResult = CKR_ARGUMENTS_BAD;
|
|
xDone = pdTRUE;
|
|
}
|
|
|
|
if( ( pdFALSE == xDone ) && ( ( CK_BBOOL ) CK_TRUE == pxSession->xFindObjectComplete ) )
|
|
{
|
|
*pulObjectCount = 0;
|
|
xResult = CKR_OK;
|
|
xDone = pdTRUE;
|
|
}
|
|
|
|
/*
|
|
* Load the default private key and certificate.
|
|
*/
|
|
|
|
if( ( pdFALSE == xDone ) && ( NULL == pxSession->pxCurrentKey ) )
|
|
{
|
|
if( CKR_OK != ( xResult = prvLoadAndInitializeDefaultCertificateAndKey( pxSession ) ) )
|
|
{
|
|
xDone = pdTRUE;
|
|
}
|
|
}
|
|
|
|
if( pdFALSE == xDone )
|
|
{
|
|
/*
|
|
* Return object handles based on find type.
|
|
*/
|
|
|
|
switch( pxSession->xFindObjectClass )
|
|
{
|
|
case CKO_PRIVATE_KEY:
|
|
*pxObject = pkcs11OBJECT_HANDLE_PRIVATE_KEY;
|
|
*pulObjectCount = 1;
|
|
break;
|
|
|
|
case CKO_PUBLIC_KEY:
|
|
*pxObject = pkcs11OBJECT_HANDLE_PUBLIC_KEY;
|
|
*pulObjectCount = 1;
|
|
break;
|
|
|
|
case CKO_CERTIFICATE:
|
|
*pxObject = pkcs11OBJECT_HANDLE_CERTIFICATE;
|
|
*pulObjectCount = 1;
|
|
break;
|
|
|
|
default:
|
|
*pxObject = 0;
|
|
*pulObjectCount = 0;
|
|
break;
|
|
}
|
|
|
|
pxSession->xFindObjectComplete = CK_TRUE;
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Terminate object enumeration.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_FindObjectsFinal )( CK_SESSION_HANDLE xSession )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSession = prvSessionPointerFromHandle( xSession );
|
|
|
|
/*
|
|
* Check parameters.
|
|
*/
|
|
|
|
if( ( CK_BBOOL ) CK_FALSE == pxSession->xFindObjectInit )
|
|
{
|
|
xResult = CKR_OPERATION_NOT_INITIALIZED;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Clean-up find objects state.
|
|
*/
|
|
|
|
pxSession->xFindObjectInit = CK_FALSE;
|
|
pxSession->xFindObjectComplete = CK_FALSE;
|
|
pxSession->xFindObjectClass = 0;
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Begin a digital signature generation session.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_SignInit )( CK_SESSION_HANDLE xSession,
|
|
CK_MECHANISM_PTR pxMechanism,
|
|
CK_OBJECT_HANDLE xKey )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( xSession );
|
|
( void ) ( pxMechanism );
|
|
( void ) ( xKey );
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Digitally sign the indicated cryptographic hash bytes.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_Sign )( CK_SESSION_HANDLE xSession,
|
|
CK_BYTE_PTR pucData,
|
|
CK_ULONG ulDataLen,
|
|
CK_BYTE_PTR pucSignature,
|
|
CK_ULONG_PTR pulSignatureLen )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSessionObj = prvSessionPointerFromHandle( xSession );
|
|
|
|
/*
|
|
* Support length check.
|
|
*/
|
|
|
|
if( NULL == pucSignature )
|
|
{
|
|
*pulSignatureLen = pkcs11SUPPORTED_KEY_BITS / 8;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Check algorithm support.
|
|
*/
|
|
|
|
if( ( CK_ULONG ) cryptoSHA256_DIGEST_BYTES != ulDataLen )
|
|
{
|
|
xResult = CKR_DATA_LEN_RANGE;
|
|
}
|
|
|
|
/*
|
|
* Sign the data.
|
|
*/
|
|
|
|
if( CKR_OK == xResult )
|
|
{
|
|
if( 0 != pxSessionObj->pxCurrentKey->pfnSavedMbedSign(
|
|
pxSessionObj->pxCurrentKey->pvSavedMbedPkCtx,
|
|
MBEDTLS_MD_SHA256,
|
|
pucData,
|
|
ulDataLen,
|
|
pucSignature,
|
|
( size_t * ) pulSignatureLen,
|
|
mbedtls_ctr_drbg_random,
|
|
&pxSessionObj->xMbedDrbgCtx ) )
|
|
{
|
|
xResult = CKR_FUNCTION_FAILED;
|
|
}
|
|
}
|
|
}
|
|
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Begin a digital signature verification session.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_VerifyInit )( CK_SESSION_HANDLE xSession,
|
|
CK_MECHANISM_PTR pxMechanism,
|
|
CK_OBJECT_HANDLE xKey )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
( void ) ( xSession );
|
|
( void ) ( pxMechanism );
|
|
( void ) ( xKey );
|
|
return CKR_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Verify the digital signature of the specified data using the public
|
|
* key attached to this session.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_Verify )( CK_SESSION_HANDLE xSession,
|
|
CK_BYTE_PTR pucData,
|
|
CK_ULONG ulDataLen,
|
|
CK_BYTE_PTR pucSignature,
|
|
CK_ULONG ulSignatureLen )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
CK_RV xResult = CKR_OK;
|
|
P11SessionPtr_t pxSessionObj = prvSessionPointerFromHandle( xSession );
|
|
|
|
/* Verify the signature. */
|
|
if( 0 != pxSessionObj->pxCurrentKey->xMbedPkInfo.verify_func(
|
|
pxSessionObj->pxCurrentKey->pvSavedMbedPkCtx,
|
|
MBEDTLS_MD_SHA256,
|
|
pucData,
|
|
ulDataLen,
|
|
pucSignature,
|
|
ulSignatureLen ) )
|
|
{
|
|
xResult = CKR_SIGNATURE_INVALID;
|
|
}
|
|
|
|
/* Return the signature verification result. */
|
|
return xResult;
|
|
}
|
|
|
|
/**
|
|
* @brief Generate cryptographically random bytes.
|
|
*/
|
|
CK_DEFINE_FUNCTION( CK_RV, C_GenerateRandom )( CK_SESSION_HANDLE xSession,
|
|
CK_BYTE_PTR pucRandomData,
|
|
CK_ULONG ulRandomLen )
|
|
{ /*lint !e9072 It's OK to have different parameter name. */
|
|
P11SessionPtr_t pxSessionObj = prvSessionPointerFromHandle( xSession );
|
|
|
|
if( 0 != mbedtls_ctr_drbg_random( &pxSessionObj->xMbedDrbgCtx, pucRandomData, ulRandomLen ) )
|
|
{
|
|
return CKR_FUNCTION_FAILED;
|
|
}
|
|
|
|
return CKR_OK;
|
|
}
|
|
|
|
int mbedtls_hardware_poll( void *data,
|
|
unsigned char *output, size_t len, size_t *olen )
|
|
{
|
|
static bool pic32mz_hw_init = false;
|
|
|
|
if(!pic32mz_hw_init)
|
|
{
|
|
PIC32MZ_HW_TRNG_Initialize();
|
|
pic32mz_hw_init = true;
|
|
}
|
|
|
|
((void) data);
|
|
|
|
union
|
|
{
|
|
uint64_t v64;
|
|
uint8_t v8[8];
|
|
}suint_64;
|
|
|
|
int n8Chunks = len / 8;
|
|
int nLeft = len - n8Chunks * 8;
|
|
|
|
while(n8Chunks--)
|
|
{
|
|
suint_64.v64 = PIC32MZ_HW_TRNG_Get();
|
|
memcpy(output, suint_64.v8, sizeof(suint_64.v8));
|
|
output += sizeof(suint_64.v8);
|
|
}
|
|
|
|
if(nLeft)
|
|
{
|
|
suint_64.v64 = PIC32MZ_HW_TRNG_Get();
|
|
memcpy(output, suint_64.v8, nLeft);
|
|
}
|
|
|
|
|
|
*olen = len;
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void PIC32MZ_HW_TRNG_Initialize(void)
|
|
{
|
|
RNGCONbits.TRNGMODE = 1;
|
|
RNGCONbits.TRNGEN = 1;
|
|
}
|
|
|
|
|
|
static uint64_t PIC32MZ_HW_TRNG_Get(void)
|
|
{
|
|
/* make sure that the TRNG has finished */
|
|
while (RNGCNT < 64) ;
|
|
|
|
return RNGSEED1 + ((uint64_t)RNGSEED2 << 32);
|
|
}
|