blob: 3e7508a098efde45c94913e3afe6f4cf867329c1 [file] [log] [blame]
/*
* FreeRTOS PKCS #11 PAL for LPC54018 IoT Module V1.0.3
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright 2018-2019 NXP
*
* 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.
*
* http://aws.amazon.com/freertos
* http://www.FreeRTOS.org
*/
/**
* @file iot_pkcs11_pal.c
* @brief NXP LPC54018 IoT module file save and read implementation
* for PKCS#11 based on mbedTLS with 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 "iot_crypto.h"
#include "task.h"
#include "iot_pkcs11.h"
#include "iot_pkcs11_config.h"
/* Flash write */
#include "mflash_file.h"
/* C runtime includes. */
#include <stdio.h>
#include <string.h>
#define pkcs11palFILE_NAME_CLIENT_CERTIFICATE "FreeRTOS_P11_Certificate.dat"
#define pkcs11palFILE_NAME_KEY "FreeRTOS_P11_Key.dat"
#define pkcs11palFILE_CODE_SIGN_PUBLIC_KEY "FreeRTOS_P11_CodeSignKey.dat"
enum eObjectHandles
{
eInvalidHandle = 0, /* According to PKCS #11 spec, 0 is never a valid object handle. */
eAwsDevicePrivateKey = 1,
eAwsDevicePublicKey,
eAwsDeviceCertificate,
eAwsCodeSigningKey
};
/* Flash structure */
mflash_file_t g_cert_files[] =
{
{ .path = pkcs11palFILE_NAME_CLIENT_CERTIFICATE,
.flash_addr = MFLASH_FILE_BASEADDR,
.max_size = MFLASH_FILE_SIZE },
{ .path = pkcs11palFILE_NAME_KEY,
.flash_addr = MFLASH_FILE_BASEADDR + MFLASH_FILE_SIZE,
.max_size = MFLASH_FILE_SIZE },
{ .path = pkcs11palFILE_CODE_SIGN_PUBLIC_KEY,
.flash_addr = MFLASH_FILE_BASEADDR + ( 2 * MFLASH_FILE_SIZE ),
.max_size = MFLASH_FILE_SIZE },
{ 0 }
};
/*-----------------------------------------------------------*/
/* Converts a label to its respective filename and handle. */
void prvLabelToFilenameHandle( uint8_t * pcLabel,
char ** pcFileName,
CK_OBJECT_HANDLE_PTR pHandle )
{
if( pcLabel != NULL )
{
/* Translate from the PKCS#11 label to local storage file name. */
if( 0 == memcmp( pcLabel,
&pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS,
sizeof( pkcs11configLABEL_DEVICE_CERTIFICATE_FOR_TLS ) ) )
{
*pcFileName = pkcs11palFILE_NAME_CLIENT_CERTIFICATE;
*pHandle = eAwsDeviceCertificate;
}
else if( 0 == memcmp( pcLabel,
&pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS,
sizeof( pkcs11configLABEL_DEVICE_PRIVATE_KEY_FOR_TLS ) ) )
{
*pcFileName = pkcs11palFILE_NAME_KEY;
*pHandle = eAwsDevicePrivateKey;
}
else if( 0 == memcmp( pcLabel,
&pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS,
sizeof( pkcs11configLABEL_DEVICE_PUBLIC_KEY_FOR_TLS ) ) )
{
*pcFileName = pkcs11palFILE_NAME_KEY;
*pHandle = eAwsDevicePublicKey;
}
else if( 0 == memcmp( pcLabel,
&pkcs11configLABEL_CODE_VERIFICATION_KEY,
sizeof( pkcs11configLABEL_CODE_VERIFICATION_KEY ) ) )
{
*pcFileName = pkcs11palFILE_CODE_SIGN_PUBLIC_KEY;
*pHandle = eAwsCodeSigningKey;
}
else
{
*pcFileName = NULL;
*pHandle = eInvalidHandle;
}
}
}
/**
* @brief Writes a file to local storage.
*
* Port-specific file write for crytographic information.
*
* @param[in] pxLabel Label of the object to be saved.
* @param[in] pucData Data buffer to be written to file
* @param[in] ulDataSize Size (in bytes) of data to be saved.
*
* @return The file handle of the object that was stored.
*/
CK_OBJECT_HANDLE PKCS11_PAL_SaveObject( CK_ATTRIBUTE_PTR pxLabel,
uint8_t * pucData,
uint32_t ulDataSize )
{
CK_OBJECT_HANDLE xHandle = eInvalidHandle;
char * pcFileName = NULL;
/* Translate from the PKCS#11 label to local storage file name. */
prvLabelToFilenameHandle( pxLabel->pValue, &pcFileName, &xHandle );
if( xHandle != eInvalidHandle )
{
if( pdFALSE == mflash_save_file( pcFileName, pucData, ulDataSize ) )
{
xHandle = eInvalidHandle;
}
}
return xHandle;
}
/*-----------------------------------------------------------*/
/**
* @brief Translates a PKCS #11 label into an object handle.
*
* Port-specific object handle retrieval.
*
*
* @param[in] pLabel Pointer to the label of the object
* who's handle should be found.
* @param[in] usLength The length of the label, in bytes.
*
* @return The object handle if operation was successful.
* Returns eInvalidHandle if unsuccessful.
*/
CK_OBJECT_HANDLE PKCS11_PAL_FindObject( uint8_t * pLabel,
uint8_t usLength )
{
CK_OBJECT_HANDLE xHandle = eInvalidHandle;
char * pcFileName = NULL;
/* Translate from the PKCS#11 label to local storage file name. */
prvLabelToFilenameHandle( pLabel, &pcFileName, &xHandle );
/*TODO: check if file actually there.
* Note: g_cert_files only seems to check if the entry in the array is present */
return xHandle;
}
/*-----------------------------------------------------------*/
/**
* @brief Gets the value of an object in storage, by handle.
*
* Port-specific file access for cryptographic information.
*
* This call dynamically allocates the buffer which object value
* data is copied into. PKCS11_PAL_GetObjectValueCleanup()
* should be called after each use to free the dynamically allocated
* buffer.
*
* @sa PKCS11_PAL_GetObjectValueCleanup
*
* @param[in] pcFileName The name of the file to be read.
* @param[out] ppucData Pointer to buffer for file data.
* @param[out] pulDataSize Size (in bytes) of data located in file.
* @param[out] pIsPrivate Boolean indicating if value is private (CK_TRUE)
* or exportable (CK_FALSE)
*
* @return CKR_OK if operation was successful. CKR_KEY_HANDLE_INVALID if
* no such object handle was found, CKR_DEVICE_MEMORY if memory for
* buffer could not be allocated, CKR_FUNCTION_FAILED for device driver
* error.
*/
CK_RV PKCS11_PAL_GetObjectValue( CK_OBJECT_HANDLE xHandle,
uint8_t ** ppucData,
uint32_t * pulDataSize,
CK_BBOOL * pIsPrivate )
{
char * pcFileName = NULL;
CK_RV ulReturn = CKR_OK;
if( xHandle == eAwsDeviceCertificate )
{
pcFileName = pkcs11palFILE_NAME_CLIENT_CERTIFICATE;
*pIsPrivate = CK_FALSE;
}
else if( xHandle == eAwsDevicePrivateKey )
{
pcFileName = pkcs11palFILE_NAME_KEY;
*pIsPrivate = CK_TRUE;
}
else if( xHandle == eAwsDevicePublicKey )
{
/* Public and private key are stored together in same file. */
pcFileName = pkcs11palFILE_NAME_KEY;
*pIsPrivate = CK_FALSE;
}
else if( xHandle == eAwsCodeSigningKey )
{
pcFileName = pkcs11palFILE_CODE_SIGN_PUBLIC_KEY;
*pIsPrivate = CK_FALSE;
}
else
{
ulReturn = CKR_KEY_HANDLE_INVALID;
}
if( pdFALSE == mflash_read_file( pcFileName, ppucData, pulDataSize ) )
{
ulReturn = CKR_FUNCTION_FAILED;
}
return ulReturn;
}
/**
* @brief Cleanup after PKCS11_GetObjectValue().
*
* @param[in] pucData The buffer to free.
* (*ppucData from PKCS11_PAL_GetObjectValue())
* @param[in] ulDataSize The length of the buffer to free.
* (*pulDataSize from PKCS11_PAL_GetObjectValue())
*/
void PKCS11_PAL_GetObjectValueCleanup( uint8_t * pucData,
uint32_t ulDataSize )
{
/* Unused parameters. */
( void ) pucData;
( void ) ulDataSize;
/* Since no buffer was allocated on heap, there is no cleanup
* to be done. */
}
/**
* PKCS#11 Override
*
*/
extern CK_RV prvMbedTLS_Initialize( void );
/**
* @brief Initialize the Cryptoki module for use.
*
* Overrides the implementation of C_Initialize in
* iot_pkcs11_mbedtls.c when pkcs11configC_INITIALIZE_ALT
* is defined.
*/
#ifndef pkcs11configC_INITIALIZE_ALT
#error LPC54018 requires alternate C_Initialization
#endif
CK_DEFINE_FUNCTION( CK_RV, C_Initialize )( CK_VOID_PTR pvInitArgs )
{ /*lint !e9072 It's OK to have different parameter name. */
( void ) ( pvInitArgs );
CK_RV xResult = CKR_OK;
if( !mflash_is_initialized() )
{
/* Initialize flash storage. */
if( pdTRUE != mflash_init( g_cert_files, 1 ) )
{
xResult = CKR_GENERAL_ERROR;
}
}
if( xResult == CKR_OK )
{
xResult = prvMbedTLS_Initialize();
}
return xResult;
}