2 * Copyright (c) 2010 SURFnet bv
3 * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 /*****************************************************************************
31 The implementation of the SoftHSM's main class
32 *****************************************************************************/
37 #include "Configuration.h"
38 #include "SimpleConfigLoader.h"
39 #include "MutexFactory.h"
40 #include "SecureMemoryRegistry.h"
41 #include "CryptoFactory.h"
42 #include "AsymmetricAlgorithm.h"
43 #include "SymmetricAlgorithm.h"
47 #include "RSAParameters.h"
48 #include "RSAPublicKey.h"
49 #include "RSAPrivateKey.h"
50 #include "DSAParameters.h"
51 #include "DSAPublicKey.h"
52 #include "DSAPrivateKey.h"
53 #include "ECPublicKey.h"
54 #include "ECPrivateKey.h"
55 #include "ECParameters.h"
56 #include "DHParameters.h"
57 #include "DHPublicKey.h"
58 #include "DHPrivateKey.h"
59 #include "GOSTPublicKey.h"
60 #include "GOSTPrivateKey.h"
64 #include "SessionManager.h"
65 #include "SessionObjectStore.h"
66 #include "HandleManager.h"
67 #include "P11Objects.h"
72 #if defined(WITH_OPENSSL)
73 #include "OSSLCryptoFactory.h"
75 #include "BotanCryptoFactory.h"
80 // Initialise the one-and-only instance
84 std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
85 std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
86 #if defined(WITH_OPENSSL)
87 std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
89 std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
91 std::unique_ptr<SoftHSM> SoftHSM::instance(nullptr);
95 std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
96 std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
97 #if defined(WITH_OPENSSL)
98 std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
100 std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
102 std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
106 static CK_RV Extract_key_handle(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, void *hwKeyHandle)
110 // get value of the hw key handle
111 CK_ATTRIBUTE valAttrib[] = {
112 {CKA_PRIME_1, NULL_PTR, 0}
115 // Get the length of the attribute first
116 rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE));
119 printf("Getting length of keyHandle with C_GetAttributeValue() API failed ! \n");
123 valAttrib[0].pValue = (CK_VOID_PTR) malloc(valAttrib[0].ulValueLen);
125 rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE));
127 // Convert the keyHandle from string to CK_ULONG
128 sscanf((char*) valAttrib[0].pValue, "%lx", (CK_ULONG *) hwKeyHandle);
129 printf("Extract_key_handle:: hwKeyHandle: %lu \n", (CK_ULONG) hwKeyHandle);
131 if(!(valAttrib[0].pValue))
133 free(valAttrib[0].pValue);
139 static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
143 *p11object = new P11DataObj();
145 case CKO_CERTIFICATE:
146 if (certType == CKC_X_509)
147 *p11object = new P11X509CertificateObj();
148 else if (certType == CKC_OPENPGP)
149 *p11object = new P11OpenPGPPublicKeyObj();
151 return CKR_ATTRIBUTE_VALUE_INVALID;
154 if (keyType == CKK_RSA)
155 *p11object = new P11RSAPublicKeyObj();
156 else if (keyType == CKK_DSA)
157 *p11object = new P11DSAPublicKeyObj();
158 else if (keyType == CKK_EC)
159 *p11object = new P11ECPublicKeyObj();
160 else if (keyType == CKK_DH)
161 *p11object = new P11DHPublicKeyObj();
162 else if (keyType == CKK_GOSTR3410)
163 *p11object = new P11GOSTPublicKeyObj();
165 return CKR_ATTRIBUTE_VALUE_INVALID;
167 case CKO_PRIVATE_KEY:
168 // we need to know the type too
169 if (keyType == CKK_RSA)
170 *p11object = new P11RSAPrivateKeyObj();
171 else if (keyType == CKK_DSA)
172 *p11object = new P11DSAPrivateKeyObj();
173 else if (keyType == CKK_EC)
174 *p11object = new P11ECPrivateKeyObj();
175 else if (keyType == CKK_DH)
176 *p11object = new P11DHPrivateKeyObj();
177 else if (keyType == CKK_GOSTR3410)
178 *p11object = new P11GOSTPrivateKeyObj();
180 return CKR_ATTRIBUTE_VALUE_INVALID;
183 if ((keyType == CKK_GENERIC_SECRET) ||
184 (keyType == CKK_MD5_HMAC) ||
185 (keyType == CKK_SHA_1_HMAC) ||
186 (keyType == CKK_SHA224_HMAC) ||
187 (keyType == CKK_SHA256_HMAC) ||
188 (keyType == CKK_SHA384_HMAC) ||
189 (keyType == CKK_SHA512_HMAC))
191 P11GenericSecretKeyObj* key = new P11GenericSecretKeyObj();
193 key->setKeyType(keyType);
195 else if (keyType == CKK_AES)
197 *p11object = new P11AESSecretKeyObj();
199 else if ((keyType == CKK_DES) ||
200 (keyType == CKK_DES2) ||
201 (keyType == CKK_DES3))
203 P11DESSecretKeyObj* key = new P11DESSecretKeyObj();
205 key->setKeyType(keyType);
207 else if (keyType == CKK_GOST28147)
209 *p11object = new P11GOSTSecretKeyObj();
212 return CKR_ATTRIBUTE_VALUE_INVALID;
214 case CKO_DOMAIN_PARAMETERS:
215 if (keyType == CKK_DSA)
216 *p11object = new P11DSADomainObj();
217 else if (keyType == CKK_DH)
218 *p11object = new P11DHDomainObj();
220 return CKR_ATTRIBUTE_VALUE_INVALID;
223 return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
228 static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate,
230 CK_OBJECT_CLASS &objClass,
231 CK_KEY_TYPE &keyType,
232 CK_CERTIFICATE_TYPE &certType,
237 bool bHasClass = false;
238 bool bHasKeyType = false;
239 bool bHasCertType = false;
240 bool bHasPrivate = false;
242 // Extract object information
243 for (CK_ULONG i = 0; i < ulCount; ++i)
245 switch (pTemplate[i].type)
248 if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
250 objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
255 if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
257 keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
261 case CKA_CERTIFICATE_TYPE:
262 if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
264 certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
269 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
271 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
275 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
277 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
293 return CKR_TEMPLATE_INCOMPLETE;
296 bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
297 if (bKeyTypeRequired && !bHasKeyType)
299 return CKR_TEMPLATE_INCOMPLETE;
302 if (objClass == CKO_CERTIFICATE)
306 return CKR_TEMPLATE_INCOMPLETE;
310 // Change default value for certificates
311 isPrivate = CK_FALSE;
315 if (objClass == CKO_PUBLIC_KEY && !bHasPrivate)
317 // Change default value for public keys
318 isPrivate = CK_FALSE;
324 static CK_RV newP11Object(OSObject *object, P11Object **p11object)
326 CK_OBJECT_CLASS objClass = object->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
327 CK_KEY_TYPE keyType = CKK_RSA;
328 CK_CERTIFICATE_TYPE certType = CKC_X_509;
329 if (object->attributeExists(CKA_KEY_TYPE))
330 keyType = object->getUnsignedLongValue(CKA_KEY_TYPE, CKK_RSA);
331 if (object->attributeExists(CKA_CERTIFICATE_TYPE))
332 certType = object->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_X_509);
333 CK_RV rv = newP11Object(objClass,keyType,certType,p11object);
336 if (!(*p11object)->init(object))
337 return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
342 static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
344 CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
349 /*****************************************************************************
350 Implementation of SoftHSM class specific functions
351 *****************************************************************************/
353 // Return the one-and-only instance
354 SoftHSM* SoftHSM::i()
358 instance.reset(new SoftHSM());
361 return instance.get();
364 void SoftHSM::reset()
373 isInitialised = false;
375 sessionObjectStore = NULL;
378 sessionManager = NULL;
379 handleManager = NULL;
380 isHWavailable = false;
386 if (handleManager != NULL) delete handleManager;
387 if (sessionManager != NULL) delete sessionManager;
388 if (slotManager != NULL) delete slotManager;
389 if (objectStore != NULL) delete objectStore;
390 if (sessionObjectStore != NULL) delete sessionObjectStore;
393 /*****************************************************************************
394 Implementation of PKCS #11 functions
395 *****************************************************************************/
397 // PKCS #11 initialisation function
398 CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
400 CK_C_INITIALIZE_ARGS_PTR args;
402 // Check if PKCS#11 is already initialized
405 ERROR_MSG("SoftHSM is already initialized");
406 return CKR_CRYPTOKI_ALREADY_INITIALIZED;
409 // Do we have any arguments?
410 if (pInitArgs != NULL_PTR)
412 args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
414 // Must be set to NULL_PTR in this version of PKCS#11
415 if (args->pReserved != NULL_PTR)
417 ERROR_MSG("pReserved must be set to NULL_PTR");
418 return CKR_ARGUMENTS_BAD;
421 // Can we spawn our own threads?
422 // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
424 // DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
425 // return CKR_NEED_TO_CREATE_THREADS;
428 // Are we not supplied with mutex functions?
431 args->CreateMutex == NULL_PTR &&
432 args->DestroyMutex == NULL_PTR &&
433 args->LockMutex == NULL_PTR &&
434 args->UnlockMutex == NULL_PTR
437 // Can we use our own mutex functions?
438 if (args->flags & CKF_OS_LOCKING_OK)
440 // Use our own mutex functions.
441 MutexFactory::i()->setCreateMutex(OSCreateMutex);
442 MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
443 MutexFactory::i()->setLockMutex(OSLockMutex);
444 MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
445 MutexFactory::i()->enable();
449 // The external application is not using threading
450 MutexFactory::i()->disable();
455 // We must have all mutex functions
458 args->CreateMutex == NULL_PTR ||
459 args->DestroyMutex == NULL_PTR ||
460 args->LockMutex == NULL_PTR ||
461 args->UnlockMutex == NULL_PTR
464 ERROR_MSG("Not all mutex functions are supplied");
465 return CKR_ARGUMENTS_BAD;
468 // We could use our own mutex functions if the flag is set,
469 // but we use the external functions in both cases.
471 // Load the external mutex functions
472 MutexFactory::i()->setCreateMutex(args->CreateMutex);
473 MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
474 MutexFactory::i()->setLockMutex(args->LockMutex);
475 MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
476 MutexFactory::i()->enable();
481 // No concurrent access by multiple threads
482 MutexFactory::i()->disable();
485 // Initiate SecureMemoryRegistry
486 if (SecureMemoryRegistry::i() == NULL)
488 ERROR_MSG("Could not load the SecureMemoryRegistry");
489 return CKR_GENERAL_ERROR;
492 // Build the CryptoFactory
493 if (CryptoFactory::i() == NULL)
495 ERROR_MSG("Could not load the CryptoFactory");
496 return CKR_GENERAL_ERROR;
500 // Check the FIPS status
501 if (!CryptoFactory::i()->getFipsSelfTestStatus())
503 ERROR_MSG("The FIPS self test failed");
504 return CKR_FIPS_SELF_TEST_FAILED;
508 // (Re)load the configuration
509 if (!Configuration::i()->reload(SimpleConfigLoader::i()))
511 ERROR_MSG("Could not load the configuration");
512 return CKR_GENERAL_ERROR;
515 // Configure the log level
516 if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
518 ERROR_MSG("Could not set the log level");
519 return CKR_GENERAL_ERROR;
522 // Configure object store storage backend used by all tokens.
523 if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
525 ERROR_MSG("Could not set the storage backend");
526 return CKR_GENERAL_ERROR;
529 sessionObjectStore = new SessionObjectStore();
531 // Load the object store
532 objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
533 if (!objectStore->isValid())
535 WARNING_MSG("Could not load the object store");
538 delete sessionObjectStore;
539 sessionObjectStore = NULL;
540 return CKR_GENERAL_ERROR;
543 isRemovable = Configuration::i()->getBool("slots.removable", false);
545 // Load the slot manager
546 slotManager = new SlotManager(objectStore);
548 // Load the session manager
549 sessionManager = new SessionManager();
551 // Load the handle manager
552 handleManager = new HandleManager();
554 // Set the state to initialised
555 isInitialised = true;
557 if(prepareHWPlugin())
559 printf("HW plugin NOT available to use ! \n");
560 isHWavailable = false;
564 printf("HW plugin available and initialized ! \n");
565 isHWavailable = true;
571 // PKCS #11 finalisation function
572 CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
574 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
576 // Must be set to NULL_PTR in this version of PKCS#11
577 if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
579 if (handleManager != NULL) delete handleManager;
580 handleManager = NULL;
581 if (sessionManager != NULL) delete sessionManager;
582 sessionManager = NULL;
583 if (slotManager != NULL) delete slotManager;
585 if (objectStore != NULL) delete objectStore;
587 if (sessionObjectStore != NULL) delete sessionObjectStore;
588 sessionObjectStore = NULL;
589 CryptoFactory::reset();
590 SecureMemoryRegistry::reset();
592 isInitialised = false;
598 // Return information about the PKCS #11 module
599 CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
601 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
602 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
604 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
605 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
606 memset(pInfo->manufacturerID, ' ', 32);
607 memcpy(pInfo->manufacturerID, "SoftHSM", 7);
609 memset(pInfo->libraryDescription, ' ', 32);
611 memcpy(pInfo->libraryDescription, "Implementation of PKCS11+FIPS", 29);
613 memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
615 pInfo->libraryVersion.major = VERSION_MAJOR;
616 pInfo->libraryVersion.minor = VERSION_MINOR;
621 // Return a list of available slots
622 CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
624 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
626 return slotManager->getSlotList(objectStore, tokenPresent, pSlotList, pulCount);
629 // Return information about a slot
630 CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
633 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
635 Slot* slot = slotManager->getSlot(slotID);
638 return CKR_SLOT_ID_INVALID;
641 rv = slot->getSlotInfo(pInfo);
647 pInfo->flags |= CKF_REMOVABLE_DEVICE;
653 // Return information about a token in a slot
654 CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
656 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
658 Slot* slot = slotManager->getSlot(slotID);
661 return CKR_SLOT_ID_INVALID;
664 Token* token = slot->getToken();
667 return CKR_TOKEN_NOT_PRESENT;
670 return token->getTokenInfo(pInfo);
673 // Return the list of supported mechanisms for a given slot
674 CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
676 // A list with the supported mechanisms
677 CK_ULONG nrSupportedMechanisms = 61;
679 nrSupportedMechanisms += 3;
682 nrSupportedMechanisms -= 9;
685 nrSupportedMechanisms += 5;
687 #ifdef HAVE_AES_KEY_WRAP_PAD
688 nrSupportedMechanisms += 1;
691 nrSupportedMechanisms += 1; // CKM_RSA_PKCS_PSS
694 nrSupportedMechanisms += 1;
697 CK_MECHANISM_TYPE supportedMechanisms[] =
715 CKM_RSA_PKCS_KEY_PAIR_GEN,
730 CKM_SHA1_RSA_PKCS_PSS,
731 CKM_SHA224_RSA_PKCS_PSS,
732 CKM_SHA256_RSA_PKCS_PSS,
733 CKM_SHA384_RSA_PKCS_PSS,
734 CKM_SHA512_RSA_PKCS_PSS,
744 CKM_DES_ECB_ENCRYPT_DATA,
745 CKM_DES_CBC_ENCRYPT_DATA,
750 CKM_DES3_ECB_ENCRYPT_DATA,
751 CKM_DES3_CBC_ENCRYPT_DATA,
762 #ifdef HAVE_AES_KEY_WRAP_PAD
763 CKM_AES_KEY_WRAP_PAD,
765 CKM_AES_ECB_ENCRYPT_DATA,
766 CKM_AES_CBC_ENCRYPT_DATA,
768 CKM_DSA_PARAMETER_GEN,
769 CKM_DSA_KEY_PAIR_GEN,
776 CKM_DH_PKCS_KEY_PAIR_GEN,
777 CKM_DH_PKCS_PARAMETER_GEN,
787 CKM_GOSTR3410_KEY_PAIR_GEN,
789 CKM_GOSTR3410_WITH_GOSTR3411
793 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
794 if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
796 Slot* slot = slotManager->getSlot(slotID);
799 return CKR_SLOT_ID_INVALID;
802 if (pMechanismList == NULL_PTR)
804 *pulCount = nrSupportedMechanisms;
809 if (*pulCount < nrSupportedMechanisms)
811 *pulCount = nrSupportedMechanisms;
813 return CKR_BUFFER_TOO_SMALL;
816 *pulCount = nrSupportedMechanisms;
818 for (CK_ULONG i = 0; i < nrSupportedMechanisms; i ++)
820 pMechanismList[i] = supportedMechanisms[i];
826 // Return more information about a mechanism for a given slot
827 CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
829 unsigned long rsaMinSize, rsaMaxSize;
830 unsigned long dsaMinSize, dsaMaxSize;
831 unsigned long dhMinSize, dhMaxSize;
833 unsigned long ecdsaMinSize, ecdsaMaxSize;
834 unsigned long ecdhMinSize, ecdhMaxSize;
837 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
838 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
840 Slot* slot = slotManager->getSlot(slotID);
843 return CKR_SLOT_ID_INVALID;
846 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
849 rsaMinSize = rsa->getMinKeySize();
850 rsaMaxSize = rsa->getMaxKeySize();
854 return CKR_GENERAL_ERROR;
856 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
858 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
861 dsaMinSize = dsa->getMinKeySize();
862 // Limitation in PKCS#11
863 if (dsaMinSize < 512)
868 dsaMaxSize = dsa->getMaxKeySize();
869 // Limitation in PKCS#11
870 if (dsaMaxSize > 1024)
877 return CKR_GENERAL_ERROR;
879 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
881 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
884 dhMinSize = dh->getMinKeySize();
885 dhMaxSize = dh->getMaxKeySize();
889 return CKR_GENERAL_ERROR;
891 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
894 AsymmetricAlgorithm* ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
897 ecdsaMinSize = ecdsa->getMinKeySize();
898 ecdsaMaxSize = ecdsa->getMaxKeySize();
902 return CKR_GENERAL_ERROR;
904 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
906 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
909 ecdhMinSize = ecdh->getMinKeySize();
910 ecdhMaxSize = ecdh->getMaxKeySize();
914 return CKR_GENERAL_ERROR;
916 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
929 // Key size is not in use
930 pInfo->ulMinKeySize = 0;
931 pInfo->ulMaxKeySize = 0;
932 pInfo->flags = CKF_DIGEST;
936 pInfo->ulMinKeySize = 16;
937 pInfo->ulMaxKeySize = 512;
938 pInfo->flags = CKF_SIGN | CKF_VERIFY;
942 pInfo->ulMinKeySize = 20;
943 pInfo->ulMaxKeySize = 512;
944 pInfo->flags = CKF_SIGN | CKF_VERIFY;
946 case CKM_SHA224_HMAC:
947 pInfo->ulMinKeySize = 28;
948 pInfo->ulMaxKeySize = 512;
949 pInfo->flags = CKF_SIGN | CKF_VERIFY;
951 case CKM_SHA256_HMAC:
952 pInfo->ulMinKeySize = 32;
953 pInfo->ulMaxKeySize = 512;
954 pInfo->flags = CKF_SIGN | CKF_VERIFY;
956 case CKM_SHA384_HMAC:
957 pInfo->ulMinKeySize = 48;
958 pInfo->ulMaxKeySize = 512;
959 pInfo->flags = CKF_SIGN | CKF_VERIFY;
961 case CKM_SHA512_HMAC:
962 pInfo->ulMinKeySize = 64;
963 pInfo->ulMaxKeySize = 512;
964 pInfo->flags = CKF_SIGN | CKF_VERIFY;
966 case CKM_RSA_PKCS_KEY_PAIR_GEN:
967 pInfo->ulMinKeySize = rsaMinSize;
968 pInfo->ulMaxKeySize = rsaMaxSize;
969 pInfo->flags = CKF_GENERATE_KEY_PAIR;
972 pInfo->ulMinKeySize = rsaMinSize;
973 pInfo->ulMaxKeySize = rsaMaxSize;
974 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
977 pInfo->ulMinKeySize = rsaMinSize;
978 pInfo->ulMaxKeySize = rsaMaxSize;
979 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
982 case CKM_MD5_RSA_PKCS:
984 case CKM_SHA1_RSA_PKCS:
985 case CKM_SHA224_RSA_PKCS:
986 case CKM_SHA256_RSA_PKCS:
987 case CKM_SHA384_RSA_PKCS:
988 case CKM_SHA512_RSA_PKCS:
990 case CKM_RSA_PKCS_PSS:
992 case CKM_SHA1_RSA_PKCS_PSS:
993 case CKM_SHA224_RSA_PKCS_PSS:
994 case CKM_SHA256_RSA_PKCS_PSS:
995 case CKM_SHA384_RSA_PKCS_PSS:
996 case CKM_SHA512_RSA_PKCS_PSS:
997 pInfo->ulMinKeySize = rsaMinSize;
998 pInfo->ulMaxKeySize = rsaMaxSize;
999 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1001 case CKM_RSA_PKCS_OAEP:
1002 pInfo->ulMinKeySize = rsaMinSize;
1003 pInfo->ulMaxKeySize = rsaMaxSize;
1004 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
1007 case CKM_DES_KEY_GEN:
1009 case CKM_DES2_KEY_GEN:
1010 case CKM_DES3_KEY_GEN:
1011 // Key size is not in use
1012 pInfo->ulMinKeySize = 0;
1013 pInfo->ulMaxKeySize = 0;
1014 pInfo->flags = CKF_GENERATE;
1019 case CKM_DES_CBC_PAD:
1023 case CKM_DES3_CBC_PAD:
1024 // Key size is not in use
1025 pInfo->ulMinKeySize = 0;
1026 pInfo->ulMaxKeySize = 0;
1027 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1030 // Key size is not in use
1031 pInfo->ulMinKeySize = 0;
1032 pInfo->ulMaxKeySize = 0;
1033 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1035 case CKM_AES_KEY_GEN:
1036 pInfo->ulMinKeySize = 16;
1037 pInfo->ulMaxKeySize = 32;
1038 pInfo->flags = CKF_GENERATE;
1042 case CKM_AES_CBC_PAD:
1047 pInfo->ulMinKeySize = 16;
1048 pInfo->ulMaxKeySize = 32;
1049 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1051 case CKM_AES_KEY_WRAP:
1052 pInfo->ulMinKeySize = 16;
1053 pInfo->ulMaxKeySize = 0x80000000;
1054 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1056 #ifdef HAVE_AES_KEY_WRAP_PAD
1057 case CKM_AES_KEY_WRAP_PAD:
1058 pInfo->ulMinKeySize = 1;
1059 pInfo->ulMaxKeySize = 0x80000000;
1060 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1064 case CKM_DES_ECB_ENCRYPT_DATA:
1065 case CKM_DES_CBC_ENCRYPT_DATA:
1067 case CKM_DES3_ECB_ENCRYPT_DATA:
1068 case CKM_DES3_CBC_ENCRYPT_DATA:
1069 case CKM_AES_ECB_ENCRYPT_DATA:
1070 case CKM_AES_CBC_ENCRYPT_DATA:
1071 // Key size is not in use
1072 pInfo->ulMinKeySize = 0;
1073 pInfo->ulMaxKeySize = 0;
1074 pInfo->flags = CKF_DERIVE;
1077 pInfo->ulMinKeySize = 16;
1078 pInfo->ulMaxKeySize = 32;
1079 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1081 case CKM_DSA_PARAMETER_GEN:
1082 pInfo->ulMinKeySize = dsaMinSize;
1083 pInfo->ulMaxKeySize = dsaMaxSize;
1084 pInfo->flags = CKF_GENERATE;
1086 case CKM_DSA_KEY_PAIR_GEN:
1087 pInfo->ulMinKeySize = dsaMinSize;
1088 pInfo->ulMaxKeySize = dsaMaxSize;
1089 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1093 case CKM_DSA_SHA224:
1094 case CKM_DSA_SHA256:
1095 case CKM_DSA_SHA384:
1096 case CKM_DSA_SHA512:
1097 pInfo->ulMinKeySize = dsaMinSize;
1098 pInfo->ulMaxKeySize = dsaMaxSize;
1099 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1101 case CKM_DH_PKCS_KEY_PAIR_GEN:
1102 pInfo->ulMinKeySize = dhMinSize;
1103 pInfo->ulMaxKeySize = dhMaxSize;
1104 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1106 case CKM_DH_PKCS_PARAMETER_GEN:
1107 pInfo->ulMinKeySize = dhMinSize;
1108 pInfo->ulMaxKeySize = dhMaxSize;
1109 pInfo->flags = CKF_GENERATE;
1111 case CKM_DH_PKCS_DERIVE:
1112 pInfo->ulMinKeySize = dhMinSize;
1113 pInfo->ulMaxKeySize = dhMaxSize;
1114 pInfo->flags = CKF_DERIVE;
1117 case CKM_EC_KEY_PAIR_GEN:
1118 pInfo->ulMinKeySize = ecdsaMinSize;
1119 pInfo->ulMaxKeySize = ecdsaMaxSize;
1120 #define CKF_EC_COMMOM (CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS)
1121 pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
1124 pInfo->ulMinKeySize = ecdsaMinSize;
1125 pInfo->ulMaxKeySize = ecdsaMaxSize;
1126 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
1128 case CKM_ECDH1_DERIVE:
1129 pInfo->ulMinKeySize = ecdhMinSize;
1130 pInfo->ulMaxKeySize = ecdhMaxSize;
1131 pInfo->flags = CKF_DERIVE;
1136 // Key size is not in use
1137 pInfo->ulMinKeySize = 0;
1138 pInfo->ulMaxKeySize = 0;
1139 pInfo->flags = CKF_DIGEST;
1141 case CKM_GOSTR3411_HMAC:
1142 // Key size is not in use
1143 pInfo->ulMinKeySize = 32;
1144 pInfo->ulMaxKeySize = 512;
1145 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1147 case CKM_GOSTR3410_KEY_PAIR_GEN:
1148 // Key size is not in use
1149 pInfo->ulMinKeySize = 0;
1150 pInfo->ulMaxKeySize = 0;
1151 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1154 // Key size is not in use
1155 pInfo->ulMinKeySize = 0;
1156 pInfo->ulMaxKeySize = 0;
1157 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1159 case CKM_GOSTR3410_WITH_GOSTR3411:
1160 // Key size is not in use
1161 pInfo->ulMinKeySize = 0;
1162 pInfo->ulMaxKeySize = 0;
1163 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1167 DEBUG_MSG("The selected mechanism is not supported");
1168 return CKR_MECHANISM_INVALID;
1175 // Initialise the token in the specified slot
1176 CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
1178 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1180 Slot* slot = slotManager->getSlot(slotID);
1183 return CKR_SLOT_ID_INVALID;
1186 // Check if any session is open with this token.
1187 if (sessionManager->haveSession(slotID))
1189 return CKR_SESSION_EXISTS;
1193 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1194 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
1196 ByteString soPIN(pPin, ulPinLen);
1198 return slot->initToken(soPIN, pLabel);
1201 // Initialise the user PIN
1202 CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1204 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1207 Session* session = (Session*)handleManager->getSession(hSession);
1208 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1210 // The SO must be logged in
1211 if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
1214 Token* token = session->getToken();
1215 if (token == NULL) return CKR_GENERAL_ERROR;
1218 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1219 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1221 ByteString userPIN(pPin, ulPinLen);
1223 return token->initUserPIN(userPIN);
1227 CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
1231 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1234 Session* session = (Session*)handleManager->getSession(hSession);
1235 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1237 // Check the new PINs
1238 if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1239 if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1240 if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1242 ByteString oldPIN(pOldPin, ulOldLen);
1243 ByteString newPIN(pNewPin, ulNewLen);
1246 Token* token = session->getToken();
1247 if (token == NULL) return CKR_GENERAL_ERROR;
1249 switch (session->getState())
1251 case CKS_RW_PUBLIC_SESSION:
1252 case CKS_RW_USER_FUNCTIONS:
1253 rv = token->setUserPIN(oldPIN, newPIN);
1255 case CKS_RW_SO_FUNCTIONS:
1256 rv = token->setSOPIN(oldPIN, newPIN);
1259 return CKR_SESSION_READ_ONLY;
1265 // Open a new session to the specified slot
1266 CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
1268 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1270 Slot* slot = slotManager->getSlot(slotID);
1272 CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
1276 // Get a pointer to the session object and store it in the handle manager.
1277 Session* session = sessionManager->getSession(*phSession);
1278 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1279 *phSession = handleManager->addSession(slotID,session);
1284 // Close the given session
1285 CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
1287 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1290 Session* session = (Session*)handleManager->getSession(hSession);
1291 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1293 // Tell the handle manager the session has been closed.
1294 handleManager->sessionClosed(hSession);
1297 // Tell the session object store that the session has closed.
1298 sessionObjectStore->sessionClosed(hSession);
1300 // Tell the session manager the session has been closed.
1301 return sessionManager->closeSession(session->getHandle());
1304 // Close all open sessions
1305 CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
1307 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1310 Slot* slot = slotManager->getSlot(slotID);
1311 if (slot == NULL) return CKR_SLOT_ID_INVALID;
1314 Token* token = slot->getToken();
1315 if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
1317 // Tell the handle manager all sessions were closed for the given slotID.
1318 // The handle manager should then remove all session and object handles for this slot.
1319 handleManager->allSessionsClosed(slotID);
1321 // Tell the session object store that all sessions were closed for the given slotID.
1322 // The session object store should then remove all session objects for this slot.
1323 sessionObjectStore->allSessionsClosed(slotID);
1325 // Finally tell the session manager tho close all sessions for the given slot.
1326 // This will also trigger a logout on the associated token to occur.
1327 return sessionManager->closeAllSessions(slot);
1330 // Retrieve information about the specified session
1331 CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
1333 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1336 Session* session = (Session*)handleManager->getSession(hSession);
1337 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1339 return session->getInfo(pInfo);
1342 // Determine the state of a running operation in a session
1343 CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG_PTR /*pulOperationStateLen*/)
1345 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1348 Session* session = (Session*)handleManager->getSession(hSession);
1349 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1351 return CKR_FUNCTION_NOT_SUPPORTED;
1354 // Set the operation sate in a session
1355 CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG /*ulOperationStateLen*/, CK_OBJECT_HANDLE /*hEncryptionKey*/, CK_OBJECT_HANDLE /*hAuthenticationKey*/)
1357 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1360 Session* session = (Session*)handleManager->getSession(hSession);
1361 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1363 return CKR_FUNCTION_NOT_SUPPORTED;
1366 // Login on the token in the specified session
1367 CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1371 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1374 Session* session = (Session*)handleManager->getSession(hSession);
1375 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1378 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1379 ByteString pin(pPin, ulPinLen);
1382 Token* token = session->getToken();
1383 if (token == NULL) return CKR_GENERAL_ERROR;
1388 // There cannot exist a R/O session on this slot
1389 if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
1392 rv = token->loginSO(pin);
1396 rv = token->loginUser(pin);
1398 case CKU_CONTEXT_SPECIFIC:
1399 // Check if re-authentication is required
1400 if (!session->getReAuthentication()) return CKR_OPERATION_NOT_INITIALIZED;
1403 rv = token->reAuthenticate(pin);
1404 if (rv == CKR_OK) session->setReAuthentication(false);
1407 return CKR_USER_TYPE_INVALID;
1413 // Log out of the token in the specified session
1414 CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
1416 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1419 Session* session = (Session*)handleManager->getSession(hSession);
1420 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1423 Token* token = session->getToken();
1424 if (token == NULL) return CKR_GENERAL_ERROR;
1429 // [PKCS#11 v2.40, C_Logout] When logout is successful...
1430 // a. Any of the application's handles to private objects become invalid.
1431 // b. Even if a user is later logged back into the token those handles remain invalid.
1432 // c. All private session objects from sessions belonging to the application are destroyed.
1434 // Have the handle manager remove all handles pointing to private objects for this slot.
1435 CK_SLOT_ID slotID = session->getSlot()->getSlotID();
1436 handleManager->tokenLoggedOut(slotID);
1437 sessionObjectStore->tokenLoggedOut(slotID);
1442 // Create a new object on the token in the specified session using the given attribute template
1443 CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
1445 return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
1448 // Create a copy of the object with the specified handle
1449 CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
1451 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1453 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
1454 if (phNewObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1455 *phNewObject = CK_INVALID_HANDLE;
1458 Session* session = (Session*)handleManager->getSession(hSession);
1459 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1462 Slot* slot = session->getSlot();
1463 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1466 Token* token = session->getToken();
1467 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1469 // Check the object handle.
1470 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1471 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1473 CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
1474 CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1476 // Check read user credentials
1477 CK_RV rv = haveRead(session->getState(), wasOnToken, wasPrivate);
1480 if (rv == CKR_USER_NOT_LOGGED_IN)
1481 INFO_MSG("User is not authorized");
1486 // Check if the object is copyable
1487 CK_BBOOL isCopyable = object->getBooleanValue(CKA_COPYABLE, true);
1488 if (!isCopyable) return CKR_ACTION_PROHIBITED;
1490 // Extract critical information from the template
1491 CK_BBOOL isOnToken = wasOnToken;
1492 CK_BBOOL isPrivate = wasPrivate;
1494 for (CK_ULONG i = 0; i < ulCount; i++)
1496 if ((pTemplate[i].type == CKA_TOKEN) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1498 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
1501 if ((pTemplate[i].type == CKA_PRIVATE) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1503 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
1508 // Check privacy does not downgrade
1509 if (wasPrivate && !isPrivate) return CKR_TEMPLATE_INCONSISTENT;
1511 // Check write user credentials
1512 rv = haveWrite(session->getState(), isOnToken, isPrivate);
1515 if (rv == CKR_USER_NOT_LOGGED_IN)
1516 INFO_MSG("User is not authorized");
1517 if (rv == CKR_SESSION_READ_ONLY)
1518 INFO_MSG("Session is read-only");
1523 // Create the object in session or on the token
1524 OSObject *newobject = NULL_PTR;
1527 newobject = (OSObject*) token->createObject();
1531 newobject = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
1533 if (newobject == NULL) return CKR_GENERAL_ERROR;
1535 // Copy attributes from object class (CKA_CLASS=0 so the first)
1536 if (!newobject->startTransaction())
1538 newobject->destroyObject();
1539 return CKR_FUNCTION_FAILED;
1542 CK_ATTRIBUTE_TYPE attrType = CKA_CLASS;
1545 if (!object->attributeExists(attrType))
1547 rv = CKR_FUNCTION_FAILED;
1551 OSAttribute attr = object->getAttribute(attrType);
1553 // Upgrade privacy has to encrypt byte strings
1554 if (!wasPrivate && isPrivate &&
1555 attr.isByteStringAttribute() &&
1556 attr.getByteStringValue().size() != 0)
1559 if (!token->encrypt(attr.getByteStringValue(), value) ||
1560 !newobject->setAttribute(attrType, value))
1562 rv = CKR_FUNCTION_FAILED;
1568 if (!newobject->setAttribute(attrType, attr))
1570 rv = CKR_FUNCTION_FAILED;
1574 attrType = object->nextAttributeType(attrType);
1576 while (attrType != CKA_CLASS);
1580 newobject->abortTransaction();
1582 else if (!newobject->commitTransaction())
1584 rv = CKR_FUNCTION_FAILED;
1589 newobject->destroyObject();
1593 // Get the new P11 object
1594 P11Object* newp11object = NULL;
1595 rv = newP11Object(newobject,&newp11object);
1598 newobject->destroyObject();
1602 // Apply the template
1603 rv = newp11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate, ulCount, OBJECT_OP_COPY);
1604 delete newp11object;
1608 newobject->destroyObject();
1615 *phNewObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, newobject);
1619 *phNewObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, newobject);
1625 // Destroy the specified object
1626 CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
1628 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1631 Session* session = (Session*)handleManager->getSession(hSession);
1632 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1635 Token* token = session->getToken();
1636 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1638 // Check the object handle.
1639 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1640 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1642 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1643 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1645 // Check user credentials
1646 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1649 if (rv == CKR_USER_NOT_LOGGED_IN)
1650 INFO_MSG("User is not authorized");
1651 if (rv == CKR_SESSION_READ_ONLY)
1652 INFO_MSG("Session is read-only");
1657 // Check if the object is destroyable
1658 CK_BBOOL isDestroyable = object->getBooleanValue(CKA_DESTROYABLE, true);
1659 if (!isDestroyable) return CKR_ACTION_PROHIBITED;
1661 // Tell the handleManager to forget about the object.
1662 handleManager->destroyObject(hObject);
1664 // Destroy the object
1665 if (!object->destroyObject())
1666 return CKR_FUNCTION_FAILED;
1671 // Determine the size of the specified object
1672 CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
1674 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1676 if (pulSize == NULL) return CKR_ARGUMENTS_BAD;
1679 Session* session = (Session*)handleManager->getSession(hSession);
1680 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1683 Token* token = session->getToken();
1684 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1686 // Check the object handle.
1687 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1688 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1690 *pulSize = CK_UNAVAILABLE_INFORMATION;
1695 // Retrieve the specified attributes for the given object
1696 CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1698 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1700 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1703 Session* session = (Session*)handleManager->getSession(hSession);
1704 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1707 Token* token = session->getToken();
1708 if (token == NULL) return CKR_GENERAL_ERROR;
1710 // Check the object handle.
1711 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1712 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1714 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1715 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1717 // Check read user credentials
1718 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
1721 if (rv == CKR_USER_NOT_LOGGED_IN)
1722 INFO_MSG("User is not authorized");
1724 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
1725 // so we use CKR_GENERAL_ERROR.
1726 return CKR_GENERAL_ERROR;
1729 // Wrap a P11Object around the OSObject so we can access the attributes in the
1730 // context of the object in which it is defined.
1731 P11Object* p11object = NULL;
1732 rv = newP11Object(object,&p11object);
1736 // Ask the P11Object to fill the template with attribute values.
1737 rv = p11object->loadTemplate(token, pTemplate,ulCount);
1742 // Change or set the value of the specified attributes on the specified object
1743 CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1745 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1747 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1750 Session* session = (Session*)handleManager->getSession(hSession);
1751 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1754 Token* token = session->getToken();
1755 if (token == NULL) return CKR_GENERAL_ERROR;
1757 // Check the object handle.
1758 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1759 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1761 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1762 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1764 // Check user credentials
1765 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1768 if (rv == CKR_USER_NOT_LOGGED_IN)
1769 INFO_MSG("User is not authorized");
1770 if (rv == CKR_SESSION_READ_ONLY)
1771 INFO_MSG("Session is read-only");
1776 // Check if the object is modifiable
1777 CK_BBOOL isModifiable = object->getBooleanValue(CKA_MODIFIABLE, true);
1778 if (!isModifiable) return CKR_ACTION_PROHIBITED;
1780 // Wrap a P11Object around the OSObject so we can access the attributes in the
1781 // context of the object in which it is defined.
1782 P11Object* p11object = NULL;
1783 rv = newP11Object(object,&p11object);
1787 // Ask the P11Object to save the template with attribute values.
1788 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate,ulCount,OBJECT_OP_SET);
1793 // Initialise object search in the specified session using the specified attribute template as search parameters
1794 CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1796 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1799 Session* session = (Session*)handleManager->getSession(hSession);
1800 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1803 Slot* slot = session->getSlot();
1804 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1806 // Determine whether we have a public session or not.
1807 bool isPublicSession;
1808 switch (session->getState()) {
1809 case CKS_RO_USER_FUNCTIONS:
1810 case CKS_RW_USER_FUNCTIONS:
1811 isPublicSession = false;
1814 isPublicSession = true;
1818 Token* token = session->getToken();
1819 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1821 // Check if we have another operation
1822 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
1824 session->setOpType(SESSION_OP_FIND);
1825 FindOperation *findOp = FindOperation::create();
1827 // Check if we are out of memory
1828 if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
1830 std::set<OSObject*> allObjects;
1831 token->getObjects(allObjects);
1832 sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
1834 std::set<CK_OBJECT_HANDLE> handles;
1835 std::set<OSObject*>::iterator it;
1836 for (it=allObjects.begin(); it != allObjects.end(); ++it)
1838 // Refresh object and check if it is valid
1839 if (!(*it)->isValid()) {
1840 DEBUG_MSG("Object is not valid, skipping");
1844 // Determine if the object has CKA_PRIVATE set to CK_TRUE
1845 bool isPrivateObject = (*it)->getBooleanValue(CKA_PRIVATE, true);
1847 // If the object is private, and we are in a public session then skip it !
1848 if (isPublicSession && isPrivateObject)
1849 continue; // skip object
1851 // Perform the actual attribute matching.
1852 bool bAttrMatch = true; // We let an empty template match everything.
1853 for (CK_ULONG i=0; i<ulCount; ++i)
1857 if (!(*it)->attributeExists(pTemplate[i].type))
1860 OSAttribute attr = (*it)->getAttribute(pTemplate[i].type);
1862 if (attr.isBooleanAttribute())
1864 if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
1866 bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
1867 if (attr.getBooleanValue() != bTemplateValue)
1872 if (attr.isUnsignedLongAttribute())
1874 if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
1876 CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
1877 if (attr.getUnsignedLongValue() != ulTemplateValue)
1882 if (attr.isByteStringAttribute())
1884 ByteString bsAttrValue;
1885 if (isPrivateObject && attr.getByteStringValue().size() != 0)
1887 if (!token->decrypt(attr.getByteStringValue(), bsAttrValue))
1890 return CKR_GENERAL_ERROR;
1894 bsAttrValue = attr.getByteStringValue();
1896 if (bsAttrValue.size() != pTemplate[i].ulValueLen)
1898 if (pTemplate[i].ulValueLen != 0)
1900 ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
1901 if (bsAttrValue != bsTemplateValue)
1909 // The attribute matched !
1915 CK_SLOT_ID slotID = slot->getSlotID();
1916 bool isOnToken = (*it)->getBooleanValue(CKA_TOKEN, false);
1917 bool isPrivate = (*it)->getBooleanValue(CKA_PRIVATE, true);
1918 // Create an object handle for every returned object.
1919 CK_OBJECT_HANDLE hObject;
1921 hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
1923 hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
1924 if (hObject == CK_INVALID_HANDLE)
1927 return CKR_GENERAL_ERROR;
1929 handles.insert(hObject);
1933 // Storing the object handles for the find will protect the library
1934 // whenever a stale object handle is used to access the library.
1935 findOp->setHandles(handles);
1937 session->setFindOp(findOp);
1942 // Continue the search for objects in the specified session
1943 CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
1945 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1946 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1947 if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
1950 Session* session = (Session*)handleManager->getSession(hSession);
1951 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1953 // Check if we are doing the correct operation
1954 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1956 // return the object handles that have been added to the find operation.
1957 FindOperation *findOp = session->getFindOp();
1958 if (findOp == NULL) return CKR_GENERAL_ERROR;
1960 // Ask the find operation to retrieve the object handles
1961 *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
1963 // Erase the object handles from the find operation.
1964 findOp->eraseHandles(0,*pulObjectCount);
1969 // Finish searching for objects
1970 CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1972 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1975 Session* session = (Session*)handleManager->getSession(hSession);
1976 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1978 // Check if we are doing the correct operation
1979 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1985 // Encrypt*/Decrypt*() is for Symmetrical ciphers too
1986 static bool isSymMechanism(CK_MECHANISM_PTR pMechanism)
1988 if (pMechanism == NULL_PTR) return false;
1990 switch(pMechanism->mechanism) {
1993 case CKM_DES_CBC_PAD:
1996 case CKM_DES3_CBC_PAD:
1999 case CKM_AES_CBC_PAD:
2008 // SymAlgorithm version of C_EncryptInit
2009 CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2011 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2013 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2016 Session* session = (Session*)handleManager->getSession(hSession);
2017 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2019 // Check if we have another operation
2020 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2023 Token* token = session->getToken();
2024 if (token == NULL) return CKR_GENERAL_ERROR;
2026 // Check the key handle.
2027 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2028 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2030 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2031 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2033 // Check read user credentials
2034 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2037 if (rv == CKR_USER_NOT_LOGGED_IN)
2038 INFO_MSG("User is not authorized");
2043 // Check if key can be used for encryption
2044 if (!key->getBooleanValue(CKA_ENCRYPT, false))
2045 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2047 // Check if the specified mechanism is allowed for the key
2048 if (!isMechanismPermitted(key, pMechanism))
2049 return CKR_MECHANISM_INVALID;
2051 // Get the symmetric algorithm matching the mechanism
2052 SymAlgo::Type algo = SymAlgo::Unknown;
2053 SymMode::Type mode = SymMode::Unknown;
2054 bool padding = false;
2057 size_t counterBits = 0;
2059 size_t tagBytes = 0;
2060 switch(pMechanism->mechanism) {
2063 algo = SymAlgo::DES;
2064 mode = SymMode::ECB;
2068 algo = SymAlgo::DES;
2069 mode = SymMode::CBC;
2070 if (pMechanism->pParameter == NULL_PTR ||
2071 pMechanism->ulParameterLen == 0)
2073 DEBUG_MSG("CBC mode requires an init vector");
2074 return CKR_ARGUMENTS_BAD;
2076 iv.resize(pMechanism->ulParameterLen);
2077 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2080 case CKM_DES_CBC_PAD:
2081 algo = SymAlgo::DES;
2082 mode = SymMode::CBC;
2084 if (pMechanism->pParameter == NULL_PTR ||
2085 pMechanism->ulParameterLen == 0)
2087 DEBUG_MSG("CBC mode requires an init vector");
2088 return CKR_ARGUMENTS_BAD;
2090 iv.resize(pMechanism->ulParameterLen);
2091 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2096 algo = SymAlgo::DES3;
2097 mode = SymMode::ECB;
2101 algo = SymAlgo::DES3;
2102 mode = SymMode::CBC;
2103 if (pMechanism->pParameter == NULL_PTR ||
2104 pMechanism->ulParameterLen == 0)
2106 DEBUG_MSG("CBC mode requires an init vector");
2107 return CKR_ARGUMENTS_BAD;
2109 iv.resize(pMechanism->ulParameterLen);
2110 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2113 case CKM_DES3_CBC_PAD:
2114 algo = SymAlgo::DES3;
2115 mode = SymMode::CBC;
2117 if (pMechanism->pParameter == NULL_PTR ||
2118 pMechanism->ulParameterLen == 0)
2120 DEBUG_MSG("CBC mode requires an init vector");
2121 return CKR_ARGUMENTS_BAD;
2123 iv.resize(pMechanism->ulParameterLen);
2124 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2128 algo = SymAlgo::AES;
2129 mode = SymMode::ECB;
2132 algo = SymAlgo::AES;
2133 mode = SymMode::CBC;
2134 if (pMechanism->pParameter == NULL_PTR ||
2135 pMechanism->ulParameterLen == 0)
2137 DEBUG_MSG("CBC mode requires an init vector");
2138 return CKR_ARGUMENTS_BAD;
2140 iv.resize(pMechanism->ulParameterLen);
2141 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2143 case CKM_AES_CBC_PAD:
2144 algo = SymAlgo::AES;
2145 mode = SymMode::CBC;
2147 if (pMechanism->pParameter == NULL_PTR ||
2148 pMechanism->ulParameterLen == 0)
2150 DEBUG_MSG("CBC mode requires an init vector");
2151 return CKR_ARGUMENTS_BAD;
2153 iv.resize(pMechanism->ulParameterLen);
2154 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2157 algo = SymAlgo::AES;
2158 mode = SymMode::CTR;
2159 if (pMechanism->pParameter == NULL_PTR ||
2160 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2162 DEBUG_MSG("CTR mode requires a counter block");
2163 return CKR_ARGUMENTS_BAD;
2165 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2166 if (counterBits == 0 || counterBits > 128)
2168 DEBUG_MSG("Invalid ulCounterBits");
2169 return CKR_MECHANISM_PARAM_INVALID;
2172 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2176 algo = SymAlgo::AES;
2177 mode = SymMode::GCM;
2178 if (pMechanism->pParameter == NULL_PTR ||
2179 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2181 DEBUG_MSG("GCM mode requires parameters");
2182 return CKR_ARGUMENTS_BAD;
2184 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2185 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2186 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2187 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2188 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2189 if (tagBytes > 128 || tagBytes % 8 != 0)
2191 DEBUG_MSG("Invalid ulTagBits value");
2192 return CKR_ARGUMENTS_BAD;
2194 tagBytes = tagBytes / 8;
2198 return CKR_MECHANISM_INVALID;
2200 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2201 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2203 SymmetricKey* secretkey = new SymmetricKey();
2205 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2207 cipher->recycleKey(secretkey);
2208 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2209 return CKR_GENERAL_ERROR;
2212 // adjust key bit length
2213 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2215 // Initialize encryption
2216 if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2218 cipher->recycleKey(secretkey);
2219 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2220 return CKR_MECHANISM_INVALID;
2223 session->setOpType(SESSION_OP_ENCRYPT);
2224 session->setSymmetricCryptoOp(cipher);
2225 session->setAllowMultiPartOp(true);
2226 session->setAllowSinglePartOp(true);
2227 session->setSymmetricKey(secretkey);
2232 // AsymAlgorithm version of C_EncryptInit
2233 CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2235 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2237 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2240 Session* session = (Session*)handleManager->getSession(hSession);
2241 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2243 // Check if we have another operation
2244 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2247 Token* token = session->getToken();
2248 if (token == NULL) return CKR_GENERAL_ERROR;
2250 // Check the key handle.
2251 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2252 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2254 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2255 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2257 // Check read user credentials
2258 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2261 if (rv == CKR_USER_NOT_LOGGED_IN)
2262 INFO_MSG("User is not authorized");
2267 // Check if key can be used for encryption
2268 if (!key->getBooleanValue(CKA_ENCRYPT, false))
2269 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2271 // Get the asymmetric algorithm matching the mechanism
2272 AsymMech::Type mechanism;
2274 switch(pMechanism->mechanism) {
2276 mechanism = AsymMech::RSA_PKCS;
2280 mechanism = AsymMech::RSA;
2283 case CKM_RSA_PKCS_OAEP:
2284 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
2288 mechanism = AsymMech::RSA_PKCS_OAEP;
2292 return CKR_MECHANISM_INVALID;
2295 AsymmetricAlgorithm* asymCrypto = NULL;
2296 PublicKey* publicKey = NULL;
2299 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2300 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2302 publicKey = asymCrypto->newPublicKey();
2303 if (publicKey == NULL)
2305 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2306 return CKR_HOST_MEMORY;
2309 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
2311 asymCrypto->recyclePublicKey(publicKey);
2312 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2313 return CKR_GENERAL_ERROR;
2318 return CKR_MECHANISM_INVALID;
2321 session->setOpType(SESSION_OP_ENCRYPT);
2322 session->setAsymmetricCryptoOp(asymCrypto);
2323 session->setMechanism(mechanism);
2324 session->setAllowMultiPartOp(false);
2325 session->setAllowSinglePartOp(true);
2326 session->setPublicKey(publicKey);
2331 // Initialise encryption using the specified object and mechanism
2332 CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2334 if (isSymMechanism(pMechanism))
2335 return SymEncryptInit(hSession, pMechanism, hKey);
2337 return AsymEncryptInit(hSession, pMechanism, hKey);
2340 // SymAlgorithm version of C_Encrypt
2341 static CK_RV SymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2343 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2344 if (cipher == NULL || !session->getAllowSinglePartOp())
2347 return CKR_OPERATION_NOT_INITIALIZED;
2351 CK_ULONG maxSize = ulDataLen + cipher->getTagBytes();
2352 if (cipher->isBlockCipher())
2354 CK_ULONG remainder = ulDataLen % cipher->getBlockSize();
2355 if (cipher->getPaddingMode() == false && remainder != 0)
2358 return CKR_DATA_LEN_RANGE;
2361 // Round up to block size
2364 maxSize = ulDataLen + cipher->getBlockSize() - remainder;
2366 else if (cipher->getPaddingMode() == true)
2368 maxSize = ulDataLen + cipher->getBlockSize();
2371 if (!cipher->checkMaximumBytes(ulDataLen))
2374 return CKR_DATA_LEN_RANGE;
2377 if (pEncryptedData == NULL_PTR)
2379 *pulEncryptedDataLen = maxSize;
2383 // Check buffer size
2384 if (*pulEncryptedDataLen < maxSize)
2386 *pulEncryptedDataLen = maxSize;
2387 return CKR_BUFFER_TOO_SMALL;
2391 ByteString data(pData, ulDataLen);
2392 ByteString encryptedData;
2395 if (!cipher->encryptUpdate(data, encryptedData))
2398 return CKR_GENERAL_ERROR;
2401 // Finalize encryption
2402 ByteString encryptedFinal;
2403 if (!cipher->encryptFinal(encryptedFinal))
2406 return CKR_GENERAL_ERROR;
2408 encryptedData += encryptedFinal;
2409 encryptedData.resize(maxSize);
2411 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2412 *pulEncryptedDataLen = encryptedData.size();
2418 // AsymAlgorithm version of C_Encrypt
2419 static CK_RV AsymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2421 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
2422 AsymMech::Type mechanism = session->getMechanism();
2423 PublicKey* publicKey = session->getPublicKey();
2424 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
2427 return CKR_OPERATION_NOT_INITIALIZED;
2430 // Size of the encrypted data
2431 CK_ULONG size = publicKey->getOutputLength();
2433 if (pEncryptedData == NULL_PTR)
2435 *pulEncryptedDataLen = size;
2439 // Check buffer size
2440 if (*pulEncryptedDataLen < size)
2442 *pulEncryptedDataLen = size;
2443 return CKR_BUFFER_TOO_SMALL;
2448 ByteString encryptedData;
2450 // We must allow input length <= k and therfore need to prepend the data with zeroes.
2451 if (mechanism == AsymMech::RSA) {
2452 data.wipe(size-ulDataLen);
2455 data += ByteString(pData, ulDataLen);
2458 if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
2461 return CKR_GENERAL_ERROR;
2465 if (encryptedData.size() != size)
2467 ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
2469 return CKR_GENERAL_ERROR;
2471 memcpy(pEncryptedData, encryptedData.byte_str(), size);
2472 *pulEncryptedDataLen = size;
2478 // Perform a single operation encryption operation in the specified session
2479 CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2481 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2483 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2484 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2487 Session* session = (Session*)handleManager->getSession(hSession);
2488 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2490 // Check if we are doing the correct operation
2491 if (session->getOpType() != SESSION_OP_ENCRYPT)
2492 return CKR_OPERATION_NOT_INITIALIZED;
2494 if (session->getSymmetricCryptoOp() != NULL)
2495 return SymEncrypt(session, pData, ulDataLen,
2496 pEncryptedData, pulEncryptedDataLen);
2498 return AsymEncrypt(session, pData, ulDataLen,
2499 pEncryptedData, pulEncryptedDataLen);
2502 // SymAlgorithm version of C_EncryptUpdate
2503 static CK_RV SymEncryptUpdate(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2505 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2506 if (cipher == NULL || !session->getAllowMultiPartOp())
2509 return CKR_OPERATION_NOT_INITIALIZED;
2513 size_t blockSize = cipher->getBlockSize();
2514 size_t remainingSize = cipher->getBufferSize();
2515 CK_ULONG maxSize = ulDataLen + remainingSize;
2516 if (cipher->isBlockCipher())
2518 int nrOfBlocks = (ulDataLen + remainingSize) / blockSize;
2519 maxSize = nrOfBlocks * blockSize;
2521 if (!cipher->checkMaximumBytes(ulDataLen))
2524 return CKR_DATA_LEN_RANGE;
2528 if (pEncryptedData == NULL_PTR)
2530 *pulEncryptedDataLen = maxSize;
2534 // Check output buffer size
2535 if (*pulEncryptedDataLen < maxSize)
2537 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
2538 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize);
2539 *pulEncryptedDataLen = maxSize;
2540 return CKR_BUFFER_TOO_SMALL;
2544 ByteString data(pData, ulDataLen);
2545 ByteString encryptedData;
2548 if (!cipher->encryptUpdate(data, encryptedData))
2551 return CKR_GENERAL_ERROR;
2553 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x encryptedData.size(): %#5x",
2554 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize, encryptedData.size());
2556 // Check output size from crypto. Unrecoverable error if to large.
2557 if (*pulEncryptedDataLen < encryptedData.size())
2560 ERROR_MSG("EncryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2561 *pulEncryptedDataLen, encryptedData.size());
2562 return CKR_GENERAL_ERROR;
2565 if (encryptedData.size() > 0)
2567 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2569 *pulEncryptedDataLen = encryptedData.size();
2574 // Feed data to the running encryption operation in a session
2575 CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2577 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2579 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2580 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2583 Session* session = (Session*)handleManager->getSession(hSession);
2584 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2586 // Check if we are doing the correct operation
2587 if (session->getOpType() != SESSION_OP_ENCRYPT)
2588 return CKR_OPERATION_NOT_INITIALIZED;
2590 if (session->getSymmetricCryptoOp() != NULL)
2591 return SymEncryptUpdate(session, pData, ulDataLen,
2592 pEncryptedData, pulEncryptedDataLen);
2594 return CKR_FUNCTION_NOT_SUPPORTED;
2597 // SymAlgorithm version of C_EncryptFinal
2598 static CK_RV SymEncryptFinal(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2600 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2601 if (cipher == NULL || !session->getAllowMultiPartOp())
2604 return CKR_OPERATION_NOT_INITIALIZED;
2608 size_t remainingSize = cipher->getBufferSize() + cipher->getTagBytes();
2609 CK_ULONG size = remainingSize;
2610 if (cipher->isBlockCipher())
2612 size_t blockSize = cipher->getBlockSize();
2613 bool isPadding = cipher->getPaddingMode();
2614 if ((remainingSize % blockSize) != 0 && !isPadding)
2617 DEBUG_MSG("Remaining buffer size is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
2618 blockSize, remainingSize);
2619 return CKR_DATA_LEN_RANGE;
2621 // when padding: an integral of the block size that is longer than the remaining data.
2622 size = isPadding ? ((remainingSize + blockSize) / blockSize) * blockSize : remainingSize;
2625 // Give required output buffer size.
2626 if (pEncryptedData == NULL_PTR)
2628 *pulEncryptedDataLen = size;
2632 // Check output buffer size
2633 if (*pulEncryptedDataLen < size)
2635 DEBUG_MSG("output buffer size: %#5x size: %#5x",
2636 *pulEncryptedDataLen, size);
2637 *pulEncryptedDataLen = size;
2638 return CKR_BUFFER_TOO_SMALL;
2641 // Finalize encryption
2642 ByteString encryptedFinal;
2643 if (!cipher->encryptFinal(encryptedFinal))
2646 return CKR_GENERAL_ERROR;
2648 DEBUG_MSG("output buffer size: %#2x size: %#2x encryptedFinal.size(): %#2x",
2649 *pulEncryptedDataLen, size, encryptedFinal.size());
2651 // Check output size from crypto. Unrecoverable error if to large.
2652 if (*pulEncryptedDataLen < encryptedFinal.size())
2655 ERROR_MSG("EncryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2656 *pulEncryptedDataLen, encryptedFinal.size());
2657 return CKR_GENERAL_ERROR;
2660 if (encryptedFinal.size() > 0)
2662 memcpy(pEncryptedData, encryptedFinal.byte_str(), encryptedFinal.size());
2664 *pulEncryptedDataLen = encryptedFinal.size();
2670 // Finalise the encryption operation
2671 CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2673 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2676 Session* session = (Session*)handleManager->getSession(hSession);
2677 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2679 // Check if we are doing the correct operation
2680 if (session->getOpType() != SESSION_OP_ENCRYPT) return CKR_OPERATION_NOT_INITIALIZED;
2682 if (session->getSymmetricCryptoOp() != NULL)
2683 return SymEncryptFinal(session, pEncryptedData, pulEncryptedDataLen);
2685 return CKR_FUNCTION_NOT_SUPPORTED;
2688 // SymAlgorithm version of C_DecryptInit
2689 CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2691 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2693 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2696 Session* session = (Session*)handleManager->getSession(hSession);
2697 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2700 Token* token = session->getToken();
2701 if (token == NULL) return CKR_GENERAL_ERROR;
2703 // Check if we have another operation
2704 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2706 // Check the key handle.
2707 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2708 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2710 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2711 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2713 // Check read user credentials
2714 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2717 if (rv == CKR_USER_NOT_LOGGED_IN)
2718 INFO_MSG("User is not authorized");
2723 // Check if key can be used for decryption
2724 if (!key->getBooleanValue(CKA_DECRYPT, false))
2725 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2728 // Check if the specified mechanism is allowed for the key
2729 if (!isMechanismPermitted(key, pMechanism))
2730 return CKR_MECHANISM_INVALID;
2732 // Get the symmetric algorithm matching the mechanism
2733 SymAlgo::Type algo = SymAlgo::Unknown;
2734 SymMode::Type mode = SymMode::Unknown;
2735 bool padding = false;
2738 size_t counterBits = 0;
2740 size_t tagBytes = 0;
2741 switch(pMechanism->mechanism) {
2744 algo = SymAlgo::DES;
2745 mode = SymMode::ECB;
2749 algo = SymAlgo::DES;
2750 mode = SymMode::CBC;
2751 if (pMechanism->pParameter == NULL_PTR ||
2752 pMechanism->ulParameterLen == 0)
2754 DEBUG_MSG("CBC mode requires an init vector");
2755 return CKR_ARGUMENTS_BAD;
2757 iv.resize(pMechanism->ulParameterLen);
2758 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2761 case CKM_DES_CBC_PAD:
2762 algo = SymAlgo::DES;
2763 mode = SymMode::CBC;
2765 if (pMechanism->pParameter == NULL_PTR ||
2766 pMechanism->ulParameterLen == 0)
2768 DEBUG_MSG("CBC mode requires an init vector");
2769 return CKR_ARGUMENTS_BAD;
2771 iv.resize(pMechanism->ulParameterLen);
2772 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2777 algo = SymAlgo::DES3;
2778 mode = SymMode::ECB;
2782 algo = SymAlgo::DES3;
2783 mode = SymMode::CBC;
2784 if (pMechanism->pParameter == NULL_PTR ||
2785 pMechanism->ulParameterLen == 0)
2787 DEBUG_MSG("CBC mode requires an init vector");
2788 return CKR_ARGUMENTS_BAD;
2790 iv.resize(pMechanism->ulParameterLen);
2791 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2794 case CKM_DES3_CBC_PAD:
2795 algo = SymAlgo::DES3;
2796 mode = SymMode::CBC;
2798 if (pMechanism->pParameter == NULL_PTR ||
2799 pMechanism->ulParameterLen == 0)
2801 DEBUG_MSG("CBC mode requires an init vector");
2802 return CKR_ARGUMENTS_BAD;
2804 iv.resize(pMechanism->ulParameterLen);
2805 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2809 algo = SymAlgo::AES;
2810 mode = SymMode::ECB;
2813 algo = SymAlgo::AES;
2814 mode = SymMode::CBC;
2815 if (pMechanism->pParameter == NULL_PTR ||
2816 pMechanism->ulParameterLen == 0)
2818 DEBUG_MSG("CBC mode requires an init vector");
2819 return CKR_ARGUMENTS_BAD;
2821 iv.resize(pMechanism->ulParameterLen);
2822 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2824 case CKM_AES_CBC_PAD:
2825 algo = SymAlgo::AES;
2826 mode = SymMode::CBC;
2828 if (pMechanism->pParameter == NULL_PTR ||
2829 pMechanism->ulParameterLen == 0)
2831 DEBUG_MSG("CBC mode requires an init vector");
2832 return CKR_ARGUMENTS_BAD;
2834 iv.resize(pMechanism->ulParameterLen);
2835 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2838 algo = SymAlgo::AES;
2839 mode = SymMode::CTR;
2840 if (pMechanism->pParameter == NULL_PTR ||
2841 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2843 DEBUG_MSG("CTR mode requires a counter block");
2844 return CKR_ARGUMENTS_BAD;
2846 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2847 if (counterBits == 0 || counterBits > 128)
2849 DEBUG_MSG("Invalid ulCounterBits");
2850 return CKR_MECHANISM_PARAM_INVALID;
2853 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2857 algo = SymAlgo::AES;
2858 mode = SymMode::GCM;
2859 if (pMechanism->pParameter == NULL_PTR ||
2860 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2862 DEBUG_MSG("GCM mode requires parameters");
2863 return CKR_ARGUMENTS_BAD;
2865 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2866 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2867 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2868 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2869 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2870 if (tagBytes > 128 || tagBytes % 8 != 0)
2872 DEBUG_MSG("Invalid ulTagBits value");
2873 return CKR_ARGUMENTS_BAD;
2875 tagBytes = tagBytes / 8;
2879 return CKR_MECHANISM_INVALID;
2881 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2882 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2884 SymmetricKey* secretkey = new SymmetricKey();
2886 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2888 cipher->recycleKey(secretkey);
2889 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2890 return CKR_GENERAL_ERROR;
2893 // adjust key bit length
2894 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2896 // Initialize decryption
2897 if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2899 cipher->recycleKey(secretkey);
2900 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2901 return CKR_MECHANISM_INVALID;
2904 session->setOpType(SESSION_OP_DECRYPT);
2905 session->setSymmetricCryptoOp(cipher);
2906 session->setAllowMultiPartOp(true);
2907 session->setAllowSinglePartOp(true);
2908 session->setSymmetricKey(secretkey);
2913 // AsymAlgorithm version of C_DecryptInit
2914 CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2916 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2918 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2921 Session* session = (Session*)handleManager->getSession(hSession);
2922 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2925 Token* token = session->getToken();
2926 if (token == NULL) return CKR_GENERAL_ERROR;
2928 // Check if we have another operation
2929 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2931 // Check the key handle.
2932 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2933 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2935 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2936 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2938 // Check read user credentials
2939 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2942 if (rv == CKR_USER_NOT_LOGGED_IN)
2943 INFO_MSG("User is not authorized");
2948 // Check if key can be used for decryption
2949 if (!key->getBooleanValue(CKA_DECRYPT, false))
2950 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2952 // Check if the specified mechanism is allowed for the key
2953 if (!isMechanismPermitted(key, pMechanism))
2954 return CKR_MECHANISM_INVALID;
2956 // Get the asymmetric algorithm matching the mechanism
2957 AsymMech::Type mechanism = AsymMech::Unknown;
2959 switch(pMechanism->mechanism) {
2961 mechanism = AsymMech::RSA_PKCS;
2965 mechanism = AsymMech::RSA;
2968 case CKM_RSA_PKCS_OAEP:
2969 if (pMechanism->pParameter == NULL_PTR ||
2970 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
2972 DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
2973 return CKR_ARGUMENTS_BAD;
2975 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
2977 DEBUG_MSG("hashAlg must be CKM_SHA_1");
2978 return CKR_ARGUMENTS_BAD;
2980 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
2982 DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
2983 return CKR_ARGUMENTS_BAD;
2986 mechanism = AsymMech::RSA_PKCS_OAEP;
2990 return CKR_MECHANISM_INVALID;
2993 AsymmetricAlgorithm* asymCrypto = NULL;
2994 PrivateKey* privateKey = NULL;
2997 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2998 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
3000 privateKey = asymCrypto->newPrivateKey();
3001 if (privateKey == NULL)
3003 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
3004 return CKR_HOST_MEMORY;
3007 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
3009 asymCrypto->recyclePrivateKey(privateKey);
3010 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
3011 return CKR_GENERAL_ERROR;
3016 return CKR_MECHANISM_INVALID;
3019 // Check if re-authentication is required
3020 if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
3022 session->setReAuthentication(true);
3025 session->setOpType(SESSION_OP_DECRYPT);
3026 session->setAsymmetricCryptoOp(asymCrypto);
3027 session->setMechanism(mechanism);
3028 session->setAllowMultiPartOp(false);
3029 session->setAllowSinglePartOp(true);
3030 session->setPrivateKey(privateKey);
3035 // Initialise decryption using the specified object
3036 CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3038 if (isSymMechanism(pMechanism))
3039 return SymDecryptInit(hSession, pMechanism, hKey);
3041 return AsymDecryptInit(hSession, pMechanism, hKey);
3044 // SymAlgorithm version of C_Decrypt
3045 static CK_RV SymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3047 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3048 if (cipher == NULL || !session->getAllowSinglePartOp())
3051 return CKR_OPERATION_NOT_INITIALIZED;
3054 // Check encrypted data size
3055 if (cipher->isBlockCipher() && ulEncryptedDataLen % cipher->getBlockSize() != 0)
3058 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3060 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3063 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3066 if (pData == NULL_PTR)
3068 *pulDataLen = ulEncryptedDataLen;
3072 // Check buffer size
3073 if (*pulDataLen < ulEncryptedDataLen)
3075 *pulDataLen = ulEncryptedDataLen;
3076 return CKR_BUFFER_TOO_SMALL;
3080 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3084 if (!cipher->decryptUpdate(encryptedData,data))
3087 return CKR_GENERAL_ERROR;
3090 // Finalize decryption
3091 ByteString dataFinal;
3092 if (!cipher->decryptFinal(dataFinal))
3095 return CKR_GENERAL_ERROR;
3098 if (data.size() > ulEncryptedDataLen)
3100 data.resize(ulEncryptedDataLen);
3103 if (data.size() != 0)
3105 memcpy(pData, data.byte_str(), data.size());
3107 *pulDataLen = data.size();
3114 // AsymAlgorithm version of C_Decrypt
3115 static CK_RV AsymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3117 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
3118 AsymMech::Type mechanism = session->getMechanism();
3119 PrivateKey* privateKey = session->getPrivateKey();
3120 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
3123 return CKR_OPERATION_NOT_INITIALIZED;
3126 // Check if re-authentication is required
3127 if (session->getReAuthentication())
3130 return CKR_USER_NOT_LOGGED_IN;
3134 CK_ULONG size = privateKey->getOutputLength();
3135 if (pData == NULL_PTR)
3141 // Check buffer size
3142 if (*pulDataLen < size)
3145 return CKR_BUFFER_TOO_SMALL;
3149 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3153 if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
3156 return CKR_GENERAL_ERROR;
3160 if (data.size() > size)
3162 ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
3164 return CKR_GENERAL_ERROR;
3166 if (data.size() != 0)
3168 memcpy(pData, data.byte_str(), data.size());
3170 *pulDataLen = data.size();
3177 // Perform a single operation decryption in the given session
3178 CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3180 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3182 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3183 if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3186 Session* session = (Session*)handleManager->getSession(hSession);
3187 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3189 // Check if we are doing the correct operation
3190 if (session->getOpType() != SESSION_OP_DECRYPT)
3191 return CKR_OPERATION_NOT_INITIALIZED;
3193 if (session->getSymmetricCryptoOp() != NULL)
3194 return SymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3197 return AsymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3201 // SymAlgorithm version of C_DecryptUpdate
3202 static CK_RV SymDecryptUpdate(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3204 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3205 if (cipher == NULL || !session->getAllowMultiPartOp())
3208 return CKR_OPERATION_NOT_INITIALIZED;
3211 // Check encrypted data size
3212 size_t blockSize = cipher->getBlockSize();
3213 size_t remainingSize = cipher->getBufferSize();
3214 CK_ULONG maxSize = ulEncryptedDataLen + remainingSize;
3215 if (cipher->isBlockCipher())
3217 // There must always be one block left in padding mode if next operation is DecryptFinal.
3218 // To guarantee that one byte is removed in padding mode when the number of blocks is calculated.
3219 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3220 int nrOfBlocks = (ulEncryptedDataLen + remainingSize - paddingAdjustByte) / blockSize;
3221 maxSize = nrOfBlocks * blockSize;
3223 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3226 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3229 // Give required output buffer size.
3230 if (pData == NULL_PTR)
3232 *pDataLen = maxSize;
3236 // Check output buffer size
3237 if (*pDataLen < maxSize)
3239 DEBUG_MSG("Output buffer too short ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
3240 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize);
3241 *pDataLen = maxSize;
3242 return CKR_BUFFER_TOO_SMALL;
3246 ByteString data(pEncryptedData, ulEncryptedDataLen);
3247 ByteString decryptedData;
3250 if (!cipher->decryptUpdate(data, decryptedData))
3253 return CKR_GENERAL_ERROR;
3255 DEBUG_MSG("ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x decryptedData.size(): %#5x",
3256 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize, decryptedData.size());
3258 // Check output size from crypto. Unrecoverable error if to large.
3259 if (*pDataLen < decryptedData.size())
3262 ERROR_MSG("DecryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the decrypt.",
3263 *pDataLen, decryptedData.size());
3264 return CKR_GENERAL_ERROR;
3267 if (decryptedData.size() > 0)
3269 memcpy(pData, decryptedData.byte_str(), decryptedData.size());
3271 *pDataLen = decryptedData.size();
3277 // Feed data to the running decryption operation in a session
3278 CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3280 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3282 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3283 if (pDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3286 Session* session = (Session*)handleManager->getSession(hSession);
3287 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3289 // Check if we are doing the correct operation
3290 if (session->getOpType() != SESSION_OP_DECRYPT)
3291 return CKR_OPERATION_NOT_INITIALIZED;
3293 if (session->getSymmetricCryptoOp() != NULL)
3294 return SymDecryptUpdate(session, pEncryptedData, ulEncryptedDataLen,
3297 return CKR_FUNCTION_NOT_SUPPORTED;
3300 static CK_RV SymDecryptFinal(Session* session, CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen)
3302 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3303 if (cipher == NULL || !session->getAllowMultiPartOp())
3306 return CKR_OPERATION_NOT_INITIALIZED;
3309 // Check encrypted data size
3310 size_t remainingSize = cipher->getBufferSize();
3311 CK_ULONG size = remainingSize;
3312 if (cipher->isBlockCipher())
3314 size_t blockSize = cipher->getBlockSize();
3315 if (remainingSize % blockSize != 0)
3318 DEBUG_MSG("Remaining data length is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
3319 blockSize, remainingSize);
3320 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3322 // It is at least one padding byte. If no padding the all remains will be returned.
3323 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3324 size = remainingSize - paddingAdjustByte;
3327 // Give required output buffer size.
3328 if (pDecryptedData == NULL_PTR)
3330 *pulDecryptedDataLen = size;
3334 // Check output buffer size
3335 if (*pulDecryptedDataLen < size)
3337 DEBUG_MSG("output buffer size: %#5x size: %#5x",
3338 *pulDecryptedDataLen, size);
3339 *pulDecryptedDataLen = size;
3340 return CKR_BUFFER_TOO_SMALL;
3343 // Finalize decryption
3344 ByteString decryptedFinal;
3345 if (!cipher->decryptFinal(decryptedFinal))
3348 return CKR_GENERAL_ERROR;
3350 DEBUG_MSG("output buffer size: %#2x size: %#2x decryptedFinal.size(): %#2x",
3351 *pulDecryptedDataLen, size, decryptedFinal.size());
3353 // Check output size from crypto. Unrecoverable error if to large.
3354 if (*pulDecryptedDataLen < decryptedFinal.size())
3357 ERROR_MSG("DecryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
3358 *pulDecryptedDataLen, decryptedFinal.size());
3359 return CKR_GENERAL_ERROR;
3362 if (decryptedFinal.size() > 0)
3364 memcpy(pDecryptedData, decryptedFinal.byte_str(), decryptedFinal.size());
3366 *pulDecryptedDataLen = decryptedFinal.size();
3372 // Finalise the decryption operation
3373 CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3375 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3378 Session* session = (Session*)handleManager->getSession(hSession);
3379 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3381 // Check if we are doing the correct operation
3382 if (session->getOpType() != SESSION_OP_DECRYPT) return CKR_OPERATION_NOT_INITIALIZED;
3384 if (session->getSymmetricCryptoOp() != NULL)
3385 return SymDecryptFinal(session, pData, pDataLen);
3387 return CKR_FUNCTION_NOT_SUPPORTED;
3390 // Initialise digesting using the specified mechanism in the specified session
3391 CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
3393 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3395 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3398 Session* session = (Session*)handleManager->getSession(hSession);
3399 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3401 // Check if we have another operation
3402 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3404 // Get the mechanism
3405 HashAlgo::Type algo = HashAlgo::Unknown;
3406 switch(pMechanism->mechanism) {
3409 algo = HashAlgo::MD5;
3413 algo = HashAlgo::SHA1;
3416 algo = HashAlgo::SHA224;
3419 algo = HashAlgo::SHA256;
3422 algo = HashAlgo::SHA384;
3425 algo = HashAlgo::SHA512;
3429 algo = HashAlgo::GOST;
3433 return CKR_MECHANISM_INVALID;
3435 HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(algo);
3436 if (hash == NULL) return CKR_MECHANISM_INVALID;
3438 // Initialize hashing
3439 if (hash->hashInit() == false)
3441 CryptoFactory::i()->recycleHashAlgorithm(hash);
3442 return CKR_GENERAL_ERROR;
3445 session->setOpType(SESSION_OP_DIGEST);
3446 session->setDigestOp(hash);
3447 session->setHashAlgo(algo);
3452 // Digest the specified data in a one-pass operation and return the resulting digest
3453 CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3455 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3457 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3458 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3461 Session* session = (Session*)handleManager->getSession(hSession);
3462 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3464 // Check if we are doing the correct operation
3465 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3468 CK_ULONG size = session->getDigestOp()->getHashSize();
3469 if (pDigest == NULL_PTR)
3471 *pulDigestLen = size;
3475 // Check buffer size
3476 if (*pulDigestLen < size)
3478 *pulDigestLen = size;
3479 return CKR_BUFFER_TOO_SMALL;
3483 ByteString data(pData, ulDataLen);
3486 if (session->getDigestOp()->hashUpdate(data) == false)
3489 return CKR_GENERAL_ERROR;
3494 if (session->getDigestOp()->hashFinal(digest) == false)
3497 return CKR_GENERAL_ERROR;
3501 if (digest.size() != size)
3503 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3505 return CKR_GENERAL_ERROR;
3507 memcpy(pDigest, digest.byte_str(), size);
3508 *pulDigestLen = size;
3515 // Update a running digest operation
3516 CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
3518 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3520 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
3523 Session* session = (Session*)handleManager->getSession(hSession);
3524 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3526 // Check if we are doing the correct operation
3527 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3530 ByteString data(pPart, ulPartLen);
3533 if (session->getDigestOp()->hashUpdate(data) == false)
3536 return CKR_GENERAL_ERROR;
3542 // Update a running digest operation by digesting a secret key with the specified handle
3543 CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3545 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3548 Session* session = (Session*)handleManager->getSession(hSession);
3549 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3551 // Check if we are doing the correct operation
3552 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3555 Token* token = session->getToken();
3556 if (token == NULL) return CKR_GENERAL_ERROR;
3558 // Check the key handle.
3559 OSObject *key = (OSObject *)handleManager->getObject(hObject);
3560 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
3562 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3563 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3565 // Check read user credentials
3566 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3569 if (rv == CKR_USER_NOT_LOGGED_IN)
3570 INFO_MSG("User is not authorized");
3572 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
3573 // so we use CKR_GENERAL_ERROR.
3574 return CKR_GENERAL_ERROR;
3578 HashAlgo::Type algo = session->getHashAlgo();
3579 if (algo != HashAlgo::SHA1 &&
3580 algo != HashAlgo::SHA224 &&
3581 algo != HashAlgo::SHA256 &&
3582 algo != HashAlgo::SHA384 &&
3583 algo != HashAlgo::SHA512)
3586 if (!key->getBooleanValue(CKA_EXTRACTABLE, false))
3587 return CKR_KEY_INDIGESTIBLE;
3588 if (key->getBooleanValue(CKA_SENSITIVE, false))
3589 return CKR_KEY_INDIGESTIBLE;
3593 if (!key->attributeExists(CKA_VALUE))
3594 return CKR_KEY_INDIGESTIBLE;
3598 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
3599 return CKR_GENERAL_ERROR;
3603 keybits = key->getByteStringValue(CKA_VALUE);
3607 if (session->getDigestOp()->hashUpdate(keybits) == false)
3610 return CKR_GENERAL_ERROR;
3616 // Finalise the digest operation in the specified session and return the digest
3617 CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3619 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3621 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3624 Session* session = (Session*)handleManager->getSession(hSession);
3625 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3627 // Check if we are doing the correct operation
3628 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3631 CK_ULONG size = session->getDigestOp()->getHashSize();
3632 if (pDigest == NULL_PTR)
3634 *pulDigestLen = size;
3638 // Check buffer size
3639 if (*pulDigestLen < size)
3641 *pulDigestLen = size;
3642 return CKR_BUFFER_TOO_SMALL;
3647 if (session->getDigestOp()->hashFinal(digest) == false)
3650 return CKR_GENERAL_ERROR;
3654 if (digest.size() != size)
3656 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3658 return CKR_GENERAL_ERROR;
3660 memcpy(pDigest, digest.byte_str(), size);
3661 *pulDigestLen = size;
3668 // Sign*/Verify*() is for MACs too
3669 static bool isMacMechanism(CK_MECHANISM_PTR pMechanism)
3671 if (pMechanism == NULL_PTR) return false;
3673 switch(pMechanism->mechanism) {
3675 case CKM_SHA_1_HMAC:
3676 case CKM_SHA224_HMAC:
3677 case CKM_SHA256_HMAC:
3678 case CKM_SHA384_HMAC:
3679 case CKM_SHA512_HMAC:
3681 case CKM_GOSTR3411_HMAC:
3691 // MacAlgorithm version of C_SignInit
3692 CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3694 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3696 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3699 Session* session = (Session*)handleManager->getSession(hSession);
3700 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3702 // Check if we have another operation
3703 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3706 Token* token = session->getToken();
3707 if (token == NULL) return CKR_GENERAL_ERROR;
3709 // Check the key handle.
3710 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3711 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3713 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3714 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3716 // Check read user credentials
3717 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3720 if (rv == CKR_USER_NOT_LOGGED_IN)
3721 INFO_MSG("User is not authorized");
3726 // Check if key can be used for signing
3727 if (!key->getBooleanValue(CKA_SIGN, false))
3728 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3730 // Check if the specified mechanism is allowed for the key
3731 if (!isMechanismPermitted(key, pMechanism))
3732 return CKR_MECHANISM_INVALID;
3735 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
3737 // Get the MAC algorithm matching the mechanism
3738 // Also check mechanism constraints
3739 MacAlgo::Type algo = MacAlgo::Unknown;
3742 switch(pMechanism->mechanism) {
3745 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
3746 return CKR_KEY_TYPE_INCONSISTENT;
3748 algo = MacAlgo::HMAC_MD5;
3751 case CKM_SHA_1_HMAC:
3752 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
3753 return CKR_KEY_TYPE_INCONSISTENT;
3755 algo = MacAlgo::HMAC_SHA1;
3757 case CKM_SHA224_HMAC:
3758 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
3759 return CKR_KEY_TYPE_INCONSISTENT;
3761 algo = MacAlgo::HMAC_SHA224;
3763 case CKM_SHA256_HMAC:
3764 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
3765 return CKR_KEY_TYPE_INCONSISTENT;
3767 algo = MacAlgo::HMAC_SHA256;
3769 case CKM_SHA384_HMAC:
3770 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
3771 return CKR_KEY_TYPE_INCONSISTENT;
3773 algo = MacAlgo::HMAC_SHA384;
3775 case CKM_SHA512_HMAC:
3776 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
3777 return CKR_KEY_TYPE_INCONSISTENT;
3779 algo = MacAlgo::HMAC_SHA512;
3782 case CKM_GOSTR3411_HMAC:
3783 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
3784 return CKR_KEY_TYPE_INCONSISTENT;
3786 algo = MacAlgo::HMAC_GOST;
3790 if (keyType != CKK_DES2 && keyType != CKK_DES3)
3791 return CKR_KEY_TYPE_INCONSISTENT;
3792 algo = MacAlgo::CMAC_DES;
3796 if (keyType != CKK_AES)
3797 return CKR_KEY_TYPE_INCONSISTENT;
3798 algo = MacAlgo::CMAC_AES;
3801 return CKR_MECHANISM_INVALID;
3803 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
3804 if (mac == NULL) return CKR_MECHANISM_INVALID;
3806 SymmetricKey* privkey = new SymmetricKey();
3808 if (getSymmetricKey(privkey, token, key) != CKR_OK)
3810 mac->recycleKey(privkey);
3811 CryptoFactory::i()->recycleMacAlgorithm(mac);
3812 return CKR_GENERAL_ERROR;
3815 // Adjust key bit length
3816 privkey->setBitLen(privkey->getKeyBits().size() * bb);
3819 if (privkey->getBitLen() < (minSize*8))
3821 mac->recycleKey(privkey);
3822 CryptoFactory::i()->recycleMacAlgorithm(mac);
3823 return CKR_KEY_SIZE_RANGE;
3826 // Initialize signing
3827 if (!mac->signInit(privkey))
3829 mac->recycleKey(privkey);
3830 CryptoFactory::i()->recycleMacAlgorithm(mac);
3831 return CKR_MECHANISM_INVALID;
3834 session->setOpType(SESSION_OP_SIGN);
3835 session->setMacOp(mac);
3836 session->setAllowMultiPartOp(true);
3837 session->setAllowSinglePartOp(true);
3838 session->setSymmetricKey(privkey);
3843 // AsymmetricAlgorithm version of C_SignInit
3844 CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3846 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3848 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3851 Session* session = (Session*)handleManager->getSession(hSession);
3852 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3854 // Check if we have another operation
3855 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3858 Token* token = session->getToken();
3859 if (token == NULL) return CKR_GENERAL_ERROR;
3861 // Check the key handle.
3862 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3863 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3865 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3866 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3868 // Check read user credentials
3869 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3872 if (rv == CKR_USER_NOT_LOGGED_IN)
3873 INFO_MSG("User is not authorized");
3878 // Check if key can be used for signing
3879 if (!key->getBooleanValue(CKA_SIGN, false))
3880 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3882 // Check if the specified mechanism is allowed for the key
3883 if (!isMechanismPermitted(key, pMechanism))
3884 return CKR_MECHANISM_INVALID;
3886 // Get the asymmetric algorithm matching the mechanism
3887 AsymMech::Type mechanism = AsymMech::Unknown;
3889 size_t paramLen = 0;
3890 RSA_PKCS_PSS_PARAMS pssParam;
3891 bool bAllowMultiPartOp;
3894 bool isECDSA = false;
3895 switch(pMechanism->mechanism) {
3897 mechanism = AsymMech::RSA_PKCS;
3898 bAllowMultiPartOp = false;
3902 mechanism = AsymMech::RSA;
3903 bAllowMultiPartOp = false;
3907 case CKM_MD5_RSA_PKCS:
3908 mechanism = AsymMech::RSA_MD5_PKCS;
3909 bAllowMultiPartOp = true;
3913 case CKM_SHA1_RSA_PKCS:
3914 mechanism = AsymMech::RSA_SHA1_PKCS;
3915 bAllowMultiPartOp = true;
3918 case CKM_SHA224_RSA_PKCS:
3919 mechanism = AsymMech::RSA_SHA224_PKCS;
3920 bAllowMultiPartOp = true;
3923 case CKM_SHA256_RSA_PKCS:
3924 mechanism = AsymMech::RSA_SHA256_PKCS;
3925 bAllowMultiPartOp = true;
3928 case CKM_SHA384_RSA_PKCS:
3929 mechanism = AsymMech::RSA_SHA384_PKCS;
3930 bAllowMultiPartOp = true;
3933 case CKM_SHA512_RSA_PKCS:
3934 mechanism = AsymMech::RSA_SHA512_PKCS;
3935 bAllowMultiPartOp = true;
3939 case CKM_RSA_PKCS_PSS:
3940 if (pMechanism->pParameter == NULL_PTR ||
3941 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3943 ERROR_MSG("Invalid RSA-PSS parameters");
3944 return CKR_ARGUMENTS_BAD;
3946 mechanism = AsymMech::RSA_PKCS_PSS;
3947 unsigned long allowedMgf;
3949 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
3951 pssParam.hashAlg = HashAlgo::SHA1;
3952 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3953 allowedMgf = CKG_MGF1_SHA1;
3956 pssParam.hashAlg = HashAlgo::SHA224;
3957 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
3958 allowedMgf = CKG_MGF1_SHA224;
3961 pssParam.hashAlg = HashAlgo::SHA256;
3962 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
3963 allowedMgf = CKG_MGF1_SHA256;
3966 pssParam.hashAlg = HashAlgo::SHA384;
3967 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
3968 allowedMgf = CKG_MGF1_SHA384;
3971 pssParam.hashAlg = HashAlgo::SHA512;
3972 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
3973 allowedMgf = CKG_MGF1_SHA512;
3976 ERROR_MSG("Invalid RSA-PSS hash");
3977 return CKR_ARGUMENTS_BAD;
3980 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != allowedMgf) {
3981 ERROR_MSG("Hash and MGF don't match");
3982 return CKR_ARGUMENTS_BAD;
3985 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3987 paramLen = sizeof(pssParam);
3988 bAllowMultiPartOp = false;
3992 case CKM_SHA1_RSA_PKCS_PSS:
3993 if (pMechanism->pParameter == NULL_PTR ||
3994 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3995 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
3996 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
3998 ERROR_MSG("Invalid parameters");
3999 return CKR_ARGUMENTS_BAD;
4001 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
4002 pssParam.hashAlg = HashAlgo::SHA1;
4003 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
4004 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4006 paramLen = sizeof(pssParam);
4007 bAllowMultiPartOp = true;
4010 case CKM_SHA224_RSA_PKCS_PSS:
4011 if (pMechanism->pParameter == NULL_PTR ||
4012 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4013 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
4014 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
4016 ERROR_MSG("Invalid parameters");
4017 return CKR_ARGUMENTS_BAD;
4019 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
4020 pssParam.hashAlg = HashAlgo::SHA224;
4021 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
4022 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4024 paramLen = sizeof(pssParam);
4025 bAllowMultiPartOp = true;
4028 case CKM_SHA256_RSA_PKCS_PSS:
4029 if (pMechanism->pParameter == NULL_PTR ||
4030 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4031 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
4032 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
4034 ERROR_MSG("Invalid parameters");
4035 return CKR_ARGUMENTS_BAD;
4037 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
4038 pssParam.hashAlg = HashAlgo::SHA256;
4039 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
4040 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4042 paramLen = sizeof(pssParam);
4043 bAllowMultiPartOp = true;
4046 case CKM_SHA384_RSA_PKCS_PSS:
4047 if (pMechanism->pParameter == NULL_PTR ||
4048 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4049 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
4050 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
4052 ERROR_MSG("Invalid parameters");
4053 return CKR_ARGUMENTS_BAD;
4055 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
4056 pssParam.hashAlg = HashAlgo::SHA384;
4057 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4058 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4060 paramLen = sizeof(pssParam);
4061 bAllowMultiPartOp = true;
4064 case CKM_SHA512_RSA_PKCS_PSS:
4065 if (pMechanism->pParameter == NULL_PTR ||
4066 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4067 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
4068 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
4070 ERROR_MSG("Invalid parameters");
4071 return CKR_ARGUMENTS_BAD;
4073 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
4074 pssParam.hashAlg = HashAlgo::SHA512;
4075 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4076 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4078 paramLen = sizeof(pssParam);
4079 bAllowMultiPartOp = true;
4083 mechanism = AsymMech::DSA;
4084 bAllowMultiPartOp = false;
4088 mechanism = AsymMech::DSA_SHA1;
4089 bAllowMultiPartOp = true;
4092 case CKM_DSA_SHA224:
4093 mechanism = AsymMech::DSA_SHA224;
4094 bAllowMultiPartOp = true;
4097 case CKM_DSA_SHA256:
4098 mechanism = AsymMech::DSA_SHA256;
4099 bAllowMultiPartOp = true;
4102 case CKM_DSA_SHA384:
4103 mechanism = AsymMech::DSA_SHA384;
4104 bAllowMultiPartOp = true;
4107 case CKM_DSA_SHA512:
4108 mechanism = AsymMech::DSA_SHA512;
4109 bAllowMultiPartOp = true;
4114 mechanism = AsymMech::ECDSA;
4115 bAllowMultiPartOp = false;
4121 mechanism = AsymMech::GOST;
4122 bAllowMultiPartOp = false;
4124 case CKM_GOSTR3410_WITH_GOSTR3411:
4125 mechanism = AsymMech::GOST_GOST;
4126 bAllowMultiPartOp = true;
4130 return CKR_MECHANISM_INVALID;
4133 AsymmetricAlgorithm* asymCrypto = NULL;
4134 PrivateKey* privateKey = NULL;
4137 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
4138 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4140 privateKey = asymCrypto->newPrivateKey();
4141 if (privateKey == NULL)
4143 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4144 return CKR_HOST_MEMORY;
4147 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
4149 asymCrypto->recyclePrivateKey(privateKey);
4150 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4151 return CKR_GENERAL_ERROR;
4156 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
4157 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4159 privateKey = asymCrypto->newPrivateKey();
4160 if (privateKey == NULL)
4162 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4163 return CKR_HOST_MEMORY;
4166 if (getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key) != CKR_OK)
4168 asymCrypto->recyclePrivateKey(privateKey);
4169 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4170 return CKR_GENERAL_ERROR;
4176 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
4177 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4179 privateKey = asymCrypto->newPrivateKey();
4180 if (privateKey == NULL)
4182 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4183 return CKR_HOST_MEMORY;
4186 if (getECPrivateKey((ECPrivateKey*)privateKey, token, key) != CKR_OK)
4188 asymCrypto->recyclePrivateKey(privateKey);
4189 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4190 return CKR_GENERAL_ERROR;
4197 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
4198 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4200 privateKey = asymCrypto->newPrivateKey();
4201 if (privateKey == NULL)
4203 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4204 return CKR_HOST_MEMORY;
4207 if (getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key) != CKR_OK)
4209 asymCrypto->recyclePrivateKey(privateKey);
4210 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4211 return CKR_GENERAL_ERROR;
4214 return CKR_MECHANISM_INVALID;
4218 // Initialize signing
4221 // Extract HW key handle
4222 CK_ULONG hwKeyHandle = 0;
4223 if(!Extract_key_handle (hSession, hKey, &hwKeyHandle))
4225 LOG("ERROR in extracting key handle \n");
4227 return CKR_GENERAL_ERROR;
4229 LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4231 if(! HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen))
4233 return CKR_MECHANISM_INVALID;
4238 if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
4240 asymCrypto->recyclePrivateKey(privateKey);
4241 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4242 return CKR_MECHANISM_INVALID;
4245 session->setOpType(SESSION_OP_SIGN);
4246 session->setAsymmetricCryptoOp(asymCrypto);
4247 session->setMechanism(mechanism);
4248 session->setParameters(param, paramLen);
4249 session->setAllowMultiPartOp(bAllowMultiPartOp);
4250 session->setAllowSinglePartOp(true);
4251 session->setPrivateKey(privateKey);
4252 session->setKeyHandle(hKey);
4257 // Initialise a signing operation using the specified key and mechanism
4258 CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4260 if (isMacMechanism(pMechanism))
4261 return MacSignInit(hSession, pMechanism, hKey);
4263 return AsymSignInit(hSession, pMechanism, hKey);
4266 // MacAlgorithm version of C_Sign
4267 static CK_RV MacSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4269 MacAlgorithm* mac = session->getMacOp();
4270 if (mac == NULL || !session->getAllowSinglePartOp())
4273 return CKR_OPERATION_NOT_INITIALIZED;
4276 // Size of the signature
4277 CK_ULONG size = mac->getMacSize();
4278 if (pSignature == NULL_PTR)
4280 *pulSignatureLen = size;
4284 // Check buffer size
4285 if (*pulSignatureLen < size)
4287 *pulSignatureLen = size;
4288 return CKR_BUFFER_TOO_SMALL;
4292 ByteString data(pData, ulDataLen);
4295 if (!mac->signUpdate(data))
4298 return CKR_GENERAL_ERROR;
4301 // Get the signature
4302 ByteString signature;
4303 if (!mac->signFinal(signature))
4306 return CKR_GENERAL_ERROR;
4310 if (signature.size() != size)
4312 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4314 return CKR_GENERAL_ERROR;
4316 memcpy(pSignature, signature.byte_str(), size);
4317 *pulSignatureLen = size;
4323 // AsymmetricAlgorithm version of C_Sign
4324 static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4326 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4327 AsymMech::Type mechanism = session->getMechanism();
4328 PrivateKey* privateKey = session->getPrivateKey();
4330 void* param = session->getParameters(paramLen);
4331 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4334 return CKR_OPERATION_NOT_INITIALIZED;
4337 // Check if re-authentication is required
4338 if (session->getReAuthentication())
4341 return CKR_USER_NOT_LOGGED_IN;
4344 // Size of the signature
4345 CK_ULONG size = privateKey->getOutputLength();
4346 if (pSignature == NULL_PTR)
4348 *pulSignatureLen = size;
4352 // Check buffer size
4353 if (*pulSignatureLen < size)
4355 *pulSignatureLen = size;
4356 return CKR_BUFFER_TOO_SMALL;
4362 // We must allow input length <= k and therfore need to prepend the data with zeroes.
4363 if (mechanism == AsymMech::RSA) {
4364 data.wipe(size-ulDataLen);
4367 data += ByteString(pData, ulDataLen);
4368 ByteString signature;
4371 if (session->getAllowMultiPartOp())
4373 if (!asymCrypto->signUpdate(data) ||
4374 !asymCrypto->signFinal(signature))
4377 return CKR_GENERAL_ERROR;
4380 else if (!asymCrypto->sign(privateKey,data,signature,mechanism,param,paramLen))
4383 return CKR_GENERAL_ERROR;
4387 if (signature.size() != size)
4389 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4391 return CKR_GENERAL_ERROR;
4393 memcpy(pSignature, signature.byte_str(), size);
4394 *pulSignatureLen = size;
4400 // AsymmetricAlgorithm version of C_Sign
4401 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)
4403 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4404 AsymMech::Type mechanism = session->getMechanism();
4405 PrivateKey* privateKey = session->getPrivateKey();
4406 CK_ULONG hwKeyHandle = 0;
4407 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4410 return CKR_OPERATION_NOT_INITIALIZED;
4413 // Size of the signature
4414 CK_ULONG size = privateKey->getOutputLength();
4415 if (pSignature == NULL_PTR)
4417 *pulSignatureLen = size;
4421 // Check buffer sizeq
4422 if (*pulSignatureLen < size)
4424 *pulSignatureLen = size;
4425 return CKR_BUFFER_TOO_SMALL;
4431 // We must allow input length <= k and therfore need to prepend the data with zeroes.
4432 if (mechanism == AsymMech::RSA) {
4433 data.wipe(size-ulDataLen);
4436 data += ByteString(pData, ulDataLen);
4437 ByteString signature;
4439 // Extract HW key handle
4440 CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4441 if(!Extract_key_handle (hSession, hKey, &hwKeyHandle))
4443 LOG("ERROR in extracting key handle \n");
4445 return CKR_GENERAL_ERROR;
4447 LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4450 if(!HwInfraSign((void *)&hwKeyHandle, mechanism,
4452 pSignature, (int *) pulSignatureLen))
4455 return CKR_GENERAL_ERROR;
4459 if (*pulSignatureLen != size)
4461 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4463 return CKR_GENERAL_ERROR;
4473 // Sign the data in a single pass operation
4474 CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4476 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4478 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
4479 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4482 Session* session = (Session*)handleManager->getSession(hSession);
4483 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4485 // Check if we are doing the correct operation
4486 if (session->getOpType() != SESSION_OP_SIGN)
4487 return CKR_OPERATION_NOT_INITIALIZED;
4489 if (session->getMacOp() != NULL)
4490 return MacSign(session, pData, ulDataLen,
4491 pSignature, pulSignatureLen);
4496 return AsymSignHW(hSession, session, pData, ulDataLen,
4497 pSignature, pulSignatureLen);
4501 return AsymSign(session, pData, ulDataLen,
4502 pSignature, pulSignatureLen);
4507 // MacAlgorithm version of C_SignUpdate
4508 static CK_RV MacSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4510 MacAlgorithm* mac = session->getMacOp();
4511 if (mac == NULL || !session->getAllowMultiPartOp())
4514 return CKR_OPERATION_NOT_INITIALIZED;
4518 ByteString part(pPart, ulPartLen);
4521 if (!mac->signUpdate(part))
4524 return CKR_GENERAL_ERROR;
4527 session->setAllowSinglePartOp(false);
4531 // AsymmetricAlgorithm version of C_SignUpdate
4532 static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4534 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4535 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4538 return CKR_OPERATION_NOT_INITIALIZED;
4541 // Check if re-authentication is required
4542 if (session->getReAuthentication())
4545 return CKR_USER_NOT_LOGGED_IN;
4549 ByteString part(pPart, ulPartLen);
4552 if (!asymCrypto->signUpdate(part))
4555 return CKR_GENERAL_ERROR;
4558 session->setAllowSinglePartOp(false);
4562 // Update a running signing operation with additional data
4563 CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4565 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4567 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
4570 Session* session = (Session*)handleManager->getSession(hSession);
4571 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4573 // Check if we are doing the correct operation
4574 if (session->getOpType() != SESSION_OP_SIGN)
4575 return CKR_OPERATION_NOT_INITIALIZED;
4577 if (session->getMacOp() != NULL)
4578 return MacSignUpdate(session, pPart, ulPartLen);
4580 return AsymSignUpdate(session, pPart, ulPartLen);
4583 // MacAlgorithm version of C_SignFinal
4584 static CK_RV MacSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4586 MacAlgorithm* mac = session->getMacOp();
4590 return CKR_OPERATION_NOT_INITIALIZED;
4593 // Size of the signature
4594 CK_ULONG size = mac->getMacSize();
4595 if (pSignature == NULL_PTR)
4597 *pulSignatureLen = size;
4601 // Check buffer size
4602 if (*pulSignatureLen < size)
4604 *pulSignatureLen = size;
4605 return CKR_BUFFER_TOO_SMALL;
4608 // Get the signature
4609 ByteString signature;
4610 if (!mac->signFinal(signature))
4613 return CKR_GENERAL_ERROR;
4617 if (signature.size() != size)
4619 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4621 return CKR_GENERAL_ERROR;
4623 memcpy(pSignature, signature.byte_str(), size);
4624 *pulSignatureLen = size;
4630 // AsymmetricAlgorithm version of C_SignFinal
4631 static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4633 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4634 PrivateKey* privateKey = session->getPrivateKey();
4635 if (asymCrypto == NULL || privateKey == NULL)
4638 return CKR_OPERATION_NOT_INITIALIZED;
4641 // Check if re-authentication is required
4642 if (session->getReAuthentication())
4645 return CKR_USER_NOT_LOGGED_IN;
4648 // Size of the signature
4649 CK_ULONG size = privateKey->getOutputLength();
4650 if (pSignature == NULL_PTR)
4652 *pulSignatureLen = size;
4656 // Check buffer size
4657 if (*pulSignatureLen < size)
4659 *pulSignatureLen = size;
4660 return CKR_BUFFER_TOO_SMALL;
4663 // Get the signature
4664 ByteString signature;
4665 if (!asymCrypto->signFinal(signature))
4668 return CKR_GENERAL_ERROR;
4672 if (signature.size() != size)
4674 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4676 return CKR_GENERAL_ERROR;
4678 memcpy(pSignature, signature.byte_str(), size);
4679 *pulSignatureLen = size;
4685 // Finalise a running signing operation and return the signature
4686 CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4688 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4690 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4693 Session* session = (Session*)handleManager->getSession(hSession);
4694 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4696 // Check if we are doing the correct operation
4697 if (session->getOpType() != SESSION_OP_SIGN || !session->getAllowMultiPartOp())
4698 return CKR_OPERATION_NOT_INITIALIZED;
4700 if (session->getMacOp() != NULL)
4701 return MacSignFinal(session, pSignature, pulSignatureLen);
4703 return AsymSignFinal(session, pSignature, pulSignatureLen);
4706 // Initialise a signing operation that allows recovery of the signed data
4707 CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
4709 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4712 Session* session = (Session*)handleManager->getSession(hSession);
4713 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4715 // Check if we have another operation
4716 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4718 return CKR_FUNCTION_NOT_SUPPORTED;
4721 // Perform a single part signing operation that allows recovery of the signed data
4722 CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pData*/, CK_ULONG /*ulDataLen*/, CK_BYTE_PTR /*pSignature*/, CK_ULONG_PTR /*pulSignatureLen*/)
4724 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4727 Session* session = (Session*)handleManager->getSession(hSession);
4728 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4730 return CKR_FUNCTION_NOT_SUPPORTED;
4733 // MacAlgorithm version of C_VerifyInit
4734 CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4736 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4738 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4741 Session* session = (Session*)handleManager->getSession(hSession);
4742 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4744 // Check if we have another operation
4745 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4748 Token* token = session->getToken();
4749 if (token == NULL) return CKR_GENERAL_ERROR;
4751 // Check the key handle.
4752 OSObject *key = (OSObject *)handleManager->getObject(hKey);
4753 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4755 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4756 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4758 // Check read user credentials
4759 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4762 if (rv == CKR_USER_NOT_LOGGED_IN)
4763 INFO_MSG("User is not authorized");
4768 // Check if key can be used for verifying
4769 if (!key->getBooleanValue(CKA_VERIFY, false))
4770 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4772 // Check if the specified mechanism is allowed for the key
4773 if (!isMechanismPermitted(key, pMechanism))
4774 return CKR_MECHANISM_INVALID;
4777 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
4779 // Get the MAC algorithm matching the mechanism
4780 // Also check mechanism constraints
4781 MacAlgo::Type algo = MacAlgo::Unknown;
4784 switch(pMechanism->mechanism) {
4787 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
4788 return CKR_KEY_TYPE_INCONSISTENT;
4790 algo = MacAlgo::HMAC_MD5;
4793 case CKM_SHA_1_HMAC:
4794 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
4795 return CKR_KEY_TYPE_INCONSISTENT;
4797 algo = MacAlgo::HMAC_SHA1;
4799 case CKM_SHA224_HMAC:
4800 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
4801 return CKR_KEY_TYPE_INCONSISTENT;
4803 algo = MacAlgo::HMAC_SHA224;
4805 case CKM_SHA256_HMAC:
4806 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
4807 return CKR_KEY_TYPE_INCONSISTENT;
4809 algo = MacAlgo::HMAC_SHA256;
4811 case CKM_SHA384_HMAC:
4812 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
4813 return CKR_KEY_TYPE_INCONSISTENT;
4815 algo = MacAlgo::HMAC_SHA384;
4817 case CKM_SHA512_HMAC:
4818 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
4819 return CKR_KEY_TYPE_INCONSISTENT;
4821 algo = MacAlgo::HMAC_SHA512;
4824 case CKM_GOSTR3411_HMAC:
4825 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
4826 return CKR_KEY_TYPE_INCONSISTENT;
4828 algo = MacAlgo::HMAC_GOST;
4832 if (keyType != CKK_DES2 && keyType != CKK_DES3)
4833 return CKR_KEY_TYPE_INCONSISTENT;
4834 algo = MacAlgo::CMAC_DES;
4838 if (keyType != CKK_AES)
4839 return CKR_KEY_TYPE_INCONSISTENT;
4840 algo = MacAlgo::CMAC_AES;
4843 return CKR_MECHANISM_INVALID;
4845 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
4846 if (mac == NULL) return CKR_MECHANISM_INVALID;
4848 SymmetricKey* pubkey = new SymmetricKey();
4850 if (getSymmetricKey(pubkey, token, key) != CKR_OK)
4852 mac->recycleKey(pubkey);
4853 CryptoFactory::i()->recycleMacAlgorithm(mac);
4854 return CKR_GENERAL_ERROR;
4857 // Adjust key bit length
4858 pubkey->setBitLen(pubkey->getKeyBits().size() * bb);
4861 if (pubkey->getBitLen() < (minSize*8))
4863 mac->recycleKey(pubkey);
4864 CryptoFactory::i()->recycleMacAlgorithm(mac);
4865 return CKR_KEY_SIZE_RANGE;
4868 // Initialize verifying
4869 if (!mac->verifyInit(pubkey))
4871 mac->recycleKey(pubkey);
4872 CryptoFactory::i()->recycleMacAlgorithm(mac);
4873 return CKR_MECHANISM_INVALID;
4876 session->setOpType(SESSION_OP_VERIFY);
4877 session->setMacOp(mac);
4878 session->setAllowMultiPartOp(true);
4879 session->setAllowSinglePartOp(true);
4880 session->setSymmetricKey(pubkey);
4885 // AsymmetricAlgorithm version of C_VerifyInit
4886 CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4888 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4890 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4893 Session* session = (Session*)handleManager->getSession(hSession);
4894 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4896 // Check if we have another operation
4897 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4900 Token* token = session->getToken();
4901 if (token == NULL) return CKR_GENERAL_ERROR;
4903 // Check the key handle.
4904 OSObject *key = (OSObject *)handleManager->getObject(hKey);
4905 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4907 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4908 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4910 // Check read user credentials
4911 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4914 if (rv == CKR_USER_NOT_LOGGED_IN)
4915 INFO_MSG("User is not authorized");
4920 // Check if key can be used for verifying
4921 if (!key->getBooleanValue(CKA_VERIFY, false))
4922 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4924 // Check if the specified mechanism is allowed for the key
4925 if (!isMechanismPermitted(key, pMechanism))
4926 return CKR_MECHANISM_INVALID;
4928 // Get the asymmetric algorithm matching the mechanism
4929 AsymMech::Type mechanism = AsymMech::Unknown;
4931 size_t paramLen = 0;
4932 RSA_PKCS_PSS_PARAMS pssParam;
4933 bool bAllowMultiPartOp;
4936 bool isECDSA = false;
4937 switch(pMechanism->mechanism) {
4939 mechanism = AsymMech::RSA_PKCS;
4940 bAllowMultiPartOp = false;
4944 mechanism = AsymMech::RSA;
4945 bAllowMultiPartOp = false;
4949 case CKM_MD5_RSA_PKCS:
4950 mechanism = AsymMech::RSA_MD5_PKCS;
4951 bAllowMultiPartOp = true;
4955 case CKM_SHA1_RSA_PKCS:
4956 mechanism = AsymMech::RSA_SHA1_PKCS;
4957 bAllowMultiPartOp = true;
4960 case CKM_SHA224_RSA_PKCS:
4961 mechanism = AsymMech::RSA_SHA224_PKCS;
4962 bAllowMultiPartOp = true;
4965 case CKM_SHA256_RSA_PKCS:
4966 mechanism = AsymMech::RSA_SHA256_PKCS;
4967 bAllowMultiPartOp = true;
4970 case CKM_SHA384_RSA_PKCS:
4971 mechanism = AsymMech::RSA_SHA384_PKCS;
4972 bAllowMultiPartOp = true;
4975 case CKM_SHA512_RSA_PKCS:
4976 mechanism = AsymMech::RSA_SHA512_PKCS;
4977 bAllowMultiPartOp = true;
4981 case CKM_RSA_PKCS_PSS:
4982 if (pMechanism->pParameter == NULL_PTR ||
4983 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
4985 ERROR_MSG("Invalid parameters");
4986 return CKR_ARGUMENTS_BAD;
4988 mechanism = AsymMech::RSA_PKCS_PSS;
4990 unsigned long expectedMgf;
4991 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
4993 pssParam.hashAlg = HashAlgo::SHA1;
4994 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
4995 expectedMgf = CKG_MGF1_SHA1;
4998 pssParam.hashAlg = HashAlgo::SHA224;
4999 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5000 expectedMgf = CKG_MGF1_SHA224;
5003 pssParam.hashAlg = HashAlgo::SHA256;
5004 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5005 expectedMgf = CKG_MGF1_SHA256;
5008 pssParam.hashAlg = HashAlgo::SHA384;
5009 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5010 expectedMgf = CKG_MGF1_SHA384;
5013 pssParam.hashAlg = HashAlgo::SHA512;
5014 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5015 expectedMgf = CKG_MGF1_SHA512;
5018 return CKR_ARGUMENTS_BAD;
5021 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != expectedMgf) {
5022 return CKR_ARGUMENTS_BAD;
5025 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5027 paramLen = sizeof(pssParam);
5028 bAllowMultiPartOp = false;
5032 case CKM_SHA1_RSA_PKCS_PSS:
5033 if (pMechanism->pParameter == NULL_PTR ||
5034 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5035 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
5036 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
5038 ERROR_MSG("Invalid parameters");
5039 return CKR_ARGUMENTS_BAD;
5041 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
5042 pssParam.hashAlg = HashAlgo::SHA1;
5043 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
5044 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5046 paramLen = sizeof(pssParam);
5047 bAllowMultiPartOp = true;
5050 case CKM_SHA224_RSA_PKCS_PSS:
5051 if (pMechanism->pParameter == NULL_PTR ||
5052 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5053 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
5054 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
5056 ERROR_MSG("Invalid parameters");
5057 return CKR_ARGUMENTS_BAD;
5059 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
5060 pssParam.hashAlg = HashAlgo::SHA224;
5061 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5062 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5064 paramLen = sizeof(pssParam);
5065 bAllowMultiPartOp = true;
5068 case CKM_SHA256_RSA_PKCS_PSS:
5069 if (pMechanism->pParameter == NULL_PTR ||
5070 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5071 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
5072 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
5074 ERROR_MSG("Invalid parameters");
5075 return CKR_ARGUMENTS_BAD;
5077 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
5078 pssParam.hashAlg = HashAlgo::SHA256;
5079 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5080 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5082 paramLen = sizeof(pssParam);
5083 bAllowMultiPartOp = true;
5086 case CKM_SHA384_RSA_PKCS_PSS:
5087 if (pMechanism->pParameter == NULL_PTR ||
5088 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5089 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
5090 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
5092 ERROR_MSG("Invalid parameters");
5093 return CKR_ARGUMENTS_BAD;
5095 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
5096 pssParam.hashAlg = HashAlgo::SHA384;
5097 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5098 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5100 paramLen = sizeof(pssParam);
5101 bAllowMultiPartOp = true;
5104 case CKM_SHA512_RSA_PKCS_PSS:
5105 if (pMechanism->pParameter == NULL_PTR ||
5106 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5107 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
5108 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
5110 ERROR_MSG("Invalid parameters");
5111 return CKR_ARGUMENTS_BAD;
5113 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
5114 pssParam.hashAlg = HashAlgo::SHA512;
5115 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5116 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5118 paramLen = sizeof(pssParam);
5119 bAllowMultiPartOp = true;
5123 mechanism = AsymMech::DSA;
5124 bAllowMultiPartOp = false;
5128 mechanism = AsymMech::DSA_SHA1;
5129 bAllowMultiPartOp = true;
5132 case CKM_DSA_SHA224:
5133 mechanism = AsymMech::DSA_SHA224;
5134 bAllowMultiPartOp = true;
5137 case CKM_DSA_SHA256:
5138 mechanism = AsymMech::DSA_SHA256;
5139 bAllowMultiPartOp = true;
5142 case CKM_DSA_SHA384:
5143 mechanism = AsymMech::DSA_SHA384;
5144 bAllowMultiPartOp = true;
5147 case CKM_DSA_SHA512:
5148 mechanism = AsymMech::DSA_SHA512;
5149 bAllowMultiPartOp = true;
5154 mechanism = AsymMech::ECDSA;
5155 bAllowMultiPartOp = false;
5161 mechanism = AsymMech::GOST;
5162 bAllowMultiPartOp = false;
5164 case CKM_GOSTR3410_WITH_GOSTR3411:
5165 mechanism = AsymMech::GOST_GOST;
5166 bAllowMultiPartOp = true;
5170 return CKR_MECHANISM_INVALID;
5173 AsymmetricAlgorithm* asymCrypto = NULL;
5174 PublicKey* publicKey = NULL;
5177 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
5178 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5180 publicKey = asymCrypto->newPublicKey();
5181 if (publicKey == NULL)
5183 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5184 return CKR_HOST_MEMORY;
5187 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
5189 asymCrypto->recyclePublicKey(publicKey);
5190 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5191 return CKR_GENERAL_ERROR;
5196 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
5197 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5199 publicKey = asymCrypto->newPublicKey();
5200 if (publicKey == NULL)
5202 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5203 return CKR_HOST_MEMORY;
5206 if (getDSAPublicKey((DSAPublicKey*)publicKey, token, key) != CKR_OK)
5208 asymCrypto->recyclePublicKey(publicKey);
5209 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5210 return CKR_GENERAL_ERROR;
5216 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
5217 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5219 publicKey = asymCrypto->newPublicKey();
5220 if (publicKey == NULL)
5222 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5223 return CKR_HOST_MEMORY;
5226 if (getECPublicKey((ECPublicKey*)publicKey, token, key) != CKR_OK)
5228 asymCrypto->recyclePublicKey(publicKey);
5229 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5230 return CKR_GENERAL_ERROR;
5237 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
5238 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5240 publicKey = asymCrypto->newPublicKey();
5241 if (publicKey == NULL)
5243 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5244 return CKR_HOST_MEMORY;
5247 if (getGOSTPublicKey((GOSTPublicKey*)publicKey, token, key) != CKR_OK)
5249 asymCrypto->recyclePublicKey(publicKey);
5250 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5251 return CKR_GENERAL_ERROR;
5254 return CKR_MECHANISM_INVALID;
5258 // Initialize verifying
5259 if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))
5261 asymCrypto->recyclePublicKey(publicKey);
5262 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5263 return CKR_MECHANISM_INVALID;
5266 session->setOpType(SESSION_OP_VERIFY);
5267 session->setAsymmetricCryptoOp(asymCrypto);
5268 session->setMechanism(mechanism);
5269 session->setParameters(param, paramLen);
5270 session->setAllowMultiPartOp(bAllowMultiPartOp);
5271 session->setAllowSinglePartOp(true);
5272 session->setPublicKey(publicKey);
5277 // Initialise a verification operation using the specified key and mechanism
5278 CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5280 if (isMacMechanism(pMechanism))
5281 return MacVerifyInit(hSession, pMechanism, hKey);
5283 return AsymVerifyInit(hSession, pMechanism, hKey);
5286 // MacAlgorithm version of C_Verify
5287 static CK_RV MacVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5289 MacAlgorithm* mac = session->getMacOp();
5290 if (mac == NULL || !session->getAllowSinglePartOp())
5293 return CKR_OPERATION_NOT_INITIALIZED;
5296 // Size of the signature
5297 CK_ULONG size = mac->getMacSize();
5299 // Check buffer size
5300 if (ulSignatureLen != size)
5302 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5304 return CKR_SIGNATURE_LEN_RANGE;
5308 ByteString data(pData, ulDataLen);
5311 if (!mac->verifyUpdate(data))
5314 return CKR_GENERAL_ERROR;
5317 // Get the signature
5318 ByteString signature(pSignature, ulSignatureLen);
5320 // Verify the signature
5321 if (!mac->verifyFinal(signature))
5324 return CKR_SIGNATURE_INVALID;
5331 // AsymmetricAlgorithm version of C_Verify
5332 static CK_RV AsymVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5334 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5335 AsymMech::Type mechanism = session->getMechanism();
5336 PublicKey* publicKey = session->getPublicKey();
5338 void* param = session->getParameters(paramLen);
5339 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
5342 return CKR_OPERATION_NOT_INITIALIZED;
5345 // Size of the signature
5346 CK_ULONG size = publicKey->getOutputLength();
5348 // Check buffer size
5349 if (ulSignatureLen != size)
5351 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5353 return CKR_SIGNATURE_LEN_RANGE;
5359 // We must allow input length <= k and therfore need to prepend the data with zeroes.
5360 if (mechanism == AsymMech::RSA) {
5361 data.wipe(size-ulDataLen);
5364 data += ByteString(pData, ulDataLen);
5365 ByteString signature(pSignature, ulSignatureLen);
5368 if (session->getAllowMultiPartOp())
5370 if (!asymCrypto->verifyUpdate(data) ||
5371 !asymCrypto->verifyFinal(signature))
5374 return CKR_SIGNATURE_INVALID;
5377 else if (!asymCrypto->verify(publicKey,data,signature,mechanism,param,paramLen))
5380 return CKR_SIGNATURE_INVALID;
5387 // Perform a single pass verification operation
5388 CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5390 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5392 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
5393 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5396 Session* session = (Session*)handleManager->getSession(hSession);
5397 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5399 // Check if we are doing the correct operation
5400 if (session->getOpType() != SESSION_OP_VERIFY)
5401 return CKR_OPERATION_NOT_INITIALIZED;
5403 if (session->getMacOp() != NULL)
5404 return MacVerify(session, pData, ulDataLen,
5405 pSignature, ulSignatureLen);
5407 return AsymVerify(session, pData, ulDataLen,
5408 pSignature, ulSignatureLen);
5411 // MacAlgorithm version of C_VerifyUpdate
5412 static CK_RV MacVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5414 MacAlgorithm* mac = session->getMacOp();
5415 if (mac == NULL || !session->getAllowMultiPartOp())
5418 return CKR_OPERATION_NOT_INITIALIZED;
5422 ByteString part(pPart, ulPartLen);
5425 if (!mac->verifyUpdate(part))
5427 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5429 return CKR_GENERAL_ERROR;
5432 session->setAllowSinglePartOp(false);
5436 // AsymmetricAlgorithm version of C_VerifyUpdate
5437 static CK_RV AsymVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5439 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5440 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
5443 return CKR_OPERATION_NOT_INITIALIZED;
5447 ByteString part(pPart, ulPartLen);
5450 if (!asymCrypto->verifyUpdate(part))
5452 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5454 return CKR_GENERAL_ERROR;
5457 session->setAllowSinglePartOp(false);
5461 // Update a running verification operation with additional data
5462 CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5464 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5466 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
5469 Session* session = (Session*)handleManager->getSession(hSession);
5470 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5472 // Check if we are doing the correct operation
5473 if (session->getOpType() != SESSION_OP_VERIFY)
5474 return CKR_OPERATION_NOT_INITIALIZED;
5476 if (session->getMacOp() != NULL)
5477 return MacVerifyUpdate(session, pPart, ulPartLen);
5479 return AsymVerifyUpdate(session, pPart, ulPartLen);
5482 // MacAlgorithm version of C_SignFinal
5483 static CK_RV MacVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5485 MacAlgorithm* mac = session->getMacOp();
5489 return CKR_OPERATION_NOT_INITIALIZED;
5492 // Size of the signature
5493 CK_ULONG size = mac->getMacSize();
5495 // Check buffer size
5496 if (ulSignatureLen != size)
5498 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5500 return CKR_SIGNATURE_LEN_RANGE;
5503 // Get the signature
5504 ByteString signature(pSignature, ulSignatureLen);
5507 if (!mac->verifyFinal(signature))
5510 return CKR_SIGNATURE_INVALID;
5517 // AsymmetricAlgorithm version of C_VerifyFinal
5518 static CK_RV AsymVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5520 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5521 PublicKey* publicKey = session->getPublicKey();
5522 if (asymCrypto == NULL || publicKey == NULL)
5525 return CKR_OPERATION_NOT_INITIALIZED;
5528 // Size of the signature
5529 CK_ULONG size = publicKey->getOutputLength();
5531 // Check buffer size
5532 if (ulSignatureLen != size)
5534 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5536 return CKR_SIGNATURE_LEN_RANGE;
5540 ByteString signature(pSignature, ulSignatureLen);
5543 if (!asymCrypto->verifyFinal(signature))
5546 return CKR_SIGNATURE_INVALID;
5553 // Finalise the verification operation and check the signature
5554 CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5556 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5558 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5561 Session* session = (Session*)handleManager->getSession(hSession);
5562 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5564 // Check if we are doing the correct operation
5565 if (session->getOpType() != SESSION_OP_VERIFY || !session->getAllowMultiPartOp())
5566 return CKR_OPERATION_NOT_INITIALIZED;
5568 if (session->getMacOp() != NULL)
5569 return MacVerifyFinal(session, pSignature, ulSignatureLen);
5571 return AsymVerifyFinal(session, pSignature, ulSignatureLen);
5574 // Initialise a verification operation the allows recovery of the signed data from the signature
5575 CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
5577 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5580 Session* session = (Session*)handleManager->getSession(hSession);
5581 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5583 // Check if we have another operation
5584 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5586 return CKR_FUNCTION_NOT_SUPPORTED;
5589 // Perform a single part verification operation and recover the signed data
5590 CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pSignature*/, CK_ULONG /*ulSignatureLen*/, CK_BYTE_PTR /*pData*/, CK_ULONG_PTR /*pulDataLen*/)
5592 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5595 Session* session = (Session*)handleManager->getSession(hSession);
5596 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5598 return CKR_FUNCTION_NOT_SUPPORTED;
5601 // Update a running multi-part encryption and digesting operation
5602 CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5604 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5607 Session* session = (Session*)handleManager->getSession(hSession);
5608 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5610 return CKR_FUNCTION_NOT_SUPPORTED;
5613 // Update a running multi-part decryption and digesting operation
5614 CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pDecryptedPart*/, CK_ULONG_PTR /*pulDecryptedPartLen*/)
5616 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5619 Session* session = (Session*)handleManager->getSession(hSession);
5620 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5622 return CKR_FUNCTION_NOT_SUPPORTED;
5625 // Update a running multi-part signing and encryption operation
5626 CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5628 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5631 Session* session = (Session*)handleManager->getSession(hSession);
5632 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5634 return CKR_FUNCTION_NOT_SUPPORTED;
5637 // Update a running multi-part decryption and verification operation
5638 CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG /*ulEncryptedPartLen*/, CK_BYTE_PTR /*pPart*/, CK_ULONG_PTR /*pulPartLen*/)
5640 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5643 Session* session = (Session*)handleManager->getSession(hSession);
5644 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5646 return CKR_FUNCTION_NOT_SUPPORTED;
5649 // Generate a secret key or a domain parameter set using the specified mechanism
5650 CK_RV SoftHSM::C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
5652 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5654 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5655 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5658 Session* session = (Session*)handleManager->getSession(hSession);
5659 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5661 // Check the mechanism, only accept DSA and DH parameters
5662 // and symmetric ciphers
5663 CK_OBJECT_CLASS objClass;
5664 CK_KEY_TYPE keyType;
5665 switch (pMechanism->mechanism)
5667 case CKM_DSA_PARAMETER_GEN:
5668 objClass = CKO_DOMAIN_PARAMETERS;
5671 case CKM_DH_PKCS_PARAMETER_GEN:
5672 objClass = CKO_DOMAIN_PARAMETERS;
5676 case CKM_DES_KEY_GEN:
5677 objClass = CKO_SECRET_KEY;
5681 case CKM_DES2_KEY_GEN:
5682 objClass = CKO_SECRET_KEY;
5685 case CKM_DES3_KEY_GEN:
5686 objClass = CKO_SECRET_KEY;
5689 case CKM_AES_KEY_GEN:
5690 objClass = CKO_SECRET_KEY;
5694 return CKR_MECHANISM_INVALID;
5697 // Extract information from the template that is needed to create the object.
5698 CK_BBOOL isOnToken = CK_FALSE;
5699 CK_BBOOL isPrivate = CK_TRUE;
5700 CK_CERTIFICATE_TYPE dummy;
5701 bool isImplicit = true;
5702 extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
5704 // Report errors and/or unexpected usage.
5705 if (objClass != CKO_SECRET_KEY && objClass != CKO_DOMAIN_PARAMETERS)
5706 return CKR_ATTRIBUTE_VALUE_INVALID;
5707 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN &&
5708 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DSA))
5709 return CKR_TEMPLATE_INCONSISTENT;
5710 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN &&
5711 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DH))
5712 return CKR_TEMPLATE_INCONSISTENT;
5713 if (pMechanism->mechanism == CKM_DES_KEY_GEN &&
5714 (objClass != CKO_SECRET_KEY || keyType != CKK_DES))
5715 return CKR_TEMPLATE_INCONSISTENT;
5716 if (pMechanism->mechanism == CKM_DES2_KEY_GEN &&
5717 (objClass != CKO_SECRET_KEY || keyType != CKK_DES2))
5718 return CKR_TEMPLATE_INCONSISTENT;
5719 if (pMechanism->mechanism == CKM_DES3_KEY_GEN &&
5720 (objClass != CKO_SECRET_KEY || keyType != CKK_DES3))
5721 return CKR_TEMPLATE_INCONSISTENT;
5722 if (pMechanism->mechanism == CKM_AES_KEY_GEN &&
5723 (objClass != CKO_SECRET_KEY || keyType != CKK_AES))
5724 return CKR_TEMPLATE_INCONSISTENT;
5726 // Check authorization
5727 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
5730 if (rv == CKR_USER_NOT_LOGGED_IN)
5731 INFO_MSG("User is not authorized");
5732 if (rv == CKR_SESSION_READ_ONLY)
5733 INFO_MSG("Session is read-only");
5738 // Generate DSA domain parameters
5739 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN)
5741 return this->generateDSAParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5744 // Generate DH domain parameters
5745 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN)
5747 return this->generateDHParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5750 // Generate DES secret key
5751 if (pMechanism->mechanism == CKM_DES_KEY_GEN)
5753 return this->generateDES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5756 // Generate DES2 secret key
5757 if (pMechanism->mechanism == CKM_DES2_KEY_GEN)
5759 return this->generateDES2(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5762 // Generate DES3 secret key
5763 if (pMechanism->mechanism == CKM_DES3_KEY_GEN)
5765 return this->generateDES3(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5768 // Generate AES secret key
5769 if (pMechanism->mechanism == CKM_AES_KEY_GEN)
5771 return this->generateAES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5774 return CKR_GENERAL_ERROR;
5777 // Generate a key-pair using the specified mechanism
5778 CK_RV SoftHSM::C_GenerateKeyPair
5780 CK_SESSION_HANDLE hSession,
5781 CK_MECHANISM_PTR pMechanism,
5782 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5783 CK_ULONG ulPublicKeyAttributeCount,
5784 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5785 CK_ULONG ulPrivateKeyAttributeCount,
5786 CK_OBJECT_HANDLE_PTR phPublicKey,
5787 CK_OBJECT_HANDLE_PTR phPrivateKey
5790 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5792 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5793 if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5794 if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5797 Session* session = (Session*)handleManager->getSession(hSession);
5798 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5800 // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation.
5801 CK_KEY_TYPE keyType;
5802 switch (pMechanism->mechanism)
5804 case CKM_RSA_PKCS_KEY_PAIR_GEN:
5807 case CKM_DSA_KEY_PAIR_GEN:
5810 case CKM_DH_PKCS_KEY_PAIR_GEN:
5814 case CKM_EC_KEY_PAIR_GEN:
5819 case CKM_GOSTR3410_KEY_PAIR_GEN:
5820 keyType = CKK_GOSTR3410;
5824 return CKR_MECHANISM_INVALID;
5826 CK_CERTIFICATE_TYPE dummy;
5828 // Extract information from the public key template that is needed to create the object.
5829 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
5830 CK_BBOOL ispublicKeyToken = CK_FALSE;
5831 CK_BBOOL ispublicKeyPrivate = CK_FALSE;
5832 bool isPublicKeyImplicit = true;
5833 extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate, isPublicKeyImplicit);
5835 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5836 if (publicKeyClass != CKO_PUBLIC_KEY)
5837 return CKR_ATTRIBUTE_VALUE_INVALID;
5838 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5839 return CKR_TEMPLATE_INCONSISTENT;
5840 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5841 return CKR_TEMPLATE_INCONSISTENT;
5842 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5843 return CKR_TEMPLATE_INCONSISTENT;
5844 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5845 return CKR_TEMPLATE_INCONSISTENT;
5846 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5847 return CKR_TEMPLATE_INCONSISTENT;
5849 // Extract information from the private key template that is needed to create the object.
5850 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
5851 CK_BBOOL isprivateKeyToken = CK_FALSE;
5852 CK_BBOOL isprivateKeyPrivate = CK_TRUE;
5853 bool isPrivateKeyImplicit = true;
5854 extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit);
5856 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5857 if (privateKeyClass != CKO_PRIVATE_KEY)
5858 return CKR_ATTRIBUTE_VALUE_INVALID;
5859 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5860 return CKR_TEMPLATE_INCONSISTENT;
5861 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5862 return CKR_TEMPLATE_INCONSISTENT;
5863 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5864 return CKR_TEMPLATE_INCONSISTENT;
5865 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5866 return CKR_TEMPLATE_INCONSISTENT;
5867 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5868 return CKR_TEMPLATE_INCONSISTENT;
5870 // Check user credentials
5871 CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
5874 if (rv == CKR_USER_NOT_LOGGED_IN)
5875 INFO_MSG("User is not authorized");
5876 if (rv == CKR_SESSION_READ_ONLY)
5877 INFO_MSG("Session is read-only");
5882 // Generate RSA keys
5883 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
5885 return this->generateRSA(hSession,
5886 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5887 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5888 phPublicKey, phPrivateKey,
5889 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5892 // Generate DSA keys
5893 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
5895 return this->generateDSA(hSession,
5896 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5897 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5898 phPublicKey, phPrivateKey,
5899 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5903 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
5905 return this->generateEC(hSession,
5906 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5907 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5908 phPublicKey, phPrivateKey,
5909 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5913 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN)
5915 return this->generateDH(hSession,
5916 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5917 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5918 phPublicKey, phPrivateKey,
5919 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5922 // Generate GOST keys
5923 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
5925 return this->generateGOST(hSession,
5926 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5927 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5928 phPublicKey, phPrivateKey,
5929 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5932 return CKR_GENERAL_ERROR;
5935 // Internal: Wrap blob using symmetric key
5936 CK_RV SoftHSM::WrapKeySym
5938 CK_MECHANISM_PTR pMechanism,
5941 ByteString& keydata,
5945 // Get the symmetric algorithm matching the mechanism
5946 SymAlgo::Type algo = SymAlgo::Unknown;
5947 SymWrap::Type mode = SymWrap::Unknown;
5949 #ifdef HAVE_AES_KEY_WRAP
5950 CK_ULONG wrappedlen = keydata.size();
5952 // [PKCS#11 v2.40, 2.14.3 AES Key Wrap]
5953 // A key whose length is not a multiple of the AES Key Wrap block
5954 // size (8 bytes) will be zero padded to fit.
5955 CK_ULONG alignment = wrappedlen % 8;
5958 keydata.resize(wrappedlen + 8 - alignment);
5959 memset(&keydata[wrappedlen], 0, 8 - alignment);
5960 wrappedlen = keydata.size();
5963 switch(pMechanism->mechanism) {
5964 #ifdef HAVE_AES_KEY_WRAP
5965 case CKM_AES_KEY_WRAP:
5966 if ((wrappedlen < 16) || ((wrappedlen % 8) != 0))
5967 return CKR_KEY_SIZE_RANGE;
5968 algo = SymAlgo::AES;
5969 mode = SymWrap::AES_KEYWRAP;
5972 #ifdef HAVE_AES_KEY_WRAP_PAD
5973 case CKM_AES_KEY_WRAP_PAD:
5974 algo = SymAlgo::AES;
5975 mode = SymWrap::AES_KEYWRAP_PAD;
5979 return CKR_MECHANISM_INVALID;
5981 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
5982 if (cipher == NULL) return CKR_MECHANISM_INVALID;
5984 SymmetricKey* wrappingkey = new SymmetricKey();
5986 if (getSymmetricKey(wrappingkey, token, wrapKey) != CKR_OK)
5988 cipher->recycleKey(wrappingkey);
5989 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
5990 return CKR_GENERAL_ERROR;
5993 // adjust key bit length
5994 wrappingkey->setBitLen(wrappingkey->getKeyBits().size() * bb);
5997 if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped))
5999 cipher->recycleKey(wrappingkey);
6000 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6001 return CKR_GENERAL_ERROR;
6004 cipher->recycleKey(wrappingkey);
6005 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6009 // Internal: Wrap blob using asymmetric key
6010 CK_RV SoftHSM::WrapKeyAsym
6012 CK_MECHANISM_PTR pMechanism,
6015 ByteString& keydata,
6019 const size_t bb = 8;
6020 AsymAlgo::Type algo = AsymAlgo::Unknown;
6021 AsymMech::Type mech = AsymMech::Unknown;
6023 CK_ULONG modulus_length;
6024 switch(pMechanism->mechanism) {
6026 case CKM_RSA_PKCS_OAEP:
6027 algo = AsymAlgo::RSA;
6028 if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
6029 return CKR_GENERAL_ERROR;
6030 modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
6031 // adjust key bit length
6032 modulus_length /= bb;
6036 return CKR_MECHANISM_INVALID;
6039 switch(pMechanism->mechanism) {
6041 mech = AsymMech::RSA_PKCS;
6042 // RFC 3447 section 7.2.1
6043 if (keydata.size() > modulus_length - 11)
6044 return CKR_KEY_SIZE_RANGE;
6047 case CKM_RSA_PKCS_OAEP:
6048 mech = AsymMech::RSA_PKCS_OAEP;
6049 // SHA-1 is the only supported option
6050 // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
6051 if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
6052 return CKR_KEY_SIZE_RANGE;
6056 return CKR_MECHANISM_INVALID;
6059 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6060 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6062 PublicKey* publicKey = cipher->newPublicKey();
6063 if (publicKey == NULL)
6065 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6066 return CKR_HOST_MEMORY;
6069 switch(pMechanism->mechanism) {
6071 case CKM_RSA_PKCS_OAEP:
6072 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
6074 cipher->recyclePublicKey(publicKey);
6075 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6076 return CKR_GENERAL_ERROR;
6081 return CKR_MECHANISM_INVALID;
6084 if (!cipher->wrapKey(publicKey, keydata, wrapped, mech))
6086 cipher->recyclePublicKey(publicKey);
6087 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6088 return CKR_GENERAL_ERROR;
6091 cipher->recyclePublicKey(publicKey);
6092 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6098 // Wrap the specified key using the specified wrapping key and mechanism
6099 CK_RV SoftHSM::C_WrapKey
6101 CK_SESSION_HANDLE hSession,
6102 CK_MECHANISM_PTR pMechanism,
6103 CK_OBJECT_HANDLE hWrappingKey,
6104 CK_OBJECT_HANDLE hKey,
6105 CK_BYTE_PTR pWrappedKey,
6106 CK_ULONG_PTR pulWrappedKeyLen
6109 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6111 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6112 if (pulWrappedKeyLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
6115 Session* session = (Session*)handleManager->getSession(hSession);
6116 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6119 // Check the mechanism, only accept advanced AES key wrapping and RSA
6120 switch(pMechanism->mechanism)
6122 #ifdef HAVE_AES_KEY_WRAP
6123 case CKM_AES_KEY_WRAP:
6125 #ifdef HAVE_AES_KEY_WRAP_PAD
6126 case CKM_AES_KEY_WRAP_PAD:
6129 // Does not handle optional init vector
6130 if (pMechanism->pParameter != NULL_PTR ||
6131 pMechanism->ulParameterLen != 0)
6132 return CKR_ARGUMENTS_BAD;
6134 case CKM_RSA_PKCS_OAEP:
6135 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6141 return CKR_MECHANISM_INVALID;
6145 Token* token = session->getToken();
6146 if (token == NULL) return CKR_GENERAL_ERROR;
6148 // Check the wrapping key handle.
6149 OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
6150 if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
6152 CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
6153 CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
6155 // Check user credentials for the wrapping key
6156 rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
6159 if (rv == CKR_USER_NOT_LOGGED_IN)
6160 INFO_MSG("User is not authorized");
6165 // Check wrapping key class and type
6166 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6167 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6168 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
6169 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6170 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6171 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6172 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6173 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6174 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6175 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6177 // Check if the wrapping key can be used for wrapping
6178 if (wrapKey->getBooleanValue(CKA_WRAP, false) == false)
6179 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6181 // Check if the specified mechanism is allowed for the wrapping key
6182 if (!isMechanismPermitted(wrapKey, pMechanism))
6183 return CKR_MECHANISM_INVALID;
6185 // Check the to be wrapped key handle.
6186 OSObject *key = (OSObject *)handleManager->getObject(hKey);
6187 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
6189 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6190 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6192 // Check user credentials for the to be wrapped key
6193 rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6196 if (rv == CKR_USER_NOT_LOGGED_IN)
6197 INFO_MSG("User is not authorized");
6202 // Check if the to be wrapped key can be wrapped
6203 if (key->getBooleanValue(CKA_EXTRACTABLE, false) == false)
6204 return CKR_KEY_UNEXTRACTABLE;
6205 if (key->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false) && wrapKey->getBooleanValue(CKA_TRUSTED, false) == false)
6206 return CKR_KEY_NOT_WRAPPABLE;
6209 CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6210 if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
6211 return CKR_KEY_NOT_WRAPPABLE;
6212 // CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA & section 2.1.8 PKCS #1 RSA OAEP
6213 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
6214 return CKR_KEY_NOT_WRAPPABLE;
6216 // Verify the wrap template attribute
6217 if (wrapKey->attributeExists(CKA_WRAP_TEMPLATE))
6219 OSAttribute attr = wrapKey->getAttribute(CKA_WRAP_TEMPLATE);
6221 if (attr.isAttributeMapAttribute())
6223 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6225 const attrmap_type& map = attr.getAttributeMapValue();
6227 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6229 if (!key->attributeExists(it->first))
6231 return CKR_KEY_NOT_WRAPPABLE;
6234 OSAttribute keyAttr = key->getAttribute(it->first);
6236 if (!keyAttr.peekValue(v1) || !it->second.peekValue(v2) || (v1 != v2))
6238 return CKR_KEY_NOT_WRAPPABLE;
6244 // Get the key data to encrypt
6246 if (keyClass == CKO_SECRET_KEY)
6250 bool bOK = token->decrypt(key->getByteStringValue(CKA_VALUE), keydata);
6251 if (!bOK) return CKR_GENERAL_ERROR;
6255 keydata = key->getByteStringValue(CKA_VALUE);
6260 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6261 AsymAlgo::Type alg = AsymAlgo::Unknown;
6264 alg = AsymAlgo::RSA;
6267 alg = AsymAlgo::DSA;
6274 // can be ecdh too but it doesn't matter
6275 alg = AsymAlgo::ECDSA;
6280 alg = AsymAlgo::GOST;
6284 return CKR_KEY_NOT_WRAPPABLE;
6286 AsymmetricAlgorithm* asymCrypto = NULL;
6287 PrivateKey* privateKey = NULL;
6288 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6289 if (asymCrypto == NULL)
6290 return CKR_GENERAL_ERROR;
6291 privateKey = asymCrypto->newPrivateKey();
6292 if (privateKey == NULL)
6294 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6295 return CKR_HOST_MEMORY;
6299 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6302 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6305 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6309 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6314 rv = getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key);
6320 asymCrypto->recyclePrivateKey(privateKey);
6321 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6322 return CKR_GENERAL_ERROR;
6324 keydata = privateKey->PKCS8Encode();
6325 asymCrypto->recyclePrivateKey(privateKey);
6326 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6328 if (keydata.size() == 0)
6329 return CKR_KEY_NOT_WRAPPABLE;
6331 keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6333 if (keyClass == CKO_SECRET_KEY)
6334 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6336 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6340 if (pWrappedKey != NULL) {
6341 if (*pulWrappedKeyLen >= wrapped.size())
6342 memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6344 rv = CKR_BUFFER_TOO_SMALL;
6347 *pulWrappedKeyLen = wrapped.size();
6351 // Internal: Unwrap blob using symmetric key
6352 CK_RV SoftHSM::UnwrapKeySym
6354 CK_MECHANISM_PTR pMechanism,
6355 ByteString& wrapped,
6357 OSObject* unwrapKey,
6361 // Get the symmetric algorithm matching the mechanism
6362 SymAlgo::Type algo = SymAlgo::Unknown;
6363 SymWrap::Type mode = SymWrap::Unknown;
6365 switch(pMechanism->mechanism) {
6366 #ifdef HAVE_AES_KEY_WRAP
6367 case CKM_AES_KEY_WRAP:
6368 algo = SymAlgo::AES;
6369 mode = SymWrap::AES_KEYWRAP;
6372 #ifdef HAVE_AES_KEY_WRAP_PAD
6373 case CKM_AES_KEY_WRAP_PAD:
6374 algo = SymAlgo::AES;
6375 mode = SymWrap::AES_KEYWRAP_PAD;
6379 return CKR_MECHANISM_INVALID;
6381 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6382 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6384 SymmetricKey* unwrappingkey = new SymmetricKey();
6386 if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6388 cipher->recycleKey(unwrappingkey);
6389 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6390 return CKR_GENERAL_ERROR;
6393 // adjust key bit length
6394 unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6398 if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6399 rv = CKR_GENERAL_ERROR;
6400 cipher->recycleKey(unwrappingkey);
6401 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6405 // Internal: Unwrap blob using asymmetric key
6406 CK_RV SoftHSM::UnwrapKeyAsym
6408 CK_MECHANISM_PTR pMechanism,
6409 ByteString& wrapped,
6411 OSObject* unwrapKey,
6415 // Get the symmetric algorithm matching the mechanism
6416 AsymAlgo::Type algo = AsymAlgo::Unknown;
6417 AsymMech::Type mode = AsymMech::Unknown;
6418 switch(pMechanism->mechanism) {
6420 algo = AsymAlgo::RSA;
6421 mode = AsymMech::RSA_PKCS;
6424 case CKM_RSA_PKCS_OAEP:
6425 algo = AsymAlgo::RSA;
6426 mode = AsymMech::RSA_PKCS_OAEP;
6430 return CKR_MECHANISM_INVALID;
6432 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6433 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6435 PrivateKey* unwrappingkey = cipher->newPrivateKey();
6436 if (unwrappingkey == NULL)
6438 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6439 return CKR_HOST_MEMORY;
6442 switch(pMechanism->mechanism) {
6444 case CKM_RSA_PKCS_OAEP:
6445 if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6447 cipher->recyclePrivateKey(unwrappingkey);
6448 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6449 return CKR_GENERAL_ERROR;
6454 return CKR_MECHANISM_INVALID;
6459 if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6460 rv = CKR_GENERAL_ERROR;
6461 cipher->recyclePrivateKey(unwrappingkey);
6462 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6466 // Unwrap the specified key using the specified unwrapping key
6467 CK_RV SoftHSM::C_UnwrapKey
6469 CK_SESSION_HANDLE hSession,
6470 CK_MECHANISM_PTR pMechanism,
6471 CK_OBJECT_HANDLE hUnwrappingKey,
6472 CK_BYTE_PTR pWrappedKey,
6473 CK_ULONG ulWrappedKeyLen,
6474 CK_ATTRIBUTE_PTR pTemplate,
6476 CK_OBJECT_HANDLE_PTR hKey
6479 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6481 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6482 if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6483 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6484 if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6487 Session* session = (Session*)handleManager->getSession(hSession);
6488 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6491 // Check the mechanism
6492 switch(pMechanism->mechanism)
6494 #ifdef HAVE_AES_KEY_WRAP
6495 case CKM_AES_KEY_WRAP:
6496 if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
6497 return CKR_WRAPPED_KEY_LEN_RANGE;
6498 // Does not handle optional init vector
6499 if (pMechanism->pParameter != NULL_PTR ||
6500 pMechanism->ulParameterLen != 0)
6501 return CKR_ARGUMENTS_BAD;
6504 #ifdef HAVE_AES_KEY_WRAP_PAD
6505 case CKM_AES_KEY_WRAP_PAD:
6506 if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6507 return CKR_WRAPPED_KEY_LEN_RANGE;
6508 // Does not handle optional init vector
6509 if (pMechanism->pParameter != NULL_PTR ||
6510 pMechanism->ulParameterLen != 0)
6511 return CKR_ARGUMENTS_BAD;
6515 // Input length checks needs to be done later when unwrapping key is known
6517 case CKM_RSA_PKCS_OAEP:
6518 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6524 return CKR_MECHANISM_INVALID;
6528 Token* token = session->getToken();
6529 if (token == NULL) return CKR_GENERAL_ERROR;
6531 // Check the unwrapping key handle.
6532 OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6533 if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6535 CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6536 CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6538 // Check user credentials
6539 rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6542 if (rv == CKR_USER_NOT_LOGGED_IN)
6543 INFO_MSG("User is not authorized");
6548 // Check unwrapping key class and type
6549 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6550 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6551 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6552 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6553 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6554 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6555 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6556 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6557 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6558 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6560 // Check if the unwrapping key can be used for unwrapping
6561 if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6562 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6564 // Check if the specified mechanism is allowed for the unwrap key
6565 if (!isMechanismPermitted(unwrapKey, pMechanism))
6566 return CKR_MECHANISM_INVALID;
6568 // Extract information from the template that is needed to create the object.
6569 CK_OBJECT_CLASS objClass;
6570 CK_KEY_TYPE keyType;
6571 CK_BBOOL isOnToken = CK_FALSE;
6572 CK_BBOOL isPrivate = CK_TRUE;
6573 CK_CERTIFICATE_TYPE dummy;
6574 bool isImplicit = false;
6575 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6578 ERROR_MSG("Mandatory attribute not present in template");
6582 // Report errors and/or unexpected usage.
6583 if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6584 return CKR_ATTRIBUTE_VALUE_INVALID;
6585 // Key type will be handled at object creation
6587 // Check authorization
6588 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6591 if (rv == CKR_USER_NOT_LOGGED_IN)
6592 INFO_MSG("User is not authorized");
6593 if (rv == CKR_SESSION_READ_ONLY)
6594 INFO_MSG("Session is read-only");
6599 // Build unwrapped key template
6600 const CK_ULONG maxAttribs = 32;
6601 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6602 { CKA_CLASS, &objClass, sizeof(objClass) },
6603 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6604 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6605 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6607 CK_ULONG secretAttribsCount = 4;
6609 // Add the additional
6610 if (ulCount > (maxAttribs - secretAttribsCount))
6611 return CKR_TEMPLATE_INCONSISTENT;
6612 for (CK_ULONG i = 0; i < ulCount; ++i)
6614 switch (pTemplate[i].type)
6622 secretAttribs[secretAttribsCount++] = pTemplate[i];
6626 // Apply the unwrap template
6627 if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6629 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6631 if (unwrapAttr.isAttributeMapAttribute())
6633 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6635 const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6637 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6639 CK_ATTRIBUTE* attr = NULL;
6640 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6642 if (it->first == secretAttribs[i].type)
6646 return CKR_TEMPLATE_INCONSISTENT;
6648 attr = &secretAttribs[i];
6650 it->second.peekValue(value);
6651 if (attr->ulValueLen != value.size())
6653 return CKR_TEMPLATE_INCONSISTENT;
6655 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6657 return CKR_TEMPLATE_INCONSISTENT;
6663 return CKR_TEMPLATE_INCONSISTENT;
6669 *hKey = CK_INVALID_HANDLE;
6672 ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6674 if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6675 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6676 else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6677 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6679 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6683 // Create the secret object using C_CreateObject
6684 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6686 // Store the attributes that are being supplied
6689 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6690 if (osobject == NULL_PTR || !osobject->isValid())
6691 rv = CKR_FUNCTION_FAILED;
6692 if (osobject->startTransaction())
6696 // Common Attributes
6697 bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6699 // Common Secret Key Attributes
6700 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6701 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6703 // Secret Attributes
6704 if (objClass == CKO_SECRET_KEY)
6708 token->encrypt(keydata, value);
6711 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6713 else if (keyType == CKK_RSA)
6715 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6717 else if (keyType == CKK_DSA)
6719 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6721 else if (keyType == CKK_DH)
6723 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6726 else if (keyType == CKK_EC)
6728 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6732 else if (keyType == CKK_GOSTR3410)
6734 bOK = bOK && setGOSTPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6741 bOK = osobject->commitTransaction();
6743 osobject->abortTransaction();
6746 rv = CKR_FUNCTION_FAILED;
6749 rv = CKR_FUNCTION_FAILED;
6752 // Remove secret that may have been created already when the function fails.
6755 if (*hKey != CK_INVALID_HANDLE)
6757 OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6758 handleManager->destroyObject(*hKey);
6759 if (obj) obj->destroyObject();
6760 *hKey = CK_INVALID_HANDLE;
6768 // Derive a key from the specified base key
6769 CK_RV SoftHSM::C_DeriveKey
6771 CK_SESSION_HANDLE hSession,
6772 CK_MECHANISM_PTR pMechanism,
6773 CK_OBJECT_HANDLE hBaseKey,
6774 CK_ATTRIBUTE_PTR pTemplate,
6776 CK_OBJECT_HANDLE_PTR phKey
6779 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6781 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6782 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6783 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6786 Session* session = (Session*)handleManager->getSession(hSession);
6787 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6789 // Check the mechanism, only accept DH and ECDH derive
6790 switch (pMechanism->mechanism)
6792 case CKM_DH_PKCS_DERIVE:
6794 case CKM_ECDH1_DERIVE:
6797 case CKM_DES_ECB_ENCRYPT_DATA:
6798 case CKM_DES_CBC_ENCRYPT_DATA:
6800 case CKM_DES3_ECB_ENCRYPT_DATA:
6801 case CKM_DES3_CBC_ENCRYPT_DATA:
6802 case CKM_AES_ECB_ENCRYPT_DATA:
6803 case CKM_AES_CBC_ENCRYPT_DATA:
6806 ERROR_MSG("Invalid mechanism");
6807 return CKR_MECHANISM_INVALID;
6811 Token* token = session->getToken();
6812 if (token == NULL) return CKR_GENERAL_ERROR;
6814 // Check the key handle.
6815 OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6816 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6818 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6819 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6821 // Check user credentials
6822 CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6825 if (rv == CKR_USER_NOT_LOGGED_IN)
6826 INFO_MSG("User is not authorized");
6831 // Check if key can be used for derive
6832 if (!key->getBooleanValue(CKA_DERIVE, false))
6833 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6835 // Check if the specified mechanism is allowed for the key
6836 if (!isMechanismPermitted(key, pMechanism))
6837 return CKR_MECHANISM_INVALID;
6839 // Extract information from the template that is needed to create the object.
6840 CK_OBJECT_CLASS objClass;
6841 CK_KEY_TYPE keyType;
6842 CK_BBOOL isOnToken = CK_FALSE;
6843 CK_BBOOL isPrivate = CK_TRUE;
6844 CK_CERTIFICATE_TYPE dummy;
6845 bool isImplicit = false;
6846 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6849 ERROR_MSG("Mandatory attribute not present in template");
6853 // Report errors and/or unexpected usage.
6854 if (objClass != CKO_SECRET_KEY)
6855 return CKR_ATTRIBUTE_VALUE_INVALID;
6856 if (keyType != CKK_GENERIC_SECRET &&
6857 keyType != CKK_DES &&
6858 keyType != CKK_DES2 &&
6859 keyType != CKK_DES3 &&
6861 return CKR_TEMPLATE_INCONSISTENT;
6863 // Check authorization
6864 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6867 if (rv == CKR_USER_NOT_LOGGED_IN)
6868 INFO_MSG("User is not authorized");
6869 if (rv == CKR_SESSION_READ_ONLY)
6870 INFO_MSG("Session is read-only");
6876 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
6878 // Check key class and type
6879 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6880 return CKR_KEY_TYPE_INCONSISTENT;
6881 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
6882 return CKR_KEY_TYPE_INCONSISTENT;
6884 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6888 // Derive ECDH secret
6889 if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
6891 // Check key class and type
6892 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6893 return CKR_KEY_TYPE_INCONSISTENT;
6894 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
6895 return CKR_KEY_TYPE_INCONSISTENT;
6897 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6901 // Derive symmetric secret
6902 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
6903 pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
6904 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
6905 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
6906 pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
6907 pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
6909 // Check key class and type
6910 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6911 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6912 return CKR_KEY_TYPE_INCONSISTENT;
6913 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
6914 baseKeyType != CKK_DES)
6915 return CKR_KEY_TYPE_INCONSISTENT;
6916 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
6917 baseKeyType != CKK_DES)
6918 return CKR_KEY_TYPE_INCONSISTENT;
6919 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
6920 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6921 return CKR_KEY_TYPE_INCONSISTENT;
6922 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
6923 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6924 return CKR_KEY_TYPE_INCONSISTENT;
6925 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
6926 baseKeyType != CKK_AES)
6927 return CKR_KEY_TYPE_INCONSISTENT;
6928 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
6929 baseKeyType != CKK_AES)
6930 return CKR_KEY_TYPE_INCONSISTENT;
6932 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6935 return CKR_MECHANISM_INVALID;
6938 // Seed the random number generator with new data
6939 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
6941 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6943 if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
6946 Session* session = (Session*)handleManager->getSession(hSession);
6947 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6950 RNG* rng = CryptoFactory::i()->getRNG();
6951 if (rng == NULL) return CKR_GENERAL_ERROR;
6954 ByteString seed(pSeed, ulSeedLen);
6960 // Generate the specified amount of random data
6961 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
6963 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6965 if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
6968 Session* session = (Session*)handleManager->getSession(hSession);
6969 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6972 RNG* rng = CryptoFactory::i()->getRNG();
6973 if (rng == NULL) return CKR_GENERAL_ERROR;
6975 // Generate random data
6976 ByteString randomData;
6977 if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
6979 // Return random data
6980 if (ulRandomLen != 0)
6982 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
6989 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
6991 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6994 Session* session = (Session*)handleManager->getSession(hSession);
6995 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6997 return CKR_FUNCTION_NOT_PARALLEL;
7001 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
7003 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7006 Session* session = (Session*)handleManager->getSession(hSession);
7007 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7009 return CKR_FUNCTION_NOT_PARALLEL;
7012 // Wait or poll for a slot event on the specified slot
7013 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
7015 return CKR_FUNCTION_NOT_SUPPORTED;
7018 // Generate an AES secret key
7019 CK_RV SoftHSM::generateAES
7020 (CK_SESSION_HANDLE hSession,
7021 CK_ATTRIBUTE_PTR pTemplate,
7023 CK_OBJECT_HANDLE_PTR phKey,
7027 *phKey = CK_INVALID_HANDLE;
7030 Session* session = (Session*)handleManager->getSession(hSession);
7031 if (session == NULL)
7032 return CKR_SESSION_HANDLE_INVALID;
7035 Token* token = session->getToken();
7037 return CKR_GENERAL_ERROR;
7039 // Extract desired parameter information
7041 bool checkValue = true;
7042 for (CK_ULONG i = 0; i < ulCount; i++)
7044 switch (pTemplate[i].type)
7047 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
7049 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
7050 return CKR_ATTRIBUTE_VALUE_INVALID;
7052 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
7054 case CKA_CHECK_VALUE:
7055 if (pTemplate[i].ulValueLen > 0)
7057 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7058 return CKR_ATTRIBUTE_VALUE_INVALID;
7067 // CKA_VALUE_LEN must be specified
7070 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
7071 return CKR_TEMPLATE_INCOMPLETE;
7074 // keyLen must be 16, 24, or 32
7075 if (keyLen != 16 && keyLen != 24 && keyLen != 32)
7077 INFO_MSG("bad AES key length");
7078 return CKR_ATTRIBUTE_VALUE_INVALID;
7081 // Generate the secret key
7082 AESKey* key = new AESKey(keyLen * 8);
7083 SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
7086 ERROR_MSG("Could not get SymmetricAlgorithm");
7088 return CKR_GENERAL_ERROR;
7090 RNG* rng = CryptoFactory::i()->getRNG();
7093 ERROR_MSG("Could not get RNG");
7094 aes->recycleKey(key);
7095 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7096 return CKR_GENERAL_ERROR;
7098 if (!aes->generateKey(*key, rng))
7100 ERROR_MSG("Could not generate AES secret key");
7101 aes->recycleKey(key);
7102 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7103 return CKR_GENERAL_ERROR;
7108 // Create the secret key object using C_CreateObject
7109 const CK_ULONG maxAttribs = 32;
7110 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7111 CK_KEY_TYPE keyType = CKK_AES;
7112 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7113 { CKA_CLASS, &objClass, sizeof(objClass) },
7114 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7115 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7116 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7118 CK_ULONG keyAttribsCount = 4;
7120 // Add the additional
7121 if (ulCount > (maxAttribs - keyAttribsCount))
7122 rv = CKR_TEMPLATE_INCONSISTENT;
7123 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7125 switch (pTemplate[i].type)
7131 case CKA_CHECK_VALUE:
7134 keyAttribs[keyAttribsCount++] = pTemplate[i];
7139 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7141 // Store the attributes that are being supplied
7144 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7145 if (osobject == NULL_PTR || !osobject->isValid()) {
7146 rv = CKR_FUNCTION_FAILED;
7147 } else if (osobject->startTransaction()) {
7150 // Common Attributes
7151 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7152 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
7153 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7155 // Common Secret Key Attributes
7156 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7157 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7158 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7159 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7161 // AES Secret Key Attributes
7166 token->encrypt(key->getKeyBits(), value);
7167 token->encrypt(key->getKeyCheckValue(), kcv);
7171 value = key->getKeyBits();
7172 kcv = key->getKeyCheckValue();
7174 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7176 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7179 bOK = osobject->commitTransaction();
7181 osobject->abortTransaction();
7184 rv = CKR_FUNCTION_FAILED;
7186 rv = CKR_FUNCTION_FAILED;
7190 aes->recycleKey(key);
7191 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7193 // Remove the key that may have been created already when the function fails.
7196 if (*phKey != CK_INVALID_HANDLE)
7198 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7199 handleManager->destroyObject(*phKey);
7200 if (oskey) oskey->destroyObject();
7201 *phKey = CK_INVALID_HANDLE;
7208 // Generate a DES secret key
7209 CK_RV SoftHSM::generateDES
7210 (CK_SESSION_HANDLE hSession,
7211 CK_ATTRIBUTE_PTR pTemplate,
7213 CK_OBJECT_HANDLE_PTR phKey,
7217 *phKey = CK_INVALID_HANDLE;
7220 Session* session = (Session*)handleManager->getSession(hSession);
7221 if (session == NULL)
7222 return CKR_SESSION_HANDLE_INVALID;
7225 Token* token = session->getToken();
7227 return CKR_GENERAL_ERROR;
7229 // Extract desired parameter information
7230 bool checkValue = true;
7231 for (CK_ULONG i = 0; i < ulCount; i++)
7233 switch (pTemplate[i].type)
7235 case CKA_CHECK_VALUE:
7236 if (pTemplate[i].ulValueLen > 0)
7238 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7239 return CKR_ATTRIBUTE_VALUE_INVALID;
7248 // Generate the secret key
7249 DESKey* key = new DESKey(56);
7250 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7253 ERROR_MSG("Could not get SymmetricAlgorithm");
7255 return CKR_GENERAL_ERROR;
7257 RNG* rng = CryptoFactory::i()->getRNG();
7260 ERROR_MSG("Could not get RNG");
7261 des->recycleKey(key);
7262 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7263 return CKR_GENERAL_ERROR;
7265 if (!des->generateKey(*key, rng))
7267 ERROR_MSG("Could not generate DES secret key");
7268 des->recycleKey(key);
7269 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7270 return CKR_GENERAL_ERROR;
7275 // Create the secret key object using C_CreateObject
7276 const CK_ULONG maxAttribs = 32;
7277 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7278 CK_KEY_TYPE keyType = CKK_DES;
7279 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7280 { CKA_CLASS, &objClass, sizeof(objClass) },
7281 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7282 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7283 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7285 CK_ULONG keyAttribsCount = 4;
7287 // Add the additional
7288 if (ulCount > (maxAttribs - keyAttribsCount))
7289 rv = CKR_TEMPLATE_INCONSISTENT;
7290 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7292 switch (pTemplate[i].type)
7298 case CKA_CHECK_VALUE:
7301 keyAttribs[keyAttribsCount++] = pTemplate[i];
7306 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7308 // Store the attributes that are being supplied
7311 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7312 if (osobject == NULL_PTR || !osobject->isValid()) {
7313 rv = CKR_FUNCTION_FAILED;
7314 } else if (osobject->startTransaction()) {
7317 // Common Attributes
7318 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7319 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7320 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7322 // Common Secret Key Attributes
7323 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7324 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7325 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7326 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7328 // DES Secret Key Attributes
7333 token->encrypt(key->getKeyBits(), value);
7334 token->encrypt(key->getKeyCheckValue(), kcv);
7338 value = key->getKeyBits();
7339 kcv = key->getKeyCheckValue();
7341 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7343 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7346 bOK = osobject->commitTransaction();
7348 osobject->abortTransaction();
7351 rv = CKR_FUNCTION_FAILED;
7353 rv = CKR_FUNCTION_FAILED;
7357 des->recycleKey(key);
7358 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7360 // Remove the key that may have been created already when the function fails.
7363 if (*phKey != CK_INVALID_HANDLE)
7365 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7366 handleManager->destroyObject(*phKey);
7367 if (oskey) oskey->destroyObject();
7368 *phKey = CK_INVALID_HANDLE;
7375 // Generate a DES2 secret key
7376 CK_RV SoftHSM::generateDES2
7377 (CK_SESSION_HANDLE hSession,
7378 CK_ATTRIBUTE_PTR pTemplate,
7380 CK_OBJECT_HANDLE_PTR phKey,
7384 *phKey = CK_INVALID_HANDLE;
7387 Session* session = (Session*)handleManager->getSession(hSession);
7388 if (session == NULL)
7389 return CKR_SESSION_HANDLE_INVALID;
7392 Token* token = session->getToken();
7394 return CKR_GENERAL_ERROR;
7396 // Extract desired parameter information
7397 bool checkValue = true;
7398 for (CK_ULONG i = 0; i < ulCount; i++)
7400 switch (pTemplate[i].type)
7402 case CKA_CHECK_VALUE:
7403 if (pTemplate[i].ulValueLen > 0)
7405 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7406 return CKR_ATTRIBUTE_VALUE_INVALID;
7415 // Generate the secret key
7416 DESKey* key = new DESKey(112);
7417 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7420 ERROR_MSG("Could not get SymmetricAlgorith");
7422 return CKR_GENERAL_ERROR;
7424 RNG* rng = CryptoFactory::i()->getRNG();
7427 ERROR_MSG("Could not get RNG");
7428 des->recycleKey(key);
7429 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7430 return CKR_GENERAL_ERROR;
7432 if (!des->generateKey(*key, rng))
7434 ERROR_MSG("Could not generate DES secret key");
7435 des->recycleKey(key);
7436 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7437 return CKR_GENERAL_ERROR;
7442 // Create the secret key object using C_CreateObject
7443 const CK_ULONG maxAttribs = 32;
7444 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7445 CK_KEY_TYPE keyType = CKK_DES2;
7446 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7447 { CKA_CLASS, &objClass, sizeof(objClass) },
7448 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7449 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7450 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7452 CK_ULONG keyAttribsCount = 4;
7454 // Add the additional
7455 if (ulCount > (maxAttribs - keyAttribsCount))
7456 rv = CKR_TEMPLATE_INCONSISTENT;
7457 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7459 switch (pTemplate[i].type)
7465 case CKA_CHECK_VALUE:
7468 keyAttribs[keyAttribsCount++] = pTemplate[i];
7473 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7475 // Store the attributes that are being supplied
7478 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7479 if (osobject == NULL_PTR || !osobject->isValid()) {
7480 rv = CKR_FUNCTION_FAILED;
7481 } else if (osobject->startTransaction()) {
7484 // Common Attributes
7485 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7486 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7487 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7489 // Common Secret Key Attributes
7490 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7491 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7492 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7493 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7495 // DES Secret Key Attributes
7500 token->encrypt(key->getKeyBits(), value);
7501 token->encrypt(key->getKeyCheckValue(), kcv);
7505 value = key->getKeyBits();
7506 kcv = key->getKeyCheckValue();
7508 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7510 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7513 bOK = osobject->commitTransaction();
7515 osobject->abortTransaction();
7518 rv = CKR_FUNCTION_FAILED;
7520 rv = CKR_FUNCTION_FAILED;
7524 des->recycleKey(key);
7525 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7527 // Remove the key that may have been created already when the function fails.
7530 if (*phKey != CK_INVALID_HANDLE)
7532 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7533 handleManager->destroyObject(*phKey);
7534 if (oskey) oskey->destroyObject();
7535 *phKey = CK_INVALID_HANDLE;
7542 // Generate a DES3 secret key
7543 CK_RV SoftHSM::generateDES3
7544 (CK_SESSION_HANDLE hSession,
7545 CK_ATTRIBUTE_PTR pTemplate,
7547 CK_OBJECT_HANDLE_PTR phKey,
7551 *phKey = CK_INVALID_HANDLE;
7554 Session* session = (Session*)handleManager->getSession(hSession);
7555 if (session == NULL)
7556 return CKR_SESSION_HANDLE_INVALID;
7559 Token* token = session->getToken();
7561 return CKR_GENERAL_ERROR;
7563 // Extract desired parameter information
7564 bool checkValue = true;
7565 for (CK_ULONG i = 0; i < ulCount; i++)
7567 switch (pTemplate[i].type)
7569 case CKA_CHECK_VALUE:
7570 if (pTemplate[i].ulValueLen > 0)
7572 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7573 return CKR_ATTRIBUTE_VALUE_INVALID;
7582 // Generate the secret key
7583 DESKey* key = new DESKey(168);
7584 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7587 ERROR_MSG("Could not get SymmetricAlgorithm");
7589 return CKR_GENERAL_ERROR;
7591 RNG* rng = CryptoFactory::i()->getRNG();
7594 ERROR_MSG("Could not get RNG");
7595 des->recycleKey(key);
7596 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7597 return CKR_GENERAL_ERROR;
7599 if (!des->generateKey(*key, rng))
7601 ERROR_MSG("Could not generate DES secret key");
7602 des->recycleKey(key);
7603 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7604 return CKR_GENERAL_ERROR;
7609 // Create the secret key object using C_CreateObject
7610 const CK_ULONG maxAttribs = 32;
7611 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7612 CK_KEY_TYPE keyType = CKK_DES3;
7613 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7614 { CKA_CLASS, &objClass, sizeof(objClass) },
7615 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7616 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7617 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7619 CK_ULONG keyAttribsCount = 4;
7621 // Add the additional
7622 if (ulCount > (maxAttribs - keyAttribsCount))
7623 rv = CKR_TEMPLATE_INCONSISTENT;
7624 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7626 switch (pTemplate[i].type)
7632 case CKA_CHECK_VALUE:
7635 keyAttribs[keyAttribsCount++] = pTemplate[i];
7640 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7642 // Store the attributes that are being supplied
7645 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7646 if (osobject == NULL_PTR || !osobject->isValid()) {
7647 rv = CKR_FUNCTION_FAILED;
7648 } else if (osobject->startTransaction()) {
7651 // Common Attributes
7652 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7653 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7654 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7656 // Common Secret Key Attributes
7657 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7658 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7659 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7660 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7662 // DES Secret Key Attributes
7667 token->encrypt(key->getKeyBits(), value);
7668 token->encrypt(key->getKeyCheckValue(), kcv);
7672 value = key->getKeyBits();
7673 kcv = key->getKeyCheckValue();
7675 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7677 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7680 bOK = osobject->commitTransaction();
7682 osobject->abortTransaction();
7685 rv = CKR_FUNCTION_FAILED;
7687 rv = CKR_FUNCTION_FAILED;
7691 des->recycleKey(key);
7692 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7694 // Remove the key that may have been created already when the function fails.
7697 if (*phKey != CK_INVALID_HANDLE)
7699 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7700 handleManager->destroyObject(*phKey);
7701 if (oskey) oskey->destroyObject();
7702 *phKey = CK_INVALID_HANDLE;
7709 // Generate an RSA key pair
7710 CK_RV SoftHSM::generateRSA
7711 (CK_SESSION_HANDLE hSession,
7712 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7713 CK_ULONG ulPublicKeyAttributeCount,
7714 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7715 CK_ULONG ulPrivateKeyAttributeCount,
7716 CK_OBJECT_HANDLE_PTR phPublicKey,
7717 CK_OBJECT_HANDLE_PTR phPrivateKey,
7718 CK_BBOOL isPublicKeyOnToken,
7719 CK_BBOOL isPublicKeyPrivate,
7720 CK_BBOOL isPrivateKeyOnToken,
7721 CK_BBOOL isPrivateKeyPrivate
7724 *phPublicKey = CK_INVALID_HANDLE;
7725 *phPrivateKey = CK_INVALID_HANDLE;
7728 Session* session = (Session*)handleManager->getSession(hSession);
7729 if (session == NULL)
7730 return CKR_SESSION_HANDLE_INVALID;
7733 Token* token = session->getToken();
7735 return CKR_GENERAL_ERROR;
7737 // Extract desired key information: bitlen and public exponent
7739 ByteString exponent("010001");
7740 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7742 switch (pPublicKeyTemplate[i].type)
7744 case CKA_MODULUS_BITS:
7745 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7747 INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7748 return CKR_ATTRIBUTE_VALUE_INVALID;
7750 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7752 case CKA_PUBLIC_EXPONENT:
7753 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7760 // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7762 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7763 return CKR_TEMPLATE_INCOMPLETE;
7766 // Set the parameters
7769 p.setBitLength(bitLen);
7771 // Generate key pair
7772 AsymmetricKeyPair* kp = NULL;
7773 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7775 return CKR_GENERAL_ERROR;
7776 if (!rsa->generateKeyPair(&kp, &p))
7778 ERROR_MSG("Could not generate key pair");
7779 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7780 return CKR_GENERAL_ERROR;
7783 RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7784 RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7788 // Create a public key using C_CreateObject
7791 const CK_ULONG maxAttribs = 32;
7792 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7793 CK_KEY_TYPE publicKeyType = CKK_RSA;
7794 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7795 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7796 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7797 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7798 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7800 CK_ULONG publicKeyAttribsCount = 4;
7802 // Add the additional
7803 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7804 rv = CKR_TEMPLATE_INCONSISTENT;
7805 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7807 switch (pPublicKeyTemplate[i].type)
7813 case CKA_PUBLIC_EXPONENT:
7816 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7821 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7823 // Store the attributes that are being supplied by the key generation to the object
7826 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7827 if (osobject == NULL_PTR || !osobject->isValid()) {
7828 rv = CKR_FUNCTION_FAILED;
7829 } else if (osobject->startTransaction()) {
7832 // Common Key Attributes
7833 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7834 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7835 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7837 // RSA Public Key Attributes
7839 ByteString publicExponent;
7840 if (isPublicKeyPrivate)
7842 token->encrypt(pub->getN(), modulus);
7843 token->encrypt(pub->getE(), publicExponent);
7847 modulus = pub->getN();
7848 publicExponent = pub->getE();
7850 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7851 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7854 bOK = osobject->commitTransaction();
7856 osobject->abortTransaction();
7859 rv = CKR_FUNCTION_FAILED;
7861 rv = CKR_FUNCTION_FAILED;
7865 // Create a private key using C_CreateObject
7868 const CK_ULONG maxAttribs = 32;
7869 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7870 CK_KEY_TYPE privateKeyType = CKK_RSA;
7871 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7872 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7873 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7874 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7875 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7877 CK_ULONG privateKeyAttribsCount = 4;
7878 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7879 rv = CKR_TEMPLATE_INCONSISTENT;
7880 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
7882 switch (pPrivateKeyTemplate[i].type)
7890 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
7895 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
7897 // Store the attributes that are being supplied by the key generation to the object
7900 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
7901 if (osobject == NULL_PTR || !osobject->isValid()) {
7902 rv = CKR_FUNCTION_FAILED;
7903 } else if (osobject->startTransaction()) {
7906 // Common Key Attributes
7907 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7908 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7909 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7911 // Common Private Key Attributes
7912 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7913 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7914 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7915 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7917 // RSA Private Key Attributes
7919 ByteString publicExponent;
7920 ByteString privateExponent;
7923 ByteString exponent1;
7924 ByteString exponent2;
7925 ByteString coefficient;
7926 if (isPrivateKeyPrivate)
7928 token->encrypt(priv->getN(), modulus);
7929 token->encrypt(priv->getE(), publicExponent);
7930 token->encrypt(priv->getD(), privateExponent);
7931 token->encrypt(priv->getP(), prime1);
7932 token->encrypt(priv->getQ(), prime2);
7933 token->encrypt(priv->getDP1(), exponent1);
7934 token->encrypt(priv->getDQ1(), exponent2);
7935 token->encrypt(priv->getPQ(), coefficient);
7939 modulus = priv->getN();
7940 publicExponent = priv->getE();
7941 privateExponent = priv->getD();
7942 prime1 = priv->getP();
7943 prime2 = priv->getQ();
7944 exponent1 = priv->getDP1();
7945 exponent2 = priv->getDQ1();
7946 coefficient = priv->getPQ();
7948 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7949 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7950 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
7951 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
7952 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
7953 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
7954 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
7955 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
7958 bOK = osobject->commitTransaction();
7960 osobject->abortTransaction();
7963 rv = CKR_FUNCTION_FAILED;
7965 rv = CKR_FUNCTION_FAILED;
7970 rsa->recycleKeyPair(kp);
7971 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7973 // Remove keys that may have been created already when the function fails.
7976 if (*phPrivateKey != CK_INVALID_HANDLE)
7978 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
7979 handleManager->destroyObject(*phPrivateKey);
7980 if (ospriv) ospriv->destroyObject();
7981 *phPrivateKey = CK_INVALID_HANDLE;
7984 if (*phPublicKey != CK_INVALID_HANDLE)
7986 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
7987 handleManager->destroyObject(*phPublicKey);
7988 if (ospub) ospub->destroyObject();
7989 *phPublicKey = CK_INVALID_HANDLE;
7996 // Generate a DSA key pair
7997 CK_RV SoftHSM::generateDSA
7998 (CK_SESSION_HANDLE hSession,
7999 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8000 CK_ULONG ulPublicKeyAttributeCount,
8001 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8002 CK_ULONG ulPrivateKeyAttributeCount,
8003 CK_OBJECT_HANDLE_PTR phPublicKey,
8004 CK_OBJECT_HANDLE_PTR phPrivateKey,
8005 CK_BBOOL isPublicKeyOnToken,
8006 CK_BBOOL isPublicKeyPrivate,
8007 CK_BBOOL isPrivateKeyOnToken,
8008 CK_BBOOL isPrivateKeyPrivate)
8010 *phPublicKey = CK_INVALID_HANDLE;
8011 *phPrivateKey = CK_INVALID_HANDLE;
8014 Session* session = (Session*)handleManager->getSession(hSession);
8015 if (session == NULL)
8016 return CKR_SESSION_HANDLE_INVALID;
8019 Token* token = session->getToken();
8021 return CKR_GENERAL_ERROR;
8023 // Extract desired key information
8025 ByteString subprime;
8026 ByteString generator;
8027 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8029 switch (pPublicKeyTemplate[i].type)
8032 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8035 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8038 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8045 // The parameters must be specified to be able to generate a key pair.
8046 if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
8047 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8048 return CKR_TEMPLATE_INCOMPLETE;
8051 // Set the parameters
8057 // Generate key pair
8058 AsymmetricKeyPair* kp = NULL;
8059 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8060 if (dsa == NULL) return CKR_GENERAL_ERROR;
8061 if (!dsa->generateKeyPair(&kp, &p))
8063 ERROR_MSG("Could not generate key pair");
8064 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8065 return CKR_GENERAL_ERROR;
8068 DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
8069 DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
8073 // Create a public key using C_CreateObject
8076 const CK_ULONG maxAttribs = 32;
8077 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8078 CK_KEY_TYPE publicKeyType = CKK_DSA;
8079 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8080 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8081 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8082 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8083 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8085 CK_ULONG publicKeyAttribsCount = 4;
8087 // Add the additional
8088 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8089 rv = CKR_TEMPLATE_INCONSISTENT;
8090 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8092 switch (pPublicKeyTemplate[i].type)
8100 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8105 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8107 // Store the attributes that are being supplied by the key generation to the object
8110 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8111 if (osobject == NULL_PTR || !osobject->isValid()) {
8112 rv = CKR_FUNCTION_FAILED;
8113 } else if (osobject->startTransaction()) {
8116 // Common Key Attributes
8117 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8118 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8119 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8121 // DSA Public Key Attributes
8123 if (isPublicKeyPrivate)
8125 token->encrypt(pub->getY(), value);
8129 value = pub->getY();
8131 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8134 bOK = osobject->commitTransaction();
8136 osobject->abortTransaction();
8139 rv = CKR_FUNCTION_FAILED;
8141 rv = CKR_FUNCTION_FAILED;
8145 // Create a private key using C_CreateObject
8148 const CK_ULONG maxAttribs = 32;
8149 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8150 CK_KEY_TYPE privateKeyType = CKK_DSA;
8151 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8152 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8153 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8154 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8155 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8157 CK_ULONG privateKeyAttribsCount = 4;
8158 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8159 rv = CKR_TEMPLATE_INCONSISTENT;
8160 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8162 switch (pPrivateKeyTemplate[i].type)
8170 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8175 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8177 // Store the attributes that are being supplied by the key generation to the object
8180 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8181 if (osobject == NULL_PTR || !osobject->isValid()) {
8182 rv = CKR_FUNCTION_FAILED;
8183 } else if (osobject->startTransaction()) {
8186 // Common Key Attributes
8187 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8188 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8189 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8191 // Common Private Key Attributes
8192 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8193 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8194 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8195 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8197 // DSA Private Key Attributes
8199 ByteString bSubprime;
8200 ByteString bGenerator;
8202 if (isPrivateKeyPrivate)
8204 token->encrypt(priv->getP(), bPrime);
8205 token->encrypt(priv->getQ(), bSubprime);
8206 token->encrypt(priv->getG(), bGenerator);
8207 token->encrypt(priv->getX(), bValue);
8211 bPrime = priv->getP();
8212 bSubprime = priv->getQ();
8213 bGenerator = priv->getG();
8214 bValue = priv->getX();
8216 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8217 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8218 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8219 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8222 bOK = osobject->commitTransaction();
8224 osobject->abortTransaction();
8227 rv = CKR_FUNCTION_FAILED;
8229 rv = CKR_FUNCTION_FAILED;
8234 dsa->recycleKeyPair(kp);
8235 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8237 // Remove keys that may have been created already when the function fails.
8240 if (*phPrivateKey != CK_INVALID_HANDLE)
8242 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8243 handleManager->destroyObject(*phPrivateKey);
8244 if (ospriv) ospriv->destroyObject();
8245 *phPrivateKey = CK_INVALID_HANDLE;
8248 if (*phPublicKey != CK_INVALID_HANDLE)
8250 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8251 handleManager->destroyObject(*phPublicKey);
8252 if (ospub) ospub->destroyObject();
8253 *phPublicKey = CK_INVALID_HANDLE;
8260 // Generate a DSA domain parameter set
8261 CK_RV SoftHSM::generateDSAParameters
8262 (CK_SESSION_HANDLE hSession,
8263 CK_ATTRIBUTE_PTR pTemplate,
8265 CK_OBJECT_HANDLE_PTR phKey,
8269 *phKey = CK_INVALID_HANDLE;
8272 Session* session = (Session*)handleManager->getSession(hSession);
8273 if (session == NULL)
8274 return CKR_SESSION_HANDLE_INVALID;
8277 Token* token = session->getToken();
8279 return CKR_GENERAL_ERROR;
8281 // Extract desired parameter information
8284 for (CK_ULONG i = 0; i < ulCount; i++)
8286 switch (pTemplate[i].type)
8288 case CKA_PRIME_BITS:
8289 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8291 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8292 return CKR_ATTRIBUTE_VALUE_INVALID;
8294 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8296 case CKA_SUBPRIME_BITS:
8297 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8299 INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8300 return CKR_ATTRIBUTE_VALUE_INVALID;
8302 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8309 // CKA_PRIME_BITS must be specified
8312 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8313 return CKR_TEMPLATE_INCOMPLETE;
8316 // No real choice for CKA_SUBPRIME_BITS
8318 (((bitLen >= 2048) && (qLen != 256)) ||
8319 ((bitLen < 2048) && (qLen != 160))))
8320 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8323 // Generate domain parameters
8324 AsymmetricParameters* p = NULL;
8325 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8326 if (dsa == NULL) return CKR_GENERAL_ERROR;
8327 if (!dsa->generateParameters(&p, (void *)bitLen))
8329 ERROR_MSG("Could not generate parameters");
8330 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8331 return CKR_GENERAL_ERROR;
8334 DSAParameters* params = (DSAParameters*) p;
8338 // Create the domain parameter object using C_CreateObject
8339 const CK_ULONG maxAttribs = 32;
8340 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8341 CK_KEY_TYPE keyType = CKK_DSA;
8342 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8343 { CKA_CLASS, &objClass, sizeof(objClass) },
8344 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8345 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8346 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8348 CK_ULONG paramsAttribsCount = 4;
8350 // Add the additional
8351 if (ulCount > (maxAttribs - paramsAttribsCount))
8352 rv = CKR_TEMPLATE_INCONSISTENT;
8353 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8355 switch (pTemplate[i].type)
8363 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8368 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8370 // Store the attributes that are being supplied
8373 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8374 if (osobject == NULL_PTR || !osobject->isValid()) {
8375 rv = CKR_FUNCTION_FAILED;
8376 } else if (osobject->startTransaction()) {
8379 // Common Attributes
8380 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8381 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8382 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8384 // DSA Domain Parameters Attributes
8386 ByteString subprime;
8387 ByteString generator;
8390 token->encrypt(params->getP(), prime);
8391 token->encrypt(params->getQ(), subprime);
8392 token->encrypt(params->getG(), generator);
8396 prime = params->getP();
8397 subprime = params->getQ();
8398 generator = params->getG();
8400 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8401 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8402 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8405 bOK = osobject->commitTransaction();
8407 osobject->abortTransaction();
8410 rv = CKR_FUNCTION_FAILED;
8412 rv = CKR_FUNCTION_FAILED;
8416 dsa->recycleParameters(p);
8417 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8419 // Remove parameters that may have been created already when the function fails.
8422 if (*phKey != CK_INVALID_HANDLE)
8424 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8425 handleManager->destroyObject(*phKey);
8426 if (osparams) osparams->destroyObject();
8427 *phKey = CK_INVALID_HANDLE;
8434 // Generate an EC key pair
8435 CK_RV SoftHSM::generateEC
8436 (CK_SESSION_HANDLE hSession,
8437 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8438 CK_ULONG ulPublicKeyAttributeCount,
8439 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8440 CK_ULONG ulPrivateKeyAttributeCount,
8441 CK_OBJECT_HANDLE_PTR phPublicKey,
8442 CK_OBJECT_HANDLE_PTR phPrivateKey,
8443 CK_BBOOL isPublicKeyOnToken,
8444 CK_BBOOL isPublicKeyPrivate,
8445 CK_BBOOL isPrivateKeyOnToken,
8446 CK_BBOOL isPrivateKeyPrivate)
8448 *phPublicKey = CK_INVALID_HANDLE;
8449 *phPrivateKey = CK_INVALID_HANDLE;
8452 Session* session = (Session*)handleManager->getSession(hSession);
8453 if (session == NULL)
8454 return CKR_SESSION_HANDLE_INVALID;
8457 Token* token = session->getToken();
8459 return CKR_GENERAL_ERROR;
8461 // Extract desired key information
8463 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8465 switch (pPublicKeyTemplate[i].type)
8468 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8475 // The parameters must be specified to be able to generate a key pair.
8476 if (params.size() == 0) {
8477 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8478 return CKR_TEMPLATE_INCOMPLETE;
8481 // Set the parameters
8485 // Generate key pair
8486 AsymmetricKeyPair* kp = NULL;
8487 AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8488 if (ec == NULL) return CKR_GENERAL_ERROR;
8489 if (!ec->generateKeyPair(&kp, &p))
8491 ERROR_MSG("Could not generate key pair");
8492 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8493 return CKR_GENERAL_ERROR;
8496 ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8497 ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8501 // Create a public key using C_CreateObject
8504 const CK_ULONG maxAttribs = 32;
8505 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8506 CK_KEY_TYPE publicKeyType = CKK_EC;
8507 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8508 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8509 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8510 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8511 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8513 CK_ULONG publicKeyAttribsCount = 4;
8515 // Add the additional
8516 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8517 rv = CKR_TEMPLATE_INCONSISTENT;
8518 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8520 switch (pPublicKeyTemplate[i].type)
8528 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8533 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8535 // Store the attributes that are being supplied by the key generation to the object
8538 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8539 if (osobject == NULL_PTR || !osobject->isValid()) {
8540 rv = CKR_FUNCTION_FAILED;
8541 } else if (osobject->startTransaction()) {
8544 // Common Key Attributes
8545 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8546 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8547 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8549 // EC Public Key Attributes
8551 if (isPublicKeyPrivate)
8553 token->encrypt(pub->getQ(), point);
8557 point = pub->getQ();
8559 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8562 bOK = osobject->commitTransaction();
8564 osobject->abortTransaction();
8567 rv = CKR_FUNCTION_FAILED;
8569 rv = CKR_FUNCTION_FAILED;
8573 // Create a private key using C_CreateObject
8576 const CK_ULONG maxAttribs = 32;
8577 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8578 CK_KEY_TYPE privateKeyType = CKK_EC;
8579 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8580 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8581 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8582 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8583 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8585 CK_ULONG privateKeyAttribsCount = 4;
8586 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8587 rv = CKR_TEMPLATE_INCONSISTENT;
8588 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8590 switch (pPrivateKeyTemplate[i].type)
8598 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8603 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8605 // Store the attributes that are being supplied by the key generation to the object
8608 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8609 if (osobject == NULL_PTR || !osobject->isValid()) {
8610 rv = CKR_FUNCTION_FAILED;
8611 } else if (osobject->startTransaction()) {
8614 // Common Key Attributes
8615 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8616 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8617 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8619 // Common Private Key Attributes
8620 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8621 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8622 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8623 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8625 // EC Private Key Attributes
8628 if (isPrivateKeyPrivate)
8630 token->encrypt(priv->getEC(), group);
8631 token->encrypt(priv->getD(), value);
8635 group = priv->getEC();
8636 value = priv->getD();
8638 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8639 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8642 bOK = osobject->commitTransaction();
8644 osobject->abortTransaction();
8647 rv = CKR_FUNCTION_FAILED;
8649 rv = CKR_FUNCTION_FAILED;
8654 ec->recycleKeyPair(kp);
8655 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8657 // Remove keys that may have been created already when the function fails.
8660 if (*phPrivateKey != CK_INVALID_HANDLE)
8662 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8663 handleManager->destroyObject(*phPrivateKey);
8664 if (ospriv) ospriv->destroyObject();
8665 *phPrivateKey = CK_INVALID_HANDLE;
8668 if (*phPublicKey != CK_INVALID_HANDLE)
8670 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8671 handleManager->destroyObject(*phPublicKey);
8672 if (ospub) ospub->destroyObject();
8673 *phPublicKey = CK_INVALID_HANDLE;
8680 // Generate a DH key pair
8681 CK_RV SoftHSM::generateDH
8682 (CK_SESSION_HANDLE hSession,
8683 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8684 CK_ULONG ulPublicKeyAttributeCount,
8685 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8686 CK_ULONG ulPrivateKeyAttributeCount,
8687 CK_OBJECT_HANDLE_PTR phPublicKey,
8688 CK_OBJECT_HANDLE_PTR phPrivateKey,
8689 CK_BBOOL isPublicKeyOnToken,
8690 CK_BBOOL isPublicKeyPrivate,
8691 CK_BBOOL isPrivateKeyOnToken,
8692 CK_BBOOL isPrivateKeyPrivate)
8694 *phPublicKey = CK_INVALID_HANDLE;
8695 *phPrivateKey = CK_INVALID_HANDLE;
8698 Session* session = (Session*)handleManager->getSession(hSession);
8699 if (session == NULL)
8700 return CKR_SESSION_HANDLE_INVALID;
8703 Token* token = session->getToken();
8705 return CKR_GENERAL_ERROR;
8707 // Extract desired key information
8709 ByteString generator;
8710 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8712 switch (pPublicKeyTemplate[i].type)
8715 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8718 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8725 // The parameters must be specified to be able to generate a key pair.
8726 if (prime.size() == 0 || generator.size() == 0) {
8727 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8728 return CKR_TEMPLATE_INCOMPLETE;
8731 // Extract optional bit length
8733 for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8735 switch (pPrivateKeyTemplate[i].type)
8737 case CKA_VALUE_BITS:
8738 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8745 // Set the parameters
8749 p.setXBitLength(bitLen);
8751 // Generate key pair
8752 AsymmetricKeyPair* kp = NULL;
8753 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8754 if (dh == NULL) return CKR_GENERAL_ERROR;
8755 if (!dh->generateKeyPair(&kp, &p))
8757 ERROR_MSG("Could not generate key pair");
8758 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8759 return CKR_GENERAL_ERROR;
8762 DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8763 DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8767 // Create a public key using C_CreateObject
8770 const CK_ULONG maxAttribs = 32;
8771 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8772 CK_KEY_TYPE publicKeyType = CKK_DH;
8773 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8774 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8775 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8776 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8777 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8779 CK_ULONG publicKeyAttribsCount = 4;
8781 // Add the additional
8782 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8783 rv = CKR_TEMPLATE_INCONSISTENT;
8784 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8786 switch (pPublicKeyTemplate[i].type)
8794 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8799 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8801 // Store the attributes that are being supplied by the key generation to the object
8804 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8805 if (osobject == NULL_PTR || !osobject->isValid()) {
8806 rv = CKR_FUNCTION_FAILED;
8807 } else if (osobject->startTransaction()) {
8810 // Common Key Attributes
8811 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8812 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8813 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8815 // DH Public Key Attributes
8817 if (isPublicKeyPrivate)
8819 token->encrypt(pub->getY(), value);
8823 value = pub->getY();
8825 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8828 bOK = osobject->commitTransaction();
8830 osobject->abortTransaction();
8833 rv = CKR_FUNCTION_FAILED;
8835 rv = CKR_FUNCTION_FAILED;
8839 // Create a private key using C_CreateObject
8842 const CK_ULONG maxAttribs = 32;
8843 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8844 CK_KEY_TYPE privateKeyType = CKK_DH;
8845 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8846 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8847 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8848 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8849 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8851 CK_ULONG privateKeyAttribsCount = 4;
8852 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8853 rv = CKR_TEMPLATE_INCONSISTENT;
8854 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8856 switch (pPrivateKeyTemplate[i].type)
8864 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8869 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8871 // Store the attributes that are being supplied by the key generation to the object
8874 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8875 if (osobject == NULL_PTR || !osobject->isValid()) {
8876 rv = CKR_FUNCTION_FAILED;
8877 } else if (osobject->startTransaction()) {
8880 // Common Key Attributes
8881 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8882 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8883 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8885 // Common Private Key Attributes
8886 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8887 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8888 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8889 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8891 // DH Private Key Attributes
8893 ByteString bGenerator;
8895 if (isPrivateKeyPrivate)
8897 token->encrypt(priv->getP(), bPrime);
8898 token->encrypt(priv->getG(), bGenerator);
8899 token->encrypt(priv->getX(), bValue);
8903 bPrime = priv->getP();
8904 bGenerator = priv->getG();
8905 bValue = priv->getX();
8907 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8908 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8909 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8913 bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
8917 bOK = osobject->commitTransaction();
8919 osobject->abortTransaction();
8922 rv = CKR_FUNCTION_FAILED;
8924 rv = CKR_FUNCTION_FAILED;
8929 dh->recycleKeyPair(kp);
8930 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8932 // Remove keys that may have been created already when the function fails.
8935 if (*phPrivateKey != CK_INVALID_HANDLE)
8937 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8938 handleManager->destroyObject(*phPrivateKey);
8939 if (ospriv) ospriv->destroyObject();
8940 *phPrivateKey = CK_INVALID_HANDLE;
8943 if (*phPublicKey != CK_INVALID_HANDLE)
8945 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8946 handleManager->destroyObject(*phPublicKey);
8947 if (ospub) ospub->destroyObject();
8948 *phPublicKey = CK_INVALID_HANDLE;
8955 // Generate a DH domain parameter set
8956 CK_RV SoftHSM::generateDHParameters
8957 (CK_SESSION_HANDLE hSession,
8958 CK_ATTRIBUTE_PTR pTemplate,
8960 CK_OBJECT_HANDLE_PTR phKey,
8964 *phKey = CK_INVALID_HANDLE;
8967 Session* session = (Session*)handleManager->getSession(hSession);
8968 if (session == NULL)
8969 return CKR_SESSION_HANDLE_INVALID;
8972 Token* token = session->getToken();
8974 return CKR_GENERAL_ERROR;
8976 // Extract desired parameter information
8978 for (CK_ULONG i = 0; i < ulCount; i++)
8980 switch (pTemplate[i].type)
8982 case CKA_PRIME_BITS:
8983 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8985 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8986 return CKR_ATTRIBUTE_VALUE_INVALID;
8988 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8995 // CKA_PRIME_BITS must be specified
8998 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8999 return CKR_TEMPLATE_INCOMPLETE;
9002 // Generate domain parameters
9003 AsymmetricParameters* p = NULL;
9004 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9005 if (dh == NULL) return CKR_GENERAL_ERROR;
9006 if (!dh->generateParameters(&p, (void *)bitLen))
9008 ERROR_MSG("Could not generate parameters");
9009 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9010 return CKR_GENERAL_ERROR;
9013 DHParameters* params = (DHParameters*) p;
9017 // Create the domain parameter object using C_CreateObject
9018 const CK_ULONG maxAttribs = 32;
9019 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
9020 CK_KEY_TYPE keyType = CKK_DH;
9021 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
9022 { CKA_CLASS, &objClass, sizeof(objClass) },
9023 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9024 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9025 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9027 CK_ULONG paramsAttribsCount = 4;
9029 // Add the additional
9030 if (ulCount > (maxAttribs - paramsAttribsCount))
9031 rv = CKR_TEMPLATE_INCONSISTENT;
9032 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9034 switch (pTemplate[i].type)
9042 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
9047 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
9049 // Store the attributes that are being supplied
9052 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9053 if (osobject == NULL_PTR || !osobject->isValid()) {
9054 rv = CKR_FUNCTION_FAILED;
9055 } else if (osobject->startTransaction()) {
9058 // Common Attributes
9059 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9060 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
9061 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9063 // DH Domain Parameters Attributes
9065 ByteString generator;
9068 token->encrypt(params->getP(), prime);
9069 token->encrypt(params->getG(), generator);
9073 prime = params->getP();
9074 generator = params->getG();
9076 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
9077 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
9080 bOK = osobject->commitTransaction();
9082 osobject->abortTransaction();
9085 rv = CKR_FUNCTION_FAILED;
9087 rv = CKR_FUNCTION_FAILED;
9091 dh->recycleParameters(p);
9092 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9094 // Remove parameters that may have been created already when the function fails.
9097 if (*phKey != CK_INVALID_HANDLE)
9099 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
9100 handleManager->destroyObject(*phKey);
9101 if (osparams) osparams->destroyObject();
9102 *phKey = CK_INVALID_HANDLE;
9109 // Generate a GOST key pair
9110 CK_RV SoftHSM::generateGOST
9111 (CK_SESSION_HANDLE hSession,
9112 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
9113 CK_ULONG ulPublicKeyAttributeCount,
9114 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
9115 CK_ULONG ulPrivateKeyAttributeCount,
9116 CK_OBJECT_HANDLE_PTR phPublicKey,
9117 CK_OBJECT_HANDLE_PTR phPrivateKey,
9118 CK_BBOOL isPublicKeyOnToken,
9119 CK_BBOOL isPublicKeyPrivate,
9120 CK_BBOOL isPrivateKeyOnToken,
9121 CK_BBOOL isPrivateKeyPrivate)
9123 *phPublicKey = CK_INVALID_HANDLE;
9124 *phPrivateKey = CK_INVALID_HANDLE;
9127 Session* session = (Session*)handleManager->getSession(hSession);
9128 if (session == NULL)
9129 return CKR_SESSION_HANDLE_INVALID;
9132 Token* token = session->getToken();
9134 return CKR_GENERAL_ERROR;
9136 // Extract desired key information
9137 ByteString param_3410;
9138 ByteString param_3411;
9139 ByteString param_28147;
9140 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
9142 switch (pPublicKeyTemplate[i].type)
9144 case CKA_GOSTR3410_PARAMS:
9145 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9147 case CKA_GOSTR3411_PARAMS:
9148 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9150 case CKA_GOST28147_PARAMS:
9151 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9158 // The parameters must be specified to be able to generate a key pair.
9159 if (param_3410.size() == 0 || param_3411.size() == 0) {
9160 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
9161 return CKR_TEMPLATE_INCOMPLETE;
9164 // Set the parameters
9166 p.setEC(param_3410);
9168 // Generate key pair
9169 AsymmetricKeyPair* kp = NULL;
9170 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9171 if (gost == NULL) return CKR_GENERAL_ERROR;
9172 if (!gost->generateKeyPair(&kp, &p))
9174 ERROR_MSG("Could not generate key pair");
9175 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9176 return CKR_GENERAL_ERROR;
9179 GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9180 GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9184 // Create a public key using C_CreateObject
9187 const CK_ULONG maxAttribs = 32;
9188 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9189 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9190 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9191 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9192 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9193 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9194 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9196 CK_ULONG publicKeyAttribsCount = 4;
9198 // Add the additional
9199 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9200 rv = CKR_TEMPLATE_INCONSISTENT;
9201 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9203 switch (pPublicKeyTemplate[i].type)
9211 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9216 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9218 // Store the attributes that are being supplied by the key generation to the object
9221 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9222 if (osobject == NULL_PTR || !osobject->isValid()) {
9223 rv = CKR_FUNCTION_FAILED;
9224 } else if (osobject->startTransaction()) {
9227 // Common Key Attributes
9228 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9229 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9230 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9232 // EC Public Key Attributes
9234 if (isPublicKeyPrivate)
9236 token->encrypt(pub->getQ(), point);
9240 point = pub->getQ();
9242 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9245 bOK = osobject->commitTransaction();
9247 osobject->abortTransaction();
9250 rv = CKR_FUNCTION_FAILED;
9252 rv = CKR_FUNCTION_FAILED;
9256 // Create a private key using C_CreateObject
9259 const CK_ULONG maxAttribs = 32;
9260 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9261 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9262 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9263 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9264 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9265 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9266 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9268 CK_ULONG privateKeyAttribsCount = 4;
9269 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9270 rv = CKR_TEMPLATE_INCONSISTENT;
9271 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9273 switch (pPrivateKeyTemplate[i].type)
9281 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9286 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9288 // Store the attributes that are being supplied by the key generation to the object
9291 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9292 if (osobject == NULL_PTR || !osobject->isValid()) {
9293 rv = CKR_FUNCTION_FAILED;
9294 } else if (osobject->startTransaction()) {
9297 // Common Key Attributes
9298 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9299 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9300 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9302 // Common Private Key Attributes
9303 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9304 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9305 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9306 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9308 // GOST Private Key Attributes
9313 if (isPrivateKeyPrivate)
9315 token->encrypt(priv->getD(), value);
9316 token->encrypt(priv->getEC(), param_a);
9317 token->encrypt(param_3411, param_b);
9318 token->encrypt(param_28147, param_c);
9322 value = priv->getD();
9323 param_a = priv->getEC();
9324 param_b = param_3411;
9325 param_c = param_28147;
9327 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9328 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9329 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9330 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9333 bOK = osobject->commitTransaction();
9335 osobject->abortTransaction();
9338 rv = CKR_FUNCTION_FAILED;
9340 rv = CKR_FUNCTION_FAILED;
9345 gost->recycleKeyPair(kp);
9346 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9348 // Remove keys that may have been created already when the function fails.
9351 if (*phPrivateKey != CK_INVALID_HANDLE)
9353 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9354 handleManager->destroyObject(*phPrivateKey);
9355 if (ospriv) ospriv->destroyObject();
9356 *phPrivateKey = CK_INVALID_HANDLE;
9359 if (*phPublicKey != CK_INVALID_HANDLE)
9361 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9362 handleManager->destroyObject(*phPublicKey);
9363 if (ospub) ospub->destroyObject();
9364 *phPublicKey = CK_INVALID_HANDLE;
9371 // Derive a DH secret
9372 CK_RV SoftHSM::deriveDH
9373 (CK_SESSION_HANDLE hSession,
9374 CK_MECHANISM_PTR pMechanism,
9375 CK_OBJECT_HANDLE hBaseKey,
9376 CK_ATTRIBUTE_PTR pTemplate,
9378 CK_OBJECT_HANDLE_PTR phKey,
9379 CK_KEY_TYPE keyType,
9383 *phKey = CK_INVALID_HANDLE;
9385 if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9386 if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9389 Session* session = (Session*)handleManager->getSession(hSession);
9390 if (session == NULL)
9391 return CKR_SESSION_HANDLE_INVALID;
9394 Token* token = session->getToken();
9396 return CKR_GENERAL_ERROR;
9398 // Extract desired parameter information
9400 bool checkValue = true;
9401 for (CK_ULONG i = 0; i < ulCount; i++)
9403 switch (pTemplate[i].type)
9406 INFO_MSG("CKA_VALUE must not be included");
9407 return CKR_ATTRIBUTE_READ_ONLY;
9409 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9411 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9412 return CKR_ATTRIBUTE_VALUE_INVALID;
9414 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9416 case CKA_CHECK_VALUE:
9417 if (pTemplate[i].ulValueLen > 0)
9419 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9420 return CKR_ATTRIBUTE_VALUE_INVALID;
9432 case CKK_GENERIC_SECRET:
9435 INFO_MSG("CKA_VALUE_LEN must be set");
9436 return CKR_TEMPLATE_INCOMPLETE;
9443 INFO_MSG("CKA_VALUE_LEN must not be set");
9444 return CKR_ATTRIBUTE_READ_ONLY;
9452 INFO_MSG("CKA_VALUE_LEN must not be set");
9453 return CKR_ATTRIBUTE_READ_ONLY;
9460 INFO_MSG("CKA_VALUE_LEN must not be set");
9461 return CKR_ATTRIBUTE_READ_ONLY;
9466 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9468 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9469 return CKR_ATTRIBUTE_VALUE_INVALID;
9473 return CKR_ATTRIBUTE_VALUE_INVALID;
9476 // Get the base key handle
9477 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9478 if (baseKey == NULL || !baseKey->isValid())
9479 return CKR_KEY_HANDLE_INVALID;
9481 // Get the DH algorithm handler
9482 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9484 return CKR_MECHANISM_INVALID;
9487 PrivateKey* privateKey = dh->newPrivateKey();
9488 if (privateKey == NULL)
9490 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9491 return CKR_HOST_MEMORY;
9493 if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9495 dh->recyclePrivateKey(privateKey);
9496 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9497 return CKR_GENERAL_ERROR;
9500 ByteString mechParameters;
9501 mechParameters.resize(pMechanism->ulParameterLen);
9502 memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9503 PublicKey* publicKey = dh->newPublicKey();
9504 if (publicKey == NULL)
9506 dh->recyclePrivateKey(privateKey);
9507 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9508 return CKR_HOST_MEMORY;
9510 if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9512 dh->recyclePrivateKey(privateKey);
9513 dh->recyclePublicKey(publicKey);
9514 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9515 return CKR_GENERAL_ERROR;
9518 // Derive the secret
9519 SymmetricKey* secret = NULL;
9521 if (!dh->deriveKey(&secret, publicKey, privateKey))
9522 rv = CKR_GENERAL_ERROR;
9523 dh->recyclePrivateKey(privateKey);
9524 dh->recyclePublicKey(publicKey);
9526 // Create the secret object using C_CreateObject
9527 const CK_ULONG maxAttribs = 32;
9528 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9529 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9530 { CKA_CLASS, &objClass, sizeof(objClass) },
9531 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9532 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9533 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9535 CK_ULONG secretAttribsCount = 4;
9537 // Add the additional
9538 if (ulCount > (maxAttribs - secretAttribsCount))
9539 rv = CKR_TEMPLATE_INCONSISTENT;
9540 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9542 switch (pTemplate[i].type)
9548 case CKA_CHECK_VALUE:
9551 secretAttribs[secretAttribsCount++] = pTemplate[i];
9556 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9558 // Store the attributes that are being supplied
9561 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9562 if (osobject == NULL_PTR || !osobject->isValid()) {
9563 rv = CKR_FUNCTION_FAILED;
9564 } else if (osobject->startTransaction()) {
9567 // Common Attributes
9568 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9570 // Common Secret Key Attributes
9571 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9573 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9574 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9578 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9580 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9582 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9583 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9587 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9590 // Secret Attributes
9591 ByteString secretValue = secret->getKeyBits();
9593 ByteString plainKCV;
9596 if (byteLen > secretValue.size())
9598 INFO_MSG("The derived secret is too short");
9603 // Truncate value when requested, remove from the leading end
9604 if (byteLen < secretValue.size())
9605 secretValue.split(secretValue.size() - byteLen);
9607 // Fix the odd parity for DES
9608 if (keyType == CKK_DES ||
9609 keyType == CKK_DES2 ||
9610 keyType == CKK_DES3)
9612 for (size_t i = 0; i < secretValue.size(); i++)
9614 secretValue[i] = odd_parity[secretValue[i]];
9621 case CKK_GENERIC_SECRET:
9622 secret->setBitLen(byteLen * 8);
9623 plainKCV = secret->getKeyCheckValue();
9628 secret->setBitLen(byteLen * 7);
9629 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9632 secret->setBitLen(byteLen * 8);
9633 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9642 token->encrypt(secretValue, value);
9643 token->encrypt(plainKCV, kcv);
9647 value = secretValue;
9651 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9653 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9656 bOK = osobject->commitTransaction();
9658 osobject->abortTransaction();
9661 rv = CKR_FUNCTION_FAILED;
9663 rv = CKR_FUNCTION_FAILED;
9667 dh->recycleSymmetricKey(secret);
9668 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9670 // Remove secret that may have been created already when the function fails.
9673 if (*phKey != CK_INVALID_HANDLE)
9675 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9676 handleManager->destroyObject(*phKey);
9677 if (ossecret) ossecret->destroyObject();
9678 *phKey = CK_INVALID_HANDLE;
9685 // Derive an ECDH secret
9686 CK_RV SoftHSM::deriveECDH
9687 (CK_SESSION_HANDLE hSession,
9688 CK_MECHANISM_PTR pMechanism,
9689 CK_OBJECT_HANDLE hBaseKey,
9690 CK_ATTRIBUTE_PTR pTemplate,
9692 CK_OBJECT_HANDLE_PTR phKey,
9693 CK_KEY_TYPE keyType,
9698 *phKey = CK_INVALID_HANDLE;
9700 if ((pMechanism->pParameter == NULL_PTR) ||
9701 (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9703 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9704 return CKR_MECHANISM_PARAM_INVALID;
9706 if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9708 DEBUG_MSG("kdf must be CKD_NULL");
9709 return CKR_MECHANISM_PARAM_INVALID;
9711 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9712 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9714 DEBUG_MSG("there must be no shared data");
9715 return CKR_MECHANISM_PARAM_INVALID;
9717 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9718 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9720 DEBUG_MSG("there must be a public data");
9721 return CKR_MECHANISM_PARAM_INVALID;
9725 Session* session = (Session*)handleManager->getSession(hSession);
9726 if (session == NULL)
9727 return CKR_SESSION_HANDLE_INVALID;
9730 Token* token = session->getToken();
9732 return CKR_GENERAL_ERROR;
9734 // Extract desired parameter information
9736 bool checkValue = true;
9737 for (CK_ULONG i = 0; i < ulCount; i++)
9739 switch (pTemplate[i].type)
9742 INFO_MSG("CKA_VALUE must not be included");
9743 return CKR_ATTRIBUTE_READ_ONLY;
9745 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9747 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9748 return CKR_ATTRIBUTE_VALUE_INVALID;
9750 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9752 case CKA_CHECK_VALUE:
9753 if (pTemplate[i].ulValueLen > 0)
9755 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9756 return CKR_ATTRIBUTE_VALUE_INVALID;
9766 // byteLen == 0 impiles return max size the ECC can derive
9769 case CKK_GENERIC_SECRET:
9773 if (byteLen != 0 && byteLen != 8)
9775 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9776 return CKR_ATTRIBUTE_VALUE_INVALID;
9782 if (byteLen != 0 && byteLen != 16)
9784 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9785 return CKR_ATTRIBUTE_VALUE_INVALID;
9790 if (byteLen != 0 && byteLen != 24)
9792 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9793 return CKR_ATTRIBUTE_VALUE_INVALID;
9798 if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9800 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9801 return CKR_ATTRIBUTE_VALUE_INVALID;
9805 return CKR_ATTRIBUTE_VALUE_INVALID;
9808 // Get the base key handle
9809 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9810 if (baseKey == NULL || !baseKey->isValid())
9811 return CKR_KEY_HANDLE_INVALID;
9813 // Get the ECDH algorithm handler
9814 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9816 return CKR_MECHANISM_INVALID;
9819 PrivateKey* privateKey = ecdh->newPrivateKey();
9820 if (privateKey == NULL)
9822 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9823 return CKR_HOST_MEMORY;
9825 if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9827 ecdh->recyclePrivateKey(privateKey);
9828 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9829 return CKR_GENERAL_ERROR;
9832 ByteString publicData;
9833 publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9834 memcpy(&publicData[0],
9835 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9836 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9837 PublicKey* publicKey = ecdh->newPublicKey();
9838 if (publicKey == NULL)
9840 ecdh->recyclePrivateKey(privateKey);
9841 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9842 return CKR_HOST_MEMORY;
9844 if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9846 ecdh->recyclePrivateKey(privateKey);
9847 ecdh->recyclePublicKey(publicKey);
9848 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9849 return CKR_GENERAL_ERROR;
9852 // Derive the secret
9853 SymmetricKey* secret = NULL;
9855 if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9856 rv = CKR_GENERAL_ERROR;
9857 ecdh->recyclePrivateKey(privateKey);
9858 ecdh->recyclePublicKey(publicKey);
9860 // Create the secret object using C_CreateObject
9861 const CK_ULONG maxAttribs = 32;
9862 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9863 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9864 { CKA_CLASS, &objClass, sizeof(objClass) },
9865 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9866 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9867 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9869 CK_ULONG secretAttribsCount = 4;
9871 // Add the additional
9872 if (ulCount > (maxAttribs - secretAttribsCount))
9873 rv = CKR_TEMPLATE_INCONSISTENT;
9874 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9876 switch (pTemplate[i].type)
9882 case CKA_CHECK_VALUE:
9885 secretAttribs[secretAttribsCount++] = pTemplate[i];
9890 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9892 // Store the attributes that are being supplied
9895 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9896 if (osobject == NULL_PTR || !osobject->isValid()) {
9897 rv = CKR_FUNCTION_FAILED;
9898 } else if (osobject->startTransaction()) {
9901 // Common Attributes
9902 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9904 // Common Secret Key Attributes
9905 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9907 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9908 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9912 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9914 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9916 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9917 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9921 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9924 // Secret Attributes
9925 ByteString secretValue = secret->getKeyBits();
9927 ByteString plainKCV;
9930 // For generic and AES keys:
9931 // default to return max size available.
9936 case CKK_GENERIC_SECRET:
9937 byteLen = secretValue.size();
9940 if (secretValue.size() >= 32)
9942 else if (secretValue.size() >= 24)
9949 if (byteLen > secretValue.size())
9951 INFO_MSG("The derived secret is too short");
9956 // Truncate value when requested, remove from the leading end
9957 if (byteLen < secretValue.size())
9958 secretValue.split(secretValue.size() - byteLen);
9960 // Fix the odd parity for DES
9961 if (keyType == CKK_DES ||
9962 keyType == CKK_DES2 ||
9963 keyType == CKK_DES3)
9965 for (size_t i = 0; i < secretValue.size(); i++)
9967 secretValue[i] = odd_parity[secretValue[i]];
9974 case CKK_GENERIC_SECRET:
9975 secret->setBitLen(byteLen * 8);
9976 plainKCV = secret->getKeyCheckValue();
9981 secret->setBitLen(byteLen * 7);
9982 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9985 secret->setBitLen(byteLen * 8);
9986 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9995 token->encrypt(secretValue, value);
9996 token->encrypt(plainKCV, kcv);
10000 value = secretValue;
10004 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10006 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10009 bOK = osobject->commitTransaction();
10011 osobject->abortTransaction();
10014 rv = CKR_FUNCTION_FAILED;
10016 rv = CKR_FUNCTION_FAILED;
10020 ecdh->recycleSymmetricKey(secret);
10021 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
10023 // Remove secret that may have been created already when the function fails.
10026 if (*phKey != CK_INVALID_HANDLE)
10028 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10029 handleManager->destroyObject(*phKey);
10030 if (ossecret) ossecret->destroyObject();
10031 *phKey = CK_INVALID_HANDLE;
10037 return CKR_MECHANISM_INVALID;
10041 // Derive an symmetric secret
10042 CK_RV SoftHSM::deriveSymmetric
10043 (CK_SESSION_HANDLE hSession,
10044 CK_MECHANISM_PTR pMechanism,
10045 CK_OBJECT_HANDLE hBaseKey,
10046 CK_ATTRIBUTE_PTR pTemplate,
10048 CK_OBJECT_HANDLE_PTR phKey,
10049 CK_KEY_TYPE keyType,
10050 CK_BBOOL isOnToken,
10051 CK_BBOOL isPrivate)
10053 *phKey = CK_INVALID_HANDLE;
10055 if (pMechanism->pParameter == NULL_PTR)
10057 DEBUG_MSG("pParameter must be supplied");
10058 return CKR_MECHANISM_PARAM_INVALID;
10063 if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
10064 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
10065 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10067 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10068 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10069 if (ulLen == 0 || pData == NULL_PTR)
10071 DEBUG_MSG("There must be data in the parameter");
10072 return CKR_MECHANISM_PARAM_INVALID;
10074 if (ulLen % 8 != 0)
10076 DEBUG_MSG("The data must be a multiple of 8 bytes long");
10077 return CKR_MECHANISM_PARAM_INVALID;
10079 data.resize(ulLen);
10084 else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
10085 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
10086 pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
10088 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10089 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10090 if (length == 0 || pData == NULL_PTR)
10092 DEBUG_MSG("There must be data in the parameter");
10093 return CKR_MECHANISM_PARAM_INVALID;
10095 if (length % 8 != 0)
10097 DEBUG_MSG("The data must be a multiple of 8 bytes long");
10098 return CKR_MECHANISM_PARAM_INVALID;
10100 data.resize(length);
10105 else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
10106 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10108 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10109 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10110 if (ulLen == 0 || pData == NULL_PTR)
10112 DEBUG_MSG("There must be data in the parameter");
10113 return CKR_MECHANISM_PARAM_INVALID;
10115 if (ulLen % 16 != 0)
10117 DEBUG_MSG("The data must be a multiple of 16 bytes long");
10118 return CKR_MECHANISM_PARAM_INVALID;
10120 data.resize(ulLen);
10125 else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
10126 pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
10128 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10129 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10130 if (length == 0 || pData == NULL_PTR)
10132 DEBUG_MSG("There must be data in the parameter");
10133 return CKR_MECHANISM_PARAM_INVALID;
10135 if (length % 16 != 0)
10137 DEBUG_MSG("The data must be a multiple of 16 bytes long");
10138 return CKR_MECHANISM_PARAM_INVALID;
10140 data.resize(length);
10147 DEBUG_MSG("pParameter is invalid");
10148 return CKR_MECHANISM_PARAM_INVALID;
10152 Session* session = (Session*)handleManager->getSession(hSession);
10153 if (session == NULL)
10154 return CKR_SESSION_HANDLE_INVALID;
10157 Token* token = session->getToken();
10159 return CKR_GENERAL_ERROR;
10161 // Extract desired parameter information
10162 size_t byteLen = 0;
10163 bool checkValue = true;
10164 for (CK_ULONG i = 0; i < ulCount; i++)
10166 switch (pTemplate[i].type)
10169 INFO_MSG("CKA_VALUE must not be included");
10170 return CKR_ATTRIBUTE_READ_ONLY;
10171 case CKA_VALUE_LEN:
10172 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10174 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10175 return CKR_ATTRIBUTE_VALUE_INVALID;
10177 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10179 case CKA_CHECK_VALUE:
10180 if (pTemplate[i].ulValueLen > 0)
10182 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10183 return CKR_ATTRIBUTE_VALUE_INVALID;
10185 checkValue = false;
10192 // Check the length
10195 case CKK_GENERIC_SECRET:
10198 INFO_MSG("CKA_VALUE_LEN must be set");
10199 return CKR_TEMPLATE_INCOMPLETE;
10206 INFO_MSG("CKA_VALUE_LEN must not be set");
10207 return CKR_ATTRIBUTE_READ_ONLY;
10215 INFO_MSG("CKA_VALUE_LEN must not be set");
10216 return CKR_ATTRIBUTE_READ_ONLY;
10223 INFO_MSG("CKA_VALUE_LEN must not be set");
10224 return CKR_ATTRIBUTE_READ_ONLY;
10229 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10231 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10232 return CKR_ATTRIBUTE_VALUE_INVALID;
10236 return CKR_ATTRIBUTE_VALUE_INVALID;
10239 // Get the symmetric algorithm matching the mechanism
10240 SymAlgo::Type algo = SymAlgo::Unknown;
10241 SymMode::Type mode = SymMode::Unknown;
10242 bool padding = false;
10245 switch(pMechanism->mechanism) {
10247 case CKM_DES_ECB_ENCRYPT_DATA:
10248 algo = SymAlgo::DES;
10249 mode = SymMode::ECB;
10252 case CKM_DES_CBC_ENCRYPT_DATA:
10253 algo = SymAlgo::DES;
10254 mode = SymMode::CBC;
10258 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10262 case CKM_DES3_ECB_ENCRYPT_DATA:
10263 algo = SymAlgo::DES3;
10264 mode = SymMode::ECB;
10267 case CKM_DES3_CBC_ENCRYPT_DATA:
10268 algo = SymAlgo::DES3;
10269 mode = SymMode::CBC;
10273 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10276 case CKM_AES_ECB_ENCRYPT_DATA:
10277 algo = SymAlgo::AES;
10278 mode = SymMode::ECB;
10280 case CKM_AES_CBC_ENCRYPT_DATA:
10281 algo = SymAlgo::AES;
10282 mode = SymMode::CBC;
10285 &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10289 return CKR_MECHANISM_INVALID;
10292 // Check the key handle
10293 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10294 if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10296 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10297 if (cipher == NULL) return CKR_MECHANISM_INVALID;
10299 SymmetricKey* secretkey = new SymmetricKey();
10301 if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10303 cipher->recycleKey(secretkey);
10304 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10305 return CKR_GENERAL_ERROR;
10308 // adjust key bit length
10309 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10311 // Initialize encryption
10312 if (!cipher->encryptInit(secretkey, mode, iv, padding))
10314 cipher->recycleKey(secretkey);
10315 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10316 return CKR_MECHANISM_INVALID;
10320 ByteString secretValue;
10322 // Encrypt the data
10323 if (!cipher->encryptUpdate(data, secretValue))
10325 cipher->recycleKey(secretkey);
10326 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10327 return CKR_GENERAL_ERROR;
10330 // Finalize encryption
10331 ByteString encryptedFinal;
10332 if (!cipher->encryptFinal(encryptedFinal))
10334 cipher->recycleKey(secretkey);
10335 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10336 return CKR_GENERAL_ERROR;
10338 cipher->recycleKey(secretkey);
10339 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10340 secretValue += encryptedFinal;
10342 // Create the secret object using C_CreateObject
10343 const CK_ULONG maxAttribs = 32;
10344 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10345 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10346 { CKA_CLASS, &objClass, sizeof(objClass) },
10347 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10348 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10349 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10351 CK_ULONG secretAttribsCount = 4;
10353 // Add the additional
10355 if (ulCount > (maxAttribs - secretAttribsCount))
10356 rv = CKR_TEMPLATE_INCONSISTENT;
10357 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10359 switch (pTemplate[i].type)
10365 case CKA_CHECK_VALUE:
10368 secretAttribs[secretAttribsCount++] = pTemplate[i];
10373 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10375 // Store the attributes that are being supplied
10378 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10379 if (osobject == NULL_PTR || !osobject->isValid()) {
10380 rv = CKR_FUNCTION_FAILED;
10381 } else if (osobject->startTransaction()) {
10384 // Common Attributes
10385 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10387 // Common Secret Key Attributes
10388 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10390 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10391 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10395 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10397 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10399 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10400 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10404 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10408 ByteString plainKCV;
10411 if (byteLen > secretValue.size())
10413 INFO_MSG("The derived secret is too short");
10418 // Truncate value when requested, remove from the trailing end
10419 if (byteLen < secretValue.size())
10420 secretValue.resize(byteLen);
10422 // Fix the odd parity for DES
10423 if (keyType == CKK_DES ||
10424 keyType == CKK_DES2 ||
10425 keyType == CKK_DES3)
10427 for (size_t i = 0; i < secretValue.size(); i++)
10429 secretValue[i] = odd_parity[secretValue[i]];
10434 SymmetricKey* secret = new SymmetricKey();
10435 secret->setKeyBits(secretValue);
10438 case CKK_GENERIC_SECRET:
10439 secret->setBitLen(byteLen * 8);
10440 plainKCV = secret->getKeyCheckValue();
10445 secret->setBitLen(byteLen * 7);
10446 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10449 secret->setBitLen(byteLen * 8);
10450 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10460 token->encrypt(secretValue, value);
10461 token->encrypt(plainKCV, kcv);
10465 value = secretValue;
10469 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10471 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10474 bOK = osobject->commitTransaction();
10476 osobject->abortTransaction();
10479 rv = CKR_FUNCTION_FAILED;
10481 rv = CKR_FUNCTION_FAILED;
10484 // Remove secret that may have been created already when the function fails.
10487 if (*phKey != CK_INVALID_HANDLE)
10489 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10490 handleManager->destroyObject(*phKey);
10491 if (ossecret) ossecret->destroyObject();
10492 *phKey = CK_INVALID_HANDLE;
10499 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10501 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10503 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10504 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10507 Session* session = (Session*)handleManager->getSession(hSession);
10508 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10511 Slot* slot = session->getSlot();
10512 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10515 Token* token = session->getToken();
10516 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10518 // Extract information from the template that is needed to create the object.
10519 CK_OBJECT_CLASS objClass = CKO_DATA;
10520 CK_KEY_TYPE keyType = CKK_RSA;
10521 CK_CERTIFICATE_TYPE certType = CKC_X_509;
10522 CK_BBOOL isOnToken = CK_FALSE;
10523 CK_BBOOL isPrivate = CK_TRUE;
10524 bool isImplicit = false;
10525 CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10528 ERROR_MSG("Mandatory attribute not present in template");
10532 // Check user credentials
10533 rv = haveWrite(session->getState(), isOnToken, isPrivate);
10536 if (rv == CKR_USER_NOT_LOGGED_IN)
10537 INFO_MSG("User is not authorized");
10538 if (rv == CKR_SESSION_READ_ONLY)
10539 INFO_MSG("Session is read-only");
10544 // Change order of attributes
10545 const CK_ULONG maxAttribs = 32;
10546 CK_ATTRIBUTE attribs[maxAttribs];
10547 CK_ATTRIBUTE saveAttribs[maxAttribs];
10548 CK_ULONG attribsCount = 0;
10549 CK_ULONG saveAttribsCount = 0;
10550 if (ulCount > maxAttribs)
10552 return CKR_TEMPLATE_INCONSISTENT;
10554 for (CK_ULONG i=0; i < ulCount; i++)
10556 switch (pTemplate[i].type)
10558 case CKA_CHECK_VALUE:
10559 saveAttribs[saveAttribsCount++] = pTemplate[i];
10562 attribs[attribsCount++] = pTemplate[i];
10565 for (CK_ULONG i=0; i < saveAttribsCount; i++)
10567 attribs[attribsCount++] = saveAttribs[i];
10570 P11Object* p11object = NULL;
10571 rv = newP11Object(objClass,keyType,certType,&p11object);
10575 // Create the object in session or on the token
10576 OSObject *object = NULL_PTR;
10579 object = (OSObject*) token->createObject();
10583 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10586 if (object == NULL || !p11object->init(object))
10589 return CKR_GENERAL_ERROR;
10592 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10597 if (op == OBJECT_OP_CREATE)
10599 if (objClass == CKO_PUBLIC_KEY &&
10600 (!object->startTransaction() ||
10601 !object->setAttribute(CKA_LOCAL, false) ||
10602 !object->commitTransaction()))
10604 return CKR_GENERAL_ERROR;
10607 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10608 (!object->startTransaction() ||
10609 !object->setAttribute(CKA_LOCAL, false) ||
10610 !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10611 !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10612 !object->commitTransaction()))
10614 return CKR_GENERAL_ERROR;
10620 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10622 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10628 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10630 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10631 if (token == NULL) return CKR_ARGUMENTS_BAD;
10632 if (key == NULL) return CKR_ARGUMENTS_BAD;
10634 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10635 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10637 // RSA Private Key Attributes
10638 ByteString modulus;
10639 ByteString publicExponent;
10640 ByteString privateExponent;
10643 ByteString exponent1;
10644 ByteString exponent2;
10645 ByteString coefficient;
10649 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10650 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10651 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10652 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10653 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10654 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10655 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10656 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10658 return CKR_GENERAL_ERROR;
10662 modulus = key->getByteStringValue(CKA_MODULUS);
10663 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10664 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10665 prime1 = key->getByteStringValue(CKA_PRIME_1);
10666 prime2 = key->getByteStringValue(CKA_PRIME_2);
10667 exponent1 = key->getByteStringValue(CKA_EXPONENT_1);
10668 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10669 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10672 privateKey->setN(modulus);
10673 privateKey->setE(publicExponent);
10674 privateKey->setD(privateExponent);
10675 privateKey->setP(prime1);
10676 privateKey->setQ(prime2);
10677 privateKey->setDP1(exponent1);
10678 privateKey->setDQ1(exponent2);
10679 privateKey->setPQ(coefficient);
10684 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10686 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10687 if (token == NULL) return CKR_ARGUMENTS_BAD;
10688 if (key == NULL) return CKR_ARGUMENTS_BAD;
10690 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10691 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10693 // RSA Public Key Attributes
10694 ByteString modulus;
10695 ByteString publicExponent;
10699 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10700 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10702 return CKR_GENERAL_ERROR;
10706 modulus = key->getByteStringValue(CKA_MODULUS);
10707 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10710 publicKey->setN(modulus);
10711 publicKey->setE(publicExponent);
10716 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10718 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10719 if (token == NULL) return CKR_ARGUMENTS_BAD;
10720 if (key == NULL) return CKR_ARGUMENTS_BAD;
10722 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10723 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10725 // DSA Private Key Attributes
10727 ByteString subprime;
10728 ByteString generator;
10733 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10734 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10735 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10736 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10738 return CKR_GENERAL_ERROR;
10742 prime = key->getByteStringValue(CKA_PRIME);
10743 subprime = key->getByteStringValue(CKA_SUBPRIME);
10744 generator = key->getByteStringValue(CKA_BASE);
10745 value = key->getByteStringValue(CKA_VALUE);
10748 privateKey->setP(prime);
10749 privateKey->setQ(subprime);
10750 privateKey->setG(generator);
10751 privateKey->setX(value);
10756 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10758 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10759 if (token == NULL) return CKR_ARGUMENTS_BAD;
10760 if (key == NULL) return CKR_ARGUMENTS_BAD;
10762 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10763 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10765 // DSA Public Key Attributes
10767 ByteString subprime;
10768 ByteString generator;
10773 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10774 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10775 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10776 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10778 return CKR_GENERAL_ERROR;
10782 prime = key->getByteStringValue(CKA_PRIME);
10783 subprime = key->getByteStringValue(CKA_SUBPRIME);
10784 generator = key->getByteStringValue(CKA_BASE);
10785 value = key->getByteStringValue(CKA_VALUE);
10788 publicKey->setP(prime);
10789 publicKey->setQ(subprime);
10790 publicKey->setG(generator);
10791 publicKey->setY(value);
10796 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10798 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10799 if (token == NULL) return CKR_ARGUMENTS_BAD;
10800 if (key == NULL) return CKR_ARGUMENTS_BAD;
10802 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10803 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10805 // EC Private Key Attributes
10811 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10812 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10814 return CKR_GENERAL_ERROR;
10818 group = key->getByteStringValue(CKA_EC_PARAMS);
10819 value = key->getByteStringValue(CKA_VALUE);
10822 privateKey->setEC(group);
10823 privateKey->setD(value);
10828 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10830 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10831 if (token == NULL) return CKR_ARGUMENTS_BAD;
10832 if (key == NULL) return CKR_ARGUMENTS_BAD;
10834 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10835 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10837 // EC Public Key Attributes
10843 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10844 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10846 return CKR_GENERAL_ERROR;
10850 group = key->getByteStringValue(CKA_EC_PARAMS);
10851 point = key->getByteStringValue(CKA_EC_POINT);
10854 publicKey->setEC(group);
10855 publicKey->setQ(point);
10860 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10862 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10863 if (token == NULL) return CKR_ARGUMENTS_BAD;
10864 if (key == NULL) return CKR_ARGUMENTS_BAD;
10866 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10867 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10869 // DH Private Key Attributes
10871 ByteString generator;
10876 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10877 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10878 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10880 return CKR_GENERAL_ERROR;
10884 prime = key->getByteStringValue(CKA_PRIME);
10885 generator = key->getByteStringValue(CKA_BASE);
10886 value = key->getByteStringValue(CKA_VALUE);
10889 privateKey->setP(prime);
10890 privateKey->setG(generator);
10891 privateKey->setX(value);
10896 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
10898 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10899 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10901 // Copy Domain Parameters from Private Key
10902 publicKey->setP(privateKey->getP());
10903 publicKey->setG(privateKey->getG());
10906 publicKey->setY(pubParams);
10911 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
10913 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10914 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10916 // Copy Domain Parameters from Private Key
10917 publicKey->setEC(privateKey->getEC());
10920 ByteString data = getECDHPubData(pubData);
10921 publicKey->setQ(data);
10926 // ECDH pubData can be in RAW or DER format.
10927 // Need to convert RAW as SoftHSM uses DER.
10928 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
10930 size_t len = pubData.size();
10931 size_t controlOctets = 2;
10932 if (len == 65 || len == 97 || len == 133)
10934 // Raw: Length matches the public key size of P-256, P-384, or P-521
10937 else if (len < controlOctets || pubData[0] != 0x04)
10939 // Raw: Too short or does not start with 0x04
10942 else if (pubData[1] < 0x80)
10944 // Raw: Length octet does not match remaining data length
10945 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
10949 size_t lengthOctets = pubData[1] & 0x7F;
10950 controlOctets += lengthOctets;
10952 if (controlOctets >= len)
10959 ByteString length(&pubData[2], lengthOctets);
10961 if (length.long_val() != (len - controlOctets))
10963 // Raw: Length octets does not match remaining data length
10970 if (controlOctets != 0) return pubData;
10977 header[0] = (unsigned char)0x04;
10978 header[1] = (unsigned char)(len & 0x7F);
10982 // Count significate bytes
10983 size_t bytes = sizeof(size_t);
10984 for(; bytes > 0; bytes--)
10986 size_t value = len >> ((bytes - 1) * 8);
10987 if (value & 0xFF) break;
10991 header.resize(2 + bytes);
10992 header[0] = (unsigned char)0x04;
10993 header[1] = (unsigned char)(0x80 | bytes);
10994 for (size_t i = 1; i <= bytes; i++)
10996 header[2+bytes-i] = (unsigned char) (len & 0xFF);
11001 return header + pubData;
11004 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
11006 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11007 if (token == NULL) return CKR_ARGUMENTS_BAD;
11008 if (key == NULL) return CKR_ARGUMENTS_BAD;
11010 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11011 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11013 // GOST Private Key Attributes
11019 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
11020 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11022 return CKR_GENERAL_ERROR;
11026 value = key->getByteStringValue(CKA_VALUE);
11027 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11030 privateKey->setD(value);
11031 privateKey->setEC(param);
11036 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
11038 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11039 if (token == NULL) return CKR_ARGUMENTS_BAD;
11040 if (key == NULL) return CKR_ARGUMENTS_BAD;
11042 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11043 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11045 // GOST Public Key Attributes
11051 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
11052 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11054 return CKR_GENERAL_ERROR;
11058 point = key->getByteStringValue(CKA_VALUE);
11059 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11062 publicKey->setQ(point);
11063 publicKey->setEC(param);
11068 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
11070 if (skey == NULL) return CKR_ARGUMENTS_BAD;
11071 if (token == NULL) return CKR_ARGUMENTS_BAD;
11072 if (key == NULL) return CKR_ARGUMENTS_BAD;
11074 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11075 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11077 ByteString keybits;
11080 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
11081 return CKR_GENERAL_ERROR;
11085 keybits = key->getByteStringValue(CKA_VALUE);
11088 skey->setKeyBits(keybits);
11093 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11095 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
11098 PrivateKey* priv = rsa->newPrivateKey();
11101 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11104 if (!priv->PKCS8Decode(ber))
11106 rsa->recyclePrivateKey(priv);
11107 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11110 // RSA Private Key Attributes
11111 ByteString modulus;
11112 ByteString publicExponent;
11113 ByteString privateExponent;
11116 ByteString exponent1;
11117 ByteString exponent2;
11118 ByteString coefficient;
11121 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
11122 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
11123 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
11124 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
11125 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
11126 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
11127 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
11128 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
11132 modulus = ((RSAPrivateKey*)priv)->getN();
11133 publicExponent = ((RSAPrivateKey*)priv)->getE();
11134 privateExponent = ((RSAPrivateKey*)priv)->getD();
11135 prime1 = ((RSAPrivateKey*)priv)->getP();
11136 prime2 = ((RSAPrivateKey*)priv)->getQ();
11137 exponent1 = ((RSAPrivateKey*)priv)->getDP1();
11138 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
11139 coefficient = ((RSAPrivateKey*)priv)->getPQ();
11142 bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
11143 bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
11144 bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
11145 bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
11146 bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
11147 bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
11148 bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
11149 bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
11151 rsa->recyclePrivateKey(priv);
11152 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11157 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11159 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
11162 PrivateKey* priv = dsa->newPrivateKey();
11165 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11168 if (!priv->PKCS8Decode(ber))
11170 dsa->recyclePrivateKey(priv);
11171 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11174 // DSA Private Key Attributes
11176 ByteString subprime;
11177 ByteString generator;
11181 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11182 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11183 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11184 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11188 prime = ((DSAPrivateKey*)priv)->getP();
11189 subprime = ((DSAPrivateKey*)priv)->getQ();
11190 generator = ((DSAPrivateKey*)priv)->getG();
11191 value = ((DSAPrivateKey*)priv)->getX();
11194 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11195 bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11196 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11197 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11199 dsa->recyclePrivateKey(priv);
11200 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11205 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11207 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11210 PrivateKey* priv = dh->newPrivateKey();
11213 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11216 if (!priv->PKCS8Decode(ber))
11218 dh->recyclePrivateKey(priv);
11219 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11222 // DH Private Key Attributes
11224 ByteString generator;
11228 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11229 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11230 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11234 prime = ((DHPrivateKey*)priv)->getP();
11235 generator = ((DHPrivateKey*)priv)->getG();
11236 value = ((DHPrivateKey*)priv)->getX();
11239 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11240 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11241 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11243 dh->recyclePrivateKey(priv);
11244 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11249 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11251 AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11254 PrivateKey* priv = ecc->newPrivateKey();
11257 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11260 if (!priv->PKCS8Decode(ber))
11262 ecc->recyclePrivateKey(priv);
11263 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11266 // EC Private Key Attributes
11271 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11272 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11276 group = ((ECPrivateKey*)priv)->getEC();
11277 value = ((ECPrivateKey*)priv)->getD();
11280 bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11281 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11283 ecc->recyclePrivateKey(priv);
11284 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11289 bool SoftHSM::setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11291 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
11294 PrivateKey* priv = gost->newPrivateKey();
11297 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11300 if (!priv->PKCS8Decode(ber))
11302 gost->recyclePrivateKey(priv);
11303 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11306 // GOST Private Key Attributes
11308 ByteString param_a;
11311 token->encrypt(((GOSTPrivateKey*)priv)->getD(), value);
11312 token->encrypt(((GOSTPrivateKey*)priv)->getEC(), param_a);
11316 value = ((GOSTPrivateKey*)priv)->getD();
11317 param_a = ((GOSTPrivateKey*)priv)->getEC();
11320 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11321 bOK = bOK && key->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
11323 gost->recyclePrivateKey(priv);
11324 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11329 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11331 // This is a programming error
11332 if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11333 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11334 return CKR_GENERAL_ERROR;
11337 if (pMechanism->pParameter == NULL_PTR ||
11338 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11340 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11341 return CKR_ARGUMENTS_BAD;
11344 CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11345 if (params->hashAlg != CKM_SHA_1)
11347 ERROR_MSG("hashAlg must be CKM_SHA_1");
11348 return CKR_ARGUMENTS_BAD;
11350 if (params->mgf != CKG_MGF1_SHA1)
11352 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11353 return CKR_ARGUMENTS_BAD;
11355 if (params->source != CKZ_DATA_SPECIFIED)
11357 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11358 return CKR_ARGUMENTS_BAD;
11360 if (params->pSourceData != NULL)
11362 ERROR_MSG("pSourceData must be NULL");
11363 return CKR_ARGUMENTS_BAD;
11365 if (params->ulSourceDataLen != 0)
11367 ERROR_MSG("ulSourceDataLen must be 0");
11368 return CKR_ARGUMENTS_BAD;
11373 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11374 OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11375 std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11376 if (allowed.empty()) {
11380 return allowed.find(pMechanism->mechanism) != allowed.end();