From 57c7ad1aa0e485b5594f27f1ab501ff0306fe2fc Mon Sep 17 00:00:00 2001 From: Ritu Sood Date: Thu, 26 Apr 2018 01:50:05 +0000 Subject: Added a new Attribute to store TPM key handle Includes changes to detect existing instances of key and also some bug fixes. Also added new functionality for RSA_SignUpdate, RSA_SignFinal and RSA_Cleanup Issue-ID: AAF-260 Change-Id: Ib064e86b8f112784ed6d352ab1557ab9a13c5978 Signed-off-by: Ritu Sood --- SoftHSMv2/src/lib/HwInfra/HwInfra.c | 719 ----------------------- SoftHSMv2/src/lib/HwInfra/HwInfra.cpp | 814 ++++++++++++++++++++++++++ SoftHSMv2/src/lib/HwInfra/HwInfra.h | 21 +- SoftHSMv2/src/lib/HwInfra/Makefile.am | 2 +- SoftHSMv2/src/lib/HwInfra/hwpluginif.h | 60 +- SoftHSMv2/src/lib/P11Attributes.cpp | 34 ++ SoftHSMv2/src/lib/P11Attributes.h | 19 + SoftHSMv2/src/lib/P11Objects.cpp | 8 + SoftHSMv2/src/lib/SoftHSM.cpp | 213 +++++-- SoftHSMv2/src/lib/object_store/DBObject.cpp | 2 + SoftHSMv2/src/lib/object_store/OSAttributes.h | 2 + SoftHSMv2/src/lib/session_mgr/Session.cpp | 13 + SoftHSMv2/src/lib/session_mgr/Session.h | 6 + 13 files changed, 1140 insertions(+), 773 deletions(-) delete mode 100644 SoftHSMv2/src/lib/HwInfra/HwInfra.c create mode 100644 SoftHSMv2/src/lib/HwInfra/HwInfra.cpp (limited to 'SoftHSMv2/src/lib') diff --git a/SoftHSMv2/src/lib/HwInfra/HwInfra.c b/SoftHSMv2/src/lib/HwInfra/HwInfra.c deleted file mode 100644 index 528097d..0000000 --- a/SoftHSMv2/src/lib/HwInfra/HwInfra.c +++ /dev/null @@ -1,719 +0,0 @@ -/* Copyright 2018 Intel Corporation, Inc -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "HwInfra.h" -#include "hwpluginif.h" - -#include "cryptoki.h" - -char hw_plugins_parent_dir[MAX_PARENT_PATH_NAME+1] = ""; -char *default_hw_plugin_parent_dir = "/tmp/hwparent/"; -void *g_dl_handle; -SSHSM_HW_FUNCTIONS_t g_pluginfuncs; - - -/** - Function name : prepareHWPlugin - Description: This function is expected to be called by C_Initialize - of softHSM. This function does following - -- Reads the parent directory entries - -- If the subdirectory entry starts with 'S', then it calls loadHWPlugin - -- if the loadHWPlugin returns failure, then it finds the next subdirectory - that start with 'S' and calls loadHWPlugin. -**/ - -int prepareHWPlugin() -{ - DIR *dirhandle; - struct dirent *entry; - int len; - char *env; - int ret_val = 0; - - LOG("%s() called \n", __func__); - /** check if there is any envrionment variable defined to represent - ** hw plugin parent directory. - **/ - env = getenv("SSHSM_HW_PLUGINS_PARENT_DIR"); - if (env != NULL) - { - len = strlen(env); - if (len > MAX_PARENT_PATH_NAME) - { - LOG("SSHSM_HW_PLUGINS_PARENT_DIR environment is too long %d \n", len); - return(SSHSM_HW_PLUGIN_ERROR_BASE + ENVIRONMENT_TOO_LONG); - } - strcpy(hw_plugins_parent_dir, env); - } - else - { - strcpy(hw_plugins_parent_dir, default_hw_plugin_parent_dir); - } - - /**Read parent directory entries **/ - ret_val = -1; - dirhandle = opendir (hw_plugins_parent_dir); - if (dirhandle != NULL) - { - int count = 0; - while (NULL != (entry = readdir (dirhandle)) ) - { - count++; - /**Check if it is directory **/ - if (entry->d_type == DT_DIR) - { - /** See if it starts with 'S' **/ - if ((entry->d_name[0] == 'S') || - (entry->d_name[0] == 's') ) - { - /** Load plugin.so file if it exists in the subdirectory - load it and check whether the HW is present by calling - init function **/ - ret_val = loadHWPlugin( hw_plugins_parent_dir, - entry->d_name); - if(ret_val == 0) - { - break; - } - } - } - } - } - else - { - LOG ("Couldn't open the directory \n"); - return ret_val; - } - - closedir(dirhandle); - return ret_val; -} - -/** - Function name : loadHWPlugin - Description: It first checks whether there is plugin.so file, activate - directory and at least one key directory. if any of them not present, then - it returns error. If all three are present, then it calls - of softHSM. It calls HwPlugin_Initiate_Activate_and_load_key() function. -**/ - -int loadHWPlugin(char *parent_dir, char *pluginsubdir) -{ - char fullpath[256+1]; - DIR *dirhandle; - struct dirent *entry; - char so_present, activate_dir_present, key_dir_present; - hwpluginentries_t *entries; - int ret_val = -1; - - if (strlen(parent_dir) + strlen(pluginsubdir) > 256 ) - { - LOG("hwpluing path is too long \n"); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - } - - strcpy(fullpath, parent_dir); - strcat(fullpath, pluginsubdir); - - dirhandle = opendir(fullpath); - - entries = malloc(sizeof(hwpluginentries_t)); - if (entries == NULL ) - { - LOG("Could not allocate entries \n"); - closedir(dirhandle); - return(SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); - } - memset(entries, 0, sizeof(hwpluginentries_t)); - - if (dirhandle != NULL) - { - so_present = 0; - activate_dir_present = 0; - key_dir_present = 0; - while (NULL != (entry = readdir (dirhandle)) ) - { - /** Ensure that the directory has plugin.so file, activate directory, - ** at least one key directory - **/ - - if ((entry->d_type == DT_REG) && - (strcmp(entry->d_name, "plugin.so") == 0)) - { - so_present = 1; - if (strlen(fullpath) + strlen("/")+ strlen(entry->d_name) > 256) - { - LOG("plugin so path is too long \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - break; - } - strcpy(entries->so_full_path, fullpath); - strcat(entries->so_full_path, "/"); - strcat(entries->so_full_path, entry->d_name); - } - - if ((entry->d_type == DT_DIR) && - (strcmp(entry->d_name, "activate") == 0 )) - { - activate_dir_present = 1; - if (strlen(fullpath) + 2*strlen("/")+ strlen(entry->d_name) > 256) - { - LOG("activate path is too long \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - break; - } - strcpy(entries->activate_dir_full_path, fullpath); - strcat(entries->activate_dir_full_path, "/"); - strcat(entries->activate_dir_full_path, entry->d_name); - strcat(entries->activate_dir_full_path, "/"); - } - - if ((entry->d_type == DT_DIR) && - (strncmp(entry->d_name, "key", 3) == 0 )) - { - key_dir_present = 1; - if (strlen(fullpath) + 2*strlen("/")+ strlen(entry->d_name) > 256) - { - LOG("activate path is too long \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - break; - } - strcpy(entries->key_dir_full_path[entries->num_key_dirs], - fullpath); - strcat(entries->key_dir_full_path[entries->num_key_dirs], "/"); - strcat(entries->key_dir_full_path[entries->num_key_dirs], - entry->d_name); - strcat(entries->key_dir_full_path[entries->num_key_dirs], "/"); - entries->num_key_dirs++; - } - - if (so_present && activate_dir_present && key_dir_present) - { - printf("so dir path: %s \n", entries->so_full_path); - printf("activate dir path: %s \n", entries->activate_dir_full_path); - ret_val = HwPlugin_Initiate_Activate_and_load_keys(entries); - break; - } - } - - if (!so_present || !activate_dir_present || !key_dir_present) - { - LOG("Minimum set of entries not present hwplugin dir plugindir %s so_present %d activate present %d key present %d \n", fullpath, so_present, activate_dir_present, key_dir_present); - return(SSHSM_HW_PLUGIN_ERROR_BASE + INCOMPLETE_PLUGIN_DIR); - } - } - else - { - LOG("Could not open hwplugin directory %s \n", fullpath); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_OPEN_ERROR); - } - free(entries); - closedir(dirhandle); - return(ret_val); -} - - -/** -** Function name: HWPlugin_Initiate_Activate_and_load_keys -** Description: This function loads plugin, gets the function pointers, -** activates the plugin and then finally loads the keys -**/ -int HwPlugin_Initiate_Activate_and_load_keys(hwpluginentries_t *entries) -{ - int ret_val; - - ret_val = load_hw_plugin_and_get_function_pointers(entries->so_full_path, - &g_pluginfuncs); - if(ret_val != 0) - return(ret_val); - - ret_val = init_hw_plugin(&g_pluginfuncs); - if(ret_val != 0 ) - return(ret_val); - - ret_val = activate_hw_plugin(entries, &g_pluginfuncs); - if (ret_val != 0 ) - return(ret_val); - - ret_val = load_keys_in_hw_plugin(entries, &g_pluginfuncs); - if (ret_val != 0 ) - return(ret_val); - - return(0); -} - - -/** - Function name : load_hw_plugin_and_get_function_pointers -**/ - -int load_hw_plugin_and_get_function_pointers(char *so_path, - SSHSM_HW_FUNCTIONS_t *funcs) -{ - int (*functogetpluginfuncs)(SSHSM_HW_FUNCTIONS_t *fs); - int ret_val; - - g_dl_handle = dlopen(so_path, RTLD_NOW); - if(g_dl_handle == NULL ) - { - LOG("dlopen on %s failed: %s \n", so_path, dlerror()); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_DL_OPEN_ERROR); - } - - functogetpluginfuncs = NULL; - functogetpluginfuncs = dlsym(g_dl_handle, - "sshsm_hw_plugin_get_plugin_functions"); - - if (functogetpluginfuncs == NULL) - { - LOG("dlsym of sshsm_hw_plugin_get_plugin_functions : %s \n", dlerror() ); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_DL_SYM_ERROR); - } - - ret_val = functogetpluginfuncs(funcs); - - return ret_val; -} - -int init_hw_plugin(SSHSM_HW_FUNCTIONS_t *funcs) -{ - int ret_val; - - ret_val = (funcs->xxx_init)(); - - if(ret_val != 0 ) - { - LOG("HWPlugin init failed \n" ); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); - - } - return(ret_val); -} - - -int activate_hw_plugin(hwpluginentries_t *entries, SSHSM_HW_FUNCTIONS_t *funcs) -{ - int ret_val; - - if( (entries == NULL) || (funcs == NULL) ) - { - ret_val = -1; - LOG("activate_hw_plugin: Input values are NULL \n"); - return ret_val; - } - /** Read all files starting with 'A' and pass the information to - ** plugin - **/ - - SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t comp_buffers; - - memset(&comp_buffers, 0, sizeof(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t)); - - ret_val = get_all_file_contents(entries->activate_dir_full_path, 'A', - &comp_buffers); - - if (ret_val == 0 ) - { - ret_val = (funcs->xxx_activate)(&comp_buffers); - //free_buffers(&comp_buffers); - } - - return(ret_val); -} - - -int load_keys_in_hw_plugin(hwpluginentries_t *entries, - SSHSM_HW_FUNCTIONS_t *funcs) -{ - - int ret_val; - void *key_handle; - int ii; - //unsigned long hwkeyhandle=987654321; - //key_handle = (void *) &hwkeyhandle; - - SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t comp_buffers; - - /** - Travese through all key directories and load the key in plugin - **/ - - ret_val = -1; - for(ii = 0; ii < entries->num_key_dirs; ii++) - { - memset(&comp_buffers, 0, - sizeof(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t)); - - ret_val = get_all_file_contents(entries->key_dir_full_path[ii], 'K', - &comp_buffers); - - if(ret_val == 0) - { - ret_val = (funcs->xxx_load_key)(&comp_buffers, &key_handle); - //free_buffers(&comp_buffers); - if(ret_val == 0) - { - /** Get PKCS11 information **/ - /** Call SoftHSM functions to create private key object */ - ret_val = program_pkcs11_info(entries->key_dir_full_path[ii], &key_handle); - } - } - - } - - return(0); -} - -int get_all_file_contents(char *dirpath, char starting_char, - SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ) -{ - DIR *dirhandle; - struct dirent *entry; - - buffer_info_t *buffer; - char *token; - - struct stat st; - int fd; - - int ret_val = 0; - - - char fullpath[256+1]; - - dirhandle = opendir(dirpath); - if (dirhandle != NULL) - { - while (NULL != (entry = readdir (dirhandle))) - { - if ((entry->d_type == DT_REG) && - (entry->d_name[0] == starting_char)) - { - buffer = malloc(sizeof(buffer_info_t)); - if (buffer == NULL ) - { - LOG("Could not allocate entries \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); - break; - } - token = strchr(entry->d_name, '.'); - strcpy(buffer->id, token+1); - - /** get full path of the file **/ - if ((strlen(dirpath) + strlen(entry->d_name)) > 256) - { - LOG("file path is too long \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - free(buffer); - break; - } - strcpy(fullpath,dirpath); - strcat(fullpath, entry->d_name); - stat(fullpath, &st); - buffer->buffer = malloc(st.st_size); - if(buffer->buffer == NULL) - { - LOG("Could not allocate entries \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); - free(buffer); - break; - } - buffer->length_of_buffer = st.st_size; - fd = open(fullpath, O_RDONLY); - if (fd == -1 ) - { - LOG("Could not open file %s \n", fullpath); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); - free(buffer->buffer); - free(buffer); - break; - } - - if(read(fd, buffer->buffer, st.st_size) < 0) - { - LOG("Reading from file %s failed \n", fullpath); - continue; - } - - close(fd); - - /** Now write this buffer in c_buffers **/ - c_buffers->buffer_info[c_buffers->num_buffers] = buffer; - c_buffers->num_buffers++; - - } - } - } - else - { - LOG("Could not open hwplugin directory %s \n", dirpath); - return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_OPEN_ERROR); - } - - closedir(dirhandle); - //if (ret_val != 0 ) - //free_buffers(c_buffers); - - return(ret_val); -} - -void free_buffers ( SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ) -{ - int ii; - - for(ii = 0; ii < c_buffers->num_buffers; ii++) - { - free(c_buffers->buffer_info[ii]->buffer); - free(c_buffers->buffer_info[ii]); - } -} - -int program_pkcs11_info (char *dirpath, void *key_handle) -{ - DIR *dirhandle; - struct dirent *entry; - - char fullpath[256+1]; - int ret_val = 0; - - FILE *fp; - char buffer[80+1]; - - unsigned int slot_id = 0; - unsigned char upin[64+1]; - int upin_len = 0; - unsigned char keyid[64+1]; - int key_id_len = 0; - unsigned char key_label[64+1] = ""; - char *valuep; - char *endvalue; - - - dirhandle = opendir(dirpath); - if (dirhandle != NULL) - { - while (NULL != (entry = readdir (dirhandle))) - { - if (strcmp(entry->d_name, "pkcs11.cfg") == 0 ) - { - /** get full path of the file **/ - if ((strlen(dirpath) + strlen(entry->d_name)) > 256) - { - LOG("file path is too long \n"); - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - break; - } - strcpy(fullpath,dirpath); - strcat(fullpath, entry->d_name); - - fp = fopen(fullpath, "r"); - if(fp == NULL ) - { - ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); - break; - } - while (fgets(buffer, 80, fp) != NULL) - { - valuep = strchr(buffer, ':'); - if(valuep == NULL) - continue; - valuep[0] = '\0'; - - /** Looks like \n is part of buffer that is read via fgets - ** Replacce tha with 0 **/ - endvalue = strchr(valuep+1, '\n'); - if(endvalue != NULL) - endvalue[0] = '\0'; - if (strcmp(buffer, "slot") == 0) - { - slot_id = strtoul(valuep+1, NULL, 10); - continue; - } - if(strcmp(buffer, "key_id") == 0 ) - { - strcpy((char*)keyid, valuep+1); - key_id_len = strlen((char*)keyid); - continue; - } - if(strcmp(buffer, "key_label") == 0 ) - { - strcpy((char*)key_label, valuep+1); - continue; - } - if(strcmp(buffer, "upin") == 0 ) - { - strcpy((char*) upin, valuep+1); - upin_len = strlen((char *) upin); - continue; - } - } - fclose(fp); - - /** Program key in SoftHSM **/ - ret_val = PrepareKeyInSoftHSM(slot_id, upin, upin_len, keyid, - key_id_len, key_label, key_handle); - - break; - } - - } - } - - return ret_val; -} - - -/*** PrepareKeyInSoftHSM -** Description: It creates the object in softhsm with given key id and -** key label and also stores the keyhandle that was returned by hardware plugin -** Inputs: -** - Slot ID -** - Key ID -** - Key Label -** - upin -** - pluginkeyHandle -** Output: -** - None -** Renturs -** - SUCCESS or FAILURE -*****/ -int PrepareKeyInSoftHSM(unsigned int slot_id, - unsigned char *upin, int upin_len, - unsigned char *key_id, int key_id_len, - unsigned char *key_label, void *key_handle) -{ - CK_SESSION_HANDLE hSession; - CK_RV ret_val; - int ii; - CK_OBJECT_HANDLE hKey; - unsigned char key_handle_str[32] = {0}; - - printf ("slot %ul upin %s key_id %s key_label %s \n", slot_id, upin, key_id, - key_label); - - if(!key_handle) - { - //ultoa((CK_ULONG)key_handle, key_handle_str, 16); // Linking error seen - printf("Key_handle to be stored: %lx \n", *((CK_ULONG *)key_handle) ); - sprintf((char *) key_handle_str, "%lx", *((CK_ULONG *)key_handle)); - } - else - { - printf("Input Key handle is NULL ! \n"); - } - - /** For creating the key object, first the session needs to be opened - C_OpenSession is used to open the session - **/ - ret_val = C_OpenSession(slot_id, CKF_SERIAL_SESSION | CKF_RW_SESSION, - NULL_PTR, NULL_PTR, &hSession); - - if (ret_val != CKR_OK) - { - printf("OpenSession failed for slot %x \n", slot_id); - return(ret_val); - } - - /** Next step is login - ** C_Login is used to login to the session - **/ - ret_val = C_Login(hSession, CKU_USER, upin, upin_len); - if (ret_val != CKR_OK) - { - printf("Login failed: 0x%lx | for slot %x upin below \n", ret_val, slot_id); - for (ii = 0; ii < upin_len; ii++ ) - printf("%2x %c \n", upin[ii], upin[ii]); - return(ret_val); - } - - CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; - CK_KEY_TYPE keyType = CKK_RSA; - CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE ; - - CK_ATTRIBUTE keyTemplate[] = { - { CKA_CLASS, &privClass, sizeof(privClass) }, - { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, - { CKA_LABEL, key_label, strlen((char *) key_label) }, - { CKA_ID, key_id, (CK_ULONG)key_id_len }, - { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, - { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, - { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) }, - { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, - { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, - { CKA_EXTRACTABLE, &ckTrue, sizeof(ckTrue) }, - { CKA_PUBLIC_EXPONENT, 0, 0}, - { CKA_MODULUS, 0, 0}, - { CKA_PRIVATE_EXPONENT, 0, 0}, - { CKA_PRIME_2, 0, 0}, - { CKA_EXPONENT_1, 0, 0}, - { CKA_EXPONENT_2, 0, 0}, - { CKA_COEFFICIENT, 0, 0}, - { CKA_PRIME_1, key_handle_str, strlen((char *)key_handle_str) } - /** For now keep the key handle returned by Plugin in CK_PRIME_1. - ** TBD - Define new attribute to store this in future - ***/ - }; - - ret_val = C_CreateObject(hSession, keyTemplate, - sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE),&hKey); - if (ret_val != CKR_OK) - { - printf("CreateObject failed: 0x%lx | for slot %x | keylabel %s | keyid below \n", - ret_val, slot_id, key_label); - for (ii = 0; ii < key_id_len; ii++ ) - printf("%2x %c \n", key_id[ii], key_id[ii]); - //return(ret_val); - } - - ret_val = C_Logout(hSession); - if (ret_val != CKR_OK) - { - printf("Logout failed 0x%lx | for slot %x \n", ret_val, slot_id); - return(ret_val); - } - - ret_val = C_CloseSession(hSession); - if (ret_val != CKR_OK) - { - printf("C_CloseSession failed for slot %x \n", slot_id); - return(ret_val); - } - - return ret_val; -} - -int HwInfraSignInit(void *keyHandle, unsigned long mechanism, - void* param, int paramLen) -{ - return ( g_pluginfuncs.xxx_rsa_sign_init(keyHandle, mechanism, param, paramLen) ); -} - -int HwInfraSign( void *keyHandle, unsigned long mechanism, - unsigned char *msg, int msg_len, - unsigned char *outsig, int *outsiglen) -{ - return ( g_pluginfuncs.xxx_rsa_sign(keyHandle, mechanism, msg, msg_len, - outsig, outsiglen) ); -} - diff --git a/SoftHSMv2/src/lib/HwInfra/HwInfra.cpp b/SoftHSMv2/src/lib/HwInfra/HwInfra.cpp new file mode 100644 index 0000000..557630b --- /dev/null +++ b/SoftHSMv2/src/lib/HwInfra/HwInfra.cpp @@ -0,0 +1,814 @@ +/* Copyright 2018 Intel Corporation, Inc +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "HwInfra.h" +#include "hwpluginif.h" +#include "OSAttributes.h" +#include "cryptoki.h" + +char hw_plugins_parent_dir[MAX_PARENT_PATH_NAME+1] = ""; +char *default_hw_plugin_parent_dir = "/tmp/hwparent/"; +void *g_dl_handle; +SSHSM_HW_FUNCTIONS_t g_pluginfuncs; + +/** + Function name : prepareHWPlugin + Description: This function is expected to be called by C_Initialize + of softHSM. This function does following + -- Reads the parent directory entries + -- If the subdirectory entry starts with 'S', then it calls loadHWPlugin + -- if the loadHWPlugin returns failure, then it finds the next subdirectory + that start with 'S' and calls loadHWPlugin. +**/ + +int prepareHWPlugin() +{ + DIR *dirhandle; + struct dirent *entry; + int len; + char *env; + int ret_val = 0; + + LOG("%s() called \n", __func__); + /** check if there is any envrionment variable defined to represent + ** hw plugin parent directory. + **/ + env = getenv("SSHSM_HW_PLUGINS_PARENT_DIR"); + if (env != NULL) + { + len = strlen(env); + if (len > MAX_PARENT_PATH_NAME) + { + LOG("SSHSM_HW_PLUGINS_PARENT_DIR environment is too long %d \n", len); + return(SSHSM_HW_PLUGIN_ERROR_BASE + ENVIRONMENT_TOO_LONG); + } + strcpy(hw_plugins_parent_dir, env); + } + else + { + strcpy(hw_plugins_parent_dir, default_hw_plugin_parent_dir); + } + + /**Read parent directory entries **/ + ret_val = -1; + dirhandle = opendir (hw_plugins_parent_dir); + if (dirhandle != NULL) + { + int count = 0; + while (NULL != (entry = readdir (dirhandle)) ) + { + count++; + /**Check if it is directory **/ + if (entry->d_type == DT_DIR) + { + /** See if it starts with 'S' **/ + if ((entry->d_name[0] == 'S') || + (entry->d_name[0] == 's') ) + { + /** Load plugin.so file if it exists in the subdirectory + load it and check whether the HW is present by calling + init function **/ + ret_val = loadHWPlugin( hw_plugins_parent_dir, + entry->d_name); + if(ret_val == 0) + { + break; + } + } + } + } + } + else + { + LOG ("Couldn't open the directory \n"); + return ret_val; + } + + closedir(dirhandle); + return ret_val; +} + +/** + Function name : loadHWPlugin + Description: It first checks whether there is plugin.so file, activate + directory and at least one key directory. if any of them not present, then + it returns error. If all three are present, then it calls + of softHSM. It calls HwPlugin_Initiate_Activate_and_load_key() function. +**/ + +int loadHWPlugin(char *parent_dir, char *pluginsubdir) +{ + char fullpath[256+1]; + DIR *dirhandle; + struct dirent *entry; + char so_present, activate_dir_present, key_dir_present; + hwpluginentries_t *entries; + int ret_val = -1; + + if (strlen(parent_dir) + strlen(pluginsubdir) > 256 ) + { + LOG("hwpluing path is too long \n"); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + } + + strcpy(fullpath, parent_dir); + strcat(fullpath, pluginsubdir); + + dirhandle = opendir(fullpath); + + entries = (hwpluginentries_t*)malloc(sizeof(hwpluginentries_t)); + if (entries == NULL ) + { + LOG("Could not allocate entries \n"); + closedir(dirhandle); + return(SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); + } + memset(entries, 0, sizeof(hwpluginentries_t)); + + if (dirhandle != NULL) + { + so_present = 0; + activate_dir_present = 0; + key_dir_present = 0; + while (NULL != (entry = readdir (dirhandle)) ) + { + /** Ensure that the directory has plugin.so file, activate directory, + ** at least one key directory + **/ + + if ((entry->d_type == DT_REG) && + (strcmp(entry->d_name, "plugin.so") == 0)) + { + so_present = 1; + if (strlen(fullpath) + strlen("/")+ strlen(entry->d_name) > 256) + { + LOG("plugin so path is too long \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + break; + } + strcpy(entries->so_full_path, fullpath); + strcat(entries->so_full_path, "/"); + strcat(entries->so_full_path, entry->d_name); + } + + if ((entry->d_type == DT_DIR) && + (strcmp(entry->d_name, "activate") == 0 )) + { + activate_dir_present = 1; + if (strlen(fullpath) + 2*strlen("/")+ strlen(entry->d_name) > 256) + { + LOG("activate path is too long \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + break; + } + strcpy(entries->activate_dir_full_path, fullpath); + strcat(entries->activate_dir_full_path, "/"); + strcat(entries->activate_dir_full_path, entry->d_name); + strcat(entries->activate_dir_full_path, "/"); + } + + if ((entry->d_type == DT_DIR) && + (strncmp(entry->d_name, "key", 3) == 0 )) + { + key_dir_present = 1; + if (strlen(fullpath) + 2*strlen("/")+ strlen(entry->d_name) > 256) + { + LOG("activate path is too long \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + break; + } + strcpy(entries->key_dir_full_path[entries->num_key_dirs], + fullpath); + strcat(entries->key_dir_full_path[entries->num_key_dirs], "/"); + strcat(entries->key_dir_full_path[entries->num_key_dirs], + entry->d_name); + strcat(entries->key_dir_full_path[entries->num_key_dirs], "/"); + entries->num_key_dirs++; + } + + if (so_present && activate_dir_present && key_dir_present) + { + printf("so dir path: %s \n", entries->so_full_path); + printf("activate dir path: %s \n", entries->activate_dir_full_path); + ret_val = HwPlugin_Initiate_Activate_and_load_keys(entries); + break; + } + } + + if (!so_present || !activate_dir_present || !key_dir_present) + { + LOG("Minimum set of entries not present hwplugin dir plugindir %s so_present %d activate present %d key present %d \n", fullpath, so_present, activate_dir_present, key_dir_present); + return(SSHSM_HW_PLUGIN_ERROR_BASE + INCOMPLETE_PLUGIN_DIR); + } + } + else + { + LOG("Could not open hwplugin directory %s \n", fullpath); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_OPEN_ERROR); + } + free(entries); + closedir(dirhandle); + return(ret_val); +} + + +/** +** Function name: HWPlugin_Initiate_Activate_and_load_keys +** Description: This function loads plugin, gets the function pointers, +** activates the plugin and then finally loads the keys +**/ +int HwPlugin_Initiate_Activate_and_load_keys(hwpluginentries_t *entries) +{ + int ret_val; + + ret_val = load_hw_plugin_and_get_function_pointers(entries->so_full_path, + &g_pluginfuncs); + if(ret_val != 0) + return(ret_val); + + ret_val = init_hw_plugin(&g_pluginfuncs); + if(ret_val != 0 ) + return(ret_val); + + ret_val = activate_hw_plugin(entries, &g_pluginfuncs); + if (ret_val != 0 ) + return(ret_val); + + ret_val = load_keys_in_hw_plugin(entries, &g_pluginfuncs); + if (ret_val != 0 ) + return(ret_val); + + return(0); +} + + +/** + Function name : load_hw_plugin_and_get_function_pointers +**/ + +int load_hw_plugin_and_get_function_pointers(char *so_path, + SSHSM_HW_FUNCTIONS_t *funcs) +{ + int (*functogetpluginfuncs)(SSHSM_HW_FUNCTIONS_t *fs); + int ret_val; + + g_dl_handle = dlopen(so_path, RTLD_NOW); + if(g_dl_handle == NULL ) + { + LOG("dlopen on %s failed: %s \n", so_path, dlerror()); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_DL_OPEN_ERROR); + } + + functogetpluginfuncs = NULL; + functogetpluginfuncs = (int (*)(SSHSM_HW_FUNCTIONS_t *)) dlsym(g_dl_handle, + "sshsm_hw_plugin_get_plugin_functions"); + + if (functogetpluginfuncs == NULL) + { + LOG("dlsym of sshsm_hw_plugin_get_plugin_functions : %s \n", dlerror() ); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_DL_SYM_ERROR); + } + + ret_val = functogetpluginfuncs(funcs); + + return ret_val; +} + +int init_hw_plugin(SSHSM_HW_FUNCTIONS_t *funcs) +{ + int ret_val; + + ret_val = (funcs->xxx_init)(); + + if(ret_val != 0 ) + { + LOG("HWPlugin init failed \n" ); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + } + return(ret_val); +} + + +int activate_hw_plugin(hwpluginentries_t *entries, SSHSM_HW_FUNCTIONS_t *funcs) +{ + int ret_val; + + if( (entries == NULL) || (funcs == NULL) ) + { + ret_val = -1; + LOG("activate_hw_plugin: Input values are NULL \n"); + return ret_val; + } + /** Read all files starting with 'A' and pass the information to + ** plugin + **/ + + SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t comp_buffers; + + memset(&comp_buffers, 0, sizeof(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t)); + + ret_val = get_all_file_contents(entries->activate_dir_full_path, 'A', + &comp_buffers); + + if (ret_val == 0 ) + { + ret_val = (funcs->xxx_activate)(&comp_buffers); + //free_buffers(&comp_buffers); + } + + return(ret_val); +} + +int load_keys_in_hw_plugin(hwpluginentries_t *entries, + SSHSM_HW_FUNCTIONS_t *funcs) +{ + + int ret_val; + void *key_handle; + int ii; + //unsigned long hwkeyhandle=987654321; + //key_handle = (void *) &hwkeyhandle; + + SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t comp_buffers; + SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t import_public_key; + + /** + Travese through all key directories and load the key in plugin + **/ + + ret_val = -1; + for(ii = 0; ii < entries->num_key_dirs; ii++) + { + memset(&comp_buffers, 0, + sizeof(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t)); + + ret_val = get_all_file_contents(entries->key_dir_full_path[ii], 'K', + &comp_buffers); + + if(ret_val == 0) + { + ret_val = (funcs->xxx_load_key)(&comp_buffers, &key_handle, + &import_public_key); + //free_buffers(&comp_buffers); + if(ret_val == 0) + { + /** Get PKCS11 information **/ + /** Call SoftHSM functions to create private key object */ + if (ret_val == 0) { + ret_val = program_pkcs11_info(entries->key_dir_full_path[ii], + &key_handle, &import_public_key); + if (import_public_key.modulus != NULL) + free(import_public_key.modulus); + if (import_public_key.exponent != NULL) + free(import_public_key.exponent); + } + } + } + + } + + return(ret_val); +} + +int get_all_file_contents(char *dirpath, char starting_char, + SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ) +{ + DIR *dirhandle; + struct dirent *entry; + + buffer_info_t *buffer; + char *token; + + struct stat st; + int fd; + + int ret_val = 0; + + + char fullpath[256+1]; + + dirhandle = opendir(dirpath); + if (dirhandle != NULL) + { + while (NULL != (entry = readdir (dirhandle))) + { + if ((entry->d_type == DT_REG) && + (entry->d_name[0] == starting_char)) + { + buffer = (buffer_info_t*) malloc(sizeof(buffer_info_t)); + if (buffer == NULL ) + { + LOG("Could not allocate entries \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); + break; + } + token = strchr(entry->d_name, '.'); + strcpy(buffer->id, token+1); + + /** get full path of the file **/ + if ((strlen(dirpath) + strlen(entry->d_name)) > 256) + { + LOG("file path is too long \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + free(buffer); + break; + } + strcpy(fullpath,dirpath); + strcat(fullpath, entry->d_name); + stat(fullpath, &st); + buffer->buffer = (unsigned char*) malloc(st.st_size); + if(buffer->buffer == NULL) + { + LOG("Could not allocate entries \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); + free(buffer); + break; + } + buffer->length_of_buffer = st.st_size; + fd = open(fullpath, O_RDONLY); + if (fd == -1 ) + { + LOG("Could not open file %s \n", fullpath); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + ALLOCATION_ERROR); + free(buffer->buffer); + free(buffer); + break; + } + + if(read(fd, buffer->buffer, st.st_size) < 0) + { + LOG("Reading from file %s failed \n", fullpath); + continue; + } + + close(fd); + + /** Now write this buffer in c_buffers **/ + c_buffers->buffer_info[c_buffers->num_buffers] = buffer; + c_buffers->num_buffers++; + + } + } + } + else + { + LOG("Could not open hwplugin directory %s \n", dirpath); + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_OPEN_ERROR); + } + + closedir(dirhandle); + //if (ret_val != 0 ) + //free_buffers(c_buffers); + + return(ret_val); +} + +void free_buffers ( SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ) +{ + int ii; + + for(ii = 0; ii < c_buffers->num_buffers; ii++) + { + free(c_buffers->buffer_info[ii]->buffer); + free(c_buffers->buffer_info[ii]); + } +} + +int program_pkcs11_info (char *dirpath, void *key_handle, + SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *import_public_key) +{ + DIR *dirhandle; + struct dirent *entry; + + char fullpath[256+1]; + int ret_val = 0; + + FILE *fp; + char buffer[80+1]; + + unsigned int slot_id = 0; + unsigned char upin[64+1]; + int upin_len = 0; + unsigned char keyid[64+1]; + int key_id_len = 0; + unsigned char key_label[64+1] = ""; + char *valuep; + char *endvalue; + + + dirhandle = opendir(dirpath); + if (dirhandle != NULL) + { + while (NULL != (entry = readdir (dirhandle))) + { + if (strcmp(entry->d_name, "pkcs11.cfg") == 0 ) + { + /** get full path of the file **/ + if ((strlen(dirpath) + strlen(entry->d_name)) > 256) + { + LOG("file path is too long \n"); + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + break; + } + strcpy(fullpath,dirpath); + strcat(fullpath, entry->d_name); + + fp = fopen(fullpath, "r"); + if(fp == NULL ) + { + ret_val = (SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_PATH_TOO_LONG); + break; + } + while (fgets(buffer, 80, fp) != NULL) + { + valuep = strchr(buffer, ':'); + if(valuep == NULL) + continue; + valuep[0] = '\0'; + + /** Looks like \n is part of buffer that is read via fgets + ** Replacce tha with 0 **/ + endvalue = strchr(valuep+1, '\n'); + if(endvalue != NULL) + endvalue[0] = '\0'; + if (strcmp(buffer, "slot") == 0) + { + slot_id = strtoul(valuep+1, NULL, 10); + continue; + } + if(strcmp(buffer, "key_id") == 0 ) + { + strcpy((char*)keyid, valuep+1); + key_id_len = strlen((char*)keyid); + continue; + } + if(strcmp(buffer, "key_label") == 0 ) + { + strcpy((char*)key_label, valuep+1); + continue; + } + if(strcmp(buffer, "upin") == 0 ) + { + strcpy((char*) upin, valuep+1); + upin_len = strlen((char *) upin); + continue; + } + } + fclose(fp); + + /** Program key in SoftHSM **/ + ret_val = PrepareKeyInSoftHSM(slot_id, upin, upin_len, keyid, + key_id_len, key_label, key_handle, import_public_key); + + break; + } + + } + } + + return ret_val; +} + + +void long_to_byte_string(const unsigned long longValue, unsigned char *out, size_t *outlen) +{ + unsigned long setValue = longValue; + unsigned char byteStrIn[8]; + size_t i; + + for (i = 0; i < 8; i++) + { + byteStrIn[7-i] = (unsigned char) (setValue & 0xFF); + setValue >>= 8; + } + for (i = 0; i < 8; i++) + { + if (byteStrIn[i]) + break; + } + memcpy(out, &byteStrIn[i], 8-i); + *outlen = 8-i; +} + + + +/*** PrepareKeyInSoftHSM +** Description: It creates the object in softhsm with given key id and +** key label and also stores the keyhandle that was returned by hardware plugin +** Inputs: +** - Slot ID +** - Key ID +** - Key Label +** - upin +** - pluginkeyHandle +** Output: +** - None +** Renturs +** - SUCCESS or FAILURE +*****/ +int PrepareKeyInSoftHSM(unsigned int slot_id, + unsigned char *upin, int upin_len, + unsigned char *key_id, int key_id_len, + unsigned char *key_label, void *key_handle, + SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *import_public_key) +{ + CK_SESSION_HANDLE hSession; + CK_RV ret_val; + int ii; + CK_OBJECT_HANDLE hKey; + unsigned char key_handle_str[32] = {0}; + + printf ("slot %ul upin %s key_id %s key_label %s \n", slot_id, upin, key_id, + key_label); + if(!key_handle) + { + printf("Input Key handle is NULL ! \n"); + return (SSHSM_HW_PLUGIN_ERROR_BASE + INVALID_KEY_ERROR); + } + if (import_public_key->modulus == NULL || + import_public_key->exponent == NULL) + { + return (SSHSM_HW_PLUGIN_ERROR_BASE + INVALID_KEY_ERROR); + } + + /** For creating the key object, first the session needs to be opened + C_OpenSession is used to open the session + **/ + ret_val = C_OpenSession(slot_id, CKF_SERIAL_SESSION | CKF_RW_SESSION, + NULL_PTR, NULL_PTR, &hSession); + + if (ret_val != CKR_OK) + { + printf("OpenSession failed for slot %x \n", slot_id); + return(ret_val); + } + + /** Next step is login + ** C_Login is used to login to the session + **/ + ret_val = C_Login(hSession, CKU_USER, upin, upin_len); + if (ret_val != CKR_OK) + { + printf("Login failed: 0x%lx | for slot %x upin below \n", ret_val, slot_id); + for (ii = 0; ii < upin_len; ii++ ) + printf("%2x %c \n", upin[ii], upin[ii]); + return(ret_val); + } + + CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; + CK_KEY_TYPE keyType = CKK_RSA; + CK_BBOOL ckTrue = CK_TRUE, ckFalse = CK_FALSE ; + + unsigned long int key_id_int = atol( (const char*) key_id ); + unsigned char byte_str[8]; + size_t outlen; + long_to_byte_string(key_id_int, byte_str, &outlen); + + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privClass, sizeof(privClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_LABEL, key_label, strlen((char *) key_label) }, + { CKA_ID, byte_str, outlen }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_UNWRAP, &ckFalse, sizeof(ckFalse) }, + { CKA_TOKEN, &ckTrue, sizeof(ckTrue) }, + { CKA_PRIVATE, &ckTrue, sizeof(ckTrue) }, + { CKA_EXTRACTABLE, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckFalse, sizeof(ckFalse) }, + { CKA_PUBLIC_EXPONENT, import_public_key->exponent, import_public_key->exponent_size}, + //{ CKA_MODULUS, pN, sizeof(pN) }, + { CKA_MODULUS, import_public_key->modulus, import_public_key->modulus_size }, + { CKA_PRIVATE_EXPONENT, 0, 0 }, + { CKA_PRIME_2, 0, 0}, + { CKA_EXPONENT_1, 0, 0}, + { CKA_EXPONENT_2, 0, 0}, + { CKA_COEFFICIENT, 0, 0}, + { CKA_OS_PRIVATE_HANDLE, (CK_VOID_PTR ) *((CK_ULONG*)key_handle), sizeof(CK_ULONG) } + }; + + + CK_OBJECT_HANDLE hObject; + CK_ULONG ulObjectCount; + CK_RV rv; + + rv = C_FindObjectsInit(hSession, keyTemplate, 0); + if(rv != CKR_OK) { + LOG ("C_FindObjectsInit rv %ld\n", rv); + } + rv = C_FindObjects(hSession, &hObject, 16, &ulObjectCount); + printf("PrepareKeyInSoftHSM: ulObjectCount %ld\n", ulObjectCount); + if(rv != CKR_OK || ulObjectCount == 0) { + ret_val = C_CreateObject(hSession, keyTemplate, + sizeof(keyTemplate)/sizeof(CK_ATTRIBUTE),&hKey); + if (ret_val != CKR_OK) + { + printf("CreateObject failed: 0x%lx | for slot %x | keylabel %s | keyid below \n", + ret_val, slot_id, key_label); + for (ii = 0; ii < key_id_len; ii++ ) + printf("%2x %c \n", key_id[ii], key_id[ii]); + //return(ret_val); + } + } + else { + printf("PrepareKeyInSoftHSM: Object already exists\n"); + } + + rv = C_FindObjectsFinal(hSession); + if(rv != CKR_OK) { + LOG ("C_FindObjectsFinal rv %ld\n", rv); + } + + ret_val = C_Logout(hSession); + if (ret_val != CKR_OK) + { + printf("Logout failed 0x%lx | for slot %x \n", ret_val, slot_id); + return(ret_val); + } + + ret_val = C_CloseSession(hSession); + if (ret_val != CKR_OK) + { + printf("C_CloseSession failed for slot %x \n", slot_id); + return(ret_val); + } + + return ret_val; +} + +int HwInfraSignInit(void *keyHandle, unsigned long mechanism, + void* param, int paramLen, void **hwCryptoOpaque) +{ + if (g_pluginfuncs.xxx_rsa_sign_init == NULL) + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + return (g_pluginfuncs.xxx_rsa_sign_init(keyHandle, mechanism, param, + paramLen, hwCryptoOpaque)) ; + +} + +int HwInfraSign(void *keyHandle, unsigned long mechanism, + unsigned char *msg, int msg_len, void *hwCryptoOpaque, + unsigned char *outsig, int *outsiglen) +{ + if (g_pluginfuncs.xxx_rsa_sign == NULL) + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + return ( g_pluginfuncs.xxx_rsa_sign(keyHandle, mechanism, msg, msg_len, + hwCryptoOpaque, outsig, outsiglen) ); +} + +int HwInfraSignUpdate(void *keyHandle, unsigned long mechanism, + unsigned char *param, int paramLen, void *hwCryptoOpaque) +{ + if (g_pluginfuncs.xxx_rsa_sign_update == NULL) + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + int x = ( g_pluginfuncs.xxx_rsa_sign_update(keyHandle, mechanism, param, + paramLen, hwCryptoOpaque) ); + return 0; +} + +int HwInfraSignFinal(void *keyHandle, unsigned long mechanism, + void *hwCryptoOpaque, + unsigned char *outsig, int *outsiglen) +{ + if (g_pluginfuncs.xxx_rsa_sign_final == NULL) + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + return ( g_pluginfuncs.xxx_rsa_sign_final(keyHandle, mechanism, + hwCryptoOpaque, outsig, outsiglen) ); +} + +int HwInfraSignCleanup(void *keyHandle, unsigned long mechanism, + void *hwCryptoOpaque) +{ + if (g_pluginfuncs.xxx_rsa_sign_cleanup == NULL) + return(SSHSM_HW_PLUGIN_ERROR_BASE + PLUGIN_INIT_ERROR); + + return ( g_pluginfuncs.xxx_rsa_sign_cleanup(keyHandle, mechanism, + hwCryptoOpaque) ); +} + diff --git a/SoftHSMv2/src/lib/HwInfra/HwInfra.h b/SoftHSMv2/src/lib/HwInfra/HwInfra.h index a62bd7d..8cbbada 100644 --- a/SoftHSMv2/src/lib/HwInfra/HwInfra.h +++ b/SoftHSMv2/src/lib/HwInfra/HwInfra.h @@ -50,18 +50,26 @@ int get_all_file_contents(char *dirpath, char starting_char, SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ); void free_buffers ( SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *c_buffers ); -int program_pkcs11_info (char *dirpath, void *key_handle); +int program_pkcs11_info (char *dirpath, void *key_handle, SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t* ik); int PrepareKeyInSoftHSM(unsigned int slot_id, unsigned char *upin, int upin_len, unsigned char *key_id, int key_id_len, - unsigned char *key_label, void *key_handle); + unsigned char *key_label, void *key_handle, + SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t* ik); int HwInfraSignInit(void *keyHandle, unsigned long mechanism, - void* param, int paramLen); - -int HwInfraSign( void *keyHandle, unsigned long mechanism, - unsigned char *msg, int msg_len, + void* param, int paramLen, void **hwCryptoOpaque); +int HwInfraSign(void *keyHandle, unsigned long mechanism, + unsigned char *msg, int msg_len, void *hwCryptoOpaque, + unsigned char *outsig, int *outsiglen); +int HwInfraSignUpdate(void *keyHandle, unsigned long mechanism, + unsigned char *msg, int msg_len, void *hwCryptoOpaque); +int HwInfraSignFinal(void *keyHandle, unsigned long mechanism, + void *hwCryptoOpaque, unsigned char *outsig, int *outsiglen); +int HwInfraSignCleanup(void *keyHandle, unsigned long mechanism, + void *hwCryptoOpaque); + #define MAX_PARENT_PATH_NAME 256 @@ -76,6 +84,7 @@ int HwInfraSign( void *keyHandle, unsigned long mechanism, #define PLUGIN_DL_OPEN_ERROR (06) #define PLUGIN_DL_SYM_ERROR (07) #define PLUGIN_INIT_ERROR (10) +#define INVALID_KEY_ERROR (11) #if defined(__cplusplus) } diff --git a/SoftHSMv2/src/lib/HwInfra/Makefile.am b/SoftHSMv2/src/lib/HwInfra/Makefile.am index b327b15..3ff3726 100644 --- a/SoftHSMv2/src/lib/HwInfra/Makefile.am +++ b/SoftHSMv2/src/lib/HwInfra/Makefile.am @@ -9,7 +9,7 @@ AM_CPPFLAGS = -I$(srcdir)/.. \ -I$(srcdir)/../session_mgr noinst_LTLIBRARIES = libsofthsm_hwinfra.la -libsofthsm_hwinfra_la_SOURCES = HwInfra.c +libsofthsm_hwinfra_la_SOURCES = HwInfra.cpp SUBDIRS = diff --git a/SoftHSMv2/src/lib/HwInfra/hwpluginif.h b/SoftHSMv2/src/lib/HwInfra/hwpluginif.h index b078be3..a8ade2a 100755 --- a/SoftHSMv2/src/lib/HwInfra/hwpluginif.h +++ b/SoftHSMv2/src/lib/HwInfra/hwpluginif.h @@ -94,6 +94,20 @@ typedef int (*sshsm_hw_plugin_activate)( ); +/*** + * Import Public Key + * Description: This is called by HWPluginInfra after load key to get the public + * key modulus and exponent. Plugin to allocate memory for modulus and exponent + * based on size. HwInfra will release the buffers after using them. + */ + +typedef struct sshsm_hw_plugin_import_public_key_info_s { + unsigned long modulus_size; + unsigned char *modulus; + unsigned long exponent_size; + unsigned char *exponent; +}SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t; + /*** * Load Key Callback @@ -141,32 +155,30 @@ typedef struct sshsm_hw_plugin_load_key_in_info_s { typedef int (*sshsm_hw_plugin_load_key)( SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info, - void **keyHandle + void **keyHandle, + SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *import_public_key ); typedef int (*sshsm_hw_plugin_unload_key)( void **keyHandle ); - - - /*** * Callback: RSA Sign Init * Description: This is called by HWPluginInfra as part of C_SignInit function - * for RSA keys + * for RSA keys. Plugin can allocate memory for any state and can add its reference to + * pluginOutDataRef. This pointer is passed to sign, signupdate and signfinal. */ typedef int (*sshsm_hw_plugin_rsa_sign_init)( void *keyHandle, unsigned long mechanism, void *param, - int len + int len, + void **pluginOutDataRef ); - - /*** - * Callback: RSA Sign Init + * Callback: RSA Sign * Description: This is called by HWPluginInfra as part of C_Sign function * for RSA keys. HWPluginInfra get the keyHandle from the key object. * @@ -181,10 +193,37 @@ typedef int (*sshsm_hw_plugin_rsa_sign)( unsigned long mechanism, unsigned char *msg, int msg_len, + void *pluginDataRef, unsigned char *outsig, int *outsiglen ); +typedef int (*sshsm_hw_plugin_rsa_sign_update)( + void *keyHandle, + unsigned long mechanism, + unsigned char *msg, + int msg_len, + void *pluginDataRef + ); + +typedef int (*sshsm_hw_plugin_rsa_sign_final)( + void *keyHandle, + unsigned long mechanism, + void *pluginDataRef, + unsigned char *outsig, + int *outsiglen + ); + +/** This function is called by SSHSM only if there sign_final function is not called. +If sign_final function is called, it is assumed that plugin would have cleaned this up. +***/ + +typedef int (*sshsm_hw_plugin_rsa_sign_cleanup)( + void *keyHandle, + unsigned long mechanism, + void *pluginDataRef + ); + /*** * Function Name: sshsm_hw_plugin_get_plugin_functions * Descrpiton: Every HW plugin is expected to define this function. @@ -208,6 +247,9 @@ typedef struct sshsm_hw_functions_s sshsm_hw_plugin_unload_key xxx_unload_key; sshsm_hw_plugin_rsa_sign_init xxx_rsa_sign_init; sshsm_hw_plugin_rsa_sign xxx_rsa_sign; + sshsm_hw_plugin_rsa_sign_update xxx_rsa_sign_update; + sshsm_hw_plugin_rsa_sign_final xxx_rsa_sign_final; + sshsm_hw_plugin_rsa_sign_cleanup xxx_rsa_sign_cleanup; }SSHSM_HW_FUNCTIONS_t; diff --git a/SoftHSMv2/src/lib/P11Attributes.cpp b/SoftHSMv2/src/lib/P11Attributes.cpp index 28d0f9b..5a56097 100644 --- a/SoftHSMv2/src/lib/P11Attributes.cpp +++ b/SoftHSMv2/src/lib/P11Attributes.cpp @@ -294,6 +294,10 @@ CK_RV P11Attribute::retrieve(Token *token, bool isPrivate, CK_VOID_PTR pValue, C { attrSize = attr.getAttributeMapValue().size() * sizeof(CK_ATTRIBUTE); } + else if (attr.isUnsignedLongAttribute()) + { + attrSize = sizeof(unsigned long); + } else { // Should be impossible. @@ -2512,3 +2516,33 @@ CK_RV P11AttrAllowedMechanisms::updateAttr(Token* /*token*/, bool /*isPrivate*/, osobject->setAttribute(type, OSAttribute(data)); return CKR_OK; } + + +// Set default value +bool P11AttrPrivateHandle::setDefault() +{ + OSAttribute attr((CK_ULONG)0); + return osobject->setAttribute(type, attr); +} + +// Update the value if allowed +CK_RV P11AttrPrivateHandle::updateAttr(Token* /*token*/, bool /*isPrivate*/, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op) +{ + // Attribute specific checks + if (op != OBJECT_OP_CREATE) + { + return CKR_ATTRIBUTE_READ_ONLY; + } + + if (ulValueLen !=sizeof(CK_ULONG)) + { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + // Store data + osobject->setAttribute(type, *((CK_ULONG*)pValue)); + + return CKR_OK; +} + + diff --git a/SoftHSMv2/src/lib/P11Attributes.h b/SoftHSMv2/src/lib/P11Attributes.h index 3cddf30..7cc9976 100644 --- a/SoftHSMv2/src/lib/P11Attributes.h +++ b/SoftHSMv2/src/lib/P11Attributes.h @@ -36,6 +36,7 @@ #include "cryptoki.h" #include "OSObject.h" #include "Token.h" +#include "OSAttributes.h" // The operation types #define OBJECT_OP_NONE 0x0 @@ -1261,4 +1262,22 @@ protected: virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op); }; +/***************************************** + * CKA_COEFFICIENT + *****************************************/ + +class P11AttrPrivateHandle : public P11Attribute +{ +public: + // Constructor + P11AttrPrivateHandle(OSObject* inobject) : P11Attribute(inobject) { type = CKA_OS_PRIVATE_HANDLE; checks = ck1; } + +protected: + // Set the default value of the attribute + virtual bool setDefault(); + // Update the value if allowed + virtual CK_RV updateAttr(Token *token, bool isPrivate, CK_VOID_PTR pValue, CK_ULONG ulValueLen, int op); +}; + + #endif // !_SOFTHSM_V2_P11ATTRIBUTES_H diff --git a/SoftHSMv2/src/lib/P11Objects.cpp b/SoftHSMv2/src/lib/P11Objects.cpp index c58d4ec..3e663b2 100644 --- a/SoftHSMv2/src/lib/P11Objects.cpp +++ b/SoftHSMv2/src/lib/P11Objects.cpp @@ -1107,6 +1107,7 @@ bool P11RSAPrivateKeyObj::init(OSObject *inobject) P11Attribute* attrExponent1 = new P11AttrExponent1(osobject); P11Attribute* attrExponent2 = new P11AttrExponent2(osobject); P11Attribute* attrCoefficient = new P11AttrCoefficient(osobject); + P11Attribute* attrPrivateHandle = new P11AttrPrivateHandle(osobject); // Initialize the attributes if @@ -1118,6 +1119,7 @@ bool P11RSAPrivateKeyObj::init(OSObject *inobject) !attrPrime2->init() || !attrExponent1->init() || !attrExponent2->init() || + !attrPrivateHandle->init() || !attrCoefficient->init() ) { @@ -1130,6 +1132,7 @@ bool P11RSAPrivateKeyObj::init(OSObject *inobject) delete attrExponent1; delete attrExponent2; delete attrCoefficient; + delete attrPrivateHandle; return false; } @@ -1142,6 +1145,7 @@ bool P11RSAPrivateKeyObj::init(OSObject *inobject) attributes[attrExponent1->getType()] = attrExponent1; attributes[attrExponent2->getType()] = attrExponent2; attributes[attrCoefficient->getType()] = attrCoefficient; + attributes[attrPrivateHandle->getType()] = attrPrivateHandle; initialized = true; return true; @@ -1223,23 +1227,27 @@ bool P11ECPrivateKeyObj::init(OSObject *inobject) // Create attributes P11Attribute* attrEcParams = new P11AttrEcParams(osobject,P11Attribute::ck4|P11Attribute::ck6); P11Attribute* attrValue = new P11AttrValue(osobject,P11Attribute::ck1|P11Attribute::ck4|P11Attribute::ck6|P11Attribute::ck7); + P11Attribute* attrPrivateHandle = new P11AttrPrivateHandle(osobject); // Initialize the attributes if ( !attrEcParams->init() || + !attrPrivateHandle->init() || !attrValue->init() ) { ERROR_MSG("Could not initialize the attribute"); delete attrEcParams; delete attrValue; + delete attrPrivateHandle; return false; } // Add them to the map attributes[attrEcParams->getType()] = attrEcParams; attributes[attrValue->getType()] = attrValue; + attributes[attrPrivateHandle->getType()] = attrPrivateHandle; initialized = true; return true; diff --git a/SoftHSMv2/src/lib/SoftHSM.cpp b/SoftHSMv2/src/lib/SoftHSM.cpp index 214178f..acb90a3 100644 --- a/SoftHSMv2/src/lib/SoftHSM.cpp +++ b/SoftHSMv2/src/lib/SoftHSM.cpp @@ -103,37 +103,26 @@ std::auto_ptr SoftHSM::instance(NULL); #endif -static CK_RV Extract_key_handle(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, void *hwKeyHandle) -{ - CK_RV rv=CK_TRUE; - - // get value of the hw key handle - CK_ATTRIBUTE valAttrib[] = { - {CKA_PRIME_1, NULL_PTR, 0} - }; - // Get the length of the attribute first - rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE)); - if(rv != CKR_OK) - { - printf("Getting length of keyHandle with C_GetAttributeValue() API failed ! \n"); - return rv; - } - - valAttrib[0].pValue = (CK_VOID_PTR) malloc(valAttrib[0].ulValueLen); +static CK_RV Extract_key_handle(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, void *private_handle) +{ + CK_RV rv=CK_TRUE; - rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE)); + // get value of the wrapped data (ck) + CK_ATTRIBUTE valAttrib[] = { + {CKA_OS_PRIVATE_HANDLE, NULL_PTR, sizeof(CK_ULONG)} + }; - // Convert the keyHandle from string to CK_ULONG - sscanf((char*) valAttrib[0].pValue, "%lx", (CK_ULONG *) hwKeyHandle); - printf("Extract_key_handle:: hwKeyHandle: %lu \n", (CK_ULONG) hwKeyHandle); + *(CK_ULONG*)private_handle = 0; + valAttrib[0].pValue = private_handle; - if(!(valAttrib[0].pValue)) - { - free(valAttrib[0].pValue); - } + rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE)); + if (rv != CKR_OK) + { + LOG("C_GetAttributeValue() API failed ! %lx\n", rv); + } - return rv; + return rv; } static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object) @@ -4214,24 +4203,25 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan return CKR_MECHANISM_INVALID; #endif } - // Initialize signing if(isHWavailable) { // Extract HW key handle CK_ULONG hwKeyHandle = 0; - if(!Extract_key_handle (hSession, hKey, &hwKeyHandle)) + if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK) { LOG("ERROR in extracting key handle \n"); session->resetOp(); return CKR_GENERAL_ERROR; } LOG("Extracted key handle value: %lu \n", hwKeyHandle); + void *hwCryptoOpaque; - if(! HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen)) + if(HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen, &hwCryptoOpaque) != 0) { return CKR_MECHANISM_INVALID; } + session->setHwCryptoOpaque(hwCryptoOpaque); } else { @@ -4249,8 +4239,7 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan session->setAllowMultiPartOp(bAllowMultiPartOp); session->setAllowSinglePartOp(true); session->setPrivateKey(privateKey); - session->setKeyHandle(hKey); - + session->setKeyHandle(hKey); return CKR_OK; } @@ -4403,7 +4392,7 @@ static CK_RV AsymSignHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PT AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp(); AsymMech::Type mechanism = session->getMechanism(); PrivateKey* privateKey = session->getPrivateKey(); - CK_ULONG hwKeyHandle = 0; + CK_ULONG hwKeyHandle = 0; if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL) { session->resetOp(); @@ -4438,7 +4427,7 @@ static CK_RV AsymSignHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PT // Extract HW key handle CK_OBJECT_HANDLE hKey = session->getKeyHandle(); - if(!Extract_key_handle (hSession, hKey, &hwKeyHandle)) + if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK) { LOG("ERROR in extracting key handle \n"); session->resetOp(); @@ -4446,10 +4435,11 @@ static CK_RV AsymSignHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PT } LOG("Extracted key handle value: %lu \n", hwKeyHandle); + void *hwCryptoOpaque = session->getHwCryptoOpaque(); // Sign the data - if(!HwInfraSign((void *)&hwKeyHandle, mechanism, - pData, ulDataLen, - pSignature, (int *) pulSignatureLen)) + if(HwInfraSign((void *)&hwKeyHandle, mechanism, + pData, ulDataLen, hwCryptoOpaque, + pSignature, (int *) pulSignatureLen) != 0) { session->resetOp(); return CKR_GENERAL_ERROR; @@ -4559,6 +4549,60 @@ static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPart return CKR_OK; } +// AsymmetricAlgorithm version of C_SignUpdate +static CK_RV AsymSignUpdateHW( CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) +{ + AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp(); + if (asymCrypto == NULL || !session->getAllowMultiPartOp()) + { + session->resetOp(); + return CKR_OPERATION_NOT_INITIALIZED; + } + + // Check if re-authentication is required + if (session->getReAuthentication()) + { + session->resetOp(); + return CKR_USER_NOT_LOGGED_IN; + } + + // Get the part + ByteString part(pPart, ulPartLen); + +#if 0 + // Sign the data + if (!asymCrypto->signUpdate(part)) + { + session->resetOp(); + return CKR_GENERAL_ERROR; + } +#endif + AsymMech::Type mechanism = session->getMechanism(); + // Extract HW key handle + CK_ULONG hwKeyHandle = 0; + CK_OBJECT_HANDLE hKey = session->getKeyHandle(); + if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK) + { + LOG("ERROR in extracting key handle \n"); + session->resetOp(); + return CKR_GENERAL_ERROR; + } + + void *hwCryptoOpaque = session->getHwCryptoOpaque(); + // Sign the data + if(HwInfraSignUpdate((void *)&hwKeyHandle, mechanism, + pPart, ulPartLen, hwCryptoOpaque ) != 0) + { + session->resetOp(); + return CKR_GENERAL_ERROR; + } + + session->setAllowSinglePartOp(false); + return CKR_OK; +} + + + // Update a running signing operation with additional data CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { @@ -4577,7 +4621,17 @@ CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_UL if (session->getMacOp() != NULL) return MacSignUpdate(session, pPart, ulPartLen); else - return AsymSignUpdate(session, pPart, ulPartLen); + { + if(isHWavailable) + { + return AsymSignUpdateHW(hSession, session, pPart, ulPartLen); + } + else + { + + return AsymSignUpdate(session, pPart, ulPartLen); + } + } } // MacAlgorithm version of C_SignFinal @@ -4682,6 +4736,81 @@ static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PT return CKR_OK; } +// AsymmetricAlgorithm version of C_SignFinal +static CK_RV AsymSignFinalHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) +{ + AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp(); + PrivateKey* privateKey = session->getPrivateKey(); + if (asymCrypto == NULL || privateKey == NULL) + { + session->resetOp(); + return CKR_OPERATION_NOT_INITIALIZED; + } + + // Check if re-authentication is required + if (session->getReAuthentication()) + { + session->resetOp(); + return CKR_USER_NOT_LOGGED_IN; + } + + // Size of the signature + CK_ULONG size = privateKey->getOutputLength(); + if (pSignature == NULL_PTR) + { + *pulSignatureLen = size; + return CKR_OK; + } + + // Check buffer size + if (*pulSignatureLen < size) + { + *pulSignatureLen = size; + return CKR_BUFFER_TOO_SMALL; + } +#if 0 + // Get the signature + ByteString signature; + if (!asymCrypto->signFinal(signature)) + { + session->resetOp(); + return CKR_GENERAL_ERROR; + } +#endif + AsymMech::Type mechanism = session->getMechanism(); + // Extract HW key handle + CK_ULONG hwKeyHandle = 0; + CK_OBJECT_HANDLE hKey = session->getKeyHandle(); + if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK) + { + LOG("ERROR in extracting key handle \n"); + session->resetOp(); + return CKR_GENERAL_ERROR; + } + LOG("Extracted key handle value : 0x%lx \n", hwKeyHandle); + + void *hwCryptoOpaque = session->getHwCryptoOpaque(); + // Sign the data + if(HwInfraSignFinal((void *)&hwKeyHandle, mechanism, + hwCryptoOpaque, pSignature, (int *) pulSignatureLen) != 0 ) + { + session->resetOp(); + return CKR_GENERAL_ERROR; + } + // Check size + if (*pulSignatureLen != size) + { + ERROR_MSG("The size of the signature differs from the size of the mechanism"); + session->resetOp(); + return CKR_GENERAL_ERROR; + } + *pulSignatureLen = size; + + session->resetOp(); + return CKR_OK; +} + + // Finalise a running signing operation and return the signature CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { @@ -4700,7 +4829,15 @@ CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, C if (session->getMacOp() != NULL) return MacSignFinal(session, pSignature, pulSignatureLen); else - return AsymSignFinal(session, pSignature, pulSignatureLen); + if(isHWavailable) + { + return AsymSignFinalHW(hSession, session, pSignature, pulSignatureLen); + } + else + { + + return AsymSignFinal(session, pSignature, pulSignatureLen); + } } // Initialise a signing operation that allows recovery of the signed data diff --git a/SoftHSMv2/src/lib/object_store/DBObject.cpp b/SoftHSMv2/src/lib/object_store/DBObject.cpp index d2515bd..a55a32a 100644 --- a/SoftHSMv2/src/lib/object_store/DBObject.cpp +++ b/SoftHSMv2/src/lib/object_store/DBObject.cpp @@ -385,6 +385,7 @@ static bool isModifiable(CK_ATTRIBUTE_TYPE type) case CKA_OS_TOKENFLAGS: case CKA_OS_SOPIN: case CKA_OS_USERPIN: + case CKA_OS_PRIVATE_HANDLE: return true; default: return false; @@ -516,6 +517,7 @@ static AttributeKind attributeKind(CK_ATTRIBUTE_TYPE type) case CKA_OS_TOKENFLAGS: return akInteger; case CKA_OS_SOPIN: return akBinary; case CKA_OS_USERPIN: return akBinary; + case CKA_OS_PRIVATE_HANDLE: return akInteger; default: return akUnknown; } diff --git a/SoftHSMv2/src/lib/object_store/OSAttributes.h b/SoftHSMv2/src/lib/object_store/OSAttributes.h index dfc5869..176ca02 100644 --- a/SoftHSMv2/src/lib/object_store/OSAttributes.h +++ b/SoftHSMv2/src/lib/object_store/OSAttributes.h @@ -46,5 +46,7 @@ #define CKA_OS_SOPIN (CKA_VENDOR_SOFTHSM + 4) #define CKA_OS_USERPIN (CKA_VENDOR_SOFTHSM + 5) +#define CKA_OS_PRIVATE_HANDLE (CKA_VENDOR_SOFTHSM + 6) + #endif // !_SOFTHSM_V2_OSATTRIBUTES_H diff --git a/SoftHSMv2/src/lib/session_mgr/Session.cpp b/SoftHSMv2/src/lib/session_mgr/Session.cpp index 54c0ff7..67820ed 100644 --- a/SoftHSMv2/src/lib/session_mgr/Session.cpp +++ b/SoftHSMv2/src/lib/session_mgr/Session.cpp @@ -61,6 +61,7 @@ Session::Session(Slot* inSlot, bool inIsReadWrite, CK_VOID_PTR inPApplication, C // Storing Key handle in session hKey = CK_INVALID_HANDLE; + hwCryptoOpaque = NULL; } // Constructor @@ -91,6 +92,7 @@ Session::Session() // Storing Key handle in session hKey = CK_INVALID_HANDLE; + hwCryptoOpaque = NULL; } // Destructor @@ -471,3 +473,14 @@ SymmetricKey* Session::getSymmetricKey() { return symmetricKey; } + +void Session::setHwCryptoOpaque(void *inHwCryptoOpaque ) +{ + hwCryptoOpaque = inHwCryptoOpaque; +} + +void* Session::getHwCryptoOpaque() +{ + return hwCryptoOpaque; +} + diff --git a/SoftHSMv2/src/lib/session_mgr/Session.h b/SoftHSMv2/src/lib/session_mgr/Session.h index 128fb2b..39f19db 100644 --- a/SoftHSMv2/src/lib/session_mgr/Session.h +++ b/SoftHSMv2/src/lib/session_mgr/Session.h @@ -127,6 +127,9 @@ public: void setKeyHandle(CK_OBJECT_HANDLE inHKey); CK_OBJECT_HANDLE getKeyHandle(); + void setHwCryptoOpaque(void* inHwCryptoOpaque); + void *getHwCryptoOpaque(); + private: // Constructor Session(); @@ -174,6 +177,9 @@ private: // Symmetric Crypto SymmetricKey* symmetricKey; + // hw plugin specific data + void *hwCryptoOpaque; + // Storing Key handle in session CK_OBJECT_HANDLE hKey; }; -- cgit 1.2.3-korg