diff options
22 files changed, 775 insertions, 150 deletions
diff --git a/SoftHSMv2/src/lib/HwInfra/HwInfra.c b/SoftHSMv2/src/lib/HwInfra/HwInfra.cpp index 528097d..557630b 100644 --- a/SoftHSMv2/src/lib/HwInfra/HwInfra.c +++ b/SoftHSMv2/src/lib/HwInfra/HwInfra.cpp @@ -24,7 +24,7 @@ #include <unistd.h> #include "HwInfra.h" #include "hwpluginif.h" - +#include "OSAttributes.h" #include "cryptoki.h" char hw_plugins_parent_dir[MAX_PARENT_PATH_NAME+1] = ""; @@ -32,7 +32,6 @@ 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 @@ -138,7 +137,7 @@ int loadHWPlugin(char *parent_dir, char *pluginsubdir) dirhandle = opendir(fullpath); - entries = malloc(sizeof(hwpluginentries_t)); + entries = (hwpluginentries_t*)malloc(sizeof(hwpluginentries_t)); if (entries == NULL ) { LOG("Could not allocate entries \n"); @@ -282,7 +281,7 @@ int load_hw_plugin_and_get_function_pointers(char *so_path, } functogetpluginfuncs = NULL; - functogetpluginfuncs = dlsym(g_dl_handle, + functogetpluginfuncs = (int (*)(SSHSM_HW_FUNCTIONS_t *)) dlsym(g_dl_handle, "sshsm_hw_plugin_get_plugin_functions"); if (functogetpluginfuncs == NULL) @@ -342,7 +341,6 @@ int activate_hw_plugin(hwpluginentries_t *entries, SSHSM_HW_FUNCTIONS_t *funcs) return(ret_val); } - int load_keys_in_hw_plugin(hwpluginentries_t *entries, SSHSM_HW_FUNCTIONS_t *funcs) { @@ -354,6 +352,7 @@ int load_keys_in_hw_plugin(hwpluginentries_t *entries, //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 @@ -370,19 +369,27 @@ int load_keys_in_hw_plugin(hwpluginentries_t *entries, if(ret_val == 0) { - ret_val = (funcs->xxx_load_key)(&comp_buffers, &key_handle); + 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 */ - ret_val = program_pkcs11_info(entries->key_dir_full_path[ii], &key_handle); + 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(0); + return(ret_val); } int get_all_file_contents(char *dirpath, char starting_char, @@ -410,7 +417,7 @@ int get_all_file_contents(char *dirpath, char starting_char, if ((entry->d_type == DT_REG) && (entry->d_name[0] == starting_char)) { - buffer = malloc(sizeof(buffer_info_t)); + buffer = (buffer_info_t*) malloc(sizeof(buffer_info_t)); if (buffer == NULL ) { LOG("Could not allocate entries \n"); @@ -431,7 +438,7 @@ int get_all_file_contents(char *dirpath, char starting_char, strcpy(fullpath,dirpath); strcat(fullpath, entry->d_name); stat(fullpath, &st); - buffer->buffer = malloc(st.st_size); + buffer->buffer = (unsigned char*) malloc(st.st_size); if(buffer->buffer == NULL) { LOG("Could not allocate entries \n"); @@ -489,7 +496,8 @@ 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 *import_public_key) { DIR *dirhandle; struct dirent *entry; @@ -572,7 +580,7 @@ int program_pkcs11_info (char *dirpath, void *key_handle) /** Program key in SoftHSM **/ ret_val = PrepareKeyInSoftHSM(slot_id, upin, upin_len, keyid, - key_id_len, key_label, key_handle); + key_id_len, key_label, key_handle, import_public_key); break; } @@ -584,6 +592,28 @@ int program_pkcs11_info (char *dirpath, void *key_handle) } +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 @@ -601,7 +631,8 @@ 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) + 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; @@ -611,16 +642,15 @@ int PrepareKeyInSoftHSM(unsigned int slot_id, 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)); + printf("Input Key handle is NULL ! \n"); + return (SSHSM_HW_PLUGIN_ERROR_BASE + INVALID_KEY_ERROR); } - else + if (import_public_key->modulus == NULL || + import_public_key->exponent == NULL) { - printf("Input Key handle is NULL ! \n"); + return (SSHSM_HW_PLUGIN_ERROR_BASE + INVALID_KEY_ERROR); } /** For creating the key object, first the session needs to be opened @@ -651,39 +681,64 @@ int PrepareKeyInSoftHSM(unsigned int slot_id, 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, key_id, (CK_ULONG)key_id_len }, + { 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, &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 - ***/ + { 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) } }; - ret_val = C_CreateObject(hSession, keyTemplate, + + 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", + 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]); + 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); @@ -704,16 +759,56 @@ int PrepareKeyInSoftHSM(unsigned int slot_id, } int HwInfraSignInit(void *keyHandle, unsigned long mechanism, - void* param, int paramLen) + void* param, int paramLen, void **hwCryptoOpaque) { - return ( g_pluginfuncs.xxx_rsa_sign_init(keyHandle, mechanism, param, paramLen) ); + 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, +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, - outsig, outsiglen) ); + 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> 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; }; diff --git a/TPM2-Plugin/bootstrap b/TPM2-Plugin/bootstrap index 2a09c33..2a09c33 100755..100644 --- a/TPM2-Plugin/bootstrap +++ b/TPM2-Plugin/bootstrap diff --git a/TPM2-Plugin/lib/include/hwpluginif.h b/TPM2-Plugin/lib/include/hwpluginif.h index d016e37..aa40411 100644 --- a/TPM2-Plugin/lib/include/hwpluginif.h +++ b/TPM2-Plugin/lib/include/hwpluginif.h @@ -143,7 +143,7 @@ typedef int (*sshsm_hw_plugin_load_key)( ); typedef int (*sshsm_hw_plugin_unload_key)( - void **keyHandle + void **keyHandle ); /*** @@ -156,7 +156,8 @@ typedef int (*sshsm_hw_plugin_rsa_sign_init)( void *keyHandle, unsigned long mechanism, void *param, - int len + int len, + void **plugin_data_ref ); /*** @@ -175,10 +176,37 @@ typedef int (*sshsm_hw_plugin_rsa_sign)( unsigned long mechanism, unsigned char *msg, int msg_len, + void *plugin_data_ref, unsigned char *outsig, int *outsiglen ); +typedef int (*sshsm_hw_plugin_rsa_sign_update)( + void *keyHandle, + unsigned long mechnaism, + unsigned char *msg, + int msg_len, + void *plugin_data_ref + ); + +typedef int (*sshsm_hw_plugin_rsa_sign_final)( + void *keyHandle, + unsigned long mechnaism, + void *plugin_data_ref, + 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 mechnaism, + void *plugin_data_ref + ); + /*** * Function Name: sshsm_hw_plugin_get_plugin_functions * Descrpiton: Every HW plugin is expected to define this function. @@ -202,6 +230,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; int sshsm_hw_plugin_get_plugin_functions(SSHSM_HW_FUNCTIONS_t *funcs); diff --git a/TPM2-Plugin/lib/include/tpm2_plugin_api.h b/TPM2-Plugin/lib/include/tpm2_plugin_api.h index f45c0bd..d96d2f9 100644 --- a/TPM2-Plugin/lib/include/tpm2_plugin_api.h +++ b/TPM2-Plugin/lib/include/tpm2_plugin_api.h @@ -141,6 +141,15 @@ typedef struct { int version; } common_opts_t; +#define MAX_DATA_SIGNUPDATE 0x2000 +#define MAX_SESSIONS 0x1000 + +typedef struct concatenate_data_signupdate { + unsigned long int session_handle; + unsigned char data_signupdate[MAX_DATA_SIGNUPDATE]; + int data_length; +}CONCATENATE_DATA_SIGNUPDATE_t; + int tpm2_plugin_init(); int tpm2_plugin_uninit(); int tpm2_plugin_activate(SSHSM_HW_PLUGIN_ACTIVATE_LOAD_IN_INFO_t *activate_in_info); @@ -150,43 +159,49 @@ int tpm2_plugin_load_key( SSHSM_HW_PLUGIN_IMPORT_PUBLIC_KEY_INFO_t *importkey_info ); -int tpm2_rsa_create_object( - unsigned long appHandle, - //DhsmWPKRSAFormat* wpk, - void *wpk, - unsigned char* swk, - int swk_len, - unsigned char* iv, - int iv_len, - int tag_len, - void **cb_object); - -int tpm2_rsa_delete_object( - void *cb_object); - int tpm2_plugin_rsa_sign_init( void *keyHandle, unsigned long mechanism, void *param, - int len); + int len, + void **plugin_data_ref + ); int tpm2_plugin_rsa_sign( void *keyHandle, unsigned long mechanism, unsigned char *msg, int msg_len, + void *plugin_data_ref, unsigned char *sig, - int *sig_len); + int *sig_len + ); + +int tpm2_plugin_rsa_sign_update( + void *keyHandle, + unsigned long mechnaism, + unsigned char *msg, + int msg_len, + void *plugin_data_ref + ); + +int tpm2_plugin_rsa_sign_final( + void *keyHandle, + unsigned long mechnaism, + void *plugin_data_ref, + 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. +***/ -int tpm2_import_object( - unsigned long appHandle, - unsigned char* tlvbuffer, - int buflen, - unsigned char* iv, - int iv_len, - unsigned char* tpm_pwd, - int tpm_pwd_len); +typedef int (*sshsm_hw_plugin_rsa_sign_cleanup)( + void *keyHandle, + unsigned long mechnaism, + void *plugin_data_ref + ); #ifdef __cplusplus diff --git a/TPM2-Plugin/lib/tpm2_plugin_api.c b/TPM2-Plugin/lib/tpm2_plugin_api.c index 356ce7b..75e4fc1 100644 --- a/TPM2-Plugin/lib/tpm2_plugin_api.c +++ b/TPM2-Plugin/lib/tpm2_plugin_api.c @@ -134,7 +134,6 @@ tcti_device_init (char const *device_file) } #endif - #ifdef HAVE_TCTI_SOCK TSS2_TCTI_CONTEXT* tcti_socket_init (char const *address, uint16_t port) { @@ -384,11 +383,18 @@ int read_public(TSS2_SYS_CONTEXT *sapi_context, importkey_info->modulus_size = public.t.publicArea.unique.rsa.t.size; printf("importkey_info->modulus_size = %ld \n", importkey_info->modulus_size); - memcpy(importkey_info->modulus, &public.t.publicArea.unique.rsa.t.buffer, importkey_info->modulus_size); + importkey_info->modulus = (unsigned char *) malloc(importkey_info->modulus_size); + if (importkey_info->modulus != NULL) { + memcpy(importkey_info->modulus, &public.t.publicArea.unique.rsa.t.buffer, importkey_info->modulus_size); + } importkey_info->exponent_size = sizeof(public.t.publicArea.parameters.rsaDetail.exponent); printf("importkey_info->exponent_size = %ld \n", importkey_info->exponent_size); - memcpy(importkey_info->exponent, &public.t.publicArea.parameters.rsaDetail.exponent, importkey_info->exponent_size); + importkey_info->exponent = (unsigned char *) malloc(importkey_info->exponent_size); + if (importkey_info->exponent != NULL) { + memcpy(importkey_info->exponent, &public.t.publicArea.parameters.rsaDetail.exponent, importkey_info->exponent_size); + } + //*importkey_info->exponent = public.t.publicArea.parameters.rsaDetail.exponent; return 0; @@ -484,17 +490,65 @@ struct tpm_sign_ctx { TSS2_SYS_CONTEXT *sapi_context; }; +//create a table to consolidate all parts of data from multiple SignUpdate from sessions +CONCATENATE_DATA_SIGNUPDATE_t data_signupdate_session[MAX_SESSIONS]; +unsigned long sign_sequence_id = 0; int tpm2_plugin_rsa_sign_init( void *keyHandle, unsigned long mechanism, void *param, - int len) + int len, + void **plugin_data_ref + ) { - printf("rsa_sign_init API mechanism is %lx \n", mechanism); + printf("rsa_sign_init API mechanism is %ld \n", mechanism); + printf("rsa_sign_init API len is %d \n", len); + int i, j; + + sign_sequence_id++; + unsigned long hSession = sign_sequence_id; + + for (i = 0; i < MAX_SESSIONS; i++){ + if (data_signupdate_session[i].session_handle == 0){ + data_signupdate_session[i].session_handle = hSession; + for (j = 0; j < MAX_DATA_SIGNUPDATE; j++ ) + data_signupdate_session[i].data_signupdate[j] = 0; + data_signupdate_session[i].data_length = 0; + } + } + *plugin_data_ref = (void *)hSession; + printf("rsa_sign_init API done for tpm2_plugin... \n"); return 0; } +/** 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. +***/ + +int tpm2_plugin_rsa_sign_cleanup( + void *keyHandle, + unsigned long mechnaism, + void *plugin_data_ref + ) +{ + int i, j; + unsigned long hSession = (unsigned long)plugin_data_ref; + for (i = 0; i < MAX_SESSIONS; i++) { + if (data_signupdate_session[i].session_handle == hSession){ + data_signupdate_session[i].session_handle = 0; + for (j =0; j < MAX_DATA_SIGNUPDATE; j++ ) + data_signupdate_session[i].data_signupdate[j] =0; + data_signupdate_session[i].data_length = 0; + } + } + + if (sign_sequence_id>0xfffffffe) + sign_sequence_id =0; + return 0; +} + + UINT32 tpm_hash(TSS2_SYS_CONTEXT *sapi_context, TPMI_ALG_HASH hashAlg, UINT16 size, BYTE *data, TPM2B_DIGEST *result) { TPM2B_MAX_BUFFER dataSizedBuffer; @@ -563,8 +617,10 @@ int tpm_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, BYTE *buffer, if (length <= MAX_DIGEST_BUFFER) { if (tpm_hash(sapi_context, halg, length, buffer, - result) == TPM_RC_SUCCESS) + result) == TPM_RC_SUCCESS){ + printf("Single hash result size: %d\n", result->t.size); return 0; + } else return -1; } @@ -588,6 +644,7 @@ int tpm_hash_compute_data(TSS2_SYS_CONTEXT *sapi_context, BYTE *buffer, TPM_RC rval = hash_sequence_ex(sapi_context, halg, numBuffers, bufferList, result); free(bufferList); + printf("Sequence hash result size: %d\n", result->t.size); return rval == TPM_RC_SUCCESS ? 0 : -3; } @@ -654,12 +711,10 @@ static bool set_scheme(TSS2_SYS_CONTEXT *sapi_context, TPMI_DH_OBJECT keyHandle, return true; } -static bool sign_and_save(tpm_sign_ctx *ctx, unsigned char *sig, int *sig_len) { +static bool sign_and_save(tpm_sign_ctx *ctx, TPMT_SIGNATURE *sig) { TPM2B_DIGEST digest = TPM2B_TYPE_INIT(TPM2B_DIGEST, buffer); TPMT_SIG_SCHEME in_scheme; - TPMT_SIGNATURE signature; - int signature_len; TSS2_SYS_CMD_AUTHS sessions_data; TPMS_AUTH_RESPONSE session_data_out; TSS2_SYS_RSP_AUTHS sessions_data_out; @@ -679,6 +734,8 @@ static bool sign_and_save(tpm_sign_ctx *ctx, unsigned char *sig, int *sig_len) return false; } + printf("Compute message hash digest size : %d \n", digest.t.size); + bool result = set_scheme(ctx->sapi_context, ctx->keyHandle, ctx->halg, &in_scheme); if (!result) { return false; @@ -686,17 +743,14 @@ static bool sign_and_save(tpm_sign_ctx *ctx, unsigned char *sig, int *sig_len) TPM_RC rval = Tss2_Sys_Sign(ctx->sapi_context, ctx->keyHandle, &sessions_data, &digest, &in_scheme, - &ctx->validation, &signature, + &ctx->validation, sig, &sessions_data_out); if (rval != TPM_RC_SUCCESS) { printf("Sys_Sign failed, error code: 0x%x", rval); return false; } - signature_len = sizeof(signature); - sig_len = &signature_len; - sig = (unsigned char *)&signature; - + return true; } @@ -705,11 +759,13 @@ int tpm2_plugin_rsa_sign( unsigned long mechanism, unsigned char *msg, int msg_len, + void *plugin_data_ref, unsigned char *sig, int *sig_len) { TPM_RC rval; common_opts_t opts = COMMON_OPTS_INITIALIZER; + TPMT_SIGNATURE signature; TSS2_TCTI_CONTEXT *tcti_ctx; tcti_ctx = tcti_init_from_options(&opts); if (tcti_ctx == NULL) @@ -732,12 +788,15 @@ int tpm2_plugin_rsa_sign( .validation = { 0 }, .sapi_context = sapi_context }; - + printf("rsa_sign API mechanism is %lx \n", mechanism); ctx.sessionData.sessionHandle = TPM_RS_PW; ctx.validation.tag = TPM_ST_HASHCHECK; ctx.validation.hierarchy = TPM_RH_NULL; - ctx.halg = TPM_ALG_SHA256; + if (mechanism == 7) + ctx.halg = TPM_ALG_SHA256; + else + printf("mechanism not supported! \n"); ctx.keyHandle = *(TPMI_DH_OBJECT *)keyHandle; rval = Tss2_Sys_ContextLoad(ctx.sapi_context, &loaded_key_context, &ctx.keyHandle); @@ -748,11 +807,15 @@ int tpm2_plugin_rsa_sign( ctx.length = msg_len; ctx.msg = msg; - if (!sign_and_save(&ctx, sig, sig_len)){ + if (!sign_and_save(&ctx, &signature)){ printf("RSA sign failed\n"); goto out; } + *sig_len = (int)signature.signature.rsassa.sig.t.size; + printf("signature length: %d \n", *sig_len); + memcpy(sig, signature.signature.rsassa.sig.t.buffer, *sig_len); + printf("signature buffer size: %ld \n", sizeof(signature.signature.rsassa.sig.t.buffer)); printf("RSA sign API successful in TPM plugin ! \n"); out: @@ -762,4 +825,50 @@ out: } +int tpm2_plugin_rsa_sign_update( + void *keyHandle, + unsigned long mechanism, + unsigned char *msg, + int msg_len, + void *plugin_data_ref + ) +{ + int i, j, n; + unsigned long hSession = (unsigned long)plugin_data_ref; + for (i = 0; i < MAX_SESSIONS; i++){ + if (data_signupdate_session[i].session_handle == hSession){ + n = data_signupdate_session[i].data_length; + for (j =0; j < msg_len; j++ ) + data_signupdate_session[i].data_signupdate[n + j] = msg[j]; + data_signupdate_session[i].data_length += msg_len; + return 0; + } + } + return -1; +} + +int tpm2_plugin_rsa_sign_final( + void *keyHandle, + unsigned long mechanism, + void *plugin_data_ref, + unsigned char *outsig, + int *outsiglen + ) +{ + int i, j; + unsigned long hSession = (unsigned long)plugin_data_ref; + unsigned char *msg; + int msg_len; + for (i = 0; i < MAX_SESSIONS; i++){ + if (data_signupdate_session[i].session_handle == hSession){ + msg = data_signupdate_session[i].data_signupdate; + msg_len = data_signupdate_session[i].data_length; + tpm2_plugin_rsa_sign(keyHandle, mechanism, msg, msg_len, plugin_data_ref, outsig, outsiglen); + tpm2_plugin_rsa_sign_cleanup(keyHandle, mechanism, plugin_data_ref); + return 0; + } + } + + return -1; +} diff --git a/TPM2-Plugin/lib/tpm2_plugin_init.c b/TPM2-Plugin/lib/tpm2_plugin_init.c index b221bd2..ef32330 100644 --- a/TPM2-Plugin/lib/tpm2_plugin_init.c +++ b/TPM2-Plugin/lib/tpm2_plugin_init.c @@ -20,13 +20,15 @@ int sshsm_hw_plugin_get_plugin_functions(SSHSM_HW_FUNCTIONS_t *funcs) { printf("%s(): Assigning Function pointers for TPM (dTPM or PTT) mode \n", __func__); - funcs->xxx_init = &tpm2_plugin_init; - funcs->xxx_uninit = &tpm2_plugin_uninit; - funcs->xxx_activate = &tpm2_plugin_activate; - funcs->xxx_load_key = &tpm2_plugin_load_key; - funcs->xxx_unload_key = NULL; - funcs->xxx_rsa_sign_init = &tpm2_plugin_rsa_sign_init; - funcs->xxx_rsa_sign = &tpm2_plugin_rsa_sign; + funcs->xxx_init = &tpm2_plugin_init; + funcs->xxx_uninit = &tpm2_plugin_uninit; + funcs->xxx_activate = &tpm2_plugin_activate; + funcs->xxx_load_key = &tpm2_plugin_load_key; + funcs->xxx_unload_key = NULL; + funcs->xxx_rsa_sign_init = &tpm2_plugin_rsa_sign_init; + funcs->xxx_rsa_sign_update = &tpm2_plugin_rsa_sign_update; + funcs->xxx_rsa_sign_final = &tpm2_plugin_rsa_sign_final; + funcs->xxx_rsa_sign = &tpm2_plugin_rsa_sign; return 0; } diff --git a/TPM2-Plugin/test/main.c b/TPM2-Plugin/test/main.c index 31fa7d6..046b3d7 100644 --- a/TPM2-Plugin/test/main.c +++ b/TPM2-Plugin/test/main.c @@ -24,6 +24,7 @@ void main(void) void *param = NULL; size_t len = 100; void *keyHandle_sign = NULL; + unsigned long int hSession = 1; unsigned char *msg; int msg_len; @@ -59,12 +60,12 @@ void main(void) tpm2_plugin_activate(activate_in_info); printf("---------------------------------------------\n"); - tpm2_plugin_rsa_sign_init(keyHandle_sign, mechanism, param, len); + tpm2_plugin_rsa_sign_init(keyHandle_sign, mechanism, param, len, (void *)hSession); printf("---------------------------------------------\n"); tpm2_plugin_load_key(loadkey_in_info, keyHandle, importkey_info); printf("---------------------------------------------\n"); - tpm2_plugin_rsa_sign(keyHandle_sign, mechanism, msg, msg_len, sig, sig_len); + tpm2_plugin_rsa_sign(keyHandle_sign, mechanism, msg, msg_len, (void *)hSession, sig, sig_len); } diff --git a/bin/README.md b/bin/README.md new file mode 100644 index 0000000..c4c54ca --- /dev/null +++ b/bin/README.md @@ -0,0 +1,27 @@ +### Building Docker Images + +``` +$ docker build -t <image name> -f tpmdockerfile . +``` + +### Running ABRMD Container + +``` +$ docker run -d --privileged -v /tmp/run/dbus:/var/run/dbus --name <container name> <image name> +``` + +### Running Tools Container +This command will drop you into the tools container with everything setup appropriately: +``` +# Runs without any privileges. +# Requires that the dbus be mounted from the same host folder +# This is to enable communication between the tools and ABRMD +$ docker run -v /tmp/run/dbus:/var/run/dbus --name <container name> -it --entrypoint /bin/bash <image name> +``` + +##### Sanity Check +Run the following command in the tools container to see if everything is setup correctly: + +``` +tpm2_listpcrs +``` diff --git a/bin/entrypoint.sh b/bin/entrypoint.sh new file mode 100755 index 0000000..b13c681 --- /dev/null +++ b/bin/entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +# Start DBUS +mkdir -p /var/run/dbus +stdbuf -oL -eL dbus-daemon --system --nofork 2>&1 1> /var/log/dbus-daemon.log & + +# Start Resource Manager +hostip=$(ip route show | awk '/default/ {print $3}') +echo "Connecting to $hostip\n" +tpm2-abrmd -a $hostip -t socket
\ No newline at end of file diff --git a/bin/tpmdockerfile b/bin/tpmdockerfile new file mode 100644 index 0000000..d1c9480 --- /dev/null +++ b/bin/tpmdockerfile @@ -0,0 +1,62 @@ +FROM ubuntu:xenial + +RUN apt-get -y update && \ + apt-get -y install \ + autoconf \ + autoconf-archive \ + libglib2.0-dev \ + libdbus-1-dev \ + automake \ + libtool \ + autotools-dev \ + libcppunit-dev \ + p11-kit \ + libcurl4-gnutls-dev \ + libcmocka0 \ + libcmocka-dev \ + build-essential \ + git \ + pkg-config \ + gcc \ + g++ \ + m4 \ + wget \ + liburiparser-dev \ + libssl-dev \ + pandoc + +RUN apt-get -y install libgcrypt20-dev + +RUN git clone https://github.com/tpm2-software/tpm2-tss.git +RUN git clone https://github.com/tpm2-software/tpm2-abrmd.git +RUN git clone https://github.com/tpm2-software/tpm2-tools.git + +RUN cd tpm2-tss && \ + git checkout 1.2.0 && \ + ./bootstrap && \ + ./configure && \ + make && \ + make install + +RUN cd tpm2-abrmd && \ + git checkout 1.1.1 && \ + useradd --system --user-group tss && \ + ./bootstrap && \ + ./configure --with-dbuspolicydir=/etc/dbus-1/system.d \ + --with-udevrulesdir=/etc/udev/rules.d/ \ + --with-systemdsystemunitdir=/lib/systemd/system && \ + make && \ + make install + +RUN cd tpm2-tools && \ + git checkout 2.1.0 && \ + ./bootstrap && \ + ./configure --with-tcti-tabrmd=yes && \ + make && \ + make install + +RUN echo "/usr/local/lib" > /etc/ld.so.conf.d/tpm2.conf && \ + ldconfig + +ADD entrypoint.sh /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"]
\ No newline at end of file @@ -1,4 +1,4 @@ -#!/etc/bash +#!/bin/bash #set -e sudo kill -9 $(ps -ef | grep "apt" | grep -v grep | awk '{print $2}') |