| /* |
| * 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; |
| } |