Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PKCS #11 Demo 1 #10

Merged
merged 1 commit into from
Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,185 @@
#include "iot_pkcs11.h"
#include "pkcs11.h"

/**
* This function details how to use the PKCS #11 "Management" functions to
* manage the internal state machine of the PKCS #11 implementation. These
* functions are all defined in
* http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html
* please consult the standard for more information regarding these functions.
*
* The standard has grouped the functions presented in this demo as:
* General Purpose Functions
* Slot and Token Management Functions
* Session Management Functions
* Random Number Generation Functions
*
* For simplicity, this file will refer to these functions as Management Functions.
*
*/
void vPKCS11ManagementDemo( void )
{
configPRINTF( ( "Hello from demo.\r\n" ) );
/* We will use the terminology as defined in the standard, Cryptoki is in
* reference to the Cryptographic Token Interface defined in the PKCS #11
* standard. An implementation of Cryptoki is referred to as a
* "Cryptoki library". */
configPRINTF( ( "Starting PKCS #11 Management Demo.\r\n" ) );

/* CK_RV is the return type for a Cryptoki function. Generally the underlying
* type is a CK_ULONG, it can also be a CKR_VENDOR_DEFINED type. */
CK_RV xResult = CKR_OK;

/* The CK_FUNCTION_LIST is a structure that contains the Cryptoki version
* and a function pointer to each function in the Cryptoki API. If the
* function pointer is NULL it is unimplemented. */
CK_FUNCTION_LIST_PTR pxFunctionList = NULL;

/* This Cryptoki library does not implement any initialization arguments. At the time of
* writing this demo, the purpose of these optional arguments is to provide
* function pointers for mutex operations. */
CK_C_INITIALIZE_ARGS xInitArgs = { 0 };

/* A slot ID is an integer that defines a slot. The Cryptoki definition of
* a slot is "A logical reader that potentially contains a token."
*
* Essentially it is an abstraction for accessing the token. The reason for
* this is Some tokens are a physical "card' that needs to be inserted into
* a slot for the device to read.
*
* A concrete example of a slot could be a USB Hardware Security Module (HSM),
* which generally appears as a singular slot, and abstracts it's internal "token".
*
* Some implementations have multiple slots mapped to a single token, or maps
* a slot per token. */
CK_SLOT_ID * pxSlotId = NULL;

/* A session is defined to be "The logical connection between an application
* and a token."
*
* The session can either be private or public, and differentiates
* your application from the other users of the token. */
CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;

/* Helper variables. */
CK_BYTE xRandomData[ 10 ] = { 0 };
uint32_t ulIndex = 0;
CK_ULONG xSlotCount = 0;

/* We use the function list returned by C_GetFunctionList to see what functions
* the Cryptoki library supports. We use asserts to ensure that all the
* functionality needed in this demo is available. */
xResult = C_GetFunctionList( &pxFunctionList );
configASSERT( xResult == CKR_OK );
configASSERT( pxFunctionList != NULL );
configASSERT( pxFunctionList->C_Initialize != NULL );
configASSERT( pxFunctionList->C_GetSlotList != NULL );
configASSERT( pxFunctionList->C_OpenSession != NULL );
configASSERT( pxFunctionList->C_Login != NULL );
configASSERT( pxFunctionList->C_GenerateRandom != NULL );
configASSERT( pxFunctionList->C_CloseSession != NULL );
configASSERT( pxFunctionList->C_Finalize != NULL );

configPRINTF( ( "Cryptoki Major Version: %lu Minor Version %lu\r\n",
pxFunctionList->version.major,
pxFunctionList->version.minor ) );

/* C_Initialize will initialize the Cryptoki library and the hardware it
* abstracts. */
xResult = pxFunctionList->C_Initialize( &xInitArgs );
configASSERT( xResult == CKR_OK );

/* C_GetSlotList will retrieve an array of CK_SLOT_IDs.
* This Cryptoki library does not implement slots, but it is important to
* highlight how Cryptoki can be used to interface with real hardware.
*
* By setting the first argument "tokenPresent" to true, we only retrieve
* slots that have a token. If the second argument "pSlotList" is NULL, the
* third argument "pulCount" will be modified to contain the total slots. */
xResult = pxFunctionList->C_GetSlotList( CK_TRUE,
NULL,
&xSlotCount );
configASSERT( xResult == CKR_OK );

/* Since C_GetSlotList does not allocate the memory itself for getting a list
* of CK_SLOT_ID, we allocate one for it to populate with the list of
* slot ids. */
pxSlotId = pvPortMalloc( sizeof( CK_SLOT_ID ) * ( xSlotCount ) );
configASSERT( pxSlotId != NULL );

/* Now since pSlotList is not NULL, C_GetSlotList will populate it with the
* available slots. */
xResult = pxFunctionList->C_GetSlotList( CK_TRUE,
pxSlotId,
&xSlotCount );
configASSERT( xResult == CKR_OK );

/* Since this Cryptoki library does not actually implement the concept of slots,
* but we will use the first available slot, so the demo code conforms to
* Cryptoki.
*
* C_OpenSession will establish a session between the application and
* the token and we can then use the returned CK_SESSION_HANDLE for
* cryptographic operations with the token.
*
* For legacy reasons, Cryptoki demands that the CKF_SERIAL_SESSION bit
* is always set. */
xResult = pxFunctionList->C_OpenSession( pxSlotId[0],
CKF_SERIAL_SESSION | CKF_RW_SESSION,
NULL, /* Application defined pointer. */
NULL, /* Callback function. */
&hSession );
configASSERT( xResult == CKR_OK );


/* C_Login is called to log the user in to the token. The login status is
* shared between sessions, so logging in once is sufficient for all the sessions
* tied to the token. Most of the behavior for C_Login is defined by the token
* so it may be necessary to modify calls to C_Login when switching to a different
* Cryptoki library or token.
*
* This Cryptoki library does not implement C_Login, and only defines the function
* for compatibility reasons.
*/
xResult = pxFunctionList->C_Login( hSession,
CKU_USER,
( CK_UTF8CHAR_PTR ) configPKCS11_DEFAULT_USER_PIN,
sizeof( configPKCS11_DEFAULT_USER_PIN ) - 1UL );
configASSERT( xResult == CKR_OK );

/* C_GenerateRandom generates random or pseudo random data. As arguments it
* takes the application session, and a pointer to a byte buffer, as well as
* the length of the byte buffer. Then it will fill this buffer with random
* bytes. */
xResult = pxFunctionList->C_GenerateRandom( hSession,
&xRandomData,
sizeof( xRandomData ) );
configASSERT( xResult == CKR_OK );

for( ulIndex = 0; ulIndex < sizeof( xRandomData ); ulIndex++ )
{
configPRINTF( ( "Generated random number: %x\r\n", xRandomData[ ulIndex ] ) );
}


/* C_CloseSession closes the session that was established between the
* application and the token. This will clean up the resources that maintained
* the link between the application and the token. If the application wishes
* to use the token again, it will need to open a new session. */
xResult = pxFunctionList->C_CloseSession( hSession );
configASSERT( xResult == CKR_OK );

/* C_Finalize signals to the Cryptoki library that the application is done
* using it. It should always be the last call to the Cryptoki library.
* NULL should always be passed as the argument, as the parameter is currently
* just reserved for future revisions.
*
* Calling this function in a multi threaded environment can lead to undefined
* behavior if other threads are accessing the Cryptoki library. */
xResult = pxFunctionList->C_Finalize( NULL );
configASSERT( xResult == CKR_OK );

configPRINTF( ( "Finished PKCS #11 Management Demo.\r\n" ) );

vPortFree( pxSlotId );
vTaskDelete( NULL );
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,6 @@
/* Event group related definitions. */
#define configUSE_EVENT_GROUPS 1

/* Run time stats gathering configuration options. */
#define configGENERATE_RUN_TIME_STATS 0
#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define portGET_RUN_TIME_COUNTER_VALUE()

/* Co-routine definitions. */
#define configUSE_CO_ROUTINES 0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
Expand Down Expand Up @@ -127,75 +122,8 @@ functions. */

/* Only used when running in the FreeRTOS Windows simulator. Defines the
priority of the task used to simulate Ethernet interrupts. */
#define configMAC_ISR_SIMULATOR_PRIORITY ( configMAX_PRIORITIES - 1 )

/* This demo creates a virtual network connection by accessing the raw Ethernet
or WiFi data to and from a real network connection. Many computers have more
than one real network port, and configNETWORK_INTERFACE_TO_USE is used to tell
the demo which real port should be used to create the virtual port. The ports
available are displayed on the console when the application is executed. For
example, on my development laptop setting configNETWORK_INTERFACE_TO_USE to 4
results in the wired network being used, while setting
configNETWORK_INTERFACE_TO_USE to 2 results in the wireless network being
used. */
#define configNETWORK_INTERFACE_TO_USE 1L

/* The address of an echo server is only left in this project as it doubles as
the address to which logging is sent should UDP logging be enabled. */
#define configECHO_SERVER_ADDR0 192
#define configECHO_SERVER_ADDR1 168
#define configECHO_SERVER_ADDR2 0
#define configECHO_SERVER_ADDR3 11

/* Default MAC address configuration. The demo creates a virtual network
connection that uses this MAC address by accessing the raw Ethernet/WiFi data
to and from a real network connection on the host PC. See the
configNETWORK_INTERFACE_TO_USE definition above for information on how to
configure the real network connection to use. */
#define configMAC_ADDR0 0x00
#define configMAC_ADDR1 0x11
#define configMAC_ADDR2 0x11
#define configMAC_ADDR3 0x11
#define configMAC_ADDR4 0x11
#define configMAC_ADDR5 0x41

/* Default IP address configuration. Used in ipconfigUSE_DNS is set to 0, or
ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configIP_ADDR0 10
#define configIP_ADDR1 10
#define configIP_ADDR2 10
#define configIP_ADDR3 200

/* Default gateway IP address configuration. Used in ipconfigUSE_DNS is set to
0, or ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configGATEWAY_ADDR0 10
#define configGATEWAY_ADDR1 10
#define configGATEWAY_ADDR2 10
#define configGATEWAY_ADDR3 1

/* Default DNS server configuration. OpenDNS addresses are 208.67.222.222 and
208.67.220.220. Used in ipconfigUSE_DNS is set to 0, or ipconfigUSE_DNS is set
to 1 but a DNS server cannot be contacted.*/
#define configDNS_SERVER_ADDR0 208
#define configDNS_SERVER_ADDR1 67
#define configDNS_SERVER_ADDR2 222
#define configDNS_SERVER_ADDR3 222

/* Default netmask configuration. Used in ipconfigUSE_DNS is set to 0, or
ipconfigUSE_DNS is set to 1 but a DNS server cannot be contacted. */
#define configNET_MASK0 255
#define configNET_MASK1 0
#define configNET_MASK2 0
#define configNET_MASK3 0

/* The UDP port to which print messages are sent. */
#define configPRINT_PORT ( 15000 )

/* Task pool definitions for the demos of IoT Libraries. */
#define configTASKPOOL_ENABLE_ASSERTS 1
#define configTASKPOOL_NUMBER_OF_WORKERS 1
#define configTASKPOOL_WORKER_PRIORITY tskIDLE_PRIORITY
#define configTASKPOOL_WORKER_STACK_SIZE_BYTES 2048
#define configMAC_ISR_SIMULATOR_PRIORITY ( configMAX_PRIORITIES - 1 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might not be needed. Could remove lated.


#if( defined( _MSC_VER ) && ( _MSC_VER <= 1600 ) && !defined( snprintf ) )
/* Map to Windows names. */
Expand Down
22 changes: 20 additions & 2 deletions FreeRTOS-Plus/Demo/FreeRTOS_Plus_PKCS11_Windows_Simulator/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,18 +48,36 @@
/* PKCS #11 Demo Series Config */
#include "pkcs11_demo_config.h"

/* Prototype for the PKCS #11 "Management" demo. This demo covers the various
* functions used to manage the internal state of the PKCS #11 stack, and then
* demonstrates how to generate random numbers using PKCS #11.
*/
extern void vPKCS11ManagementDemo( void );

/*
* Private function for starting the various PKCS #11 demos.
*
*/
static void prvStartPKCS11Demo( void )
{
configPRINTF( ( "---------STARTING DEMO---------\r\n" ) );
#if( configPKCS11_MANAGEMENT_DEMO == 1 )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll assume the macro is needed since we may have more demos...

vPKCS11ManagementDemo();
#endif
configPRINTF( ( "---------Finished DEMO---------\r\n" ) );
}

/*-----------------------------------------------------------*/

int main( void )
{
/* TODO: Start up output. */
configPRINTF( ( "Creating PKCS #11 Demo Task.\r\n" ) );
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;

/* Create the PKCS #11 demo task. */
xReturned = xTaskCreate(
vPKCS11ManagementDemo,
prvStartPKCS11Demo,
"PKCS11 Demo",
configPKCS11_DEMO_STACK_SIZE,
NULL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@
* http://www.FreeRTOS.org
*/

/*
* @brief this macro defines the stack size for the PKCS #11 demo task.
*/
#define configPKCS11_DEMO_STACK_SIZE 200

/*
* @brief set this macro to "1" in order to run the PKCS #11 management demo.
*/
#define configPKCS11_MANAGEMENT_DEMO 1