Adds the HardwareInfra layer in SoftHSM

This enables the support of multiple HSMs

Issue-ID: AAF-200
Change-Id: I825a72a0bf46827ff3be0c0311085cf970b970a6
Signed-off-by: Pramod <pramod.raghavendra.jayathirth@intel.com>
diff --git a/SoftHSMv2/configure.ac b/SoftHSMv2/configure.ac
index 216dd46..eb95bdd 100644
--- a/SoftHSMv2/configure.ac
+++ b/SoftHSMv2/configure.ac
@@ -211,6 +211,7 @@
 	src/lib/slot_mgr/test/Makefile
 	src/lib/handle_mgr/Makefile
 	src/lib/handle_mgr/test/Makefile
+	src/lib/HwInfra/Makefile
 	src/lib/test/Makefile
 	src/lib/test/softhsm2.conf
 	src/lib/test/softhsm2-alt.conf
diff --git a/SoftHSMv2/src/lib/HwInfra/HwInfra.c b/SoftHSMv2/src/lib/HwInfra/HwInfra.c
new file mode 100644
index 0000000..528097d
--- /dev/null
+++ b/SoftHSMv2/src/lib/HwInfra/HwInfra.c
@@ -0,0 +1,719 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <string.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#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.h b/SoftHSMv2/src/lib/HwInfra/HwInfra.h
new file mode 100644
index 0000000..a62bd7d
--- /dev/null
+++ b/SoftHSMv2/src/lib/HwInfra/HwInfra.h
@@ -0,0 +1,87 @@
+/* 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 <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hwpluginif.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#ifndef __SSHSM_HW_INFRA_UTIL_H__
+#define __SSHSM_HW_INFRA_UTIL_H__
+
+#define MAX_KEY_DIRS_SUPPORTED 64
+
+typedef struct hwpluginentries_s {
+   char so_full_path[256+1];
+   char activate_dir_full_path[256+1];
+   int num_key_dirs;
+   char key_dir_full_path[MAX_KEY_DIRS_SUPPORTED][256+1];
+}hwpluginentries_t;
+
+int prepareHWPlugin();
+int loadHWPlugin(char *parent_dir, char *pluginsubdir);
+int HwPlugin_Initiate_Activate_and_load_keys( hwpluginentries_t *);
+int load_hw_plugin_and_get_function_pointers(char *,
+              SSHSM_HW_FUNCTIONS_t *funcs);
+int init_hw_plugin(SSHSM_HW_FUNCTIONS_t *funcs);
+int activate_hw_plugin(hwpluginentries_t *entries, SSHSM_HW_FUNCTIONS_t *funcs);
+int load_keys_in_hw_plugin(hwpluginentries_t *entries,
+                   SSHSM_HW_FUNCTIONS_t *funcs);
+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 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);
+
+int HwInfraSignInit(void *keyHandle,  unsigned long mechanism,
+                 void* param, int paramLen);
+
+int HwInfraSign( void *keyHandle,  unsigned long mechanism,
+                 unsigned char *msg, int msg_len,
+                 unsigned char *outsig,  int *outsiglen);
+
+#define MAX_PARENT_PATH_NAME 256
+
+#define LOG printf
+#define SSHSM_HW_PLUGIN_ERROR_BASE (10000)
+
+#define ENVIRONMENT_TOO_LONG (01)
+#define PLUGIN_PATH_TOO_LONG (02)
+#define PLUGIN_PATH_OPEN_ERROR (03)
+#define INCOMPLETE_PLUGIN_DIR (04)
+#define ALLOCATION_ERROR (05)
+#define PLUGIN_DL_OPEN_ERROR (06)
+#define PLUGIN_DL_SYM_ERROR (07)
+#define PLUGIN_INIT_ERROR (10)
+
+#if defined(__cplusplus)
+}
+#endif
+
+
+#endif /* __SSHSM_HW_INFRA_UTIL_H__ */
+
+
diff --git a/SoftHSMv2/src/lib/HwInfra/Makefile.am b/SoftHSMv2/src/lib/HwInfra/Makefile.am
new file mode 100644
index 0000000..b327b15
--- /dev/null
+++ b/SoftHSMv2/src/lib/HwInfra/Makefile.am
@@ -0,0 +1,16 @@
+MAINTAINERCLEANFILES = 		$(srcdir)/Makefile.in
+
+AM_CPPFLAGS =			-I$(srcdir)/.. \
+				-I$(srcdir)/../common \
+				-I$(srcdir)/../crypto \
+				-I$(srcdir)/../data_mgr \
+				-I$(srcdir)/../object_store \
+				-I$(srcdir)/../pkcs11 \
+				-I$(srcdir)/../session_mgr
+
+noinst_LTLIBRARIES =		libsofthsm_hwinfra.la
+libsofthsm_hwinfra_la_SOURCES =	HwInfra.c
+
+SUBDIRS =
+
+EXTRA_DIST =			$(srcdir)/*.h
diff --git a/SoftHSMv2/src/lib/HwInfra/README b/SoftHSMv2/src/lib/HwInfra/README
new file mode 100755
index 0000000..ea301af
--- /dev/null
+++ b/SoftHSMv2/src/lib/HwInfra/README
@@ -0,0 +1,24 @@
+/* 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.
+*/
+
+
+#Commands to build stub plugin
+gcc -fPIC -c tpmplugin_stub.c
+ld -shared -o plugin.so tpmplugin_stub.o
+
+#Commands to build hwinfra
+gcc -o hwinfrautil hwinfrautil.c -ldl
+
+
diff --git a/SoftHSMv2/src/lib/HwInfra/hwpluginif.h b/SoftHSMv2/src/lib/HwInfra/hwpluginif.h
new file mode 100755
index 0000000..b078be3
--- /dev/null
+++ b/SoftHSMv2/src/lib/HwInfra/hwpluginif.h
@@ -0,0 +1,223 @@
+/* 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.
+*/
+
+#ifndef __SSHSM_HW_PLUGIN_IF_H__
+#define __SSHSM_HW_PLUGIN_IF_H__
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+#define MAX_ID_LENGTH (32)
+
+typedef struct buffer_info_s{
+       char id[MAX_ID_LENGTH+1];
+       int length_of_buffer;
+       unsigned char *buffer;
+    }buffer_info_t;
+
+/***
+ * Init Callback
+ * Description:
+ * This function is called by HWPluginInfra as part of C_Initialize to figure
+ * out whether there is any correspnding HW is present to use this plugin.
+ * In case of TPM2.0 Plugin,
+ *  it is expected that this function checks
+ *  whether the TPM2.0 is present or not, by checking the capabilities
+ *  using Tss2_Sys_GetCapability with TPM_CAP_TPM_PROPERTIES and
+ *  TPM_PT_MANUFACTURER property. If this function returns SUCCESS,
+ *  TPM plguin can assume that TPM2.0 is presenta nd return success
+ * In case of SGX Plugin: <To be filled>
+ * Parameters:
+ *    Inputs: None
+ *    OUtputs; None
+ *    Returns :  SUCCESS (if HW is present), FAILURE if HW is not present
+ *
+ ***/
+typedef int (*sshsm_hw_plugin_init)();
+
+/***
+ * UnInit Callback
+ * Description: This function is called by HWPluginInfra during C_Finalize().
+ * This functin is gives chance for any cleanup by plugins.
+ ***/
+typedef int (*sshsm_hw_plugin_uninit)();
+
+
+/***
+ * Activate Callback
+ * Description: This callback function is called by HWPluginInfra
+ * (as part of C_Intialize)  to activate the
+ * HW via HW plugin. SofHSM HWPluginInfra reads set of files required for
+ * activation (from
+ * activation directory) and passes them as buffers.
+ * HWPluginInfra reads the file in 'activate directory'
+ * as part of C_Initialize and passes the file content as is
+ * to the activate callback function.
+ * If there are two files, then num_buffers in in_info would be 2.
+ * 'id' is name of the file (May not be used by TPM plugin)
+ * 'length_of_buffer' is the valid length of the buffer.
+ * 'buffer' contains the file content.
+ * HWPluginInfra in SoftHSM allocates memory for this structure and internal
+ * buffers and it frees them up after this function returns. Hence,
+ * the plugin should not expect that these buffers are valid after the call
+ * is returned.
+ *
+ * In case of TPM Plugin:
+ *    It is expected that activate directory has a file with SRK Handle
+ *    saved in it. Note that SRK is saved in TPM memory (persistence)
+ *    Actiate function of TPM plugin is called with SRK handle.
+ *
+ ***/
+#define MAX_BUFFER_SEGMENTS 8
+typedef struct sshsm_hw_plugin_activate_in_info_s {
+    int num_buffers;
+    buffer_info_t *buffer_info[MAX_BUFFER_SEGMENTS];
+}SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t;
+
+
+typedef int (*sshsm_hw_plugin_activate)(
+           SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *activate_in_info
+        );
+
+
+
+/***
+ * Load Key  Callback
+ * Description: This callback function is called by SoftHSM HWPluginInfra
+ * to load private keys into the HW using HW plugin.
+ * Each HW plugin expects the keys to be specific to its HW.
+ * Since SoftHSM HWPluginInfra is expected to be generic, the design
+ * chosen is that HWPluginInfra reads key content from files and pass
+ * that information to HW Plugins via this function pointer.
+ * Yet times, Key information for HW Plugins is exposed as multiple files.
+ * Hence, HWPluginInfra reads multiple files for each key.  Since, there
+ * could be multiple keys, each set of files that correspond to one key
+ * is expected to have same file name, but with different extensions. Since
+ * the directory holding these file may also need to have other files
+ * related to key, but for PKCS11, it is expected that all HWPlugin related
+ * files should have its name start with HW.
+ *
+ * HWPluginInfra calls this callback function as many timne as number of
+ * distinct keys.  For each distinct key, it reads the HW tagged files, loads
+ * them into the buffer pointers and calls the HW Plugin -loadkey- function.
+ * HWPluginInfra also stores the any returned buffers into the SoftHSM key
+ * object.
+ *
+ * In case of TPM Plugin, it does following:
+ *
+ * -- Gets the buffers in in_info structure.
+ *    --- Typically, there are two buffers in TPM understandable way
+ *    - public & private key portion
+ *    --- From global variables, it knows SRKHandle, SAPI context.
+ *    --- Using Tss2_Sys_Load(), it loads the key.
+ *
+ * -- In both cases, it also expected to return KeyHandle, which is
+ *    keyObjectHandle in case of TPM.
+ *
+ *
+ ***/
+
+/***
+typedef struct sshsm_hw_plugin_load_key_in_info_s {
+    int num_buffers;
+    buffer_info_t buffer_info[];
+}SSHSM_HW_PLUGIN_LOAD_KEY_IN_INFO_t;
+***/
+
+
+typedef int (*sshsm_hw_plugin_load_key)(
+           SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *loadkey_in_info,
+           void **keyHandle
+        );
+
+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
+ */
+
+typedef int (*sshsm_hw_plugin_rsa_sign_init)(
+         void *keyHandle,
+         unsigned long mechanism,
+         void *param,
+         int len
+        );
+
+
+
+/***
+ * Callback:  RSA Sign Init
+ * Description: This is called by HWPluginInfra as part of C_Sign function
+ * for RSA keys. HWPluginInfra get the keyHandle from the key object.
+ *
+ * In case of TPM plugin, it does following:
+ * -- TSS2_Sys_Sing function is called.
+ *
+ *
+ */
+
+typedef int (*sshsm_hw_plugin_rsa_sign)(
+         void *keyHandle,
+         unsigned long mechanism,
+         unsigned char *msg,
+         int msg_len,
+         unsigned char *outsig,
+         int *outsiglen
+        );
+
+/***
+ * Function Name: sshsm_hw_plugin_get_plugin_functions
+ * Descrpiton:  Every HW plugin is expected to define this function.
+ * This function is expected to return its function as pointers to the
+ * caller.
+ * SoftHSM calls this function after loading the hw plugin .SO file.
+ * SoftHSM calls this function as part of C_initialize.
+ * Arugments:
+ *  Outputs: funcs
+ *  Inputs: None
+ *  Return value:  SUCCESS or FAILURE
+ *
+ ***/
+
+typedef struct sshsm_hw_functions_s
+{
+    sshsm_hw_plugin_init  xxx_init;
+    sshsm_hw_plugin_uninit  xxx_uninit;
+    sshsm_hw_plugin_activate xxx_activate;
+    sshsm_hw_plugin_load_key xxx_load_key;
+    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_FUNCTIONS_t;
+
+
+int sshsm_hw_plugin_get_plugin_functions(SSHSM_HW_FUNCTIONS_t *funcs);
+
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif
+
diff --git a/SoftHSMv2/src/lib/Makefile.am b/SoftHSMv2/src/lib/Makefile.am
index c579d62..eac1704 100644
--- a/SoftHSMv2/src/lib/Makefile.am
+++ b/SoftHSMv2/src/lib/Makefile.am
@@ -8,6 +8,7 @@
 				-I$(srcdir)/pkcs11 \
 				-I$(srcdir)/session_mgr \
 				-I$(srcdir)/slot_mgr \
+				-I$(srcdir)/HwInfra \
 				@CRYPTO_INCLUDES@
 
 lib_LTLIBRARIES =		libsofthsm2.la
@@ -23,7 +24,8 @@
 				handle_mgr/libsofthsm_handlemgr.la \
 				object_store/libsofthsm_objectstore.la \
 				session_mgr/libsofthsm_sessionmgr.la \
-				slot_mgr/libsofthsm_slotmgr.la
+				slot_mgr/libsofthsm_slotmgr.la \
+				HwInfra/libsofthsm_hwinfra.la
 libsofthsm2_la_LDFLAGS =	-version-info @VERSION_INFO@ \
 				-avoid-version -module
 
@@ -42,8 +44,9 @@
 				object_store \
 				session_mgr \
 				slot_mgr \
+				HwInfra \
 				handle_mgr \
 				test
 
 EXTRA_DIST =			$(srcdir)/*.h \
-				$(srcdir)/pkcs11/*.h 
+				$(srcdir)/pkcs11/*.h
diff --git a/SoftHSMv2/src/lib/SoftHSM.cpp b/SoftHSMv2/src/lib/SoftHSM.cpp
index 7a23a8a..214178f 100644
--- a/SoftHSMv2/src/lib/SoftHSM.cpp
+++ b/SoftHSMv2/src/lib/SoftHSM.cpp
@@ -67,6 +67,8 @@
 #include "P11Objects.h"
 #include "odd.h"
 
+#include "HwInfra.h"
+
 #if defined(WITH_OPENSSL)
 #include "OSSLCryptoFactory.h"
 #else
@@ -101,6 +103,39 @@
 
 #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);
+
+  rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE));
+
+  // 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);
+
+  if(!(valAttrib[0].pValue))
+  {
+    free(valAttrib[0].pValue);
+  }
+
+  return rv;
+}
+
 static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
 {
 	switch(objClass) {
@@ -342,6 +377,7 @@
 	slotManager = NULL;
 	sessionManager = NULL;
 	handleManager = NULL;
+	isHWavailable = false;
 }
 
 // Destructor
@@ -518,6 +554,17 @@
 	// Set the state to initialised
 	isInitialised = true;
 
+    if(prepareHWPlugin())
+    {
+       printf("HW plugin NOT available to use ! \n");
+       isHWavailable = false;
+    }
+    else
+    {
+       printf("HW plugin available and initialized ! \n");
+       isHWavailable = true;
+   }
+
 	return CKR_OK;
 }
 
@@ -4168,20 +4215,33 @@
 #endif
         }
 
-	// Initialize signing
-	if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
-	{
-		asymCrypto->recyclePrivateKey(privateKey);
-		CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
-		return CKR_MECHANISM_INVALID;
-	}
+    // Initialize signing
+    if(isHWavailable)
+    {
+        // Extract HW key handle
+        CK_ULONG hwKeyHandle = 0;
+        if(!Extract_key_handle (hSession, hKey, &hwKeyHandle))
+        {
+            LOG("ERROR in extracting key handle \n");
+            session->resetOp();
+            return CKR_GENERAL_ERROR;
+        }
+        LOG("Extracted key handle value: %lu \n", hwKeyHandle);
 
-	// Check if re-authentication is required
-	if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
-	{
-		session->setReAuthentication(true);
-	}
-
+        if(! HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen))
+        {
+            return CKR_MECHANISM_INVALID;
+        }
+    }
+    else
+    {
+        if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
+        {
+            asymCrypto->recyclePrivateKey(privateKey);
+            CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
+            return CKR_MECHANISM_INVALID;
+        }
+    }
 	session->setOpType(SESSION_OP_SIGN);
 	session->setAsymmetricCryptoOp(asymCrypto);
 	session->setMechanism(mechanism);
@@ -4189,6 +4249,7 @@
 	session->setAllowMultiPartOp(bAllowMultiPartOp);
 	session->setAllowSinglePartOp(true);
 	session->setPrivateKey(privateKey);
+    session->setKeyHandle(hKey);
 
 	return CKR_OK;
 }
@@ -4336,6 +4397,79 @@
 	return CKR_OK;
 }
 
+// AsymmetricAlgorithm version of C_Sign
+static CK_RV AsymSignHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
+{
+	AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
+	AsymMech::Type mechanism = session->getMechanism();
+	PrivateKey* privateKey = session->getPrivateKey();
+    CK_ULONG hwKeyHandle = 0;
+	if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
+	{
+		session->resetOp();
+		return CKR_OPERATION_NOT_INITIALIZED;
+	}
+
+	// Size of the signature
+	CK_ULONG size = privateKey->getOutputLength();
+	if (pSignature == NULL_PTR)
+	{
+		*pulSignatureLen = size;
+		return CKR_OK;
+	}
+
+	// Check buffer sizeq
+	if (*pulSignatureLen < size)
+	{
+		*pulSignatureLen = size;
+		return CKR_BUFFER_TOO_SMALL;
+	}
+
+	// Get the data
+	ByteString data;
+
+	// We must allow input length <= k and therfore need to prepend the data with zeroes.
+	if (mechanism == AsymMech::RSA) {
+		data.wipe(size-ulDataLen);
+	}
+
+	data += ByteString(pData, ulDataLen);
+	ByteString signature;
+
+	// Extract HW key handle
+    CK_OBJECT_HANDLE hKey = session->getKeyHandle();
+    if(!Extract_key_handle (hSession, hKey, &hwKeyHandle))
+    {
+        LOG("ERROR in extracting key handle \n");
+		session->resetOp();
+		return CKR_GENERAL_ERROR;
+    }
+    LOG("Extracted key handle value: %lu \n", hwKeyHandle);
+
+	// Sign the data
+    if(!HwInfraSign((void *)&hwKeyHandle, mechanism,
+                 pData, ulDataLen,
+                 pSignature, (int *) pulSignatureLen))
+    {
+		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;
+	}
+
+
+	session->resetOp();
+	return CKR_OK;
+}
+
+
+
 // Sign the data in a single pass operation
 CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
 {
@@ -4356,8 +4490,18 @@
 		return MacSign(session, pData, ulDataLen,
 			       pSignature, pulSignatureLen);
 	else
-		return AsymSign(session, pData, ulDataLen,
-				pSignature, pulSignatureLen);
+    {
+        if(isHWavailable)
+        {
+		    return AsymSignHW(hSession, session, pData, ulDataLen,
+			    	pSignature, pulSignatureLen);
+        }
+        else
+        {
+		    return AsymSign(session, pData, ulDataLen,
+			    	pSignature, pulSignatureLen);
+        }
+    }
 }
 
 // MacAlgorithm version of C_SignUpdate
diff --git a/SoftHSMv2/src/lib/SoftHSM.h b/SoftHSMv2/src/lib/SoftHSM.h
index 70d497a..323f3a5 100644
--- a/SoftHSMv2/src/lib/SoftHSM.h
+++ b/SoftHSMv2/src/lib/SoftHSM.h
@@ -184,6 +184,7 @@
 	// Is the SoftHSM PKCS #11 library initialised?
 	bool isInitialised;
 	bool isRemovable;
+	bool isHWavailable;
 
 	SessionObjectStore* sessionObjectStore;
 	ObjectStore* objectStore;
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.cpp b/SoftHSMv2/src/lib/session_mgr/Session.cpp
index 5db36fd..54c0ff7 100644
--- a/SoftHSMv2/src/lib/session_mgr/Session.cpp
+++ b/SoftHSMv2/src/lib/session_mgr/Session.cpp
@@ -58,6 +58,9 @@
 	symmetricKey = NULL;
 	param = NULL;
 	paramLen = 0;
+
+	// Storing Key handle in session
+	hKey = CK_INVALID_HANDLE;
 }
 
 // Constructor
@@ -85,6 +88,9 @@
 	symmetricKey = NULL;
 	param = NULL;
 	paramLen = 0;
+
+    // Storing Key handle in session
+    hKey = CK_INVALID_HANDLE;
 }
 
 // Destructor
@@ -93,6 +99,19 @@
 	resetOp();
 }
 
+void Session::setKeyHandle(CK_OBJECT_HANDLE inHKey)
+{
+    //store the key hanldle for subsequent use
+    hKey = inHKey;
+}
+
+
+CK_OBJECT_HANDLE Session::getKeyHandle()
+{
+    //return the Key handle for subsequent use
+    return hKey;
+}
+
 // Get session info
 CK_RV Session::getInfo(CK_SESSION_INFO_PTR pInfo)
 {
diff --git a/SoftHSMv2/src/lib/session_mgr/Session.h b/SoftHSMv2/src/lib/session_mgr/Session.h
index 142aaa5..128fb2b 100644
--- a/SoftHSMv2/src/lib/session_mgr/Session.h
+++ b/SoftHSMv2/src/lib/session_mgr/Session.h
@@ -124,6 +124,9 @@
 	void setSymmetricKey(SymmetricKey* inSymmetricKey);
 	SymmetricKey* getSymmetricKey();
 
+	void setKeyHandle(CK_OBJECT_HANDLE inHKey);
+	CK_OBJECT_HANDLE getKeyHandle();
+
 private:
 	// Constructor
 	Session();
@@ -170,6 +173,9 @@
 
 	// Symmetric Crypto
 	SymmetricKey* symmetricKey;
+
+    // Storing Key handle in session
+    CK_OBJECT_HANDLE hKey;
 };
 
 #endif // !_SOFTHSM_V2_SESSION_H