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);
107 static CK_RV Extract_key_handle(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, void *private_handle)
111 // get value of the wrapped data (ck)
112 CK_ATTRIBUTE valAttrib[] = {
113 {CKA_OS_PRIVATE_HANDLE, NULL_PTR, sizeof(CK_ULONG)}
116 *(CK_ULONG*)private_handle = 0;
117 valAttrib[0].pValue = private_handle;
119 rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE));
122 LOG("C_GetAttributeValue() API failed ! %lx\n", rv);
128 static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
132 *p11object = new P11DataObj();
134 case CKO_CERTIFICATE:
135 if (certType == CKC_X_509)
136 *p11object = new P11X509CertificateObj();
137 else if (certType == CKC_OPENPGP)
138 *p11object = new P11OpenPGPPublicKeyObj();
140 return CKR_ATTRIBUTE_VALUE_INVALID;
143 if (keyType == CKK_RSA)
144 *p11object = new P11RSAPublicKeyObj();
145 else if (keyType == CKK_DSA)
146 *p11object = new P11DSAPublicKeyObj();
147 else if (keyType == CKK_EC)
148 *p11object = new P11ECPublicKeyObj();
149 else if (keyType == CKK_DH)
150 *p11object = new P11DHPublicKeyObj();
151 else if (keyType == CKK_GOSTR3410)
152 *p11object = new P11GOSTPublicKeyObj();
154 return CKR_ATTRIBUTE_VALUE_INVALID;
156 case CKO_PRIVATE_KEY:
157 // we need to know the type too
158 if (keyType == CKK_RSA)
159 *p11object = new P11RSAPrivateKeyObj();
160 else if (keyType == CKK_DSA)
161 *p11object = new P11DSAPrivateKeyObj();
162 else if (keyType == CKK_EC)
163 *p11object = new P11ECPrivateKeyObj();
164 else if (keyType == CKK_DH)
165 *p11object = new P11DHPrivateKeyObj();
166 else if (keyType == CKK_GOSTR3410)
167 *p11object = new P11GOSTPrivateKeyObj();
169 return CKR_ATTRIBUTE_VALUE_INVALID;
172 if ((keyType == CKK_GENERIC_SECRET) ||
173 (keyType == CKK_MD5_HMAC) ||
174 (keyType == CKK_SHA_1_HMAC) ||
175 (keyType == CKK_SHA224_HMAC) ||
176 (keyType == CKK_SHA256_HMAC) ||
177 (keyType == CKK_SHA384_HMAC) ||
178 (keyType == CKK_SHA512_HMAC))
180 P11GenericSecretKeyObj* key = new P11GenericSecretKeyObj();
182 key->setKeyType(keyType);
184 else if (keyType == CKK_AES)
186 *p11object = new P11AESSecretKeyObj();
188 else if ((keyType == CKK_DES) ||
189 (keyType == CKK_DES2) ||
190 (keyType == CKK_DES3))
192 P11DESSecretKeyObj* key = new P11DESSecretKeyObj();
194 key->setKeyType(keyType);
196 else if (keyType == CKK_GOST28147)
198 *p11object = new P11GOSTSecretKeyObj();
201 return CKR_ATTRIBUTE_VALUE_INVALID;
203 case CKO_DOMAIN_PARAMETERS:
204 if (keyType == CKK_DSA)
205 *p11object = new P11DSADomainObj();
206 else if (keyType == CKK_DH)
207 *p11object = new P11DHDomainObj();
209 return CKR_ATTRIBUTE_VALUE_INVALID;
212 return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
217 static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate,
219 CK_OBJECT_CLASS &objClass,
220 CK_KEY_TYPE &keyType,
221 CK_CERTIFICATE_TYPE &certType,
226 bool bHasClass = false;
227 bool bHasKeyType = false;
228 bool bHasCertType = false;
229 bool bHasPrivate = false;
231 // Extract object information
232 for (CK_ULONG i = 0; i < ulCount; ++i)
234 switch (pTemplate[i].type)
237 if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
239 objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
244 if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
246 keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
250 case CKA_CERTIFICATE_TYPE:
251 if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
253 certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
258 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
260 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
264 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
266 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
282 return CKR_TEMPLATE_INCOMPLETE;
285 bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
286 if (bKeyTypeRequired && !bHasKeyType)
288 return CKR_TEMPLATE_INCOMPLETE;
291 if (objClass == CKO_CERTIFICATE)
295 return CKR_TEMPLATE_INCOMPLETE;
299 // Change default value for certificates
300 isPrivate = CK_FALSE;
304 if (objClass == CKO_PUBLIC_KEY && !bHasPrivate)
306 // Change default value for public keys
307 isPrivate = CK_FALSE;
313 static CK_RV newP11Object(OSObject *object, P11Object **p11object)
315 CK_OBJECT_CLASS objClass = object->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
316 CK_KEY_TYPE keyType = CKK_RSA;
317 CK_CERTIFICATE_TYPE certType = CKC_X_509;
318 if (object->attributeExists(CKA_KEY_TYPE))
319 keyType = object->getUnsignedLongValue(CKA_KEY_TYPE, CKK_RSA);
320 if (object->attributeExists(CKA_CERTIFICATE_TYPE))
321 certType = object->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_X_509);
322 CK_RV rv = newP11Object(objClass,keyType,certType,p11object);
325 if (!(*p11object)->init(object))
326 return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
331 static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
333 CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
338 /*****************************************************************************
339 Implementation of SoftHSM class specific functions
340 *****************************************************************************/
342 // Return the one-and-only instance
343 SoftHSM* SoftHSM::i()
347 instance.reset(new SoftHSM());
350 return instance.get();
353 void SoftHSM::reset()
362 isInitialised = false;
364 sessionObjectStore = NULL;
367 sessionManager = NULL;
368 handleManager = NULL;
369 isHWavailable = false;
375 if (handleManager != NULL) delete handleManager;
376 if (sessionManager != NULL) delete sessionManager;
377 if (slotManager != NULL) delete slotManager;
378 if (objectStore != NULL) delete objectStore;
379 if (sessionObjectStore != NULL) delete sessionObjectStore;
382 /*****************************************************************************
383 Implementation of PKCS #11 functions
384 *****************************************************************************/
386 // PKCS #11 initialisation function
387 CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
389 CK_C_INITIALIZE_ARGS_PTR args;
391 // Check if PKCS#11 is already initialized
394 ERROR_MSG("SoftHSM is already initialized");
395 return CKR_CRYPTOKI_ALREADY_INITIALIZED;
398 // Do we have any arguments?
399 if (pInitArgs != NULL_PTR)
401 args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
403 // Must be set to NULL_PTR in this version of PKCS#11
404 if (args->pReserved != NULL_PTR)
406 ERROR_MSG("pReserved must be set to NULL_PTR");
407 return CKR_ARGUMENTS_BAD;
410 // Can we spawn our own threads?
411 // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
413 // DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
414 // return CKR_NEED_TO_CREATE_THREADS;
417 // Are we not supplied with mutex functions?
420 args->CreateMutex == NULL_PTR &&
421 args->DestroyMutex == NULL_PTR &&
422 args->LockMutex == NULL_PTR &&
423 args->UnlockMutex == NULL_PTR
426 // Can we use our own mutex functions?
427 if (args->flags & CKF_OS_LOCKING_OK)
429 // Use our own mutex functions.
430 MutexFactory::i()->setCreateMutex(OSCreateMutex);
431 MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
432 MutexFactory::i()->setLockMutex(OSLockMutex);
433 MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
434 MutexFactory::i()->enable();
438 // The external application is not using threading
439 MutexFactory::i()->disable();
444 // We must have all mutex functions
447 args->CreateMutex == NULL_PTR ||
448 args->DestroyMutex == NULL_PTR ||
449 args->LockMutex == NULL_PTR ||
450 args->UnlockMutex == NULL_PTR
453 ERROR_MSG("Not all mutex functions are supplied");
454 return CKR_ARGUMENTS_BAD;
457 // We could use our own mutex functions if the flag is set,
458 // but we use the external functions in both cases.
460 // Load the external mutex functions
461 MutexFactory::i()->setCreateMutex(args->CreateMutex);
462 MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
463 MutexFactory::i()->setLockMutex(args->LockMutex);
464 MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
465 MutexFactory::i()->enable();
470 // No concurrent access by multiple threads
471 MutexFactory::i()->disable();
474 // Initiate SecureMemoryRegistry
475 if (SecureMemoryRegistry::i() == NULL)
477 ERROR_MSG("Could not load the SecureMemoryRegistry");
478 return CKR_GENERAL_ERROR;
481 // Build the CryptoFactory
482 if (CryptoFactory::i() == NULL)
484 ERROR_MSG("Could not load the CryptoFactory");
485 return CKR_GENERAL_ERROR;
489 // Check the FIPS status
490 if (!CryptoFactory::i()->getFipsSelfTestStatus())
492 ERROR_MSG("The FIPS self test failed");
493 return CKR_FIPS_SELF_TEST_FAILED;
497 // (Re)load the configuration
498 if (!Configuration::i()->reload(SimpleConfigLoader::i()))
500 ERROR_MSG("Could not load the configuration");
501 return CKR_GENERAL_ERROR;
504 // Configure the log level
505 if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
507 ERROR_MSG("Could not set the log level");
508 return CKR_GENERAL_ERROR;
511 // Configure object store storage backend used by all tokens.
512 if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
514 ERROR_MSG("Could not set the storage backend");
515 return CKR_GENERAL_ERROR;
518 sessionObjectStore = new SessionObjectStore();
520 // Load the object store
521 objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
522 if (!objectStore->isValid())
524 WARNING_MSG("Could not load the object store");
527 delete sessionObjectStore;
528 sessionObjectStore = NULL;
529 return CKR_GENERAL_ERROR;
532 isRemovable = Configuration::i()->getBool("slots.removable", false);
534 // Load the slot manager
535 slotManager = new SlotManager(objectStore);
537 // Load the session manager
538 sessionManager = new SessionManager();
540 // Load the handle manager
541 handleManager = new HandleManager();
543 // Set the state to initialised
544 isInitialised = true;
546 if(prepareHWPlugin())
548 printf("HW plugin NOT available to use ! \n");
549 isHWavailable = false;
553 printf("HW plugin available and initialized ! \n");
554 isHWavailable = true;
560 // PKCS #11 finalisation function
561 CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
563 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
565 // Must be set to NULL_PTR in this version of PKCS#11
566 if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
568 if (handleManager != NULL) delete handleManager;
569 handleManager = NULL;
570 if (sessionManager != NULL) delete sessionManager;
571 sessionManager = NULL;
572 if (slotManager != NULL) delete slotManager;
574 if (objectStore != NULL) delete objectStore;
576 if (sessionObjectStore != NULL) delete sessionObjectStore;
577 sessionObjectStore = NULL;
578 CryptoFactory::reset();
579 SecureMemoryRegistry::reset();
581 isInitialised = false;
587 // Return information about the PKCS #11 module
588 CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
590 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
591 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
593 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
594 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
595 memset(pInfo->manufacturerID, ' ', 32);
596 memcpy(pInfo->manufacturerID, "SoftHSM", 7);
598 memset(pInfo->libraryDescription, ' ', 32);
600 memcpy(pInfo->libraryDescription, "Implementation of PKCS11+FIPS", 29);
602 memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
604 pInfo->libraryVersion.major = VERSION_MAJOR;
605 pInfo->libraryVersion.minor = VERSION_MINOR;
610 // Return a list of available slots
611 CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
613 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
615 return slotManager->getSlotList(objectStore, tokenPresent, pSlotList, pulCount);
618 // Return information about a slot
619 CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
622 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
624 Slot* slot = slotManager->getSlot(slotID);
627 return CKR_SLOT_ID_INVALID;
630 rv = slot->getSlotInfo(pInfo);
636 pInfo->flags |= CKF_REMOVABLE_DEVICE;
642 // Return information about a token in a slot
643 CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
645 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
647 Slot* slot = slotManager->getSlot(slotID);
650 return CKR_SLOT_ID_INVALID;
653 Token* token = slot->getToken();
656 return CKR_TOKEN_NOT_PRESENT;
659 return token->getTokenInfo(pInfo);
662 // Return the list of supported mechanisms for a given slot
663 CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
665 // A list with the supported mechanisms
666 CK_ULONG nrSupportedMechanisms = 61;
668 nrSupportedMechanisms += 3;
671 nrSupportedMechanisms -= 9;
674 nrSupportedMechanisms += 5;
676 #ifdef HAVE_AES_KEY_WRAP_PAD
677 nrSupportedMechanisms += 1;
680 nrSupportedMechanisms += 1; // CKM_RSA_PKCS_PSS
683 nrSupportedMechanisms += 1;
686 CK_MECHANISM_TYPE supportedMechanisms[] =
704 CKM_RSA_PKCS_KEY_PAIR_GEN,
719 CKM_SHA1_RSA_PKCS_PSS,
720 CKM_SHA224_RSA_PKCS_PSS,
721 CKM_SHA256_RSA_PKCS_PSS,
722 CKM_SHA384_RSA_PKCS_PSS,
723 CKM_SHA512_RSA_PKCS_PSS,
733 CKM_DES_ECB_ENCRYPT_DATA,
734 CKM_DES_CBC_ENCRYPT_DATA,
739 CKM_DES3_ECB_ENCRYPT_DATA,
740 CKM_DES3_CBC_ENCRYPT_DATA,
751 #ifdef HAVE_AES_KEY_WRAP_PAD
752 CKM_AES_KEY_WRAP_PAD,
754 CKM_AES_ECB_ENCRYPT_DATA,
755 CKM_AES_CBC_ENCRYPT_DATA,
757 CKM_DSA_PARAMETER_GEN,
758 CKM_DSA_KEY_PAIR_GEN,
765 CKM_DH_PKCS_KEY_PAIR_GEN,
766 CKM_DH_PKCS_PARAMETER_GEN,
776 CKM_GOSTR3410_KEY_PAIR_GEN,
778 CKM_GOSTR3410_WITH_GOSTR3411
782 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
783 if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
785 Slot* slot = slotManager->getSlot(slotID);
788 return CKR_SLOT_ID_INVALID;
791 if (pMechanismList == NULL_PTR)
793 *pulCount = nrSupportedMechanisms;
798 if (*pulCount < nrSupportedMechanisms)
800 *pulCount = nrSupportedMechanisms;
802 return CKR_BUFFER_TOO_SMALL;
805 *pulCount = nrSupportedMechanisms;
807 for (CK_ULONG i = 0; i < nrSupportedMechanisms; i ++)
809 pMechanismList[i] = supportedMechanisms[i];
815 // Return more information about a mechanism for a given slot
816 CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
818 unsigned long rsaMinSize, rsaMaxSize;
819 unsigned long dsaMinSize, dsaMaxSize;
820 unsigned long dhMinSize, dhMaxSize;
822 unsigned long ecdsaMinSize, ecdsaMaxSize;
823 unsigned long ecdhMinSize, ecdhMaxSize;
826 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
827 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
829 Slot* slot = slotManager->getSlot(slotID);
832 return CKR_SLOT_ID_INVALID;
835 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
838 rsaMinSize = rsa->getMinKeySize();
839 rsaMaxSize = rsa->getMaxKeySize();
843 return CKR_GENERAL_ERROR;
845 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
847 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
850 dsaMinSize = dsa->getMinKeySize();
851 // Limitation in PKCS#11
852 if (dsaMinSize < 512)
857 dsaMaxSize = dsa->getMaxKeySize();
858 // Limitation in PKCS#11
859 if (dsaMaxSize > 1024)
866 return CKR_GENERAL_ERROR;
868 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
870 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
873 dhMinSize = dh->getMinKeySize();
874 dhMaxSize = dh->getMaxKeySize();
878 return CKR_GENERAL_ERROR;
880 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
883 AsymmetricAlgorithm* ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
886 ecdsaMinSize = ecdsa->getMinKeySize();
887 ecdsaMaxSize = ecdsa->getMaxKeySize();
891 return CKR_GENERAL_ERROR;
893 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
895 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
898 ecdhMinSize = ecdh->getMinKeySize();
899 ecdhMaxSize = ecdh->getMaxKeySize();
903 return CKR_GENERAL_ERROR;
905 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
918 // Key size is not in use
919 pInfo->ulMinKeySize = 0;
920 pInfo->ulMaxKeySize = 0;
921 pInfo->flags = CKF_DIGEST;
925 pInfo->ulMinKeySize = 16;
926 pInfo->ulMaxKeySize = 512;
927 pInfo->flags = CKF_SIGN | CKF_VERIFY;
931 pInfo->ulMinKeySize = 20;
932 pInfo->ulMaxKeySize = 512;
933 pInfo->flags = CKF_SIGN | CKF_VERIFY;
935 case CKM_SHA224_HMAC:
936 pInfo->ulMinKeySize = 28;
937 pInfo->ulMaxKeySize = 512;
938 pInfo->flags = CKF_SIGN | CKF_VERIFY;
940 case CKM_SHA256_HMAC:
941 pInfo->ulMinKeySize = 32;
942 pInfo->ulMaxKeySize = 512;
943 pInfo->flags = CKF_SIGN | CKF_VERIFY;
945 case CKM_SHA384_HMAC:
946 pInfo->ulMinKeySize = 48;
947 pInfo->ulMaxKeySize = 512;
948 pInfo->flags = CKF_SIGN | CKF_VERIFY;
950 case CKM_SHA512_HMAC:
951 pInfo->ulMinKeySize = 64;
952 pInfo->ulMaxKeySize = 512;
953 pInfo->flags = CKF_SIGN | CKF_VERIFY;
955 case CKM_RSA_PKCS_KEY_PAIR_GEN:
956 pInfo->ulMinKeySize = rsaMinSize;
957 pInfo->ulMaxKeySize = rsaMaxSize;
958 pInfo->flags = CKF_GENERATE_KEY_PAIR;
961 pInfo->ulMinKeySize = rsaMinSize;
962 pInfo->ulMaxKeySize = rsaMaxSize;
963 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
966 pInfo->ulMinKeySize = rsaMinSize;
967 pInfo->ulMaxKeySize = rsaMaxSize;
968 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
971 case CKM_MD5_RSA_PKCS:
973 case CKM_SHA1_RSA_PKCS:
974 case CKM_SHA224_RSA_PKCS:
975 case CKM_SHA256_RSA_PKCS:
976 case CKM_SHA384_RSA_PKCS:
977 case CKM_SHA512_RSA_PKCS:
979 case CKM_RSA_PKCS_PSS:
981 case CKM_SHA1_RSA_PKCS_PSS:
982 case CKM_SHA224_RSA_PKCS_PSS:
983 case CKM_SHA256_RSA_PKCS_PSS:
984 case CKM_SHA384_RSA_PKCS_PSS:
985 case CKM_SHA512_RSA_PKCS_PSS:
986 pInfo->ulMinKeySize = rsaMinSize;
987 pInfo->ulMaxKeySize = rsaMaxSize;
988 pInfo->flags = CKF_SIGN | CKF_VERIFY;
990 case CKM_RSA_PKCS_OAEP:
991 pInfo->ulMinKeySize = rsaMinSize;
992 pInfo->ulMaxKeySize = rsaMaxSize;
993 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
996 case CKM_DES_KEY_GEN:
998 case CKM_DES2_KEY_GEN:
999 case CKM_DES3_KEY_GEN:
1000 // Key size is not in use
1001 pInfo->ulMinKeySize = 0;
1002 pInfo->ulMaxKeySize = 0;
1003 pInfo->flags = CKF_GENERATE;
1008 case CKM_DES_CBC_PAD:
1012 case CKM_DES3_CBC_PAD:
1013 // Key size is not in use
1014 pInfo->ulMinKeySize = 0;
1015 pInfo->ulMaxKeySize = 0;
1016 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1019 // Key size is not in use
1020 pInfo->ulMinKeySize = 0;
1021 pInfo->ulMaxKeySize = 0;
1022 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1024 case CKM_AES_KEY_GEN:
1025 pInfo->ulMinKeySize = 16;
1026 pInfo->ulMaxKeySize = 32;
1027 pInfo->flags = CKF_GENERATE;
1031 case CKM_AES_CBC_PAD:
1036 pInfo->ulMinKeySize = 16;
1037 pInfo->ulMaxKeySize = 32;
1038 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1040 case CKM_AES_KEY_WRAP:
1041 pInfo->ulMinKeySize = 16;
1042 pInfo->ulMaxKeySize = 0x80000000;
1043 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1045 #ifdef HAVE_AES_KEY_WRAP_PAD
1046 case CKM_AES_KEY_WRAP_PAD:
1047 pInfo->ulMinKeySize = 1;
1048 pInfo->ulMaxKeySize = 0x80000000;
1049 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1053 case CKM_DES_ECB_ENCRYPT_DATA:
1054 case CKM_DES_CBC_ENCRYPT_DATA:
1056 case CKM_DES3_ECB_ENCRYPT_DATA:
1057 case CKM_DES3_CBC_ENCRYPT_DATA:
1058 case CKM_AES_ECB_ENCRYPT_DATA:
1059 case CKM_AES_CBC_ENCRYPT_DATA:
1060 // Key size is not in use
1061 pInfo->ulMinKeySize = 0;
1062 pInfo->ulMaxKeySize = 0;
1063 pInfo->flags = CKF_DERIVE;
1066 pInfo->ulMinKeySize = 16;
1067 pInfo->ulMaxKeySize = 32;
1068 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1070 case CKM_DSA_PARAMETER_GEN:
1071 pInfo->ulMinKeySize = dsaMinSize;
1072 pInfo->ulMaxKeySize = dsaMaxSize;
1073 pInfo->flags = CKF_GENERATE;
1075 case CKM_DSA_KEY_PAIR_GEN:
1076 pInfo->ulMinKeySize = dsaMinSize;
1077 pInfo->ulMaxKeySize = dsaMaxSize;
1078 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1082 case CKM_DSA_SHA224:
1083 case CKM_DSA_SHA256:
1084 case CKM_DSA_SHA384:
1085 case CKM_DSA_SHA512:
1086 pInfo->ulMinKeySize = dsaMinSize;
1087 pInfo->ulMaxKeySize = dsaMaxSize;
1088 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1090 case CKM_DH_PKCS_KEY_PAIR_GEN:
1091 pInfo->ulMinKeySize = dhMinSize;
1092 pInfo->ulMaxKeySize = dhMaxSize;
1093 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1095 case CKM_DH_PKCS_PARAMETER_GEN:
1096 pInfo->ulMinKeySize = dhMinSize;
1097 pInfo->ulMaxKeySize = dhMaxSize;
1098 pInfo->flags = CKF_GENERATE;
1100 case CKM_DH_PKCS_DERIVE:
1101 pInfo->ulMinKeySize = dhMinSize;
1102 pInfo->ulMaxKeySize = dhMaxSize;
1103 pInfo->flags = CKF_DERIVE;
1106 case CKM_EC_KEY_PAIR_GEN:
1107 pInfo->ulMinKeySize = ecdsaMinSize;
1108 pInfo->ulMaxKeySize = ecdsaMaxSize;
1109 #define CKF_EC_COMMOM (CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS)
1110 pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
1113 pInfo->ulMinKeySize = ecdsaMinSize;
1114 pInfo->ulMaxKeySize = ecdsaMaxSize;
1115 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
1117 case CKM_ECDH1_DERIVE:
1118 pInfo->ulMinKeySize = ecdhMinSize;
1119 pInfo->ulMaxKeySize = ecdhMaxSize;
1120 pInfo->flags = CKF_DERIVE;
1125 // Key size is not in use
1126 pInfo->ulMinKeySize = 0;
1127 pInfo->ulMaxKeySize = 0;
1128 pInfo->flags = CKF_DIGEST;
1130 case CKM_GOSTR3411_HMAC:
1131 // Key size is not in use
1132 pInfo->ulMinKeySize = 32;
1133 pInfo->ulMaxKeySize = 512;
1134 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1136 case CKM_GOSTR3410_KEY_PAIR_GEN:
1137 // Key size is not in use
1138 pInfo->ulMinKeySize = 0;
1139 pInfo->ulMaxKeySize = 0;
1140 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1143 // Key size is not in use
1144 pInfo->ulMinKeySize = 0;
1145 pInfo->ulMaxKeySize = 0;
1146 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1148 case CKM_GOSTR3410_WITH_GOSTR3411:
1149 // Key size is not in use
1150 pInfo->ulMinKeySize = 0;
1151 pInfo->ulMaxKeySize = 0;
1152 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1156 DEBUG_MSG("The selected mechanism is not supported");
1157 return CKR_MECHANISM_INVALID;
1164 // Initialise the token in the specified slot
1165 CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
1167 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1169 Slot* slot = slotManager->getSlot(slotID);
1172 return CKR_SLOT_ID_INVALID;
1175 // Check if any session is open with this token.
1176 if (sessionManager->haveSession(slotID))
1178 return CKR_SESSION_EXISTS;
1182 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1183 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
1185 ByteString soPIN(pPin, ulPinLen);
1187 return slot->initToken(soPIN, pLabel);
1190 // Initialise the user PIN
1191 CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1193 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1196 Session* session = (Session*)handleManager->getSession(hSession);
1197 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1199 // The SO must be logged in
1200 if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
1203 Token* token = session->getToken();
1204 if (token == NULL) return CKR_GENERAL_ERROR;
1207 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1208 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1210 ByteString userPIN(pPin, ulPinLen);
1212 return token->initUserPIN(userPIN);
1216 CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
1220 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1223 Session* session = (Session*)handleManager->getSession(hSession);
1224 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1226 // Check the new PINs
1227 if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1228 if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1229 if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1231 ByteString oldPIN(pOldPin, ulOldLen);
1232 ByteString newPIN(pNewPin, ulNewLen);
1235 Token* token = session->getToken();
1236 if (token == NULL) return CKR_GENERAL_ERROR;
1238 switch (session->getState())
1240 case CKS_RW_PUBLIC_SESSION:
1241 case CKS_RW_USER_FUNCTIONS:
1242 rv = token->setUserPIN(oldPIN, newPIN);
1244 case CKS_RW_SO_FUNCTIONS:
1245 rv = token->setSOPIN(oldPIN, newPIN);
1248 return CKR_SESSION_READ_ONLY;
1254 // Open a new session to the specified slot
1255 CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
1257 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1259 Slot* slot = slotManager->getSlot(slotID);
1261 CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
1265 // Get a pointer to the session object and store it in the handle manager.
1266 Session* session = sessionManager->getSession(*phSession);
1267 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1268 *phSession = handleManager->addSession(slotID,session);
1273 // Close the given session
1274 CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
1276 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1279 Session* session = (Session*)handleManager->getSession(hSession);
1280 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1282 // Tell the handle manager the session has been closed.
1283 handleManager->sessionClosed(hSession);
1286 // Tell the session object store that the session has closed.
1287 sessionObjectStore->sessionClosed(hSession);
1289 // Tell the session manager the session has been closed.
1290 return sessionManager->closeSession(session->getHandle());
1293 // Close all open sessions
1294 CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
1296 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1299 Slot* slot = slotManager->getSlot(slotID);
1300 if (slot == NULL) return CKR_SLOT_ID_INVALID;
1303 Token* token = slot->getToken();
1304 if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
1306 // Tell the handle manager all sessions were closed for the given slotID.
1307 // The handle manager should then remove all session and object handles for this slot.
1308 handleManager->allSessionsClosed(slotID);
1310 // Tell the session object store that all sessions were closed for the given slotID.
1311 // The session object store should then remove all session objects for this slot.
1312 sessionObjectStore->allSessionsClosed(slotID);
1314 // Finally tell the session manager tho close all sessions for the given slot.
1315 // This will also trigger a logout on the associated token to occur.
1316 return sessionManager->closeAllSessions(slot);
1319 // Retrieve information about the specified session
1320 CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
1322 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1325 Session* session = (Session*)handleManager->getSession(hSession);
1326 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1328 return session->getInfo(pInfo);
1331 // Determine the state of a running operation in a session
1332 CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG_PTR /*pulOperationStateLen*/)
1334 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1337 Session* session = (Session*)handleManager->getSession(hSession);
1338 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1340 return CKR_FUNCTION_NOT_SUPPORTED;
1343 // Set the operation sate in a session
1344 CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG /*ulOperationStateLen*/, CK_OBJECT_HANDLE /*hEncryptionKey*/, CK_OBJECT_HANDLE /*hAuthenticationKey*/)
1346 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1349 Session* session = (Session*)handleManager->getSession(hSession);
1350 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1352 return CKR_FUNCTION_NOT_SUPPORTED;
1355 // Login on the token in the specified session
1356 CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1360 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1363 Session* session = (Session*)handleManager->getSession(hSession);
1364 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1367 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1368 ByteString pin(pPin, ulPinLen);
1371 Token* token = session->getToken();
1372 if (token == NULL) return CKR_GENERAL_ERROR;
1377 // There cannot exist a R/O session on this slot
1378 if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
1381 rv = token->loginSO(pin);
1385 rv = token->loginUser(pin);
1387 case CKU_CONTEXT_SPECIFIC:
1388 // Check if re-authentication is required
1389 if (!session->getReAuthentication()) return CKR_OPERATION_NOT_INITIALIZED;
1392 rv = token->reAuthenticate(pin);
1393 if (rv == CKR_OK) session->setReAuthentication(false);
1396 return CKR_USER_TYPE_INVALID;
1402 // Log out of the token in the specified session
1403 CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
1405 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1408 Session* session = (Session*)handleManager->getSession(hSession);
1409 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1412 Token* token = session->getToken();
1413 if (token == NULL) return CKR_GENERAL_ERROR;
1418 // [PKCS#11 v2.40, C_Logout] When logout is successful...
1419 // a. Any of the application's handles to private objects become invalid.
1420 // b. Even if a user is later logged back into the token those handles remain invalid.
1421 // c. All private session objects from sessions belonging to the application are destroyed.
1423 // Have the handle manager remove all handles pointing to private objects for this slot.
1424 CK_SLOT_ID slotID = session->getSlot()->getSlotID();
1425 handleManager->tokenLoggedOut(slotID);
1426 sessionObjectStore->tokenLoggedOut(slotID);
1431 // Create a new object on the token in the specified session using the given attribute template
1432 CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
1434 return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
1437 // Create a copy of the object with the specified handle
1438 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)
1440 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1442 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
1443 if (phNewObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1444 *phNewObject = CK_INVALID_HANDLE;
1447 Session* session = (Session*)handleManager->getSession(hSession);
1448 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1451 Slot* slot = session->getSlot();
1452 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1455 Token* token = session->getToken();
1456 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1458 // Check the object handle.
1459 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1460 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1462 CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
1463 CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1465 // Check read user credentials
1466 CK_RV rv = haveRead(session->getState(), wasOnToken, wasPrivate);
1469 if (rv == CKR_USER_NOT_LOGGED_IN)
1470 INFO_MSG("User is not authorized");
1475 // Check if the object is copyable
1476 CK_BBOOL isCopyable = object->getBooleanValue(CKA_COPYABLE, true);
1477 if (!isCopyable) return CKR_ACTION_PROHIBITED;
1479 // Extract critical information from the template
1480 CK_BBOOL isOnToken = wasOnToken;
1481 CK_BBOOL isPrivate = wasPrivate;
1483 for (CK_ULONG i = 0; i < ulCount; i++)
1485 if ((pTemplate[i].type == CKA_TOKEN) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1487 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
1490 if ((pTemplate[i].type == CKA_PRIVATE) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1492 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
1497 // Check privacy does not downgrade
1498 if (wasPrivate && !isPrivate) return CKR_TEMPLATE_INCONSISTENT;
1500 // Check write user credentials
1501 rv = haveWrite(session->getState(), isOnToken, isPrivate);
1504 if (rv == CKR_USER_NOT_LOGGED_IN)
1505 INFO_MSG("User is not authorized");
1506 if (rv == CKR_SESSION_READ_ONLY)
1507 INFO_MSG("Session is read-only");
1512 // Create the object in session or on the token
1513 OSObject *newobject = NULL_PTR;
1516 newobject = (OSObject*) token->createObject();
1520 newobject = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
1522 if (newobject == NULL) return CKR_GENERAL_ERROR;
1524 // Copy attributes from object class (CKA_CLASS=0 so the first)
1525 if (!newobject->startTransaction())
1527 newobject->destroyObject();
1528 return CKR_FUNCTION_FAILED;
1531 CK_ATTRIBUTE_TYPE attrType = CKA_CLASS;
1534 if (!object->attributeExists(attrType))
1536 rv = CKR_FUNCTION_FAILED;
1540 OSAttribute attr = object->getAttribute(attrType);
1542 // Upgrade privacy has to encrypt byte strings
1543 if (!wasPrivate && isPrivate &&
1544 attr.isByteStringAttribute() &&
1545 attr.getByteStringValue().size() != 0)
1548 if (!token->encrypt(attr.getByteStringValue(), value) ||
1549 !newobject->setAttribute(attrType, value))
1551 rv = CKR_FUNCTION_FAILED;
1557 if (!newobject->setAttribute(attrType, attr))
1559 rv = CKR_FUNCTION_FAILED;
1563 attrType = object->nextAttributeType(attrType);
1565 while (attrType != CKA_CLASS);
1569 newobject->abortTransaction();
1571 else if (!newobject->commitTransaction())
1573 rv = CKR_FUNCTION_FAILED;
1578 newobject->destroyObject();
1582 // Get the new P11 object
1583 P11Object* newp11object = NULL;
1584 rv = newP11Object(newobject,&newp11object);
1587 newobject->destroyObject();
1591 // Apply the template
1592 rv = newp11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate, ulCount, OBJECT_OP_COPY);
1593 delete newp11object;
1597 newobject->destroyObject();
1604 *phNewObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, newobject);
1608 *phNewObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, newobject);
1614 // Destroy the specified object
1615 CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
1617 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1620 Session* session = (Session*)handleManager->getSession(hSession);
1621 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1624 Token* token = session->getToken();
1625 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1627 // Check the object handle.
1628 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1629 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1631 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1632 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1634 // Check user credentials
1635 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1638 if (rv == CKR_USER_NOT_LOGGED_IN)
1639 INFO_MSG("User is not authorized");
1640 if (rv == CKR_SESSION_READ_ONLY)
1641 INFO_MSG("Session is read-only");
1646 // Check if the object is destroyable
1647 CK_BBOOL isDestroyable = object->getBooleanValue(CKA_DESTROYABLE, true);
1648 if (!isDestroyable) return CKR_ACTION_PROHIBITED;
1650 // Tell the handleManager to forget about the object.
1651 handleManager->destroyObject(hObject);
1653 // Destroy the object
1654 if (!object->destroyObject())
1655 return CKR_FUNCTION_FAILED;
1660 // Determine the size of the specified object
1661 CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
1663 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1665 if (pulSize == NULL) return CKR_ARGUMENTS_BAD;
1668 Session* session = (Session*)handleManager->getSession(hSession);
1669 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1672 Token* token = session->getToken();
1673 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1675 // Check the object handle.
1676 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1677 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1679 *pulSize = CK_UNAVAILABLE_INFORMATION;
1684 // Retrieve the specified attributes for the given object
1685 CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1687 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1689 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1692 Session* session = (Session*)handleManager->getSession(hSession);
1693 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1696 Token* token = session->getToken();
1697 if (token == NULL) return CKR_GENERAL_ERROR;
1699 // Check the object handle.
1700 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1701 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1703 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1704 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1706 // Check read user credentials
1707 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
1710 if (rv == CKR_USER_NOT_LOGGED_IN)
1711 INFO_MSG("User is not authorized");
1713 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
1714 // so we use CKR_GENERAL_ERROR.
1715 return CKR_GENERAL_ERROR;
1718 // Wrap a P11Object around the OSObject so we can access the attributes in the
1719 // context of the object in which it is defined.
1720 P11Object* p11object = NULL;
1721 rv = newP11Object(object,&p11object);
1725 // Ask the P11Object to fill the template with attribute values.
1726 rv = p11object->loadTemplate(token, pTemplate,ulCount);
1731 // Change or set the value of the specified attributes on the specified object
1732 CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1734 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1736 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1739 Session* session = (Session*)handleManager->getSession(hSession);
1740 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1743 Token* token = session->getToken();
1744 if (token == NULL) return CKR_GENERAL_ERROR;
1746 // Check the object handle.
1747 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1748 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1750 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1751 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1753 // Check user credentials
1754 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1757 if (rv == CKR_USER_NOT_LOGGED_IN)
1758 INFO_MSG("User is not authorized");
1759 if (rv == CKR_SESSION_READ_ONLY)
1760 INFO_MSG("Session is read-only");
1765 // Check if the object is modifiable
1766 CK_BBOOL isModifiable = object->getBooleanValue(CKA_MODIFIABLE, true);
1767 if (!isModifiable) return CKR_ACTION_PROHIBITED;
1769 // Wrap a P11Object around the OSObject so we can access the attributes in the
1770 // context of the object in which it is defined.
1771 P11Object* p11object = NULL;
1772 rv = newP11Object(object,&p11object);
1776 // Ask the P11Object to save the template with attribute values.
1777 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate,ulCount,OBJECT_OP_SET);
1782 // Initialise object search in the specified session using the specified attribute template as search parameters
1783 CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1785 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1788 Session* session = (Session*)handleManager->getSession(hSession);
1789 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1792 Slot* slot = session->getSlot();
1793 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1795 // Determine whether we have a public session or not.
1796 bool isPublicSession;
1797 switch (session->getState()) {
1798 case CKS_RO_USER_FUNCTIONS:
1799 case CKS_RW_USER_FUNCTIONS:
1800 isPublicSession = false;
1803 isPublicSession = true;
1807 Token* token = session->getToken();
1808 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1810 // Check if we have another operation
1811 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
1813 session->setOpType(SESSION_OP_FIND);
1814 FindOperation *findOp = FindOperation::create();
1816 // Check if we are out of memory
1817 if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
1819 std::set<OSObject*> allObjects;
1820 token->getObjects(allObjects);
1821 sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
1823 std::set<CK_OBJECT_HANDLE> handles;
1824 std::set<OSObject*>::iterator it;
1825 for (it=allObjects.begin(); it != allObjects.end(); ++it)
1827 // Refresh object and check if it is valid
1828 if (!(*it)->isValid()) {
1829 DEBUG_MSG("Object is not valid, skipping");
1833 // Determine if the object has CKA_PRIVATE set to CK_TRUE
1834 bool isPrivateObject = (*it)->getBooleanValue(CKA_PRIVATE, true);
1836 // If the object is private, and we are in a public session then skip it !
1837 if (isPublicSession && isPrivateObject)
1838 continue; // skip object
1840 // Perform the actual attribute matching.
1841 bool bAttrMatch = true; // We let an empty template match everything.
1842 for (CK_ULONG i=0; i<ulCount; ++i)
1846 if (!(*it)->attributeExists(pTemplate[i].type))
1849 OSAttribute attr = (*it)->getAttribute(pTemplate[i].type);
1851 if (attr.isBooleanAttribute())
1853 if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
1855 bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
1856 if (attr.getBooleanValue() != bTemplateValue)
1861 if (attr.isUnsignedLongAttribute())
1863 if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
1865 CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
1866 if (attr.getUnsignedLongValue() != ulTemplateValue)
1871 if (attr.isByteStringAttribute())
1873 ByteString bsAttrValue;
1874 if (isPrivateObject && attr.getByteStringValue().size() != 0)
1876 if (!token->decrypt(attr.getByteStringValue(), bsAttrValue))
1879 return CKR_GENERAL_ERROR;
1883 bsAttrValue = attr.getByteStringValue();
1885 if (bsAttrValue.size() != pTemplate[i].ulValueLen)
1887 if (pTemplate[i].ulValueLen != 0)
1889 ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
1890 if (bsAttrValue != bsTemplateValue)
1898 // The attribute matched !
1904 CK_SLOT_ID slotID = slot->getSlotID();
1905 bool isOnToken = (*it)->getBooleanValue(CKA_TOKEN, false);
1906 bool isPrivate = (*it)->getBooleanValue(CKA_PRIVATE, true);
1907 // Create an object handle for every returned object.
1908 CK_OBJECT_HANDLE hObject;
1910 hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
1912 hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
1913 if (hObject == CK_INVALID_HANDLE)
1916 return CKR_GENERAL_ERROR;
1918 handles.insert(hObject);
1922 // Storing the object handles for the find will protect the library
1923 // whenever a stale object handle is used to access the library.
1924 findOp->setHandles(handles);
1926 session->setFindOp(findOp);
1931 // Continue the search for objects in the specified session
1932 CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
1934 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1935 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1936 if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
1939 Session* session = (Session*)handleManager->getSession(hSession);
1940 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1942 // Check if we are doing the correct operation
1943 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1945 // return the object handles that have been added to the find operation.
1946 FindOperation *findOp = session->getFindOp();
1947 if (findOp == NULL) return CKR_GENERAL_ERROR;
1949 // Ask the find operation to retrieve the object handles
1950 *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
1952 // Erase the object handles from the find operation.
1953 findOp->eraseHandles(0,*pulObjectCount);
1958 // Finish searching for objects
1959 CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1961 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1964 Session* session = (Session*)handleManager->getSession(hSession);
1965 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1967 // Check if we are doing the correct operation
1968 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1974 // Encrypt*/Decrypt*() is for Symmetrical ciphers too
1975 static bool isSymMechanism(CK_MECHANISM_PTR pMechanism)
1977 if (pMechanism == NULL_PTR) return false;
1979 switch(pMechanism->mechanism) {
1982 case CKM_DES_CBC_PAD:
1985 case CKM_DES3_CBC_PAD:
1988 case CKM_AES_CBC_PAD:
1997 // SymAlgorithm version of C_EncryptInit
1998 CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2000 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2002 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2005 Session* session = (Session*)handleManager->getSession(hSession);
2006 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2008 // Check if we have another operation
2009 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2012 Token* token = session->getToken();
2013 if (token == NULL) return CKR_GENERAL_ERROR;
2015 // Check the key handle.
2016 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2017 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2019 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2020 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2022 // Check read user credentials
2023 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2026 if (rv == CKR_USER_NOT_LOGGED_IN)
2027 INFO_MSG("User is not authorized");
2032 // Check if key can be used for encryption
2033 if (!key->getBooleanValue(CKA_ENCRYPT, false))
2034 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2036 // Check if the specified mechanism is allowed for the key
2037 if (!isMechanismPermitted(key, pMechanism))
2038 return CKR_MECHANISM_INVALID;
2040 // Get the symmetric algorithm matching the mechanism
2041 SymAlgo::Type algo = SymAlgo::Unknown;
2042 SymMode::Type mode = SymMode::Unknown;
2043 bool padding = false;
2046 size_t counterBits = 0;
2048 size_t tagBytes = 0;
2049 switch(pMechanism->mechanism) {
2052 algo = SymAlgo::DES;
2053 mode = SymMode::ECB;
2057 algo = SymAlgo::DES;
2058 mode = SymMode::CBC;
2059 if (pMechanism->pParameter == NULL_PTR ||
2060 pMechanism->ulParameterLen == 0)
2062 DEBUG_MSG("CBC mode requires an init vector");
2063 return CKR_ARGUMENTS_BAD;
2065 iv.resize(pMechanism->ulParameterLen);
2066 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2069 case CKM_DES_CBC_PAD:
2070 algo = SymAlgo::DES;
2071 mode = SymMode::CBC;
2073 if (pMechanism->pParameter == NULL_PTR ||
2074 pMechanism->ulParameterLen == 0)
2076 DEBUG_MSG("CBC mode requires an init vector");
2077 return CKR_ARGUMENTS_BAD;
2079 iv.resize(pMechanism->ulParameterLen);
2080 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2085 algo = SymAlgo::DES3;
2086 mode = SymMode::ECB;
2090 algo = SymAlgo::DES3;
2091 mode = SymMode::CBC;
2092 if (pMechanism->pParameter == NULL_PTR ||
2093 pMechanism->ulParameterLen == 0)
2095 DEBUG_MSG("CBC mode requires an init vector");
2096 return CKR_ARGUMENTS_BAD;
2098 iv.resize(pMechanism->ulParameterLen);
2099 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2102 case CKM_DES3_CBC_PAD:
2103 algo = SymAlgo::DES3;
2104 mode = SymMode::CBC;
2106 if (pMechanism->pParameter == NULL_PTR ||
2107 pMechanism->ulParameterLen == 0)
2109 DEBUG_MSG("CBC mode requires an init vector");
2110 return CKR_ARGUMENTS_BAD;
2112 iv.resize(pMechanism->ulParameterLen);
2113 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2117 algo = SymAlgo::AES;
2118 mode = SymMode::ECB;
2121 algo = SymAlgo::AES;
2122 mode = SymMode::CBC;
2123 if (pMechanism->pParameter == NULL_PTR ||
2124 pMechanism->ulParameterLen == 0)
2126 DEBUG_MSG("CBC mode requires an init vector");
2127 return CKR_ARGUMENTS_BAD;
2129 iv.resize(pMechanism->ulParameterLen);
2130 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2132 case CKM_AES_CBC_PAD:
2133 algo = SymAlgo::AES;
2134 mode = SymMode::CBC;
2136 if (pMechanism->pParameter == NULL_PTR ||
2137 pMechanism->ulParameterLen == 0)
2139 DEBUG_MSG("CBC mode requires an init vector");
2140 return CKR_ARGUMENTS_BAD;
2142 iv.resize(pMechanism->ulParameterLen);
2143 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2146 algo = SymAlgo::AES;
2147 mode = SymMode::CTR;
2148 if (pMechanism->pParameter == NULL_PTR ||
2149 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2151 DEBUG_MSG("CTR mode requires a counter block");
2152 return CKR_ARGUMENTS_BAD;
2154 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2155 if (counterBits == 0 || counterBits > 128)
2157 DEBUG_MSG("Invalid ulCounterBits");
2158 return CKR_MECHANISM_PARAM_INVALID;
2161 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2165 algo = SymAlgo::AES;
2166 mode = SymMode::GCM;
2167 if (pMechanism->pParameter == NULL_PTR ||
2168 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2170 DEBUG_MSG("GCM mode requires parameters");
2171 return CKR_ARGUMENTS_BAD;
2173 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2174 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2175 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2176 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2177 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2178 if (tagBytes > 128 || tagBytes % 8 != 0)
2180 DEBUG_MSG("Invalid ulTagBits value");
2181 return CKR_ARGUMENTS_BAD;
2183 tagBytes = tagBytes / 8;
2187 return CKR_MECHANISM_INVALID;
2189 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2190 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2192 SymmetricKey* secretkey = new SymmetricKey();
2194 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2196 cipher->recycleKey(secretkey);
2197 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2198 return CKR_GENERAL_ERROR;
2201 // adjust key bit length
2202 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2204 // Initialize encryption
2205 if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2207 cipher->recycleKey(secretkey);
2208 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2209 return CKR_MECHANISM_INVALID;
2212 session->setOpType(SESSION_OP_ENCRYPT);
2213 session->setSymmetricCryptoOp(cipher);
2214 session->setAllowMultiPartOp(true);
2215 session->setAllowSinglePartOp(true);
2216 session->setSymmetricKey(secretkey);
2221 // AsymAlgorithm version of C_EncryptInit
2222 CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2224 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2226 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2229 Session* session = (Session*)handleManager->getSession(hSession);
2230 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2232 // Check if we have another operation
2233 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2236 Token* token = session->getToken();
2237 if (token == NULL) return CKR_GENERAL_ERROR;
2239 // Check the key handle.
2240 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2241 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2243 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2244 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2246 // Check read user credentials
2247 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2250 if (rv == CKR_USER_NOT_LOGGED_IN)
2251 INFO_MSG("User is not authorized");
2256 // Check if key can be used for encryption
2257 if (!key->getBooleanValue(CKA_ENCRYPT, false))
2258 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2260 // Get the asymmetric algorithm matching the mechanism
2261 AsymMech::Type mechanism;
2263 switch(pMechanism->mechanism) {
2265 mechanism = AsymMech::RSA_PKCS;
2269 mechanism = AsymMech::RSA;
2272 case CKM_RSA_PKCS_OAEP:
2273 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
2277 mechanism = AsymMech::RSA_PKCS_OAEP;
2281 return CKR_MECHANISM_INVALID;
2284 AsymmetricAlgorithm* asymCrypto = NULL;
2285 PublicKey* publicKey = NULL;
2288 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2289 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2291 publicKey = asymCrypto->newPublicKey();
2292 if (publicKey == NULL)
2294 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2295 return CKR_HOST_MEMORY;
2298 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
2300 asymCrypto->recyclePublicKey(publicKey);
2301 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2302 return CKR_GENERAL_ERROR;
2307 return CKR_MECHANISM_INVALID;
2310 session->setOpType(SESSION_OP_ENCRYPT);
2311 session->setAsymmetricCryptoOp(asymCrypto);
2312 session->setMechanism(mechanism);
2313 session->setAllowMultiPartOp(false);
2314 session->setAllowSinglePartOp(true);
2315 session->setPublicKey(publicKey);
2320 // Initialise encryption using the specified object and mechanism
2321 CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2323 if (isSymMechanism(pMechanism))
2324 return SymEncryptInit(hSession, pMechanism, hKey);
2326 return AsymEncryptInit(hSession, pMechanism, hKey);
2329 // SymAlgorithm version of C_Encrypt
2330 static CK_RV SymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2332 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2333 if (cipher == NULL || !session->getAllowSinglePartOp())
2336 return CKR_OPERATION_NOT_INITIALIZED;
2340 CK_ULONG maxSize = ulDataLen + cipher->getTagBytes();
2341 if (cipher->isBlockCipher())
2343 CK_ULONG remainder = ulDataLen % cipher->getBlockSize();
2344 if (cipher->getPaddingMode() == false && remainder != 0)
2347 return CKR_DATA_LEN_RANGE;
2350 // Round up to block size
2353 maxSize = ulDataLen + cipher->getBlockSize() - remainder;
2355 else if (cipher->getPaddingMode() == true)
2357 maxSize = ulDataLen + cipher->getBlockSize();
2360 if (!cipher->checkMaximumBytes(ulDataLen))
2363 return CKR_DATA_LEN_RANGE;
2366 if (pEncryptedData == NULL_PTR)
2368 *pulEncryptedDataLen = maxSize;
2372 // Check buffer size
2373 if (*pulEncryptedDataLen < maxSize)
2375 *pulEncryptedDataLen = maxSize;
2376 return CKR_BUFFER_TOO_SMALL;
2380 ByteString data(pData, ulDataLen);
2381 ByteString encryptedData;
2384 if (!cipher->encryptUpdate(data, encryptedData))
2387 return CKR_GENERAL_ERROR;
2390 // Finalize encryption
2391 ByteString encryptedFinal;
2392 if (!cipher->encryptFinal(encryptedFinal))
2395 return CKR_GENERAL_ERROR;
2397 encryptedData += encryptedFinal;
2398 encryptedData.resize(maxSize);
2400 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2401 *pulEncryptedDataLen = encryptedData.size();
2407 // AsymAlgorithm version of C_Encrypt
2408 static CK_RV AsymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2410 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
2411 AsymMech::Type mechanism = session->getMechanism();
2412 PublicKey* publicKey = session->getPublicKey();
2413 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
2416 return CKR_OPERATION_NOT_INITIALIZED;
2419 // Size of the encrypted data
2420 CK_ULONG size = publicKey->getOutputLength();
2422 if (pEncryptedData == NULL_PTR)
2424 *pulEncryptedDataLen = size;
2428 // Check buffer size
2429 if (*pulEncryptedDataLen < size)
2431 *pulEncryptedDataLen = size;
2432 return CKR_BUFFER_TOO_SMALL;
2437 ByteString encryptedData;
2439 // We must allow input length <= k and therfore need to prepend the data with zeroes.
2440 if (mechanism == AsymMech::RSA) {
2441 data.wipe(size-ulDataLen);
2444 data += ByteString(pData, ulDataLen);
2447 if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
2450 return CKR_GENERAL_ERROR;
2454 if (encryptedData.size() != size)
2456 ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
2458 return CKR_GENERAL_ERROR;
2460 memcpy(pEncryptedData, encryptedData.byte_str(), size);
2461 *pulEncryptedDataLen = size;
2467 // Perform a single operation encryption operation in the specified session
2468 CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2470 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2472 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2473 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2476 Session* session = (Session*)handleManager->getSession(hSession);
2477 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2479 // Check if we are doing the correct operation
2480 if (session->getOpType() != SESSION_OP_ENCRYPT)
2481 return CKR_OPERATION_NOT_INITIALIZED;
2483 if (session->getSymmetricCryptoOp() != NULL)
2484 return SymEncrypt(session, pData, ulDataLen,
2485 pEncryptedData, pulEncryptedDataLen);
2487 return AsymEncrypt(session, pData, ulDataLen,
2488 pEncryptedData, pulEncryptedDataLen);
2491 // SymAlgorithm version of C_EncryptUpdate
2492 static CK_RV SymEncryptUpdate(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2494 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2495 if (cipher == NULL || !session->getAllowMultiPartOp())
2498 return CKR_OPERATION_NOT_INITIALIZED;
2502 size_t blockSize = cipher->getBlockSize();
2503 size_t remainingSize = cipher->getBufferSize();
2504 CK_ULONG maxSize = ulDataLen + remainingSize;
2505 if (cipher->isBlockCipher())
2507 int nrOfBlocks = (ulDataLen + remainingSize) / blockSize;
2508 maxSize = nrOfBlocks * blockSize;
2510 if (!cipher->checkMaximumBytes(ulDataLen))
2513 return CKR_DATA_LEN_RANGE;
2517 if (pEncryptedData == NULL_PTR)
2519 *pulEncryptedDataLen = maxSize;
2523 // Check output buffer size
2524 if (*pulEncryptedDataLen < maxSize)
2526 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
2527 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize);
2528 *pulEncryptedDataLen = maxSize;
2529 return CKR_BUFFER_TOO_SMALL;
2533 ByteString data(pData, ulDataLen);
2534 ByteString encryptedData;
2537 if (!cipher->encryptUpdate(data, encryptedData))
2540 return CKR_GENERAL_ERROR;
2542 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x encryptedData.size(): %#5x",
2543 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize, encryptedData.size());
2545 // Check output size from crypto. Unrecoverable error if to large.
2546 if (*pulEncryptedDataLen < encryptedData.size())
2549 ERROR_MSG("EncryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2550 *pulEncryptedDataLen, encryptedData.size());
2551 return CKR_GENERAL_ERROR;
2554 if (encryptedData.size() > 0)
2556 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2558 *pulEncryptedDataLen = encryptedData.size();
2563 // Feed data to the running encryption operation in a session
2564 CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2566 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2568 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2569 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2572 Session* session = (Session*)handleManager->getSession(hSession);
2573 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2575 // Check if we are doing the correct operation
2576 if (session->getOpType() != SESSION_OP_ENCRYPT)
2577 return CKR_OPERATION_NOT_INITIALIZED;
2579 if (session->getSymmetricCryptoOp() != NULL)
2580 return SymEncryptUpdate(session, pData, ulDataLen,
2581 pEncryptedData, pulEncryptedDataLen);
2583 return CKR_FUNCTION_NOT_SUPPORTED;
2586 // SymAlgorithm version of C_EncryptFinal
2587 static CK_RV SymEncryptFinal(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2589 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2590 if (cipher == NULL || !session->getAllowMultiPartOp())
2593 return CKR_OPERATION_NOT_INITIALIZED;
2597 size_t remainingSize = cipher->getBufferSize() + cipher->getTagBytes();
2598 CK_ULONG size = remainingSize;
2599 if (cipher->isBlockCipher())
2601 size_t blockSize = cipher->getBlockSize();
2602 bool isPadding = cipher->getPaddingMode();
2603 if ((remainingSize % blockSize) != 0 && !isPadding)
2606 DEBUG_MSG("Remaining buffer size is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
2607 blockSize, remainingSize);
2608 return CKR_DATA_LEN_RANGE;
2610 // when padding: an integral of the block size that is longer than the remaining data.
2611 size = isPadding ? ((remainingSize + blockSize) / blockSize) * blockSize : remainingSize;
2614 // Give required output buffer size.
2615 if (pEncryptedData == NULL_PTR)
2617 *pulEncryptedDataLen = size;
2621 // Check output buffer size
2622 if (*pulEncryptedDataLen < size)
2624 DEBUG_MSG("output buffer size: %#5x size: %#5x",
2625 *pulEncryptedDataLen, size);
2626 *pulEncryptedDataLen = size;
2627 return CKR_BUFFER_TOO_SMALL;
2630 // Finalize encryption
2631 ByteString encryptedFinal;
2632 if (!cipher->encryptFinal(encryptedFinal))
2635 return CKR_GENERAL_ERROR;
2637 DEBUG_MSG("output buffer size: %#2x size: %#2x encryptedFinal.size(): %#2x",
2638 *pulEncryptedDataLen, size, encryptedFinal.size());
2640 // Check output size from crypto. Unrecoverable error if to large.
2641 if (*pulEncryptedDataLen < encryptedFinal.size())
2644 ERROR_MSG("EncryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2645 *pulEncryptedDataLen, encryptedFinal.size());
2646 return CKR_GENERAL_ERROR;
2649 if (encryptedFinal.size() > 0)
2651 memcpy(pEncryptedData, encryptedFinal.byte_str(), encryptedFinal.size());
2653 *pulEncryptedDataLen = encryptedFinal.size();
2659 // Finalise the encryption operation
2660 CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2662 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2665 Session* session = (Session*)handleManager->getSession(hSession);
2666 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2668 // Check if we are doing the correct operation
2669 if (session->getOpType() != SESSION_OP_ENCRYPT) return CKR_OPERATION_NOT_INITIALIZED;
2671 if (session->getSymmetricCryptoOp() != NULL)
2672 return SymEncryptFinal(session, pEncryptedData, pulEncryptedDataLen);
2674 return CKR_FUNCTION_NOT_SUPPORTED;
2677 // SymAlgorithm version of C_DecryptInit
2678 CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2680 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2682 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2685 Session* session = (Session*)handleManager->getSession(hSession);
2686 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2689 Token* token = session->getToken();
2690 if (token == NULL) return CKR_GENERAL_ERROR;
2692 // Check if we have another operation
2693 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2695 // Check the key handle.
2696 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2697 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2699 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2700 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2702 // Check read user credentials
2703 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2706 if (rv == CKR_USER_NOT_LOGGED_IN)
2707 INFO_MSG("User is not authorized");
2712 // Check if key can be used for decryption
2713 if (!key->getBooleanValue(CKA_DECRYPT, false))
2714 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2717 // Check if the specified mechanism is allowed for the key
2718 if (!isMechanismPermitted(key, pMechanism))
2719 return CKR_MECHANISM_INVALID;
2721 // Get the symmetric algorithm matching the mechanism
2722 SymAlgo::Type algo = SymAlgo::Unknown;
2723 SymMode::Type mode = SymMode::Unknown;
2724 bool padding = false;
2727 size_t counterBits = 0;
2729 size_t tagBytes = 0;
2730 switch(pMechanism->mechanism) {
2733 algo = SymAlgo::DES;
2734 mode = SymMode::ECB;
2738 algo = SymAlgo::DES;
2739 mode = SymMode::CBC;
2740 if (pMechanism->pParameter == NULL_PTR ||
2741 pMechanism->ulParameterLen == 0)
2743 DEBUG_MSG("CBC mode requires an init vector");
2744 return CKR_ARGUMENTS_BAD;
2746 iv.resize(pMechanism->ulParameterLen);
2747 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2750 case CKM_DES_CBC_PAD:
2751 algo = SymAlgo::DES;
2752 mode = SymMode::CBC;
2754 if (pMechanism->pParameter == NULL_PTR ||
2755 pMechanism->ulParameterLen == 0)
2757 DEBUG_MSG("CBC mode requires an init vector");
2758 return CKR_ARGUMENTS_BAD;
2760 iv.resize(pMechanism->ulParameterLen);
2761 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2766 algo = SymAlgo::DES3;
2767 mode = SymMode::ECB;
2771 algo = SymAlgo::DES3;
2772 mode = SymMode::CBC;
2773 if (pMechanism->pParameter == NULL_PTR ||
2774 pMechanism->ulParameterLen == 0)
2776 DEBUG_MSG("CBC mode requires an init vector");
2777 return CKR_ARGUMENTS_BAD;
2779 iv.resize(pMechanism->ulParameterLen);
2780 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2783 case CKM_DES3_CBC_PAD:
2784 algo = SymAlgo::DES3;
2785 mode = SymMode::CBC;
2787 if (pMechanism->pParameter == NULL_PTR ||
2788 pMechanism->ulParameterLen == 0)
2790 DEBUG_MSG("CBC mode requires an init vector");
2791 return CKR_ARGUMENTS_BAD;
2793 iv.resize(pMechanism->ulParameterLen);
2794 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2798 algo = SymAlgo::AES;
2799 mode = SymMode::ECB;
2802 algo = SymAlgo::AES;
2803 mode = SymMode::CBC;
2804 if (pMechanism->pParameter == NULL_PTR ||
2805 pMechanism->ulParameterLen == 0)
2807 DEBUG_MSG("CBC mode requires an init vector");
2808 return CKR_ARGUMENTS_BAD;
2810 iv.resize(pMechanism->ulParameterLen);
2811 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2813 case CKM_AES_CBC_PAD:
2814 algo = SymAlgo::AES;
2815 mode = SymMode::CBC;
2817 if (pMechanism->pParameter == NULL_PTR ||
2818 pMechanism->ulParameterLen == 0)
2820 DEBUG_MSG("CBC mode requires an init vector");
2821 return CKR_ARGUMENTS_BAD;
2823 iv.resize(pMechanism->ulParameterLen);
2824 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2827 algo = SymAlgo::AES;
2828 mode = SymMode::CTR;
2829 if (pMechanism->pParameter == NULL_PTR ||
2830 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2832 DEBUG_MSG("CTR mode requires a counter block");
2833 return CKR_ARGUMENTS_BAD;
2835 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2836 if (counterBits == 0 || counterBits > 128)
2838 DEBUG_MSG("Invalid ulCounterBits");
2839 return CKR_MECHANISM_PARAM_INVALID;
2842 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2846 algo = SymAlgo::AES;
2847 mode = SymMode::GCM;
2848 if (pMechanism->pParameter == NULL_PTR ||
2849 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2851 DEBUG_MSG("GCM mode requires parameters");
2852 return CKR_ARGUMENTS_BAD;
2854 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2855 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2856 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2857 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2858 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2859 if (tagBytes > 128 || tagBytes % 8 != 0)
2861 DEBUG_MSG("Invalid ulTagBits value");
2862 return CKR_ARGUMENTS_BAD;
2864 tagBytes = tagBytes / 8;
2868 return CKR_MECHANISM_INVALID;
2870 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2871 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2873 SymmetricKey* secretkey = new SymmetricKey();
2875 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2877 cipher->recycleKey(secretkey);
2878 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2879 return CKR_GENERAL_ERROR;
2882 // adjust key bit length
2883 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2885 // Initialize decryption
2886 if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2888 cipher->recycleKey(secretkey);
2889 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2890 return CKR_MECHANISM_INVALID;
2893 session->setOpType(SESSION_OP_DECRYPT);
2894 session->setSymmetricCryptoOp(cipher);
2895 session->setAllowMultiPartOp(true);
2896 session->setAllowSinglePartOp(true);
2897 session->setSymmetricKey(secretkey);
2902 // AsymAlgorithm version of C_DecryptInit
2903 CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2905 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2907 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2910 Session* session = (Session*)handleManager->getSession(hSession);
2911 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2914 Token* token = session->getToken();
2915 if (token == NULL) return CKR_GENERAL_ERROR;
2917 // Check if we have another operation
2918 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2920 // Check the key handle.
2921 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2922 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2924 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2925 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2927 // Check read user credentials
2928 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2931 if (rv == CKR_USER_NOT_LOGGED_IN)
2932 INFO_MSG("User is not authorized");
2937 // Check if key can be used for decryption
2938 if (!key->getBooleanValue(CKA_DECRYPT, false))
2939 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2941 // Check if the specified mechanism is allowed for the key
2942 if (!isMechanismPermitted(key, pMechanism))
2943 return CKR_MECHANISM_INVALID;
2945 // Get the asymmetric algorithm matching the mechanism
2946 AsymMech::Type mechanism = AsymMech::Unknown;
2948 switch(pMechanism->mechanism) {
2950 mechanism = AsymMech::RSA_PKCS;
2954 mechanism = AsymMech::RSA;
2957 case CKM_RSA_PKCS_OAEP:
2958 if (pMechanism->pParameter == NULL_PTR ||
2959 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
2961 DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
2962 return CKR_ARGUMENTS_BAD;
2964 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
2966 DEBUG_MSG("hashAlg must be CKM_SHA_1");
2967 return CKR_ARGUMENTS_BAD;
2969 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
2971 DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
2972 return CKR_ARGUMENTS_BAD;
2975 mechanism = AsymMech::RSA_PKCS_OAEP;
2979 return CKR_MECHANISM_INVALID;
2982 AsymmetricAlgorithm* asymCrypto = NULL;
2983 PrivateKey* privateKey = NULL;
2986 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2987 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2989 privateKey = asymCrypto->newPrivateKey();
2990 if (privateKey == NULL)
2992 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2993 return CKR_HOST_MEMORY;
2996 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
2998 asymCrypto->recyclePrivateKey(privateKey);
2999 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
3000 return CKR_GENERAL_ERROR;
3005 return CKR_MECHANISM_INVALID;
3008 // Check if re-authentication is required
3009 if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
3011 session->setReAuthentication(true);
3014 session->setOpType(SESSION_OP_DECRYPT);
3015 session->setAsymmetricCryptoOp(asymCrypto);
3016 session->setMechanism(mechanism);
3017 session->setAllowMultiPartOp(false);
3018 session->setAllowSinglePartOp(true);
3019 session->setPrivateKey(privateKey);
3024 // Initialise decryption using the specified object
3025 CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3027 if (isSymMechanism(pMechanism))
3028 return SymDecryptInit(hSession, pMechanism, hKey);
3030 return AsymDecryptInit(hSession, pMechanism, hKey);
3033 // SymAlgorithm version of C_Decrypt
3034 static CK_RV SymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3036 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3037 if (cipher == NULL || !session->getAllowSinglePartOp())
3040 return CKR_OPERATION_NOT_INITIALIZED;
3043 // Check encrypted data size
3044 if (cipher->isBlockCipher() && ulEncryptedDataLen % cipher->getBlockSize() != 0)
3047 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3049 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3052 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3055 if (pData == NULL_PTR)
3057 *pulDataLen = ulEncryptedDataLen;
3061 // Check buffer size
3062 if (*pulDataLen < ulEncryptedDataLen)
3064 *pulDataLen = ulEncryptedDataLen;
3065 return CKR_BUFFER_TOO_SMALL;
3069 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3073 if (!cipher->decryptUpdate(encryptedData,data))
3076 return CKR_GENERAL_ERROR;
3079 // Finalize decryption
3080 ByteString dataFinal;
3081 if (!cipher->decryptFinal(dataFinal))
3084 return CKR_GENERAL_ERROR;
3087 if (data.size() > ulEncryptedDataLen)
3089 data.resize(ulEncryptedDataLen);
3092 if (data.size() != 0)
3094 memcpy(pData, data.byte_str(), data.size());
3096 *pulDataLen = data.size();
3103 // AsymAlgorithm version of C_Decrypt
3104 static CK_RV AsymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3106 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
3107 AsymMech::Type mechanism = session->getMechanism();
3108 PrivateKey* privateKey = session->getPrivateKey();
3109 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
3112 return CKR_OPERATION_NOT_INITIALIZED;
3115 // Check if re-authentication is required
3116 if (session->getReAuthentication())
3119 return CKR_USER_NOT_LOGGED_IN;
3123 CK_ULONG size = privateKey->getOutputLength();
3124 if (pData == NULL_PTR)
3130 // Check buffer size
3131 if (*pulDataLen < size)
3134 return CKR_BUFFER_TOO_SMALL;
3138 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3142 if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
3145 return CKR_GENERAL_ERROR;
3149 if (data.size() > size)
3151 ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
3153 return CKR_GENERAL_ERROR;
3155 if (data.size() != 0)
3157 memcpy(pData, data.byte_str(), data.size());
3159 *pulDataLen = data.size();
3166 // Perform a single operation decryption in the given session
3167 CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3169 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3171 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3172 if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3175 Session* session = (Session*)handleManager->getSession(hSession);
3176 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3178 // Check if we are doing the correct operation
3179 if (session->getOpType() != SESSION_OP_DECRYPT)
3180 return CKR_OPERATION_NOT_INITIALIZED;
3182 if (session->getSymmetricCryptoOp() != NULL)
3183 return SymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3186 return AsymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3190 // SymAlgorithm version of C_DecryptUpdate
3191 static CK_RV SymDecryptUpdate(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3193 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3194 if (cipher == NULL || !session->getAllowMultiPartOp())
3197 return CKR_OPERATION_NOT_INITIALIZED;
3200 // Check encrypted data size
3201 size_t blockSize = cipher->getBlockSize();
3202 size_t remainingSize = cipher->getBufferSize();
3203 CK_ULONG maxSize = ulEncryptedDataLen + remainingSize;
3204 if (cipher->isBlockCipher())
3206 // There must always be one block left in padding mode if next operation is DecryptFinal.
3207 // To guarantee that one byte is removed in padding mode when the number of blocks is calculated.
3208 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3209 int nrOfBlocks = (ulEncryptedDataLen + remainingSize - paddingAdjustByte) / blockSize;
3210 maxSize = nrOfBlocks * blockSize;
3212 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3215 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3218 // Give required output buffer size.
3219 if (pData == NULL_PTR)
3221 *pDataLen = maxSize;
3225 // Check output buffer size
3226 if (*pDataLen < maxSize)
3228 DEBUG_MSG("Output buffer too short ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
3229 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize);
3230 *pDataLen = maxSize;
3231 return CKR_BUFFER_TOO_SMALL;
3235 ByteString data(pEncryptedData, ulEncryptedDataLen);
3236 ByteString decryptedData;
3239 if (!cipher->decryptUpdate(data, decryptedData))
3242 return CKR_GENERAL_ERROR;
3244 DEBUG_MSG("ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x decryptedData.size(): %#5x",
3245 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize, decryptedData.size());
3247 // Check output size from crypto. Unrecoverable error if to large.
3248 if (*pDataLen < decryptedData.size())
3251 ERROR_MSG("DecryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the decrypt.",
3252 *pDataLen, decryptedData.size());
3253 return CKR_GENERAL_ERROR;
3256 if (decryptedData.size() > 0)
3258 memcpy(pData, decryptedData.byte_str(), decryptedData.size());
3260 *pDataLen = decryptedData.size();
3266 // Feed data to the running decryption operation in a session
3267 CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3269 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3271 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3272 if (pDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3275 Session* session = (Session*)handleManager->getSession(hSession);
3276 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3278 // Check if we are doing the correct operation
3279 if (session->getOpType() != SESSION_OP_DECRYPT)
3280 return CKR_OPERATION_NOT_INITIALIZED;
3282 if (session->getSymmetricCryptoOp() != NULL)
3283 return SymDecryptUpdate(session, pEncryptedData, ulEncryptedDataLen,
3286 return CKR_FUNCTION_NOT_SUPPORTED;
3289 static CK_RV SymDecryptFinal(Session* session, CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen)
3291 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3292 if (cipher == NULL || !session->getAllowMultiPartOp())
3295 return CKR_OPERATION_NOT_INITIALIZED;
3298 // Check encrypted data size
3299 size_t remainingSize = cipher->getBufferSize();
3300 CK_ULONG size = remainingSize;
3301 if (cipher->isBlockCipher())
3303 size_t blockSize = cipher->getBlockSize();
3304 if (remainingSize % blockSize != 0)
3307 DEBUG_MSG("Remaining data length is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
3308 blockSize, remainingSize);
3309 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3311 // It is at least one padding byte. If no padding the all remains will be returned.
3312 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3313 size = remainingSize - paddingAdjustByte;
3316 // Give required output buffer size.
3317 if (pDecryptedData == NULL_PTR)
3319 *pulDecryptedDataLen = size;
3323 // Check output buffer size
3324 if (*pulDecryptedDataLen < size)
3326 DEBUG_MSG("output buffer size: %#5x size: %#5x",
3327 *pulDecryptedDataLen, size);
3328 *pulDecryptedDataLen = size;
3329 return CKR_BUFFER_TOO_SMALL;
3332 // Finalize decryption
3333 ByteString decryptedFinal;
3334 if (!cipher->decryptFinal(decryptedFinal))
3337 return CKR_GENERAL_ERROR;
3339 DEBUG_MSG("output buffer size: %#2x size: %#2x decryptedFinal.size(): %#2x",
3340 *pulDecryptedDataLen, size, decryptedFinal.size());
3342 // Check output size from crypto. Unrecoverable error if to large.
3343 if (*pulDecryptedDataLen < decryptedFinal.size())
3346 ERROR_MSG("DecryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
3347 *pulDecryptedDataLen, decryptedFinal.size());
3348 return CKR_GENERAL_ERROR;
3351 if (decryptedFinal.size() > 0)
3353 memcpy(pDecryptedData, decryptedFinal.byte_str(), decryptedFinal.size());
3355 *pulDecryptedDataLen = decryptedFinal.size();
3361 // Finalise the decryption operation
3362 CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3364 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3367 Session* session = (Session*)handleManager->getSession(hSession);
3368 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3370 // Check if we are doing the correct operation
3371 if (session->getOpType() != SESSION_OP_DECRYPT) return CKR_OPERATION_NOT_INITIALIZED;
3373 if (session->getSymmetricCryptoOp() != NULL)
3374 return SymDecryptFinal(session, pData, pDataLen);
3376 return CKR_FUNCTION_NOT_SUPPORTED;
3379 // Initialise digesting using the specified mechanism in the specified session
3380 CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
3382 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3384 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3387 Session* session = (Session*)handleManager->getSession(hSession);
3388 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3390 // Check if we have another operation
3391 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3393 // Get the mechanism
3394 HashAlgo::Type algo = HashAlgo::Unknown;
3395 switch(pMechanism->mechanism) {
3398 algo = HashAlgo::MD5;
3402 algo = HashAlgo::SHA1;
3405 algo = HashAlgo::SHA224;
3408 algo = HashAlgo::SHA256;
3411 algo = HashAlgo::SHA384;
3414 algo = HashAlgo::SHA512;
3418 algo = HashAlgo::GOST;
3422 return CKR_MECHANISM_INVALID;
3424 HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(algo);
3425 if (hash == NULL) return CKR_MECHANISM_INVALID;
3427 // Initialize hashing
3428 if (hash->hashInit() == false)
3430 CryptoFactory::i()->recycleHashAlgorithm(hash);
3431 return CKR_GENERAL_ERROR;
3434 session->setOpType(SESSION_OP_DIGEST);
3435 session->setDigestOp(hash);
3436 session->setHashAlgo(algo);
3441 // Digest the specified data in a one-pass operation and return the resulting digest
3442 CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3444 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3446 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3447 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3450 Session* session = (Session*)handleManager->getSession(hSession);
3451 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3453 // Check if we are doing the correct operation
3454 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3457 CK_ULONG size = session->getDigestOp()->getHashSize();
3458 if (pDigest == NULL_PTR)
3460 *pulDigestLen = size;
3464 // Check buffer size
3465 if (*pulDigestLen < size)
3467 *pulDigestLen = size;
3468 return CKR_BUFFER_TOO_SMALL;
3472 ByteString data(pData, ulDataLen);
3475 if (session->getDigestOp()->hashUpdate(data) == false)
3478 return CKR_GENERAL_ERROR;
3483 if (session->getDigestOp()->hashFinal(digest) == false)
3486 return CKR_GENERAL_ERROR;
3490 if (digest.size() != size)
3492 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3494 return CKR_GENERAL_ERROR;
3496 memcpy(pDigest, digest.byte_str(), size);
3497 *pulDigestLen = size;
3504 // Update a running digest operation
3505 CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
3507 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3509 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
3512 Session* session = (Session*)handleManager->getSession(hSession);
3513 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3515 // Check if we are doing the correct operation
3516 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3519 ByteString data(pPart, ulPartLen);
3522 if (session->getDigestOp()->hashUpdate(data) == false)
3525 return CKR_GENERAL_ERROR;
3531 // Update a running digest operation by digesting a secret key with the specified handle
3532 CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3534 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3537 Session* session = (Session*)handleManager->getSession(hSession);
3538 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3540 // Check if we are doing the correct operation
3541 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3544 Token* token = session->getToken();
3545 if (token == NULL) return CKR_GENERAL_ERROR;
3547 // Check the key handle.
3548 OSObject *key = (OSObject *)handleManager->getObject(hObject);
3549 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
3551 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3552 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3554 // Check read user credentials
3555 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3558 if (rv == CKR_USER_NOT_LOGGED_IN)
3559 INFO_MSG("User is not authorized");
3561 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
3562 // so we use CKR_GENERAL_ERROR.
3563 return CKR_GENERAL_ERROR;
3567 HashAlgo::Type algo = session->getHashAlgo();
3568 if (algo != HashAlgo::SHA1 &&
3569 algo != HashAlgo::SHA224 &&
3570 algo != HashAlgo::SHA256 &&
3571 algo != HashAlgo::SHA384 &&
3572 algo != HashAlgo::SHA512)
3575 if (!key->getBooleanValue(CKA_EXTRACTABLE, false))
3576 return CKR_KEY_INDIGESTIBLE;
3577 if (key->getBooleanValue(CKA_SENSITIVE, false))
3578 return CKR_KEY_INDIGESTIBLE;
3582 if (!key->attributeExists(CKA_VALUE))
3583 return CKR_KEY_INDIGESTIBLE;
3587 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
3588 return CKR_GENERAL_ERROR;
3592 keybits = key->getByteStringValue(CKA_VALUE);
3596 if (session->getDigestOp()->hashUpdate(keybits) == false)
3599 return CKR_GENERAL_ERROR;
3605 // Finalise the digest operation in the specified session and return the digest
3606 CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3608 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3610 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3613 Session* session = (Session*)handleManager->getSession(hSession);
3614 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3616 // Check if we are doing the correct operation
3617 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3620 CK_ULONG size = session->getDigestOp()->getHashSize();
3621 if (pDigest == NULL_PTR)
3623 *pulDigestLen = size;
3627 // Check buffer size
3628 if (*pulDigestLen < size)
3630 *pulDigestLen = size;
3631 return CKR_BUFFER_TOO_SMALL;
3636 if (session->getDigestOp()->hashFinal(digest) == false)
3639 return CKR_GENERAL_ERROR;
3643 if (digest.size() != size)
3645 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3647 return CKR_GENERAL_ERROR;
3649 memcpy(pDigest, digest.byte_str(), size);
3650 *pulDigestLen = size;
3657 // Sign*/Verify*() is for MACs too
3658 static bool isMacMechanism(CK_MECHANISM_PTR pMechanism)
3660 if (pMechanism == NULL_PTR) return false;
3662 switch(pMechanism->mechanism) {
3664 case CKM_SHA_1_HMAC:
3665 case CKM_SHA224_HMAC:
3666 case CKM_SHA256_HMAC:
3667 case CKM_SHA384_HMAC:
3668 case CKM_SHA512_HMAC:
3670 case CKM_GOSTR3411_HMAC:
3680 // MacAlgorithm version of C_SignInit
3681 CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3683 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3685 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3688 Session* session = (Session*)handleManager->getSession(hSession);
3689 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3691 // Check if we have another operation
3692 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3695 Token* token = session->getToken();
3696 if (token == NULL) return CKR_GENERAL_ERROR;
3698 // Check the key handle.
3699 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3700 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3702 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3703 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3705 // Check read user credentials
3706 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3709 if (rv == CKR_USER_NOT_LOGGED_IN)
3710 INFO_MSG("User is not authorized");
3715 // Check if key can be used for signing
3716 if (!key->getBooleanValue(CKA_SIGN, false))
3717 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3719 // Check if the specified mechanism is allowed for the key
3720 if (!isMechanismPermitted(key, pMechanism))
3721 return CKR_MECHANISM_INVALID;
3724 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
3726 // Get the MAC algorithm matching the mechanism
3727 // Also check mechanism constraints
3728 MacAlgo::Type algo = MacAlgo::Unknown;
3731 switch(pMechanism->mechanism) {
3734 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
3735 return CKR_KEY_TYPE_INCONSISTENT;
3737 algo = MacAlgo::HMAC_MD5;
3740 case CKM_SHA_1_HMAC:
3741 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
3742 return CKR_KEY_TYPE_INCONSISTENT;
3744 algo = MacAlgo::HMAC_SHA1;
3746 case CKM_SHA224_HMAC:
3747 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
3748 return CKR_KEY_TYPE_INCONSISTENT;
3750 algo = MacAlgo::HMAC_SHA224;
3752 case CKM_SHA256_HMAC:
3753 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
3754 return CKR_KEY_TYPE_INCONSISTENT;
3756 algo = MacAlgo::HMAC_SHA256;
3758 case CKM_SHA384_HMAC:
3759 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
3760 return CKR_KEY_TYPE_INCONSISTENT;
3762 algo = MacAlgo::HMAC_SHA384;
3764 case CKM_SHA512_HMAC:
3765 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
3766 return CKR_KEY_TYPE_INCONSISTENT;
3768 algo = MacAlgo::HMAC_SHA512;
3771 case CKM_GOSTR3411_HMAC:
3772 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
3773 return CKR_KEY_TYPE_INCONSISTENT;
3775 algo = MacAlgo::HMAC_GOST;
3779 if (keyType != CKK_DES2 && keyType != CKK_DES3)
3780 return CKR_KEY_TYPE_INCONSISTENT;
3781 algo = MacAlgo::CMAC_DES;
3785 if (keyType != CKK_AES)
3786 return CKR_KEY_TYPE_INCONSISTENT;
3787 algo = MacAlgo::CMAC_AES;
3790 return CKR_MECHANISM_INVALID;
3792 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
3793 if (mac == NULL) return CKR_MECHANISM_INVALID;
3795 SymmetricKey* privkey = new SymmetricKey();
3797 if (getSymmetricKey(privkey, token, key) != CKR_OK)
3799 mac->recycleKey(privkey);
3800 CryptoFactory::i()->recycleMacAlgorithm(mac);
3801 return CKR_GENERAL_ERROR;
3804 // Adjust key bit length
3805 privkey->setBitLen(privkey->getKeyBits().size() * bb);
3808 if (privkey->getBitLen() < (minSize*8))
3810 mac->recycleKey(privkey);
3811 CryptoFactory::i()->recycleMacAlgorithm(mac);
3812 return CKR_KEY_SIZE_RANGE;
3815 // Initialize signing
3816 if (!mac->signInit(privkey))
3818 mac->recycleKey(privkey);
3819 CryptoFactory::i()->recycleMacAlgorithm(mac);
3820 return CKR_MECHANISM_INVALID;
3823 session->setOpType(SESSION_OP_SIGN);
3824 session->setMacOp(mac);
3825 session->setAllowMultiPartOp(true);
3826 session->setAllowSinglePartOp(true);
3827 session->setSymmetricKey(privkey);
3832 // AsymmetricAlgorithm version of C_SignInit
3833 CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3835 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3837 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3840 Session* session = (Session*)handleManager->getSession(hSession);
3841 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3843 // Check if we have another operation
3844 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3847 Token* token = session->getToken();
3848 if (token == NULL) return CKR_GENERAL_ERROR;
3850 // Check the key handle.
3851 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3852 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3854 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3855 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3857 // Check read user credentials
3858 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3861 if (rv == CKR_USER_NOT_LOGGED_IN)
3862 INFO_MSG("User is not authorized");
3867 // Check if key can be used for signing
3868 if (!key->getBooleanValue(CKA_SIGN, false))
3869 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3871 // Check if the specified mechanism is allowed for the key
3872 if (!isMechanismPermitted(key, pMechanism))
3873 return CKR_MECHANISM_INVALID;
3875 // Get the asymmetric algorithm matching the mechanism
3876 AsymMech::Type mechanism = AsymMech::Unknown;
3878 size_t paramLen = 0;
3879 RSA_PKCS_PSS_PARAMS pssParam;
3880 bool bAllowMultiPartOp;
3883 bool isECDSA = false;
3884 switch(pMechanism->mechanism) {
3886 mechanism = AsymMech::RSA_PKCS;
3887 bAllowMultiPartOp = false;
3891 mechanism = AsymMech::RSA;
3892 bAllowMultiPartOp = false;
3896 case CKM_MD5_RSA_PKCS:
3897 mechanism = AsymMech::RSA_MD5_PKCS;
3898 bAllowMultiPartOp = true;
3902 case CKM_SHA1_RSA_PKCS:
3903 mechanism = AsymMech::RSA_SHA1_PKCS;
3904 bAllowMultiPartOp = true;
3907 case CKM_SHA224_RSA_PKCS:
3908 mechanism = AsymMech::RSA_SHA224_PKCS;
3909 bAllowMultiPartOp = true;
3912 case CKM_SHA256_RSA_PKCS:
3913 mechanism = AsymMech::RSA_SHA256_PKCS;
3914 bAllowMultiPartOp = true;
3917 case CKM_SHA384_RSA_PKCS:
3918 mechanism = AsymMech::RSA_SHA384_PKCS;
3919 bAllowMultiPartOp = true;
3922 case CKM_SHA512_RSA_PKCS:
3923 mechanism = AsymMech::RSA_SHA512_PKCS;
3924 bAllowMultiPartOp = true;
3928 case CKM_RSA_PKCS_PSS:
3929 if (pMechanism->pParameter == NULL_PTR ||
3930 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3932 ERROR_MSG("Invalid RSA-PSS parameters");
3933 return CKR_ARGUMENTS_BAD;
3935 mechanism = AsymMech::RSA_PKCS_PSS;
3936 unsigned long allowedMgf;
3938 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
3940 pssParam.hashAlg = HashAlgo::SHA1;
3941 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3942 allowedMgf = CKG_MGF1_SHA1;
3945 pssParam.hashAlg = HashAlgo::SHA224;
3946 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
3947 allowedMgf = CKG_MGF1_SHA224;
3950 pssParam.hashAlg = HashAlgo::SHA256;
3951 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
3952 allowedMgf = CKG_MGF1_SHA256;
3955 pssParam.hashAlg = HashAlgo::SHA384;
3956 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
3957 allowedMgf = CKG_MGF1_SHA384;
3960 pssParam.hashAlg = HashAlgo::SHA512;
3961 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
3962 allowedMgf = CKG_MGF1_SHA512;
3965 ERROR_MSG("Invalid RSA-PSS hash");
3966 return CKR_ARGUMENTS_BAD;
3969 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != allowedMgf) {
3970 ERROR_MSG("Hash and MGF don't match");
3971 return CKR_ARGUMENTS_BAD;
3974 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3976 paramLen = sizeof(pssParam);
3977 bAllowMultiPartOp = false;
3981 case CKM_SHA1_RSA_PKCS_PSS:
3982 if (pMechanism->pParameter == NULL_PTR ||
3983 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3984 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
3985 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
3987 ERROR_MSG("Invalid parameters");
3988 return CKR_ARGUMENTS_BAD;
3990 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
3991 pssParam.hashAlg = HashAlgo::SHA1;
3992 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3993 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3995 paramLen = sizeof(pssParam);
3996 bAllowMultiPartOp = true;
3999 case CKM_SHA224_RSA_PKCS_PSS:
4000 if (pMechanism->pParameter == NULL_PTR ||
4001 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4002 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
4003 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
4005 ERROR_MSG("Invalid parameters");
4006 return CKR_ARGUMENTS_BAD;
4008 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
4009 pssParam.hashAlg = HashAlgo::SHA224;
4010 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
4011 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4013 paramLen = sizeof(pssParam);
4014 bAllowMultiPartOp = true;
4017 case CKM_SHA256_RSA_PKCS_PSS:
4018 if (pMechanism->pParameter == NULL_PTR ||
4019 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4020 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
4021 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
4023 ERROR_MSG("Invalid parameters");
4024 return CKR_ARGUMENTS_BAD;
4026 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
4027 pssParam.hashAlg = HashAlgo::SHA256;
4028 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
4029 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4031 paramLen = sizeof(pssParam);
4032 bAllowMultiPartOp = true;
4035 case CKM_SHA384_RSA_PKCS_PSS:
4036 if (pMechanism->pParameter == NULL_PTR ||
4037 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4038 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
4039 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
4041 ERROR_MSG("Invalid parameters");
4042 return CKR_ARGUMENTS_BAD;
4044 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
4045 pssParam.hashAlg = HashAlgo::SHA384;
4046 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4047 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4049 paramLen = sizeof(pssParam);
4050 bAllowMultiPartOp = true;
4053 case CKM_SHA512_RSA_PKCS_PSS:
4054 if (pMechanism->pParameter == NULL_PTR ||
4055 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4056 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
4057 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
4059 ERROR_MSG("Invalid parameters");
4060 return CKR_ARGUMENTS_BAD;
4062 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
4063 pssParam.hashAlg = HashAlgo::SHA512;
4064 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4065 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4067 paramLen = sizeof(pssParam);
4068 bAllowMultiPartOp = true;
4072 mechanism = AsymMech::DSA;
4073 bAllowMultiPartOp = false;
4077 mechanism = AsymMech::DSA_SHA1;
4078 bAllowMultiPartOp = true;
4081 case CKM_DSA_SHA224:
4082 mechanism = AsymMech::DSA_SHA224;
4083 bAllowMultiPartOp = true;
4086 case CKM_DSA_SHA256:
4087 mechanism = AsymMech::DSA_SHA256;
4088 bAllowMultiPartOp = true;
4091 case CKM_DSA_SHA384:
4092 mechanism = AsymMech::DSA_SHA384;
4093 bAllowMultiPartOp = true;
4096 case CKM_DSA_SHA512:
4097 mechanism = AsymMech::DSA_SHA512;
4098 bAllowMultiPartOp = true;
4103 mechanism = AsymMech::ECDSA;
4104 bAllowMultiPartOp = false;
4110 mechanism = AsymMech::GOST;
4111 bAllowMultiPartOp = false;
4113 case CKM_GOSTR3410_WITH_GOSTR3411:
4114 mechanism = AsymMech::GOST_GOST;
4115 bAllowMultiPartOp = true;
4119 return CKR_MECHANISM_INVALID;
4122 AsymmetricAlgorithm* asymCrypto = NULL;
4123 PrivateKey* privateKey = NULL;
4126 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
4127 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4129 privateKey = asymCrypto->newPrivateKey();
4130 if (privateKey == NULL)
4132 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4133 return CKR_HOST_MEMORY;
4136 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
4138 asymCrypto->recyclePrivateKey(privateKey);
4139 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4140 return CKR_GENERAL_ERROR;
4145 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
4146 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4148 privateKey = asymCrypto->newPrivateKey();
4149 if (privateKey == NULL)
4151 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4152 return CKR_HOST_MEMORY;
4155 if (getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key) != CKR_OK)
4157 asymCrypto->recyclePrivateKey(privateKey);
4158 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4159 return CKR_GENERAL_ERROR;
4165 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
4166 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4168 privateKey = asymCrypto->newPrivateKey();
4169 if (privateKey == NULL)
4171 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4172 return CKR_HOST_MEMORY;
4175 if (getECPrivateKey((ECPrivateKey*)privateKey, token, key) != CKR_OK)
4177 asymCrypto->recyclePrivateKey(privateKey);
4178 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4179 return CKR_GENERAL_ERROR;
4186 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
4187 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4189 privateKey = asymCrypto->newPrivateKey();
4190 if (privateKey == NULL)
4192 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4193 return CKR_HOST_MEMORY;
4196 if (getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key) != CKR_OK)
4198 asymCrypto->recyclePrivateKey(privateKey);
4199 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4200 return CKR_GENERAL_ERROR;
4203 return CKR_MECHANISM_INVALID;
4206 // Initialize signing
4209 // Extract HW key handle
4210 CK_ULONG hwKeyHandle = 0;
4211 if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4213 LOG("ERROR in extracting key handle \n");
4215 return CKR_GENERAL_ERROR;
4217 LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4218 void *hwCryptoOpaque;
4220 if(HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen, &hwCryptoOpaque) != 0)
4222 return CKR_MECHANISM_INVALID;
4224 session->setHwCryptoOpaque(hwCryptoOpaque);
4228 if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
4230 asymCrypto->recyclePrivateKey(privateKey);
4231 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4232 return CKR_MECHANISM_INVALID;
4235 session->setOpType(SESSION_OP_SIGN);
4236 session->setAsymmetricCryptoOp(asymCrypto);
4237 session->setMechanism(mechanism);
4238 session->setParameters(param, paramLen);
4239 session->setAllowMultiPartOp(bAllowMultiPartOp);
4240 session->setAllowSinglePartOp(true);
4241 session->setPrivateKey(privateKey);
4242 session->setKeyHandle(hKey);
4246 // Initialise a signing operation using the specified key and mechanism
4247 CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4249 if (isMacMechanism(pMechanism))
4250 return MacSignInit(hSession, pMechanism, hKey);
4252 return AsymSignInit(hSession, pMechanism, hKey);
4255 // MacAlgorithm version of C_Sign
4256 static CK_RV MacSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4258 MacAlgorithm* mac = session->getMacOp();
4259 if (mac == NULL || !session->getAllowSinglePartOp())
4262 return CKR_OPERATION_NOT_INITIALIZED;
4265 // Size of the signature
4266 CK_ULONG size = mac->getMacSize();
4267 if (pSignature == NULL_PTR)
4269 *pulSignatureLen = size;
4273 // Check buffer size
4274 if (*pulSignatureLen < size)
4276 *pulSignatureLen = size;
4277 return CKR_BUFFER_TOO_SMALL;
4281 ByteString data(pData, ulDataLen);
4284 if (!mac->signUpdate(data))
4287 return CKR_GENERAL_ERROR;
4290 // Get the signature
4291 ByteString signature;
4292 if (!mac->signFinal(signature))
4295 return CKR_GENERAL_ERROR;
4299 if (signature.size() != size)
4301 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4303 return CKR_GENERAL_ERROR;
4305 memcpy(pSignature, signature.byte_str(), size);
4306 *pulSignatureLen = size;
4312 // AsymmetricAlgorithm version of C_Sign
4313 static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4315 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4316 AsymMech::Type mechanism = session->getMechanism();
4317 PrivateKey* privateKey = session->getPrivateKey();
4319 void* param = session->getParameters(paramLen);
4320 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4323 return CKR_OPERATION_NOT_INITIALIZED;
4326 // Check if re-authentication is required
4327 if (session->getReAuthentication())
4330 return CKR_USER_NOT_LOGGED_IN;
4333 // Size of the signature
4334 CK_ULONG size = privateKey->getOutputLength();
4335 if (pSignature == NULL_PTR)
4337 *pulSignatureLen = size;
4341 // Check buffer size
4342 if (*pulSignatureLen < size)
4344 *pulSignatureLen = size;
4345 return CKR_BUFFER_TOO_SMALL;
4351 // We must allow input length <= k and therfore need to prepend the data with zeroes.
4352 if (mechanism == AsymMech::RSA) {
4353 data.wipe(size-ulDataLen);
4356 data += ByteString(pData, ulDataLen);
4357 ByteString signature;
4360 if (session->getAllowMultiPartOp())
4362 if (!asymCrypto->signUpdate(data) ||
4363 !asymCrypto->signFinal(signature))
4366 return CKR_GENERAL_ERROR;
4369 else if (!asymCrypto->sign(privateKey,data,signature,mechanism,param,paramLen))
4372 return CKR_GENERAL_ERROR;
4376 if (signature.size() != size)
4378 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4380 return CKR_GENERAL_ERROR;
4382 memcpy(pSignature, signature.byte_str(), size);
4383 *pulSignatureLen = size;
4389 // AsymmetricAlgorithm version of C_Sign
4390 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)
4392 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4393 AsymMech::Type mechanism = session->getMechanism();
4394 PrivateKey* privateKey = session->getPrivateKey();
4395 CK_ULONG hwKeyHandle = 0;
4396 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4399 return CKR_OPERATION_NOT_INITIALIZED;
4402 // Size of the signature
4403 CK_ULONG size = privateKey->getOutputLength();
4404 if (pSignature == NULL_PTR)
4406 *pulSignatureLen = size;
4410 // Check buffer sizeq
4411 if (*pulSignatureLen < size)
4413 *pulSignatureLen = size;
4414 return CKR_BUFFER_TOO_SMALL;
4420 // We must allow input length <= k and therfore need to prepend the data with zeroes.
4421 if (mechanism == AsymMech::RSA) {
4422 data.wipe(size-ulDataLen);
4425 data += ByteString(pData, ulDataLen);
4426 ByteString signature;
4428 // Extract HW key handle
4429 CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4430 if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4432 LOG("ERROR in extracting key handle \n");
4434 return CKR_GENERAL_ERROR;
4436 LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4438 void *hwCryptoOpaque = session->getHwCryptoOpaque();
4440 if(HwInfraSign((void *)&hwKeyHandle, mechanism,
4441 pData, ulDataLen, hwCryptoOpaque,
4442 pSignature, (int *) pulSignatureLen) != 0)
4445 return CKR_GENERAL_ERROR;
4449 if (*pulSignatureLen != size)
4451 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4453 return CKR_GENERAL_ERROR;
4463 // Sign the data in a single pass operation
4464 CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4466 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4468 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
4469 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4472 Session* session = (Session*)handleManager->getSession(hSession);
4473 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4475 // Check if we are doing the correct operation
4476 if (session->getOpType() != SESSION_OP_SIGN)
4477 return CKR_OPERATION_NOT_INITIALIZED;
4479 if (session->getMacOp() != NULL)
4480 return MacSign(session, pData, ulDataLen,
4481 pSignature, pulSignatureLen);
4486 return AsymSignHW(hSession, session, pData, ulDataLen,
4487 pSignature, pulSignatureLen);
4491 return AsymSign(session, pData, ulDataLen,
4492 pSignature, pulSignatureLen);
4497 // MacAlgorithm version of C_SignUpdate
4498 static CK_RV MacSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4500 MacAlgorithm* mac = session->getMacOp();
4501 if (mac == NULL || !session->getAllowMultiPartOp())
4504 return CKR_OPERATION_NOT_INITIALIZED;
4508 ByteString part(pPart, ulPartLen);
4511 if (!mac->signUpdate(part))
4514 return CKR_GENERAL_ERROR;
4517 session->setAllowSinglePartOp(false);
4521 // AsymmetricAlgorithm version of C_SignUpdate
4522 static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4524 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4525 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4528 return CKR_OPERATION_NOT_INITIALIZED;
4531 // Check if re-authentication is required
4532 if (session->getReAuthentication())
4535 return CKR_USER_NOT_LOGGED_IN;
4539 ByteString part(pPart, ulPartLen);
4542 if (!asymCrypto->signUpdate(part))
4545 return CKR_GENERAL_ERROR;
4548 session->setAllowSinglePartOp(false);
4552 // AsymmetricAlgorithm version of C_SignUpdate
4553 static CK_RV AsymSignUpdateHW( CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4555 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4556 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4559 return CKR_OPERATION_NOT_INITIALIZED;
4562 // Check if re-authentication is required
4563 if (session->getReAuthentication())
4566 return CKR_USER_NOT_LOGGED_IN;
4570 ByteString part(pPart, ulPartLen);
4574 if (!asymCrypto->signUpdate(part))
4577 return CKR_GENERAL_ERROR;
4580 AsymMech::Type mechanism = session->getMechanism();
4581 // Extract HW key handle
4582 CK_ULONG hwKeyHandle = 0;
4583 CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4584 if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4586 LOG("ERROR in extracting key handle \n");
4588 return CKR_GENERAL_ERROR;
4591 void *hwCryptoOpaque = session->getHwCryptoOpaque();
4593 if(HwInfraSignUpdate((void *)&hwKeyHandle, mechanism,
4594 pPart, ulPartLen, hwCryptoOpaque ) != 0)
4597 return CKR_GENERAL_ERROR;
4600 session->setAllowSinglePartOp(false);
4606 // Update a running signing operation with additional data
4607 CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4609 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4611 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
4614 Session* session = (Session*)handleManager->getSession(hSession);
4615 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4617 // Check if we are doing the correct operation
4618 if (session->getOpType() != SESSION_OP_SIGN)
4619 return CKR_OPERATION_NOT_INITIALIZED;
4621 if (session->getMacOp() != NULL)
4622 return MacSignUpdate(session, pPart, ulPartLen);
4627 return AsymSignUpdateHW(hSession, session, pPart, ulPartLen);
4632 return AsymSignUpdate(session, pPart, ulPartLen);
4637 // MacAlgorithm version of C_SignFinal
4638 static CK_RV MacSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4640 MacAlgorithm* mac = session->getMacOp();
4644 return CKR_OPERATION_NOT_INITIALIZED;
4647 // Size of the signature
4648 CK_ULONG size = mac->getMacSize();
4649 if (pSignature == NULL_PTR)
4651 *pulSignatureLen = size;
4655 // Check buffer size
4656 if (*pulSignatureLen < size)
4658 *pulSignatureLen = size;
4659 return CKR_BUFFER_TOO_SMALL;
4662 // Get the signature
4663 ByteString signature;
4664 if (!mac->signFinal(signature))
4667 return CKR_GENERAL_ERROR;
4671 if (signature.size() != size)
4673 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4675 return CKR_GENERAL_ERROR;
4677 memcpy(pSignature, signature.byte_str(), size);
4678 *pulSignatureLen = size;
4684 // AsymmetricAlgorithm version of C_SignFinal
4685 static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4687 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4688 PrivateKey* privateKey = session->getPrivateKey();
4689 if (asymCrypto == NULL || privateKey == NULL)
4692 return CKR_OPERATION_NOT_INITIALIZED;
4695 // Check if re-authentication is required
4696 if (session->getReAuthentication())
4699 return CKR_USER_NOT_LOGGED_IN;
4702 // Size of the signature
4703 CK_ULONG size = privateKey->getOutputLength();
4704 if (pSignature == NULL_PTR)
4706 *pulSignatureLen = size;
4710 // Check buffer size
4711 if (*pulSignatureLen < size)
4713 *pulSignatureLen = size;
4714 return CKR_BUFFER_TOO_SMALL;
4717 // Get the signature
4718 ByteString signature;
4719 if (!asymCrypto->signFinal(signature))
4722 return CKR_GENERAL_ERROR;
4726 if (signature.size() != size)
4728 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4730 return CKR_GENERAL_ERROR;
4732 memcpy(pSignature, signature.byte_str(), size);
4733 *pulSignatureLen = size;
4739 // AsymmetricAlgorithm version of C_SignFinal
4740 static CK_RV AsymSignFinalHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4742 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4743 PrivateKey* privateKey = session->getPrivateKey();
4744 if (asymCrypto == NULL || privateKey == NULL)
4747 return CKR_OPERATION_NOT_INITIALIZED;
4750 // Check if re-authentication is required
4751 if (session->getReAuthentication())
4754 return CKR_USER_NOT_LOGGED_IN;
4757 // Size of the signature
4758 CK_ULONG size = privateKey->getOutputLength();
4759 if (pSignature == NULL_PTR)
4761 *pulSignatureLen = size;
4765 // Check buffer size
4766 if (*pulSignatureLen < size)
4768 *pulSignatureLen = size;
4769 return CKR_BUFFER_TOO_SMALL;
4772 // Get the signature
4773 ByteString signature;
4774 if (!asymCrypto->signFinal(signature))
4777 return CKR_GENERAL_ERROR;
4780 AsymMech::Type mechanism = session->getMechanism();
4781 // Extract HW key handle
4782 CK_ULONG hwKeyHandle = 0;
4783 CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4784 if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4786 LOG("ERROR in extracting key handle \n");
4788 return CKR_GENERAL_ERROR;
4790 LOG("Extracted key handle value : 0x%lx \n", hwKeyHandle);
4792 void *hwCryptoOpaque = session->getHwCryptoOpaque();
4794 if(HwInfraSignFinal((void *)&hwKeyHandle, mechanism,
4795 hwCryptoOpaque, pSignature, (int *) pulSignatureLen) != 0 )
4798 return CKR_GENERAL_ERROR;
4801 if (*pulSignatureLen != size)
4803 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4805 return CKR_GENERAL_ERROR;
4807 *pulSignatureLen = size;
4814 // Finalise a running signing operation and return the signature
4815 CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4817 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4819 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4822 Session* session = (Session*)handleManager->getSession(hSession);
4823 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4825 // Check if we are doing the correct operation
4826 if (session->getOpType() != SESSION_OP_SIGN || !session->getAllowMultiPartOp())
4827 return CKR_OPERATION_NOT_INITIALIZED;
4829 if (session->getMacOp() != NULL)
4830 return MacSignFinal(session, pSignature, pulSignatureLen);
4834 return AsymSignFinalHW(hSession, session, pSignature, pulSignatureLen);
4839 return AsymSignFinal(session, pSignature, pulSignatureLen);
4843 // Initialise a signing operation that allows recovery of the signed data
4844 CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
4846 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4849 Session* session = (Session*)handleManager->getSession(hSession);
4850 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4852 // Check if we have another operation
4853 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4855 return CKR_FUNCTION_NOT_SUPPORTED;
4858 // Perform a single part signing operation that allows recovery of the signed data
4859 CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pData*/, CK_ULONG /*ulDataLen*/, CK_BYTE_PTR /*pSignature*/, CK_ULONG_PTR /*pulSignatureLen*/)
4861 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4864 Session* session = (Session*)handleManager->getSession(hSession);
4865 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4867 return CKR_FUNCTION_NOT_SUPPORTED;
4870 // MacAlgorithm version of C_VerifyInit
4871 CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4873 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4875 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4878 Session* session = (Session*)handleManager->getSession(hSession);
4879 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4881 // Check if we have another operation
4882 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4885 Token* token = session->getToken();
4886 if (token == NULL) return CKR_GENERAL_ERROR;
4888 // Check the key handle.
4889 OSObject *key = (OSObject *)handleManager->getObject(hKey);
4890 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4892 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4893 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4895 // Check read user credentials
4896 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4899 if (rv == CKR_USER_NOT_LOGGED_IN)
4900 INFO_MSG("User is not authorized");
4905 // Check if key can be used for verifying
4906 if (!key->getBooleanValue(CKA_VERIFY, false))
4907 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4909 // Check if the specified mechanism is allowed for the key
4910 if (!isMechanismPermitted(key, pMechanism))
4911 return CKR_MECHANISM_INVALID;
4914 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
4916 // Get the MAC algorithm matching the mechanism
4917 // Also check mechanism constraints
4918 MacAlgo::Type algo = MacAlgo::Unknown;
4921 switch(pMechanism->mechanism) {
4924 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
4925 return CKR_KEY_TYPE_INCONSISTENT;
4927 algo = MacAlgo::HMAC_MD5;
4930 case CKM_SHA_1_HMAC:
4931 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
4932 return CKR_KEY_TYPE_INCONSISTENT;
4934 algo = MacAlgo::HMAC_SHA1;
4936 case CKM_SHA224_HMAC:
4937 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
4938 return CKR_KEY_TYPE_INCONSISTENT;
4940 algo = MacAlgo::HMAC_SHA224;
4942 case CKM_SHA256_HMAC:
4943 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
4944 return CKR_KEY_TYPE_INCONSISTENT;
4946 algo = MacAlgo::HMAC_SHA256;
4948 case CKM_SHA384_HMAC:
4949 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
4950 return CKR_KEY_TYPE_INCONSISTENT;
4952 algo = MacAlgo::HMAC_SHA384;
4954 case CKM_SHA512_HMAC:
4955 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
4956 return CKR_KEY_TYPE_INCONSISTENT;
4958 algo = MacAlgo::HMAC_SHA512;
4961 case CKM_GOSTR3411_HMAC:
4962 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
4963 return CKR_KEY_TYPE_INCONSISTENT;
4965 algo = MacAlgo::HMAC_GOST;
4969 if (keyType != CKK_DES2 && keyType != CKK_DES3)
4970 return CKR_KEY_TYPE_INCONSISTENT;
4971 algo = MacAlgo::CMAC_DES;
4975 if (keyType != CKK_AES)
4976 return CKR_KEY_TYPE_INCONSISTENT;
4977 algo = MacAlgo::CMAC_AES;
4980 return CKR_MECHANISM_INVALID;
4982 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
4983 if (mac == NULL) return CKR_MECHANISM_INVALID;
4985 SymmetricKey* pubkey = new SymmetricKey();
4987 if (getSymmetricKey(pubkey, token, key) != CKR_OK)
4989 mac->recycleKey(pubkey);
4990 CryptoFactory::i()->recycleMacAlgorithm(mac);
4991 return CKR_GENERAL_ERROR;
4994 // Adjust key bit length
4995 pubkey->setBitLen(pubkey->getKeyBits().size() * bb);
4998 if (pubkey->getBitLen() < (minSize*8))
5000 mac->recycleKey(pubkey);
5001 CryptoFactory::i()->recycleMacAlgorithm(mac);
5002 return CKR_KEY_SIZE_RANGE;
5005 // Initialize verifying
5006 if (!mac->verifyInit(pubkey))
5008 mac->recycleKey(pubkey);
5009 CryptoFactory::i()->recycleMacAlgorithm(mac);
5010 return CKR_MECHANISM_INVALID;
5013 session->setOpType(SESSION_OP_VERIFY);
5014 session->setMacOp(mac);
5015 session->setAllowMultiPartOp(true);
5016 session->setAllowSinglePartOp(true);
5017 session->setSymmetricKey(pubkey);
5022 // AsymmetricAlgorithm version of C_VerifyInit
5023 CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5025 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5027 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5030 Session* session = (Session*)handleManager->getSession(hSession);
5031 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5033 // Check if we have another operation
5034 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5037 Token* token = session->getToken();
5038 if (token == NULL) return CKR_GENERAL_ERROR;
5040 // Check the key handle.
5041 OSObject *key = (OSObject *)handleManager->getObject(hKey);
5042 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
5044 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
5045 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
5047 // Check read user credentials
5048 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
5051 if (rv == CKR_USER_NOT_LOGGED_IN)
5052 INFO_MSG("User is not authorized");
5057 // Check if key can be used for verifying
5058 if (!key->getBooleanValue(CKA_VERIFY, false))
5059 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5061 // Check if the specified mechanism is allowed for the key
5062 if (!isMechanismPermitted(key, pMechanism))
5063 return CKR_MECHANISM_INVALID;
5065 // Get the asymmetric algorithm matching the mechanism
5066 AsymMech::Type mechanism = AsymMech::Unknown;
5068 size_t paramLen = 0;
5069 RSA_PKCS_PSS_PARAMS pssParam;
5070 bool bAllowMultiPartOp;
5073 bool isECDSA = false;
5074 switch(pMechanism->mechanism) {
5076 mechanism = AsymMech::RSA_PKCS;
5077 bAllowMultiPartOp = false;
5081 mechanism = AsymMech::RSA;
5082 bAllowMultiPartOp = false;
5086 case CKM_MD5_RSA_PKCS:
5087 mechanism = AsymMech::RSA_MD5_PKCS;
5088 bAllowMultiPartOp = true;
5092 case CKM_SHA1_RSA_PKCS:
5093 mechanism = AsymMech::RSA_SHA1_PKCS;
5094 bAllowMultiPartOp = true;
5097 case CKM_SHA224_RSA_PKCS:
5098 mechanism = AsymMech::RSA_SHA224_PKCS;
5099 bAllowMultiPartOp = true;
5102 case CKM_SHA256_RSA_PKCS:
5103 mechanism = AsymMech::RSA_SHA256_PKCS;
5104 bAllowMultiPartOp = true;
5107 case CKM_SHA384_RSA_PKCS:
5108 mechanism = AsymMech::RSA_SHA384_PKCS;
5109 bAllowMultiPartOp = true;
5112 case CKM_SHA512_RSA_PKCS:
5113 mechanism = AsymMech::RSA_SHA512_PKCS;
5114 bAllowMultiPartOp = true;
5118 case CKM_RSA_PKCS_PSS:
5119 if (pMechanism->pParameter == NULL_PTR ||
5120 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
5122 ERROR_MSG("Invalid parameters");
5123 return CKR_ARGUMENTS_BAD;
5125 mechanism = AsymMech::RSA_PKCS_PSS;
5127 unsigned long expectedMgf;
5128 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
5130 pssParam.hashAlg = HashAlgo::SHA1;
5131 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
5132 expectedMgf = CKG_MGF1_SHA1;
5135 pssParam.hashAlg = HashAlgo::SHA224;
5136 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5137 expectedMgf = CKG_MGF1_SHA224;
5140 pssParam.hashAlg = HashAlgo::SHA256;
5141 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5142 expectedMgf = CKG_MGF1_SHA256;
5145 pssParam.hashAlg = HashAlgo::SHA384;
5146 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5147 expectedMgf = CKG_MGF1_SHA384;
5150 pssParam.hashAlg = HashAlgo::SHA512;
5151 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5152 expectedMgf = CKG_MGF1_SHA512;
5155 return CKR_ARGUMENTS_BAD;
5158 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != expectedMgf) {
5159 return CKR_ARGUMENTS_BAD;
5162 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5164 paramLen = sizeof(pssParam);
5165 bAllowMultiPartOp = false;
5169 case CKM_SHA1_RSA_PKCS_PSS:
5170 if (pMechanism->pParameter == NULL_PTR ||
5171 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5172 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
5173 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
5175 ERROR_MSG("Invalid parameters");
5176 return CKR_ARGUMENTS_BAD;
5178 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
5179 pssParam.hashAlg = HashAlgo::SHA1;
5180 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
5181 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5183 paramLen = sizeof(pssParam);
5184 bAllowMultiPartOp = true;
5187 case CKM_SHA224_RSA_PKCS_PSS:
5188 if (pMechanism->pParameter == NULL_PTR ||
5189 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5190 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
5191 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
5193 ERROR_MSG("Invalid parameters");
5194 return CKR_ARGUMENTS_BAD;
5196 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
5197 pssParam.hashAlg = HashAlgo::SHA224;
5198 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5199 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5201 paramLen = sizeof(pssParam);
5202 bAllowMultiPartOp = true;
5205 case CKM_SHA256_RSA_PKCS_PSS:
5206 if (pMechanism->pParameter == NULL_PTR ||
5207 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5208 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
5209 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
5211 ERROR_MSG("Invalid parameters");
5212 return CKR_ARGUMENTS_BAD;
5214 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
5215 pssParam.hashAlg = HashAlgo::SHA256;
5216 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5217 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5219 paramLen = sizeof(pssParam);
5220 bAllowMultiPartOp = true;
5223 case CKM_SHA384_RSA_PKCS_PSS:
5224 if (pMechanism->pParameter == NULL_PTR ||
5225 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5226 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
5227 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
5229 ERROR_MSG("Invalid parameters");
5230 return CKR_ARGUMENTS_BAD;
5232 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
5233 pssParam.hashAlg = HashAlgo::SHA384;
5234 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5235 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5237 paramLen = sizeof(pssParam);
5238 bAllowMultiPartOp = true;
5241 case CKM_SHA512_RSA_PKCS_PSS:
5242 if (pMechanism->pParameter == NULL_PTR ||
5243 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5244 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
5245 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
5247 ERROR_MSG("Invalid parameters");
5248 return CKR_ARGUMENTS_BAD;
5250 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
5251 pssParam.hashAlg = HashAlgo::SHA512;
5252 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5253 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5255 paramLen = sizeof(pssParam);
5256 bAllowMultiPartOp = true;
5260 mechanism = AsymMech::DSA;
5261 bAllowMultiPartOp = false;
5265 mechanism = AsymMech::DSA_SHA1;
5266 bAllowMultiPartOp = true;
5269 case CKM_DSA_SHA224:
5270 mechanism = AsymMech::DSA_SHA224;
5271 bAllowMultiPartOp = true;
5274 case CKM_DSA_SHA256:
5275 mechanism = AsymMech::DSA_SHA256;
5276 bAllowMultiPartOp = true;
5279 case CKM_DSA_SHA384:
5280 mechanism = AsymMech::DSA_SHA384;
5281 bAllowMultiPartOp = true;
5284 case CKM_DSA_SHA512:
5285 mechanism = AsymMech::DSA_SHA512;
5286 bAllowMultiPartOp = true;
5291 mechanism = AsymMech::ECDSA;
5292 bAllowMultiPartOp = false;
5298 mechanism = AsymMech::GOST;
5299 bAllowMultiPartOp = false;
5301 case CKM_GOSTR3410_WITH_GOSTR3411:
5302 mechanism = AsymMech::GOST_GOST;
5303 bAllowMultiPartOp = true;
5307 return CKR_MECHANISM_INVALID;
5310 AsymmetricAlgorithm* asymCrypto = NULL;
5311 PublicKey* publicKey = NULL;
5314 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
5315 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5317 publicKey = asymCrypto->newPublicKey();
5318 if (publicKey == NULL)
5320 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5321 return CKR_HOST_MEMORY;
5324 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
5326 asymCrypto->recyclePublicKey(publicKey);
5327 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5328 return CKR_GENERAL_ERROR;
5333 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
5334 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5336 publicKey = asymCrypto->newPublicKey();
5337 if (publicKey == NULL)
5339 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5340 return CKR_HOST_MEMORY;
5343 if (getDSAPublicKey((DSAPublicKey*)publicKey, token, key) != CKR_OK)
5345 asymCrypto->recyclePublicKey(publicKey);
5346 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5347 return CKR_GENERAL_ERROR;
5353 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
5354 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5356 publicKey = asymCrypto->newPublicKey();
5357 if (publicKey == NULL)
5359 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5360 return CKR_HOST_MEMORY;
5363 if (getECPublicKey((ECPublicKey*)publicKey, token, key) != CKR_OK)
5365 asymCrypto->recyclePublicKey(publicKey);
5366 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5367 return CKR_GENERAL_ERROR;
5374 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
5375 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5377 publicKey = asymCrypto->newPublicKey();
5378 if (publicKey == NULL)
5380 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5381 return CKR_HOST_MEMORY;
5384 if (getGOSTPublicKey((GOSTPublicKey*)publicKey, token, key) != CKR_OK)
5386 asymCrypto->recyclePublicKey(publicKey);
5387 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5388 return CKR_GENERAL_ERROR;
5391 return CKR_MECHANISM_INVALID;
5395 // Initialize verifying
5396 if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))
5398 asymCrypto->recyclePublicKey(publicKey);
5399 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5400 return CKR_MECHANISM_INVALID;
5403 session->setOpType(SESSION_OP_VERIFY);
5404 session->setAsymmetricCryptoOp(asymCrypto);
5405 session->setMechanism(mechanism);
5406 session->setParameters(param, paramLen);
5407 session->setAllowMultiPartOp(bAllowMultiPartOp);
5408 session->setAllowSinglePartOp(true);
5409 session->setPublicKey(publicKey);
5414 // Initialise a verification operation using the specified key and mechanism
5415 CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5417 if (isMacMechanism(pMechanism))
5418 return MacVerifyInit(hSession, pMechanism, hKey);
5420 return AsymVerifyInit(hSession, pMechanism, hKey);
5423 // MacAlgorithm version of C_Verify
5424 static CK_RV MacVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5426 MacAlgorithm* mac = session->getMacOp();
5427 if (mac == NULL || !session->getAllowSinglePartOp())
5430 return CKR_OPERATION_NOT_INITIALIZED;
5433 // Size of the signature
5434 CK_ULONG size = mac->getMacSize();
5436 // Check buffer size
5437 if (ulSignatureLen != size)
5439 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5441 return CKR_SIGNATURE_LEN_RANGE;
5445 ByteString data(pData, ulDataLen);
5448 if (!mac->verifyUpdate(data))
5451 return CKR_GENERAL_ERROR;
5454 // Get the signature
5455 ByteString signature(pSignature, ulSignatureLen);
5457 // Verify the signature
5458 if (!mac->verifyFinal(signature))
5461 return CKR_SIGNATURE_INVALID;
5468 // AsymmetricAlgorithm version of C_Verify
5469 static CK_RV AsymVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5471 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5472 AsymMech::Type mechanism = session->getMechanism();
5473 PublicKey* publicKey = session->getPublicKey();
5475 void* param = session->getParameters(paramLen);
5476 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
5479 return CKR_OPERATION_NOT_INITIALIZED;
5482 // Size of the signature
5483 CK_ULONG size = publicKey->getOutputLength();
5485 // Check buffer size
5486 if (ulSignatureLen != size)
5488 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5490 return CKR_SIGNATURE_LEN_RANGE;
5496 // We must allow input length <= k and therfore need to prepend the data with zeroes.
5497 if (mechanism == AsymMech::RSA) {
5498 data.wipe(size-ulDataLen);
5501 data += ByteString(pData, ulDataLen);
5502 ByteString signature(pSignature, ulSignatureLen);
5505 if (session->getAllowMultiPartOp())
5507 if (!asymCrypto->verifyUpdate(data) ||
5508 !asymCrypto->verifyFinal(signature))
5511 return CKR_SIGNATURE_INVALID;
5514 else if (!asymCrypto->verify(publicKey,data,signature,mechanism,param,paramLen))
5517 return CKR_SIGNATURE_INVALID;
5524 // Perform a single pass verification operation
5525 CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5527 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5529 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
5530 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5533 Session* session = (Session*)handleManager->getSession(hSession);
5534 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5536 // Check if we are doing the correct operation
5537 if (session->getOpType() != SESSION_OP_VERIFY)
5538 return CKR_OPERATION_NOT_INITIALIZED;
5540 if (session->getMacOp() != NULL)
5541 return MacVerify(session, pData, ulDataLen,
5542 pSignature, ulSignatureLen);
5544 return AsymVerify(session, pData, ulDataLen,
5545 pSignature, ulSignatureLen);
5548 // MacAlgorithm version of C_VerifyUpdate
5549 static CK_RV MacVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5551 MacAlgorithm* mac = session->getMacOp();
5552 if (mac == NULL || !session->getAllowMultiPartOp())
5555 return CKR_OPERATION_NOT_INITIALIZED;
5559 ByteString part(pPart, ulPartLen);
5562 if (!mac->verifyUpdate(part))
5564 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5566 return CKR_GENERAL_ERROR;
5569 session->setAllowSinglePartOp(false);
5573 // AsymmetricAlgorithm version of C_VerifyUpdate
5574 static CK_RV AsymVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5576 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5577 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
5580 return CKR_OPERATION_NOT_INITIALIZED;
5584 ByteString part(pPart, ulPartLen);
5587 if (!asymCrypto->verifyUpdate(part))
5589 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5591 return CKR_GENERAL_ERROR;
5594 session->setAllowSinglePartOp(false);
5598 // Update a running verification operation with additional data
5599 CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5601 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5603 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
5606 Session* session = (Session*)handleManager->getSession(hSession);
5607 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5609 // Check if we are doing the correct operation
5610 if (session->getOpType() != SESSION_OP_VERIFY)
5611 return CKR_OPERATION_NOT_INITIALIZED;
5613 if (session->getMacOp() != NULL)
5614 return MacVerifyUpdate(session, pPart, ulPartLen);
5616 return AsymVerifyUpdate(session, pPart, ulPartLen);
5619 // MacAlgorithm version of C_SignFinal
5620 static CK_RV MacVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5622 MacAlgorithm* mac = session->getMacOp();
5626 return CKR_OPERATION_NOT_INITIALIZED;
5629 // Size of the signature
5630 CK_ULONG size = mac->getMacSize();
5632 // Check buffer size
5633 if (ulSignatureLen != size)
5635 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5637 return CKR_SIGNATURE_LEN_RANGE;
5640 // Get the signature
5641 ByteString signature(pSignature, ulSignatureLen);
5644 if (!mac->verifyFinal(signature))
5647 return CKR_SIGNATURE_INVALID;
5654 // AsymmetricAlgorithm version of C_VerifyFinal
5655 static CK_RV AsymVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5657 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5658 PublicKey* publicKey = session->getPublicKey();
5659 if (asymCrypto == NULL || publicKey == NULL)
5662 return CKR_OPERATION_NOT_INITIALIZED;
5665 // Size of the signature
5666 CK_ULONG size = publicKey->getOutputLength();
5668 // Check buffer size
5669 if (ulSignatureLen != size)
5671 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5673 return CKR_SIGNATURE_LEN_RANGE;
5677 ByteString signature(pSignature, ulSignatureLen);
5680 if (!asymCrypto->verifyFinal(signature))
5683 return CKR_SIGNATURE_INVALID;
5690 // Finalise the verification operation and check the signature
5691 CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5693 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5695 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5698 Session* session = (Session*)handleManager->getSession(hSession);
5699 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5701 // Check if we are doing the correct operation
5702 if (session->getOpType() != SESSION_OP_VERIFY || !session->getAllowMultiPartOp())
5703 return CKR_OPERATION_NOT_INITIALIZED;
5705 if (session->getMacOp() != NULL)
5706 return MacVerifyFinal(session, pSignature, ulSignatureLen);
5708 return AsymVerifyFinal(session, pSignature, ulSignatureLen);
5711 // Initialise a verification operation the allows recovery of the signed data from the signature
5712 CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
5714 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5717 Session* session = (Session*)handleManager->getSession(hSession);
5718 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5720 // Check if we have another operation
5721 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5723 return CKR_FUNCTION_NOT_SUPPORTED;
5726 // Perform a single part verification operation and recover the signed data
5727 CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pSignature*/, CK_ULONG /*ulSignatureLen*/, CK_BYTE_PTR /*pData*/, CK_ULONG_PTR /*pulDataLen*/)
5729 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5732 Session* session = (Session*)handleManager->getSession(hSession);
5733 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5735 return CKR_FUNCTION_NOT_SUPPORTED;
5738 // Update a running multi-part encryption and digesting operation
5739 CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5741 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5744 Session* session = (Session*)handleManager->getSession(hSession);
5745 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5747 return CKR_FUNCTION_NOT_SUPPORTED;
5750 // Update a running multi-part decryption and digesting operation
5751 CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pDecryptedPart*/, CK_ULONG_PTR /*pulDecryptedPartLen*/)
5753 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5756 Session* session = (Session*)handleManager->getSession(hSession);
5757 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5759 return CKR_FUNCTION_NOT_SUPPORTED;
5762 // Update a running multi-part signing and encryption operation
5763 CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5765 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5768 Session* session = (Session*)handleManager->getSession(hSession);
5769 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5771 return CKR_FUNCTION_NOT_SUPPORTED;
5774 // Update a running multi-part decryption and verification operation
5775 CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG /*ulEncryptedPartLen*/, CK_BYTE_PTR /*pPart*/, CK_ULONG_PTR /*pulPartLen*/)
5777 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5780 Session* session = (Session*)handleManager->getSession(hSession);
5781 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5783 return CKR_FUNCTION_NOT_SUPPORTED;
5786 // Generate a secret key or a domain parameter set using the specified mechanism
5787 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)
5789 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5791 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5792 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5795 Session* session = (Session*)handleManager->getSession(hSession);
5796 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5798 // Check the mechanism, only accept DSA and DH parameters
5799 // and symmetric ciphers
5800 CK_OBJECT_CLASS objClass;
5801 CK_KEY_TYPE keyType;
5802 switch (pMechanism->mechanism)
5804 case CKM_DSA_PARAMETER_GEN:
5805 objClass = CKO_DOMAIN_PARAMETERS;
5808 case CKM_DH_PKCS_PARAMETER_GEN:
5809 objClass = CKO_DOMAIN_PARAMETERS;
5813 case CKM_DES_KEY_GEN:
5814 objClass = CKO_SECRET_KEY;
5818 case CKM_DES2_KEY_GEN:
5819 objClass = CKO_SECRET_KEY;
5822 case CKM_DES3_KEY_GEN:
5823 objClass = CKO_SECRET_KEY;
5826 case CKM_AES_KEY_GEN:
5827 objClass = CKO_SECRET_KEY;
5831 return CKR_MECHANISM_INVALID;
5834 // Extract information from the template that is needed to create the object.
5835 CK_BBOOL isOnToken = CK_FALSE;
5836 CK_BBOOL isPrivate = CK_TRUE;
5837 CK_CERTIFICATE_TYPE dummy;
5838 bool isImplicit = true;
5839 extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
5841 // Report errors and/or unexpected usage.
5842 if (objClass != CKO_SECRET_KEY && objClass != CKO_DOMAIN_PARAMETERS)
5843 return CKR_ATTRIBUTE_VALUE_INVALID;
5844 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN &&
5845 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DSA))
5846 return CKR_TEMPLATE_INCONSISTENT;
5847 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN &&
5848 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DH))
5849 return CKR_TEMPLATE_INCONSISTENT;
5850 if (pMechanism->mechanism == CKM_DES_KEY_GEN &&
5851 (objClass != CKO_SECRET_KEY || keyType != CKK_DES))
5852 return CKR_TEMPLATE_INCONSISTENT;
5853 if (pMechanism->mechanism == CKM_DES2_KEY_GEN &&
5854 (objClass != CKO_SECRET_KEY || keyType != CKK_DES2))
5855 return CKR_TEMPLATE_INCONSISTENT;
5856 if (pMechanism->mechanism == CKM_DES3_KEY_GEN &&
5857 (objClass != CKO_SECRET_KEY || keyType != CKK_DES3))
5858 return CKR_TEMPLATE_INCONSISTENT;
5859 if (pMechanism->mechanism == CKM_AES_KEY_GEN &&
5860 (objClass != CKO_SECRET_KEY || keyType != CKK_AES))
5861 return CKR_TEMPLATE_INCONSISTENT;
5863 // Check authorization
5864 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
5867 if (rv == CKR_USER_NOT_LOGGED_IN)
5868 INFO_MSG("User is not authorized");
5869 if (rv == CKR_SESSION_READ_ONLY)
5870 INFO_MSG("Session is read-only");
5875 // Generate DSA domain parameters
5876 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN)
5878 return this->generateDSAParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5881 // Generate DH domain parameters
5882 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN)
5884 return this->generateDHParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5887 // Generate DES secret key
5888 if (pMechanism->mechanism == CKM_DES_KEY_GEN)
5890 return this->generateDES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5893 // Generate DES2 secret key
5894 if (pMechanism->mechanism == CKM_DES2_KEY_GEN)
5896 return this->generateDES2(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5899 // Generate DES3 secret key
5900 if (pMechanism->mechanism == CKM_DES3_KEY_GEN)
5902 return this->generateDES3(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5905 // Generate AES secret key
5906 if (pMechanism->mechanism == CKM_AES_KEY_GEN)
5908 return this->generateAES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5911 return CKR_GENERAL_ERROR;
5914 // Generate a key-pair using the specified mechanism
5915 CK_RV SoftHSM::C_GenerateKeyPair
5917 CK_SESSION_HANDLE hSession,
5918 CK_MECHANISM_PTR pMechanism,
5919 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5920 CK_ULONG ulPublicKeyAttributeCount,
5921 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5922 CK_ULONG ulPrivateKeyAttributeCount,
5923 CK_OBJECT_HANDLE_PTR phPublicKey,
5924 CK_OBJECT_HANDLE_PTR phPrivateKey
5927 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5929 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5930 if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5931 if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5934 Session* session = (Session*)handleManager->getSession(hSession);
5935 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5937 // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation.
5938 CK_KEY_TYPE keyType;
5939 switch (pMechanism->mechanism)
5941 case CKM_RSA_PKCS_KEY_PAIR_GEN:
5944 case CKM_DSA_KEY_PAIR_GEN:
5947 case CKM_DH_PKCS_KEY_PAIR_GEN:
5951 case CKM_EC_KEY_PAIR_GEN:
5956 case CKM_GOSTR3410_KEY_PAIR_GEN:
5957 keyType = CKK_GOSTR3410;
5961 return CKR_MECHANISM_INVALID;
5963 CK_CERTIFICATE_TYPE dummy;
5965 // Extract information from the public key template that is needed to create the object.
5966 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
5967 CK_BBOOL ispublicKeyToken = CK_FALSE;
5968 CK_BBOOL ispublicKeyPrivate = CK_FALSE;
5969 bool isPublicKeyImplicit = true;
5970 extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate, isPublicKeyImplicit);
5972 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5973 if (publicKeyClass != CKO_PUBLIC_KEY)
5974 return CKR_ATTRIBUTE_VALUE_INVALID;
5975 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5976 return CKR_TEMPLATE_INCONSISTENT;
5977 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5978 return CKR_TEMPLATE_INCONSISTENT;
5979 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5980 return CKR_TEMPLATE_INCONSISTENT;
5981 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5982 return CKR_TEMPLATE_INCONSISTENT;
5983 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5984 return CKR_TEMPLATE_INCONSISTENT;
5986 // Extract information from the private key template that is needed to create the object.
5987 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
5988 CK_BBOOL isprivateKeyToken = CK_FALSE;
5989 CK_BBOOL isprivateKeyPrivate = CK_TRUE;
5990 bool isPrivateKeyImplicit = true;
5991 extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit);
5993 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5994 if (privateKeyClass != CKO_PRIVATE_KEY)
5995 return CKR_ATTRIBUTE_VALUE_INVALID;
5996 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5997 return CKR_TEMPLATE_INCONSISTENT;
5998 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5999 return CKR_TEMPLATE_INCONSISTENT;
6000 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
6001 return CKR_TEMPLATE_INCONSISTENT;
6002 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
6003 return CKR_TEMPLATE_INCONSISTENT;
6004 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
6005 return CKR_TEMPLATE_INCONSISTENT;
6007 // Check user credentials
6008 CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
6011 if (rv == CKR_USER_NOT_LOGGED_IN)
6012 INFO_MSG("User is not authorized");
6013 if (rv == CKR_SESSION_READ_ONLY)
6014 INFO_MSG("Session is read-only");
6019 // Generate RSA keys
6020 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
6022 return this->generateRSA(hSession,
6023 pPublicKeyTemplate, ulPublicKeyAttributeCount,
6024 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6025 phPublicKey, phPrivateKey,
6026 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6029 // Generate DSA keys
6030 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
6032 return this->generateDSA(hSession,
6033 pPublicKeyTemplate, ulPublicKeyAttributeCount,
6034 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6035 phPublicKey, phPrivateKey,
6036 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6040 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
6042 return this->generateEC(hSession,
6043 pPublicKeyTemplate, ulPublicKeyAttributeCount,
6044 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6045 phPublicKey, phPrivateKey,
6046 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6050 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN)
6052 return this->generateDH(hSession,
6053 pPublicKeyTemplate, ulPublicKeyAttributeCount,
6054 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6055 phPublicKey, phPrivateKey,
6056 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6059 // Generate GOST keys
6060 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
6062 return this->generateGOST(hSession,
6063 pPublicKeyTemplate, ulPublicKeyAttributeCount,
6064 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6065 phPublicKey, phPrivateKey,
6066 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6069 return CKR_GENERAL_ERROR;
6072 // Internal: Wrap blob using symmetric key
6073 CK_RV SoftHSM::WrapKeySym
6075 CK_MECHANISM_PTR pMechanism,
6078 ByteString& keydata,
6082 // Get the symmetric algorithm matching the mechanism
6083 SymAlgo::Type algo = SymAlgo::Unknown;
6084 SymWrap::Type mode = SymWrap::Unknown;
6086 #ifdef HAVE_AES_KEY_WRAP
6087 CK_ULONG wrappedlen = keydata.size();
6089 // [PKCS#11 v2.40, 2.14.3 AES Key Wrap]
6090 // A key whose length is not a multiple of the AES Key Wrap block
6091 // size (8 bytes) will be zero padded to fit.
6092 CK_ULONG alignment = wrappedlen % 8;
6095 keydata.resize(wrappedlen + 8 - alignment);
6096 memset(&keydata[wrappedlen], 0, 8 - alignment);
6097 wrappedlen = keydata.size();
6100 switch(pMechanism->mechanism) {
6101 #ifdef HAVE_AES_KEY_WRAP
6102 case CKM_AES_KEY_WRAP:
6103 if ((wrappedlen < 16) || ((wrappedlen % 8) != 0))
6104 return CKR_KEY_SIZE_RANGE;
6105 algo = SymAlgo::AES;
6106 mode = SymWrap::AES_KEYWRAP;
6109 #ifdef HAVE_AES_KEY_WRAP_PAD
6110 case CKM_AES_KEY_WRAP_PAD:
6111 algo = SymAlgo::AES;
6112 mode = SymWrap::AES_KEYWRAP_PAD;
6116 return CKR_MECHANISM_INVALID;
6118 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6119 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6121 SymmetricKey* wrappingkey = new SymmetricKey();
6123 if (getSymmetricKey(wrappingkey, token, wrapKey) != CKR_OK)
6125 cipher->recycleKey(wrappingkey);
6126 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6127 return CKR_GENERAL_ERROR;
6130 // adjust key bit length
6131 wrappingkey->setBitLen(wrappingkey->getKeyBits().size() * bb);
6134 if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped))
6136 cipher->recycleKey(wrappingkey);
6137 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6138 return CKR_GENERAL_ERROR;
6141 cipher->recycleKey(wrappingkey);
6142 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6146 // Internal: Wrap blob using asymmetric key
6147 CK_RV SoftHSM::WrapKeyAsym
6149 CK_MECHANISM_PTR pMechanism,
6152 ByteString& keydata,
6156 const size_t bb = 8;
6157 AsymAlgo::Type algo = AsymAlgo::Unknown;
6158 AsymMech::Type mech = AsymMech::Unknown;
6160 CK_ULONG modulus_length;
6161 switch(pMechanism->mechanism) {
6163 case CKM_RSA_PKCS_OAEP:
6164 algo = AsymAlgo::RSA;
6165 if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
6166 return CKR_GENERAL_ERROR;
6167 modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
6168 // adjust key bit length
6169 modulus_length /= bb;
6173 return CKR_MECHANISM_INVALID;
6176 switch(pMechanism->mechanism) {
6178 mech = AsymMech::RSA_PKCS;
6179 // RFC 3447 section 7.2.1
6180 if (keydata.size() > modulus_length - 11)
6181 return CKR_KEY_SIZE_RANGE;
6184 case CKM_RSA_PKCS_OAEP:
6185 mech = AsymMech::RSA_PKCS_OAEP;
6186 // SHA-1 is the only supported option
6187 // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
6188 if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
6189 return CKR_KEY_SIZE_RANGE;
6193 return CKR_MECHANISM_INVALID;
6196 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6197 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6199 PublicKey* publicKey = cipher->newPublicKey();
6200 if (publicKey == NULL)
6202 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6203 return CKR_HOST_MEMORY;
6206 switch(pMechanism->mechanism) {
6208 case CKM_RSA_PKCS_OAEP:
6209 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
6211 cipher->recyclePublicKey(publicKey);
6212 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6213 return CKR_GENERAL_ERROR;
6218 return CKR_MECHANISM_INVALID;
6221 if (!cipher->wrapKey(publicKey, keydata, wrapped, mech))
6223 cipher->recyclePublicKey(publicKey);
6224 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6225 return CKR_GENERAL_ERROR;
6228 cipher->recyclePublicKey(publicKey);
6229 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6235 // Wrap the specified key using the specified wrapping key and mechanism
6236 CK_RV SoftHSM::C_WrapKey
6238 CK_SESSION_HANDLE hSession,
6239 CK_MECHANISM_PTR pMechanism,
6240 CK_OBJECT_HANDLE hWrappingKey,
6241 CK_OBJECT_HANDLE hKey,
6242 CK_BYTE_PTR pWrappedKey,
6243 CK_ULONG_PTR pulWrappedKeyLen
6246 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6248 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6249 if (pulWrappedKeyLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
6252 Session* session = (Session*)handleManager->getSession(hSession);
6253 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6256 // Check the mechanism, only accept advanced AES key wrapping and RSA
6257 switch(pMechanism->mechanism)
6259 #ifdef HAVE_AES_KEY_WRAP
6260 case CKM_AES_KEY_WRAP:
6262 #ifdef HAVE_AES_KEY_WRAP_PAD
6263 case CKM_AES_KEY_WRAP_PAD:
6266 // Does not handle optional init vector
6267 if (pMechanism->pParameter != NULL_PTR ||
6268 pMechanism->ulParameterLen != 0)
6269 return CKR_ARGUMENTS_BAD;
6271 case CKM_RSA_PKCS_OAEP:
6272 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6278 return CKR_MECHANISM_INVALID;
6282 Token* token = session->getToken();
6283 if (token == NULL) return CKR_GENERAL_ERROR;
6285 // Check the wrapping key handle.
6286 OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
6287 if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
6289 CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
6290 CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
6292 // Check user credentials for the wrapping key
6293 rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
6296 if (rv == CKR_USER_NOT_LOGGED_IN)
6297 INFO_MSG("User is not authorized");
6302 // Check wrapping key class and type
6303 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6304 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6305 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
6306 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6307 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6308 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6309 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6310 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6311 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6312 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6314 // Check if the wrapping key can be used for wrapping
6315 if (wrapKey->getBooleanValue(CKA_WRAP, false) == false)
6316 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6318 // Check if the specified mechanism is allowed for the wrapping key
6319 if (!isMechanismPermitted(wrapKey, pMechanism))
6320 return CKR_MECHANISM_INVALID;
6322 // Check the to be wrapped key handle.
6323 OSObject *key = (OSObject *)handleManager->getObject(hKey);
6324 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
6326 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6327 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6329 // Check user credentials for the to be wrapped key
6330 rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6333 if (rv == CKR_USER_NOT_LOGGED_IN)
6334 INFO_MSG("User is not authorized");
6339 // Check if the to be wrapped key can be wrapped
6340 if (key->getBooleanValue(CKA_EXTRACTABLE, false) == false)
6341 return CKR_KEY_UNEXTRACTABLE;
6342 if (key->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false) && wrapKey->getBooleanValue(CKA_TRUSTED, false) == false)
6343 return CKR_KEY_NOT_WRAPPABLE;
6346 CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6347 if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
6348 return CKR_KEY_NOT_WRAPPABLE;
6349 // 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
6350 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
6351 return CKR_KEY_NOT_WRAPPABLE;
6353 // Verify the wrap template attribute
6354 if (wrapKey->attributeExists(CKA_WRAP_TEMPLATE))
6356 OSAttribute attr = wrapKey->getAttribute(CKA_WRAP_TEMPLATE);
6358 if (attr.isAttributeMapAttribute())
6360 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6362 const attrmap_type& map = attr.getAttributeMapValue();
6364 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6366 if (!key->attributeExists(it->first))
6368 return CKR_KEY_NOT_WRAPPABLE;
6371 OSAttribute keyAttr = key->getAttribute(it->first);
6373 if (!keyAttr.peekValue(v1) || !it->second.peekValue(v2) || (v1 != v2))
6375 return CKR_KEY_NOT_WRAPPABLE;
6381 // Get the key data to encrypt
6383 if (keyClass == CKO_SECRET_KEY)
6387 bool bOK = token->decrypt(key->getByteStringValue(CKA_VALUE), keydata);
6388 if (!bOK) return CKR_GENERAL_ERROR;
6392 keydata = key->getByteStringValue(CKA_VALUE);
6397 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6398 AsymAlgo::Type alg = AsymAlgo::Unknown;
6401 alg = AsymAlgo::RSA;
6404 alg = AsymAlgo::DSA;
6411 // can be ecdh too but it doesn't matter
6412 alg = AsymAlgo::ECDSA;
6417 alg = AsymAlgo::GOST;
6421 return CKR_KEY_NOT_WRAPPABLE;
6423 AsymmetricAlgorithm* asymCrypto = NULL;
6424 PrivateKey* privateKey = NULL;
6425 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6426 if (asymCrypto == NULL)
6427 return CKR_GENERAL_ERROR;
6428 privateKey = asymCrypto->newPrivateKey();
6429 if (privateKey == NULL)
6431 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6432 return CKR_HOST_MEMORY;
6436 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6439 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6442 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6446 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6451 rv = getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key);
6457 asymCrypto->recyclePrivateKey(privateKey);
6458 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6459 return CKR_GENERAL_ERROR;
6461 keydata = privateKey->PKCS8Encode();
6462 asymCrypto->recyclePrivateKey(privateKey);
6463 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6465 if (keydata.size() == 0)
6466 return CKR_KEY_NOT_WRAPPABLE;
6468 keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6470 if (keyClass == CKO_SECRET_KEY)
6471 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6473 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6477 if (pWrappedKey != NULL) {
6478 if (*pulWrappedKeyLen >= wrapped.size())
6479 memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6481 rv = CKR_BUFFER_TOO_SMALL;
6484 *pulWrappedKeyLen = wrapped.size();
6488 // Internal: Unwrap blob using symmetric key
6489 CK_RV SoftHSM::UnwrapKeySym
6491 CK_MECHANISM_PTR pMechanism,
6492 ByteString& wrapped,
6494 OSObject* unwrapKey,
6498 // Get the symmetric algorithm matching the mechanism
6499 SymAlgo::Type algo = SymAlgo::Unknown;
6500 SymWrap::Type mode = SymWrap::Unknown;
6502 switch(pMechanism->mechanism) {
6503 #ifdef HAVE_AES_KEY_WRAP
6504 case CKM_AES_KEY_WRAP:
6505 algo = SymAlgo::AES;
6506 mode = SymWrap::AES_KEYWRAP;
6509 #ifdef HAVE_AES_KEY_WRAP_PAD
6510 case CKM_AES_KEY_WRAP_PAD:
6511 algo = SymAlgo::AES;
6512 mode = SymWrap::AES_KEYWRAP_PAD;
6516 return CKR_MECHANISM_INVALID;
6518 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6519 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6521 SymmetricKey* unwrappingkey = new SymmetricKey();
6523 if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6525 cipher->recycleKey(unwrappingkey);
6526 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6527 return CKR_GENERAL_ERROR;
6530 // adjust key bit length
6531 unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6535 if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6536 rv = CKR_GENERAL_ERROR;
6537 cipher->recycleKey(unwrappingkey);
6538 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6542 // Internal: Unwrap blob using asymmetric key
6543 CK_RV SoftHSM::UnwrapKeyAsym
6545 CK_MECHANISM_PTR pMechanism,
6546 ByteString& wrapped,
6548 OSObject* unwrapKey,
6552 // Get the symmetric algorithm matching the mechanism
6553 AsymAlgo::Type algo = AsymAlgo::Unknown;
6554 AsymMech::Type mode = AsymMech::Unknown;
6555 switch(pMechanism->mechanism) {
6557 algo = AsymAlgo::RSA;
6558 mode = AsymMech::RSA_PKCS;
6561 case CKM_RSA_PKCS_OAEP:
6562 algo = AsymAlgo::RSA;
6563 mode = AsymMech::RSA_PKCS_OAEP;
6567 return CKR_MECHANISM_INVALID;
6569 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6570 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6572 PrivateKey* unwrappingkey = cipher->newPrivateKey();
6573 if (unwrappingkey == NULL)
6575 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6576 return CKR_HOST_MEMORY;
6579 switch(pMechanism->mechanism) {
6581 case CKM_RSA_PKCS_OAEP:
6582 if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6584 cipher->recyclePrivateKey(unwrappingkey);
6585 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6586 return CKR_GENERAL_ERROR;
6591 return CKR_MECHANISM_INVALID;
6596 if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6597 rv = CKR_GENERAL_ERROR;
6598 cipher->recyclePrivateKey(unwrappingkey);
6599 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6603 // Unwrap the specified key using the specified unwrapping key
6604 CK_RV SoftHSM::C_UnwrapKey
6606 CK_SESSION_HANDLE hSession,
6607 CK_MECHANISM_PTR pMechanism,
6608 CK_OBJECT_HANDLE hUnwrappingKey,
6609 CK_BYTE_PTR pWrappedKey,
6610 CK_ULONG ulWrappedKeyLen,
6611 CK_ATTRIBUTE_PTR pTemplate,
6613 CK_OBJECT_HANDLE_PTR hKey
6616 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6618 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6619 if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6620 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6621 if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6624 Session* session = (Session*)handleManager->getSession(hSession);
6625 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6628 // Check the mechanism
6629 switch(pMechanism->mechanism)
6631 #ifdef HAVE_AES_KEY_WRAP
6632 case CKM_AES_KEY_WRAP:
6633 if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
6634 return CKR_WRAPPED_KEY_LEN_RANGE;
6635 // Does not handle optional init vector
6636 if (pMechanism->pParameter != NULL_PTR ||
6637 pMechanism->ulParameterLen != 0)
6638 return CKR_ARGUMENTS_BAD;
6641 #ifdef HAVE_AES_KEY_WRAP_PAD
6642 case CKM_AES_KEY_WRAP_PAD:
6643 if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6644 return CKR_WRAPPED_KEY_LEN_RANGE;
6645 // Does not handle optional init vector
6646 if (pMechanism->pParameter != NULL_PTR ||
6647 pMechanism->ulParameterLen != 0)
6648 return CKR_ARGUMENTS_BAD;
6652 // Input length checks needs to be done later when unwrapping key is known
6654 case CKM_RSA_PKCS_OAEP:
6655 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6661 return CKR_MECHANISM_INVALID;
6665 Token* token = session->getToken();
6666 if (token == NULL) return CKR_GENERAL_ERROR;
6668 // Check the unwrapping key handle.
6669 OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6670 if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6672 CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6673 CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6675 // Check user credentials
6676 rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6679 if (rv == CKR_USER_NOT_LOGGED_IN)
6680 INFO_MSG("User is not authorized");
6685 // Check unwrapping key class and type
6686 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6687 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6688 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6689 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6690 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6691 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6692 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6693 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6694 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6695 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6697 // Check if the unwrapping key can be used for unwrapping
6698 if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6699 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6701 // Check if the specified mechanism is allowed for the unwrap key
6702 if (!isMechanismPermitted(unwrapKey, pMechanism))
6703 return CKR_MECHANISM_INVALID;
6705 // Extract information from the template that is needed to create the object.
6706 CK_OBJECT_CLASS objClass;
6707 CK_KEY_TYPE keyType;
6708 CK_BBOOL isOnToken = CK_FALSE;
6709 CK_BBOOL isPrivate = CK_TRUE;
6710 CK_CERTIFICATE_TYPE dummy;
6711 bool isImplicit = false;
6712 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6715 ERROR_MSG("Mandatory attribute not present in template");
6719 // Report errors and/or unexpected usage.
6720 if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6721 return CKR_ATTRIBUTE_VALUE_INVALID;
6722 // Key type will be handled at object creation
6724 // Check authorization
6725 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6728 if (rv == CKR_USER_NOT_LOGGED_IN)
6729 INFO_MSG("User is not authorized");
6730 if (rv == CKR_SESSION_READ_ONLY)
6731 INFO_MSG("Session is read-only");
6736 // Build unwrapped key template
6737 const CK_ULONG maxAttribs = 32;
6738 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6739 { CKA_CLASS, &objClass, sizeof(objClass) },
6740 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6741 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6742 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6744 CK_ULONG secretAttribsCount = 4;
6746 // Add the additional
6747 if (ulCount > (maxAttribs - secretAttribsCount))
6748 return CKR_TEMPLATE_INCONSISTENT;
6749 for (CK_ULONG i = 0; i < ulCount; ++i)
6751 switch (pTemplate[i].type)
6759 secretAttribs[secretAttribsCount++] = pTemplate[i];
6763 // Apply the unwrap template
6764 if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6766 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6768 if (unwrapAttr.isAttributeMapAttribute())
6770 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6772 const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6774 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6776 CK_ATTRIBUTE* attr = NULL;
6777 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6779 if (it->first == secretAttribs[i].type)
6783 return CKR_TEMPLATE_INCONSISTENT;
6785 attr = &secretAttribs[i];
6787 it->second.peekValue(value);
6788 if (attr->ulValueLen != value.size())
6790 return CKR_TEMPLATE_INCONSISTENT;
6792 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6794 return CKR_TEMPLATE_INCONSISTENT;
6800 return CKR_TEMPLATE_INCONSISTENT;
6806 *hKey = CK_INVALID_HANDLE;
6809 ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6811 if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6812 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6813 else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6814 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6816 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6820 // Create the secret object using C_CreateObject
6821 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6823 // Store the attributes that are being supplied
6826 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6827 if (osobject == NULL_PTR || !osobject->isValid())
6828 rv = CKR_FUNCTION_FAILED;
6829 if (osobject->startTransaction())
6833 // Common Attributes
6834 bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6836 // Common Secret Key Attributes
6837 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6838 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6840 // Secret Attributes
6841 if (objClass == CKO_SECRET_KEY)
6845 token->encrypt(keydata, value);
6848 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6850 else if (keyType == CKK_RSA)
6852 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6854 else if (keyType == CKK_DSA)
6856 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6858 else if (keyType == CKK_DH)
6860 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6863 else if (keyType == CKK_EC)
6865 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6869 else if (keyType == CKK_GOSTR3410)
6871 bOK = bOK && setGOSTPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6878 bOK = osobject->commitTransaction();
6880 osobject->abortTransaction();
6883 rv = CKR_FUNCTION_FAILED;
6886 rv = CKR_FUNCTION_FAILED;
6889 // Remove secret that may have been created already when the function fails.
6892 if (*hKey != CK_INVALID_HANDLE)
6894 OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6895 handleManager->destroyObject(*hKey);
6896 if (obj) obj->destroyObject();
6897 *hKey = CK_INVALID_HANDLE;
6905 // Derive a key from the specified base key
6906 CK_RV SoftHSM::C_DeriveKey
6908 CK_SESSION_HANDLE hSession,
6909 CK_MECHANISM_PTR pMechanism,
6910 CK_OBJECT_HANDLE hBaseKey,
6911 CK_ATTRIBUTE_PTR pTemplate,
6913 CK_OBJECT_HANDLE_PTR phKey
6916 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6918 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6919 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6920 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6923 Session* session = (Session*)handleManager->getSession(hSession);
6924 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6926 // Check the mechanism, only accept DH and ECDH derive
6927 switch (pMechanism->mechanism)
6929 case CKM_DH_PKCS_DERIVE:
6931 case CKM_ECDH1_DERIVE:
6934 case CKM_DES_ECB_ENCRYPT_DATA:
6935 case CKM_DES_CBC_ENCRYPT_DATA:
6937 case CKM_DES3_ECB_ENCRYPT_DATA:
6938 case CKM_DES3_CBC_ENCRYPT_DATA:
6939 case CKM_AES_ECB_ENCRYPT_DATA:
6940 case CKM_AES_CBC_ENCRYPT_DATA:
6943 ERROR_MSG("Invalid mechanism");
6944 return CKR_MECHANISM_INVALID;
6948 Token* token = session->getToken();
6949 if (token == NULL) return CKR_GENERAL_ERROR;
6951 // Check the key handle.
6952 OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6953 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6955 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6956 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6958 // Check user credentials
6959 CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6962 if (rv == CKR_USER_NOT_LOGGED_IN)
6963 INFO_MSG("User is not authorized");
6968 // Check if key can be used for derive
6969 if (!key->getBooleanValue(CKA_DERIVE, false))
6970 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6972 // Check if the specified mechanism is allowed for the key
6973 if (!isMechanismPermitted(key, pMechanism))
6974 return CKR_MECHANISM_INVALID;
6976 // Extract information from the template that is needed to create the object.
6977 CK_OBJECT_CLASS objClass;
6978 CK_KEY_TYPE keyType;
6979 CK_BBOOL isOnToken = CK_FALSE;
6980 CK_BBOOL isPrivate = CK_TRUE;
6981 CK_CERTIFICATE_TYPE dummy;
6982 bool isImplicit = false;
6983 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6986 ERROR_MSG("Mandatory attribute not present in template");
6990 // Report errors and/or unexpected usage.
6991 if (objClass != CKO_SECRET_KEY)
6992 return CKR_ATTRIBUTE_VALUE_INVALID;
6993 if (keyType != CKK_GENERIC_SECRET &&
6994 keyType != CKK_DES &&
6995 keyType != CKK_DES2 &&
6996 keyType != CKK_DES3 &&
6998 return CKR_TEMPLATE_INCONSISTENT;
7000 // Check authorization
7001 rv = haveWrite(session->getState(), isOnToken, isPrivate);
7004 if (rv == CKR_USER_NOT_LOGGED_IN)
7005 INFO_MSG("User is not authorized");
7006 if (rv == CKR_SESSION_READ_ONLY)
7007 INFO_MSG("Session is read-only");
7013 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
7015 // Check key class and type
7016 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
7017 return CKR_KEY_TYPE_INCONSISTENT;
7018 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
7019 return CKR_KEY_TYPE_INCONSISTENT;
7021 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7025 // Derive ECDH secret
7026 if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
7028 // Check key class and type
7029 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
7030 return CKR_KEY_TYPE_INCONSISTENT;
7031 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
7032 return CKR_KEY_TYPE_INCONSISTENT;
7034 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7038 // Derive symmetric secret
7039 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
7040 pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
7041 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
7042 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
7043 pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
7044 pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
7046 // Check key class and type
7047 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
7048 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
7049 return CKR_KEY_TYPE_INCONSISTENT;
7050 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
7051 baseKeyType != CKK_DES)
7052 return CKR_KEY_TYPE_INCONSISTENT;
7053 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
7054 baseKeyType != CKK_DES)
7055 return CKR_KEY_TYPE_INCONSISTENT;
7056 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
7057 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
7058 return CKR_KEY_TYPE_INCONSISTENT;
7059 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
7060 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
7061 return CKR_KEY_TYPE_INCONSISTENT;
7062 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
7063 baseKeyType != CKK_AES)
7064 return CKR_KEY_TYPE_INCONSISTENT;
7065 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
7066 baseKeyType != CKK_AES)
7067 return CKR_KEY_TYPE_INCONSISTENT;
7069 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7072 return CKR_MECHANISM_INVALID;
7075 // Seed the random number generator with new data
7076 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
7078 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7080 if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
7083 Session* session = (Session*)handleManager->getSession(hSession);
7084 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7087 RNG* rng = CryptoFactory::i()->getRNG();
7088 if (rng == NULL) return CKR_GENERAL_ERROR;
7091 ByteString seed(pSeed, ulSeedLen);
7097 // Generate the specified amount of random data
7098 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
7100 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7102 if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
7105 Session* session = (Session*)handleManager->getSession(hSession);
7106 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7109 RNG* rng = CryptoFactory::i()->getRNG();
7110 if (rng == NULL) return CKR_GENERAL_ERROR;
7112 // Generate random data
7113 ByteString randomData;
7114 if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
7116 // Return random data
7117 if (ulRandomLen != 0)
7119 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
7126 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
7128 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7131 Session* session = (Session*)handleManager->getSession(hSession);
7132 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7134 return CKR_FUNCTION_NOT_PARALLEL;
7138 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
7140 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7143 Session* session = (Session*)handleManager->getSession(hSession);
7144 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7146 return CKR_FUNCTION_NOT_PARALLEL;
7149 // Wait or poll for a slot event on the specified slot
7150 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
7152 return CKR_FUNCTION_NOT_SUPPORTED;
7155 // Generate an AES secret key
7156 CK_RV SoftHSM::generateAES
7157 (CK_SESSION_HANDLE hSession,
7158 CK_ATTRIBUTE_PTR pTemplate,
7160 CK_OBJECT_HANDLE_PTR phKey,
7164 *phKey = CK_INVALID_HANDLE;
7167 Session* session = (Session*)handleManager->getSession(hSession);
7168 if (session == NULL)
7169 return CKR_SESSION_HANDLE_INVALID;
7172 Token* token = session->getToken();
7174 return CKR_GENERAL_ERROR;
7176 // Extract desired parameter information
7178 bool checkValue = true;
7179 for (CK_ULONG i = 0; i < ulCount; i++)
7181 switch (pTemplate[i].type)
7184 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
7186 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
7187 return CKR_ATTRIBUTE_VALUE_INVALID;
7189 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
7191 case CKA_CHECK_VALUE:
7192 if (pTemplate[i].ulValueLen > 0)
7194 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7195 return CKR_ATTRIBUTE_VALUE_INVALID;
7204 // CKA_VALUE_LEN must be specified
7207 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
7208 return CKR_TEMPLATE_INCOMPLETE;
7211 // keyLen must be 16, 24, or 32
7212 if (keyLen != 16 && keyLen != 24 && keyLen != 32)
7214 INFO_MSG("bad AES key length");
7215 return CKR_ATTRIBUTE_VALUE_INVALID;
7218 // Generate the secret key
7219 AESKey* key = new AESKey(keyLen * 8);
7220 SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
7223 ERROR_MSG("Could not get SymmetricAlgorithm");
7225 return CKR_GENERAL_ERROR;
7227 RNG* rng = CryptoFactory::i()->getRNG();
7230 ERROR_MSG("Could not get RNG");
7231 aes->recycleKey(key);
7232 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7233 return CKR_GENERAL_ERROR;
7235 if (!aes->generateKey(*key, rng))
7237 ERROR_MSG("Could not generate AES secret key");
7238 aes->recycleKey(key);
7239 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7240 return CKR_GENERAL_ERROR;
7245 // Create the secret key object using C_CreateObject
7246 const CK_ULONG maxAttribs = 32;
7247 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7248 CK_KEY_TYPE keyType = CKK_AES;
7249 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7250 { CKA_CLASS, &objClass, sizeof(objClass) },
7251 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7252 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7253 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7255 CK_ULONG keyAttribsCount = 4;
7257 // Add the additional
7258 if (ulCount > (maxAttribs - keyAttribsCount))
7259 rv = CKR_TEMPLATE_INCONSISTENT;
7260 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7262 switch (pTemplate[i].type)
7268 case CKA_CHECK_VALUE:
7271 keyAttribs[keyAttribsCount++] = pTemplate[i];
7276 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7278 // Store the attributes that are being supplied
7281 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7282 if (osobject == NULL_PTR || !osobject->isValid()) {
7283 rv = CKR_FUNCTION_FAILED;
7284 } else if (osobject->startTransaction()) {
7287 // Common Attributes
7288 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7289 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
7290 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7292 // Common Secret Key Attributes
7293 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7294 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7295 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7296 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7298 // AES Secret Key Attributes
7303 token->encrypt(key->getKeyBits(), value);
7304 token->encrypt(key->getKeyCheckValue(), kcv);
7308 value = key->getKeyBits();
7309 kcv = key->getKeyCheckValue();
7311 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7313 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7316 bOK = osobject->commitTransaction();
7318 osobject->abortTransaction();
7321 rv = CKR_FUNCTION_FAILED;
7323 rv = CKR_FUNCTION_FAILED;
7327 aes->recycleKey(key);
7328 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7330 // Remove the key that may have been created already when the function fails.
7333 if (*phKey != CK_INVALID_HANDLE)
7335 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7336 handleManager->destroyObject(*phKey);
7337 if (oskey) oskey->destroyObject();
7338 *phKey = CK_INVALID_HANDLE;
7345 // Generate a DES secret key
7346 CK_RV SoftHSM::generateDES
7347 (CK_SESSION_HANDLE hSession,
7348 CK_ATTRIBUTE_PTR pTemplate,
7350 CK_OBJECT_HANDLE_PTR phKey,
7354 *phKey = CK_INVALID_HANDLE;
7357 Session* session = (Session*)handleManager->getSession(hSession);
7358 if (session == NULL)
7359 return CKR_SESSION_HANDLE_INVALID;
7362 Token* token = session->getToken();
7364 return CKR_GENERAL_ERROR;
7366 // Extract desired parameter information
7367 bool checkValue = true;
7368 for (CK_ULONG i = 0; i < ulCount; i++)
7370 switch (pTemplate[i].type)
7372 case CKA_CHECK_VALUE:
7373 if (pTemplate[i].ulValueLen > 0)
7375 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7376 return CKR_ATTRIBUTE_VALUE_INVALID;
7385 // Generate the secret key
7386 DESKey* key = new DESKey(56);
7387 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7390 ERROR_MSG("Could not get SymmetricAlgorithm");
7392 return CKR_GENERAL_ERROR;
7394 RNG* rng = CryptoFactory::i()->getRNG();
7397 ERROR_MSG("Could not get RNG");
7398 des->recycleKey(key);
7399 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7400 return CKR_GENERAL_ERROR;
7402 if (!des->generateKey(*key, rng))
7404 ERROR_MSG("Could not generate DES secret key");
7405 des->recycleKey(key);
7406 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7407 return CKR_GENERAL_ERROR;
7412 // Create the secret key object using C_CreateObject
7413 const CK_ULONG maxAttribs = 32;
7414 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7415 CK_KEY_TYPE keyType = CKK_DES;
7416 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7417 { CKA_CLASS, &objClass, sizeof(objClass) },
7418 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7419 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7420 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7422 CK_ULONG keyAttribsCount = 4;
7424 // Add the additional
7425 if (ulCount > (maxAttribs - keyAttribsCount))
7426 rv = CKR_TEMPLATE_INCONSISTENT;
7427 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7429 switch (pTemplate[i].type)
7435 case CKA_CHECK_VALUE:
7438 keyAttribs[keyAttribsCount++] = pTemplate[i];
7443 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7445 // Store the attributes that are being supplied
7448 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7449 if (osobject == NULL_PTR || !osobject->isValid()) {
7450 rv = CKR_FUNCTION_FAILED;
7451 } else if (osobject->startTransaction()) {
7454 // Common Attributes
7455 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7456 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7457 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7459 // Common Secret Key Attributes
7460 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7461 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7462 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7463 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7465 // DES Secret Key Attributes
7470 token->encrypt(key->getKeyBits(), value);
7471 token->encrypt(key->getKeyCheckValue(), kcv);
7475 value = key->getKeyBits();
7476 kcv = key->getKeyCheckValue();
7478 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7480 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7483 bOK = osobject->commitTransaction();
7485 osobject->abortTransaction();
7488 rv = CKR_FUNCTION_FAILED;
7490 rv = CKR_FUNCTION_FAILED;
7494 des->recycleKey(key);
7495 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7497 // Remove the key that may have been created already when the function fails.
7500 if (*phKey != CK_INVALID_HANDLE)
7502 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7503 handleManager->destroyObject(*phKey);
7504 if (oskey) oskey->destroyObject();
7505 *phKey = CK_INVALID_HANDLE;
7512 // Generate a DES2 secret key
7513 CK_RV SoftHSM::generateDES2
7514 (CK_SESSION_HANDLE hSession,
7515 CK_ATTRIBUTE_PTR pTemplate,
7517 CK_OBJECT_HANDLE_PTR phKey,
7521 *phKey = CK_INVALID_HANDLE;
7524 Session* session = (Session*)handleManager->getSession(hSession);
7525 if (session == NULL)
7526 return CKR_SESSION_HANDLE_INVALID;
7529 Token* token = session->getToken();
7531 return CKR_GENERAL_ERROR;
7533 // Extract desired parameter information
7534 bool checkValue = true;
7535 for (CK_ULONG i = 0; i < ulCount; i++)
7537 switch (pTemplate[i].type)
7539 case CKA_CHECK_VALUE:
7540 if (pTemplate[i].ulValueLen > 0)
7542 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7543 return CKR_ATTRIBUTE_VALUE_INVALID;
7552 // Generate the secret key
7553 DESKey* key = new DESKey(112);
7554 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7557 ERROR_MSG("Could not get SymmetricAlgorith");
7559 return CKR_GENERAL_ERROR;
7561 RNG* rng = CryptoFactory::i()->getRNG();
7564 ERROR_MSG("Could not get RNG");
7565 des->recycleKey(key);
7566 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7567 return CKR_GENERAL_ERROR;
7569 if (!des->generateKey(*key, rng))
7571 ERROR_MSG("Could not generate DES secret key");
7572 des->recycleKey(key);
7573 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7574 return CKR_GENERAL_ERROR;
7579 // Create the secret key object using C_CreateObject
7580 const CK_ULONG maxAttribs = 32;
7581 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7582 CK_KEY_TYPE keyType = CKK_DES2;
7583 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7584 { CKA_CLASS, &objClass, sizeof(objClass) },
7585 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7586 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7587 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7589 CK_ULONG keyAttribsCount = 4;
7591 // Add the additional
7592 if (ulCount > (maxAttribs - keyAttribsCount))
7593 rv = CKR_TEMPLATE_INCONSISTENT;
7594 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7596 switch (pTemplate[i].type)
7602 case CKA_CHECK_VALUE:
7605 keyAttribs[keyAttribsCount++] = pTemplate[i];
7610 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7612 // Store the attributes that are being supplied
7615 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7616 if (osobject == NULL_PTR || !osobject->isValid()) {
7617 rv = CKR_FUNCTION_FAILED;
7618 } else if (osobject->startTransaction()) {
7621 // Common Attributes
7622 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7623 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7624 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7626 // Common Secret Key Attributes
7627 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7628 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7629 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7630 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7632 // DES Secret Key Attributes
7637 token->encrypt(key->getKeyBits(), value);
7638 token->encrypt(key->getKeyCheckValue(), kcv);
7642 value = key->getKeyBits();
7643 kcv = key->getKeyCheckValue();
7645 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7647 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7650 bOK = osobject->commitTransaction();
7652 osobject->abortTransaction();
7655 rv = CKR_FUNCTION_FAILED;
7657 rv = CKR_FUNCTION_FAILED;
7661 des->recycleKey(key);
7662 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7664 // Remove the key that may have been created already when the function fails.
7667 if (*phKey != CK_INVALID_HANDLE)
7669 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7670 handleManager->destroyObject(*phKey);
7671 if (oskey) oskey->destroyObject();
7672 *phKey = CK_INVALID_HANDLE;
7679 // Generate a DES3 secret key
7680 CK_RV SoftHSM::generateDES3
7681 (CK_SESSION_HANDLE hSession,
7682 CK_ATTRIBUTE_PTR pTemplate,
7684 CK_OBJECT_HANDLE_PTR phKey,
7688 *phKey = CK_INVALID_HANDLE;
7691 Session* session = (Session*)handleManager->getSession(hSession);
7692 if (session == NULL)
7693 return CKR_SESSION_HANDLE_INVALID;
7696 Token* token = session->getToken();
7698 return CKR_GENERAL_ERROR;
7700 // Extract desired parameter information
7701 bool checkValue = true;
7702 for (CK_ULONG i = 0; i < ulCount; i++)
7704 switch (pTemplate[i].type)
7706 case CKA_CHECK_VALUE:
7707 if (pTemplate[i].ulValueLen > 0)
7709 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7710 return CKR_ATTRIBUTE_VALUE_INVALID;
7719 // Generate the secret key
7720 DESKey* key = new DESKey(168);
7721 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7724 ERROR_MSG("Could not get SymmetricAlgorithm");
7726 return CKR_GENERAL_ERROR;
7728 RNG* rng = CryptoFactory::i()->getRNG();
7731 ERROR_MSG("Could not get RNG");
7732 des->recycleKey(key);
7733 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7734 return CKR_GENERAL_ERROR;
7736 if (!des->generateKey(*key, rng))
7738 ERROR_MSG("Could not generate DES secret key");
7739 des->recycleKey(key);
7740 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7741 return CKR_GENERAL_ERROR;
7746 // Create the secret key object using C_CreateObject
7747 const CK_ULONG maxAttribs = 32;
7748 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7749 CK_KEY_TYPE keyType = CKK_DES3;
7750 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7751 { CKA_CLASS, &objClass, sizeof(objClass) },
7752 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7753 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7754 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7756 CK_ULONG keyAttribsCount = 4;
7758 // Add the additional
7759 if (ulCount > (maxAttribs - keyAttribsCount))
7760 rv = CKR_TEMPLATE_INCONSISTENT;
7761 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7763 switch (pTemplate[i].type)
7769 case CKA_CHECK_VALUE:
7772 keyAttribs[keyAttribsCount++] = pTemplate[i];
7777 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7779 // Store the attributes that are being supplied
7782 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7783 if (osobject == NULL_PTR || !osobject->isValid()) {
7784 rv = CKR_FUNCTION_FAILED;
7785 } else if (osobject->startTransaction()) {
7788 // Common Attributes
7789 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7790 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7791 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7793 // Common Secret Key Attributes
7794 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7795 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7796 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7797 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7799 // DES Secret Key Attributes
7804 token->encrypt(key->getKeyBits(), value);
7805 token->encrypt(key->getKeyCheckValue(), kcv);
7809 value = key->getKeyBits();
7810 kcv = key->getKeyCheckValue();
7812 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7814 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7817 bOK = osobject->commitTransaction();
7819 osobject->abortTransaction();
7822 rv = CKR_FUNCTION_FAILED;
7824 rv = CKR_FUNCTION_FAILED;
7828 des->recycleKey(key);
7829 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7831 // Remove the key that may have been created already when the function fails.
7834 if (*phKey != CK_INVALID_HANDLE)
7836 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7837 handleManager->destroyObject(*phKey);
7838 if (oskey) oskey->destroyObject();
7839 *phKey = CK_INVALID_HANDLE;
7846 // Generate an RSA key pair
7847 CK_RV SoftHSM::generateRSA
7848 (CK_SESSION_HANDLE hSession,
7849 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7850 CK_ULONG ulPublicKeyAttributeCount,
7851 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7852 CK_ULONG ulPrivateKeyAttributeCount,
7853 CK_OBJECT_HANDLE_PTR phPublicKey,
7854 CK_OBJECT_HANDLE_PTR phPrivateKey,
7855 CK_BBOOL isPublicKeyOnToken,
7856 CK_BBOOL isPublicKeyPrivate,
7857 CK_BBOOL isPrivateKeyOnToken,
7858 CK_BBOOL isPrivateKeyPrivate
7861 *phPublicKey = CK_INVALID_HANDLE;
7862 *phPrivateKey = CK_INVALID_HANDLE;
7865 Session* session = (Session*)handleManager->getSession(hSession);
7866 if (session == NULL)
7867 return CKR_SESSION_HANDLE_INVALID;
7870 Token* token = session->getToken();
7872 return CKR_GENERAL_ERROR;
7874 // Extract desired key information: bitlen and public exponent
7876 ByteString exponent("010001");
7877 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7879 switch (pPublicKeyTemplate[i].type)
7881 case CKA_MODULUS_BITS:
7882 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7884 INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7885 return CKR_ATTRIBUTE_VALUE_INVALID;
7887 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7889 case CKA_PUBLIC_EXPONENT:
7890 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7897 // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7899 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7900 return CKR_TEMPLATE_INCOMPLETE;
7903 // Set the parameters
7906 p.setBitLength(bitLen);
7908 // Generate key pair
7909 AsymmetricKeyPair* kp = NULL;
7910 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7912 return CKR_GENERAL_ERROR;
7913 if (!rsa->generateKeyPair(&kp, &p))
7915 ERROR_MSG("Could not generate key pair");
7916 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7917 return CKR_GENERAL_ERROR;
7920 RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7921 RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7925 // Create a public key using C_CreateObject
7928 const CK_ULONG maxAttribs = 32;
7929 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7930 CK_KEY_TYPE publicKeyType = CKK_RSA;
7931 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7932 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7933 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7934 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7935 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7937 CK_ULONG publicKeyAttribsCount = 4;
7939 // Add the additional
7940 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7941 rv = CKR_TEMPLATE_INCONSISTENT;
7942 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7944 switch (pPublicKeyTemplate[i].type)
7950 case CKA_PUBLIC_EXPONENT:
7953 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7958 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7960 // Store the attributes that are being supplied by the key generation to the object
7963 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7964 if (osobject == NULL_PTR || !osobject->isValid()) {
7965 rv = CKR_FUNCTION_FAILED;
7966 } else if (osobject->startTransaction()) {
7969 // Common Key Attributes
7970 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7971 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7972 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7974 // RSA Public Key Attributes
7976 ByteString publicExponent;
7977 if (isPublicKeyPrivate)
7979 token->encrypt(pub->getN(), modulus);
7980 token->encrypt(pub->getE(), publicExponent);
7984 modulus = pub->getN();
7985 publicExponent = pub->getE();
7987 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7988 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7991 bOK = osobject->commitTransaction();
7993 osobject->abortTransaction();
7996 rv = CKR_FUNCTION_FAILED;
7998 rv = CKR_FUNCTION_FAILED;
8002 // Create a private key using C_CreateObject
8005 const CK_ULONG maxAttribs = 32;
8006 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8007 CK_KEY_TYPE privateKeyType = CKK_RSA;
8008 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8009 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8010 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8011 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8012 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8014 CK_ULONG privateKeyAttribsCount = 4;
8015 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8016 rv = CKR_TEMPLATE_INCONSISTENT;
8017 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8019 switch (pPrivateKeyTemplate[i].type)
8027 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8032 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8034 // Store the attributes that are being supplied by the key generation to the object
8037 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8038 if (osobject == NULL_PTR || !osobject->isValid()) {
8039 rv = CKR_FUNCTION_FAILED;
8040 } else if (osobject->startTransaction()) {
8043 // Common Key Attributes
8044 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8045 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
8046 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8048 // Common Private Key Attributes
8049 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8050 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8051 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8052 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8054 // RSA Private Key Attributes
8056 ByteString publicExponent;
8057 ByteString privateExponent;
8060 ByteString exponent1;
8061 ByteString exponent2;
8062 ByteString coefficient;
8063 if (isPrivateKeyPrivate)
8065 token->encrypt(priv->getN(), modulus);
8066 token->encrypt(priv->getE(), publicExponent);
8067 token->encrypt(priv->getD(), privateExponent);
8068 token->encrypt(priv->getP(), prime1);
8069 token->encrypt(priv->getQ(), prime2);
8070 token->encrypt(priv->getDP1(), exponent1);
8071 token->encrypt(priv->getDQ1(), exponent2);
8072 token->encrypt(priv->getPQ(), coefficient);
8076 modulus = priv->getN();
8077 publicExponent = priv->getE();
8078 privateExponent = priv->getD();
8079 prime1 = priv->getP();
8080 prime2 = priv->getQ();
8081 exponent1 = priv->getDP1();
8082 exponent2 = priv->getDQ1();
8083 coefficient = priv->getPQ();
8085 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
8086 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
8087 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
8088 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
8089 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
8090 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
8091 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
8092 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
8095 bOK = osobject->commitTransaction();
8097 osobject->abortTransaction();
8100 rv = CKR_FUNCTION_FAILED;
8102 rv = CKR_FUNCTION_FAILED;
8107 rsa->recycleKeyPair(kp);
8108 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
8110 // Remove keys that may have been created already when the function fails.
8113 if (*phPrivateKey != CK_INVALID_HANDLE)
8115 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8116 handleManager->destroyObject(*phPrivateKey);
8117 if (ospriv) ospriv->destroyObject();
8118 *phPrivateKey = CK_INVALID_HANDLE;
8121 if (*phPublicKey != CK_INVALID_HANDLE)
8123 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8124 handleManager->destroyObject(*phPublicKey);
8125 if (ospub) ospub->destroyObject();
8126 *phPublicKey = CK_INVALID_HANDLE;
8133 // Generate a DSA key pair
8134 CK_RV SoftHSM::generateDSA
8135 (CK_SESSION_HANDLE hSession,
8136 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8137 CK_ULONG ulPublicKeyAttributeCount,
8138 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8139 CK_ULONG ulPrivateKeyAttributeCount,
8140 CK_OBJECT_HANDLE_PTR phPublicKey,
8141 CK_OBJECT_HANDLE_PTR phPrivateKey,
8142 CK_BBOOL isPublicKeyOnToken,
8143 CK_BBOOL isPublicKeyPrivate,
8144 CK_BBOOL isPrivateKeyOnToken,
8145 CK_BBOOL isPrivateKeyPrivate)
8147 *phPublicKey = CK_INVALID_HANDLE;
8148 *phPrivateKey = CK_INVALID_HANDLE;
8151 Session* session = (Session*)handleManager->getSession(hSession);
8152 if (session == NULL)
8153 return CKR_SESSION_HANDLE_INVALID;
8156 Token* token = session->getToken();
8158 return CKR_GENERAL_ERROR;
8160 // Extract desired key information
8162 ByteString subprime;
8163 ByteString generator;
8164 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8166 switch (pPublicKeyTemplate[i].type)
8169 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8172 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8175 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8182 // The parameters must be specified to be able to generate a key pair.
8183 if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
8184 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8185 return CKR_TEMPLATE_INCOMPLETE;
8188 // Set the parameters
8194 // Generate key pair
8195 AsymmetricKeyPair* kp = NULL;
8196 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8197 if (dsa == NULL) return CKR_GENERAL_ERROR;
8198 if (!dsa->generateKeyPair(&kp, &p))
8200 ERROR_MSG("Could not generate key pair");
8201 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8202 return CKR_GENERAL_ERROR;
8205 DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
8206 DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
8210 // Create a public key using C_CreateObject
8213 const CK_ULONG maxAttribs = 32;
8214 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8215 CK_KEY_TYPE publicKeyType = CKK_DSA;
8216 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8217 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8218 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8219 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8220 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8222 CK_ULONG publicKeyAttribsCount = 4;
8224 // Add the additional
8225 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8226 rv = CKR_TEMPLATE_INCONSISTENT;
8227 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8229 switch (pPublicKeyTemplate[i].type)
8237 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8242 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8244 // Store the attributes that are being supplied by the key generation to the object
8247 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8248 if (osobject == NULL_PTR || !osobject->isValid()) {
8249 rv = CKR_FUNCTION_FAILED;
8250 } else if (osobject->startTransaction()) {
8253 // Common Key Attributes
8254 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8255 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8256 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8258 // DSA Public Key Attributes
8260 if (isPublicKeyPrivate)
8262 token->encrypt(pub->getY(), value);
8266 value = pub->getY();
8268 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8271 bOK = osobject->commitTransaction();
8273 osobject->abortTransaction();
8276 rv = CKR_FUNCTION_FAILED;
8278 rv = CKR_FUNCTION_FAILED;
8282 // Create a private key using C_CreateObject
8285 const CK_ULONG maxAttribs = 32;
8286 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8287 CK_KEY_TYPE privateKeyType = CKK_DSA;
8288 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8289 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8290 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8291 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8292 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8294 CK_ULONG privateKeyAttribsCount = 4;
8295 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8296 rv = CKR_TEMPLATE_INCONSISTENT;
8297 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8299 switch (pPrivateKeyTemplate[i].type)
8307 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8312 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8314 // Store the attributes that are being supplied by the key generation to the object
8317 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8318 if (osobject == NULL_PTR || !osobject->isValid()) {
8319 rv = CKR_FUNCTION_FAILED;
8320 } else if (osobject->startTransaction()) {
8323 // Common Key Attributes
8324 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8325 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8326 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8328 // Common Private Key Attributes
8329 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8330 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8331 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8332 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8334 // DSA Private Key Attributes
8336 ByteString bSubprime;
8337 ByteString bGenerator;
8339 if (isPrivateKeyPrivate)
8341 token->encrypt(priv->getP(), bPrime);
8342 token->encrypt(priv->getQ(), bSubprime);
8343 token->encrypt(priv->getG(), bGenerator);
8344 token->encrypt(priv->getX(), bValue);
8348 bPrime = priv->getP();
8349 bSubprime = priv->getQ();
8350 bGenerator = priv->getG();
8351 bValue = priv->getX();
8353 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8354 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8355 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8356 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8359 bOK = osobject->commitTransaction();
8361 osobject->abortTransaction();
8364 rv = CKR_FUNCTION_FAILED;
8366 rv = CKR_FUNCTION_FAILED;
8371 dsa->recycleKeyPair(kp);
8372 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8374 // Remove keys that may have been created already when the function fails.
8377 if (*phPrivateKey != CK_INVALID_HANDLE)
8379 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8380 handleManager->destroyObject(*phPrivateKey);
8381 if (ospriv) ospriv->destroyObject();
8382 *phPrivateKey = CK_INVALID_HANDLE;
8385 if (*phPublicKey != CK_INVALID_HANDLE)
8387 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8388 handleManager->destroyObject(*phPublicKey);
8389 if (ospub) ospub->destroyObject();
8390 *phPublicKey = CK_INVALID_HANDLE;
8397 // Generate a DSA domain parameter set
8398 CK_RV SoftHSM::generateDSAParameters
8399 (CK_SESSION_HANDLE hSession,
8400 CK_ATTRIBUTE_PTR pTemplate,
8402 CK_OBJECT_HANDLE_PTR phKey,
8406 *phKey = CK_INVALID_HANDLE;
8409 Session* session = (Session*)handleManager->getSession(hSession);
8410 if (session == NULL)
8411 return CKR_SESSION_HANDLE_INVALID;
8414 Token* token = session->getToken();
8416 return CKR_GENERAL_ERROR;
8418 // Extract desired parameter information
8421 for (CK_ULONG i = 0; i < ulCount; i++)
8423 switch (pTemplate[i].type)
8425 case CKA_PRIME_BITS:
8426 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8428 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8429 return CKR_ATTRIBUTE_VALUE_INVALID;
8431 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8433 case CKA_SUBPRIME_BITS:
8434 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8436 INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8437 return CKR_ATTRIBUTE_VALUE_INVALID;
8439 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8446 // CKA_PRIME_BITS must be specified
8449 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8450 return CKR_TEMPLATE_INCOMPLETE;
8453 // No real choice for CKA_SUBPRIME_BITS
8455 (((bitLen >= 2048) && (qLen != 256)) ||
8456 ((bitLen < 2048) && (qLen != 160))))
8457 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8460 // Generate domain parameters
8461 AsymmetricParameters* p = NULL;
8462 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8463 if (dsa == NULL) return CKR_GENERAL_ERROR;
8464 if (!dsa->generateParameters(&p, (void *)bitLen))
8466 ERROR_MSG("Could not generate parameters");
8467 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8468 return CKR_GENERAL_ERROR;
8471 DSAParameters* params = (DSAParameters*) p;
8475 // Create the domain parameter object using C_CreateObject
8476 const CK_ULONG maxAttribs = 32;
8477 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8478 CK_KEY_TYPE keyType = CKK_DSA;
8479 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8480 { CKA_CLASS, &objClass, sizeof(objClass) },
8481 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8482 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8483 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8485 CK_ULONG paramsAttribsCount = 4;
8487 // Add the additional
8488 if (ulCount > (maxAttribs - paramsAttribsCount))
8489 rv = CKR_TEMPLATE_INCONSISTENT;
8490 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8492 switch (pTemplate[i].type)
8500 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8505 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8507 // Store the attributes that are being supplied
8510 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8511 if (osobject == NULL_PTR || !osobject->isValid()) {
8512 rv = CKR_FUNCTION_FAILED;
8513 } else if (osobject->startTransaction()) {
8516 // Common Attributes
8517 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8518 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8519 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8521 // DSA Domain Parameters Attributes
8523 ByteString subprime;
8524 ByteString generator;
8527 token->encrypt(params->getP(), prime);
8528 token->encrypt(params->getQ(), subprime);
8529 token->encrypt(params->getG(), generator);
8533 prime = params->getP();
8534 subprime = params->getQ();
8535 generator = params->getG();
8537 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8538 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8539 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8542 bOK = osobject->commitTransaction();
8544 osobject->abortTransaction();
8547 rv = CKR_FUNCTION_FAILED;
8549 rv = CKR_FUNCTION_FAILED;
8553 dsa->recycleParameters(p);
8554 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8556 // Remove parameters that may have been created already when the function fails.
8559 if (*phKey != CK_INVALID_HANDLE)
8561 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8562 handleManager->destroyObject(*phKey);
8563 if (osparams) osparams->destroyObject();
8564 *phKey = CK_INVALID_HANDLE;
8571 // Generate an EC key pair
8572 CK_RV SoftHSM::generateEC
8573 (CK_SESSION_HANDLE hSession,
8574 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8575 CK_ULONG ulPublicKeyAttributeCount,
8576 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8577 CK_ULONG ulPrivateKeyAttributeCount,
8578 CK_OBJECT_HANDLE_PTR phPublicKey,
8579 CK_OBJECT_HANDLE_PTR phPrivateKey,
8580 CK_BBOOL isPublicKeyOnToken,
8581 CK_BBOOL isPublicKeyPrivate,
8582 CK_BBOOL isPrivateKeyOnToken,
8583 CK_BBOOL isPrivateKeyPrivate)
8585 *phPublicKey = CK_INVALID_HANDLE;
8586 *phPrivateKey = CK_INVALID_HANDLE;
8589 Session* session = (Session*)handleManager->getSession(hSession);
8590 if (session == NULL)
8591 return CKR_SESSION_HANDLE_INVALID;
8594 Token* token = session->getToken();
8596 return CKR_GENERAL_ERROR;
8598 // Extract desired key information
8600 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8602 switch (pPublicKeyTemplate[i].type)
8605 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8612 // The parameters must be specified to be able to generate a key pair.
8613 if (params.size() == 0) {
8614 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8615 return CKR_TEMPLATE_INCOMPLETE;
8618 // Set the parameters
8622 // Generate key pair
8623 AsymmetricKeyPair* kp = NULL;
8624 AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8625 if (ec == NULL) return CKR_GENERAL_ERROR;
8626 if (!ec->generateKeyPair(&kp, &p))
8628 ERROR_MSG("Could not generate key pair");
8629 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8630 return CKR_GENERAL_ERROR;
8633 ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8634 ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8638 // Create a public key using C_CreateObject
8641 const CK_ULONG maxAttribs = 32;
8642 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8643 CK_KEY_TYPE publicKeyType = CKK_EC;
8644 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8645 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8646 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8647 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8648 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8650 CK_ULONG publicKeyAttribsCount = 4;
8652 // Add the additional
8653 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8654 rv = CKR_TEMPLATE_INCONSISTENT;
8655 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8657 switch (pPublicKeyTemplate[i].type)
8665 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8670 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8672 // Store the attributes that are being supplied by the key generation to the object
8675 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8676 if (osobject == NULL_PTR || !osobject->isValid()) {
8677 rv = CKR_FUNCTION_FAILED;
8678 } else if (osobject->startTransaction()) {
8681 // Common Key Attributes
8682 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8683 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8684 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8686 // EC Public Key Attributes
8688 if (isPublicKeyPrivate)
8690 token->encrypt(pub->getQ(), point);
8694 point = pub->getQ();
8696 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8699 bOK = osobject->commitTransaction();
8701 osobject->abortTransaction();
8704 rv = CKR_FUNCTION_FAILED;
8706 rv = CKR_FUNCTION_FAILED;
8710 // Create a private key using C_CreateObject
8713 const CK_ULONG maxAttribs = 32;
8714 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8715 CK_KEY_TYPE privateKeyType = CKK_EC;
8716 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8717 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8718 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8719 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8720 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8722 CK_ULONG privateKeyAttribsCount = 4;
8723 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8724 rv = CKR_TEMPLATE_INCONSISTENT;
8725 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8727 switch (pPrivateKeyTemplate[i].type)
8735 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8740 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8742 // Store the attributes that are being supplied by the key generation to the object
8745 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8746 if (osobject == NULL_PTR || !osobject->isValid()) {
8747 rv = CKR_FUNCTION_FAILED;
8748 } else if (osobject->startTransaction()) {
8751 // Common Key Attributes
8752 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8753 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8754 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8756 // Common Private Key Attributes
8757 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8758 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8759 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8760 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8762 // EC Private Key Attributes
8765 if (isPrivateKeyPrivate)
8767 token->encrypt(priv->getEC(), group);
8768 token->encrypt(priv->getD(), value);
8772 group = priv->getEC();
8773 value = priv->getD();
8775 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8776 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8779 bOK = osobject->commitTransaction();
8781 osobject->abortTransaction();
8784 rv = CKR_FUNCTION_FAILED;
8786 rv = CKR_FUNCTION_FAILED;
8791 ec->recycleKeyPair(kp);
8792 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8794 // Remove keys that may have been created already when the function fails.
8797 if (*phPrivateKey != CK_INVALID_HANDLE)
8799 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8800 handleManager->destroyObject(*phPrivateKey);
8801 if (ospriv) ospriv->destroyObject();
8802 *phPrivateKey = CK_INVALID_HANDLE;
8805 if (*phPublicKey != CK_INVALID_HANDLE)
8807 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8808 handleManager->destroyObject(*phPublicKey);
8809 if (ospub) ospub->destroyObject();
8810 *phPublicKey = CK_INVALID_HANDLE;
8817 // Generate a DH key pair
8818 CK_RV SoftHSM::generateDH
8819 (CK_SESSION_HANDLE hSession,
8820 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8821 CK_ULONG ulPublicKeyAttributeCount,
8822 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8823 CK_ULONG ulPrivateKeyAttributeCount,
8824 CK_OBJECT_HANDLE_PTR phPublicKey,
8825 CK_OBJECT_HANDLE_PTR phPrivateKey,
8826 CK_BBOOL isPublicKeyOnToken,
8827 CK_BBOOL isPublicKeyPrivate,
8828 CK_BBOOL isPrivateKeyOnToken,
8829 CK_BBOOL isPrivateKeyPrivate)
8831 *phPublicKey = CK_INVALID_HANDLE;
8832 *phPrivateKey = CK_INVALID_HANDLE;
8835 Session* session = (Session*)handleManager->getSession(hSession);
8836 if (session == NULL)
8837 return CKR_SESSION_HANDLE_INVALID;
8840 Token* token = session->getToken();
8842 return CKR_GENERAL_ERROR;
8844 // Extract desired key information
8846 ByteString generator;
8847 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8849 switch (pPublicKeyTemplate[i].type)
8852 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8855 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8862 // The parameters must be specified to be able to generate a key pair.
8863 if (prime.size() == 0 || generator.size() == 0) {
8864 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8865 return CKR_TEMPLATE_INCOMPLETE;
8868 // Extract optional bit length
8870 for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8872 switch (pPrivateKeyTemplate[i].type)
8874 case CKA_VALUE_BITS:
8875 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8882 // Set the parameters
8886 p.setXBitLength(bitLen);
8888 // Generate key pair
8889 AsymmetricKeyPair* kp = NULL;
8890 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8891 if (dh == NULL) return CKR_GENERAL_ERROR;
8892 if (!dh->generateKeyPair(&kp, &p))
8894 ERROR_MSG("Could not generate key pair");
8895 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8896 return CKR_GENERAL_ERROR;
8899 DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8900 DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8904 // Create a public key using C_CreateObject
8907 const CK_ULONG maxAttribs = 32;
8908 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8909 CK_KEY_TYPE publicKeyType = CKK_DH;
8910 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8911 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8912 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8913 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8914 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8916 CK_ULONG publicKeyAttribsCount = 4;
8918 // Add the additional
8919 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8920 rv = CKR_TEMPLATE_INCONSISTENT;
8921 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8923 switch (pPublicKeyTemplate[i].type)
8931 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8936 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8938 // Store the attributes that are being supplied by the key generation to the object
8941 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8942 if (osobject == NULL_PTR || !osobject->isValid()) {
8943 rv = CKR_FUNCTION_FAILED;
8944 } else if (osobject->startTransaction()) {
8947 // Common Key Attributes
8948 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8949 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8950 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8952 // DH Public Key Attributes
8954 if (isPublicKeyPrivate)
8956 token->encrypt(pub->getY(), value);
8960 value = pub->getY();
8962 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8965 bOK = osobject->commitTransaction();
8967 osobject->abortTransaction();
8970 rv = CKR_FUNCTION_FAILED;
8972 rv = CKR_FUNCTION_FAILED;
8976 // Create a private key using C_CreateObject
8979 const CK_ULONG maxAttribs = 32;
8980 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8981 CK_KEY_TYPE privateKeyType = CKK_DH;
8982 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8983 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8984 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8985 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8986 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8988 CK_ULONG privateKeyAttribsCount = 4;
8989 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8990 rv = CKR_TEMPLATE_INCONSISTENT;
8991 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8993 switch (pPrivateKeyTemplate[i].type)
9001 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9006 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9008 // Store the attributes that are being supplied by the key generation to the object
9011 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9012 if (osobject == NULL_PTR || !osobject->isValid()) {
9013 rv = CKR_FUNCTION_FAILED;
9014 } else if (osobject->startTransaction()) {
9017 // Common Key Attributes
9018 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9019 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
9020 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9022 // Common Private Key Attributes
9023 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9024 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9025 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9026 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9028 // DH Private Key Attributes
9030 ByteString bGenerator;
9032 if (isPrivateKeyPrivate)
9034 token->encrypt(priv->getP(), bPrime);
9035 token->encrypt(priv->getG(), bGenerator);
9036 token->encrypt(priv->getX(), bValue);
9040 bPrime = priv->getP();
9041 bGenerator = priv->getG();
9042 bValue = priv->getX();
9044 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
9045 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
9046 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
9050 bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
9054 bOK = osobject->commitTransaction();
9056 osobject->abortTransaction();
9059 rv = CKR_FUNCTION_FAILED;
9061 rv = CKR_FUNCTION_FAILED;
9066 dh->recycleKeyPair(kp);
9067 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9069 // Remove keys that may have been created already when the function fails.
9072 if (*phPrivateKey != CK_INVALID_HANDLE)
9074 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9075 handleManager->destroyObject(*phPrivateKey);
9076 if (ospriv) ospriv->destroyObject();
9077 *phPrivateKey = CK_INVALID_HANDLE;
9080 if (*phPublicKey != CK_INVALID_HANDLE)
9082 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9083 handleManager->destroyObject(*phPublicKey);
9084 if (ospub) ospub->destroyObject();
9085 *phPublicKey = CK_INVALID_HANDLE;
9092 // Generate a DH domain parameter set
9093 CK_RV SoftHSM::generateDHParameters
9094 (CK_SESSION_HANDLE hSession,
9095 CK_ATTRIBUTE_PTR pTemplate,
9097 CK_OBJECT_HANDLE_PTR phKey,
9101 *phKey = CK_INVALID_HANDLE;
9104 Session* session = (Session*)handleManager->getSession(hSession);
9105 if (session == NULL)
9106 return CKR_SESSION_HANDLE_INVALID;
9109 Token* token = session->getToken();
9111 return CKR_GENERAL_ERROR;
9113 // Extract desired parameter information
9115 for (CK_ULONG i = 0; i < ulCount; i++)
9117 switch (pTemplate[i].type)
9119 case CKA_PRIME_BITS:
9120 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9122 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
9123 return CKR_ATTRIBUTE_VALUE_INVALID;
9125 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
9132 // CKA_PRIME_BITS must be specified
9135 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
9136 return CKR_TEMPLATE_INCOMPLETE;
9139 // Generate domain parameters
9140 AsymmetricParameters* p = NULL;
9141 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9142 if (dh == NULL) return CKR_GENERAL_ERROR;
9143 if (!dh->generateParameters(&p, (void *)bitLen))
9145 ERROR_MSG("Could not generate parameters");
9146 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9147 return CKR_GENERAL_ERROR;
9150 DHParameters* params = (DHParameters*) p;
9154 // Create the domain parameter object using C_CreateObject
9155 const CK_ULONG maxAttribs = 32;
9156 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
9157 CK_KEY_TYPE keyType = CKK_DH;
9158 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
9159 { CKA_CLASS, &objClass, sizeof(objClass) },
9160 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9161 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9162 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9164 CK_ULONG paramsAttribsCount = 4;
9166 // Add the additional
9167 if (ulCount > (maxAttribs - paramsAttribsCount))
9168 rv = CKR_TEMPLATE_INCONSISTENT;
9169 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9171 switch (pTemplate[i].type)
9179 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
9184 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
9186 // Store the attributes that are being supplied
9189 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9190 if (osobject == NULL_PTR || !osobject->isValid()) {
9191 rv = CKR_FUNCTION_FAILED;
9192 } else if (osobject->startTransaction()) {
9195 // Common Attributes
9196 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9197 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
9198 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9200 // DH Domain Parameters Attributes
9202 ByteString generator;
9205 token->encrypt(params->getP(), prime);
9206 token->encrypt(params->getG(), generator);
9210 prime = params->getP();
9211 generator = params->getG();
9213 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
9214 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
9217 bOK = osobject->commitTransaction();
9219 osobject->abortTransaction();
9222 rv = CKR_FUNCTION_FAILED;
9224 rv = CKR_FUNCTION_FAILED;
9228 dh->recycleParameters(p);
9229 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9231 // Remove parameters that may have been created already when the function fails.
9234 if (*phKey != CK_INVALID_HANDLE)
9236 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
9237 handleManager->destroyObject(*phKey);
9238 if (osparams) osparams->destroyObject();
9239 *phKey = CK_INVALID_HANDLE;
9246 // Generate a GOST key pair
9247 CK_RV SoftHSM::generateGOST
9248 (CK_SESSION_HANDLE hSession,
9249 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
9250 CK_ULONG ulPublicKeyAttributeCount,
9251 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
9252 CK_ULONG ulPrivateKeyAttributeCount,
9253 CK_OBJECT_HANDLE_PTR phPublicKey,
9254 CK_OBJECT_HANDLE_PTR phPrivateKey,
9255 CK_BBOOL isPublicKeyOnToken,
9256 CK_BBOOL isPublicKeyPrivate,
9257 CK_BBOOL isPrivateKeyOnToken,
9258 CK_BBOOL isPrivateKeyPrivate)
9260 *phPublicKey = CK_INVALID_HANDLE;
9261 *phPrivateKey = CK_INVALID_HANDLE;
9264 Session* session = (Session*)handleManager->getSession(hSession);
9265 if (session == NULL)
9266 return CKR_SESSION_HANDLE_INVALID;
9269 Token* token = session->getToken();
9271 return CKR_GENERAL_ERROR;
9273 // Extract desired key information
9274 ByteString param_3410;
9275 ByteString param_3411;
9276 ByteString param_28147;
9277 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
9279 switch (pPublicKeyTemplate[i].type)
9281 case CKA_GOSTR3410_PARAMS:
9282 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9284 case CKA_GOSTR3411_PARAMS:
9285 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9287 case CKA_GOST28147_PARAMS:
9288 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9295 // The parameters must be specified to be able to generate a key pair.
9296 if (param_3410.size() == 0 || param_3411.size() == 0) {
9297 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
9298 return CKR_TEMPLATE_INCOMPLETE;
9301 // Set the parameters
9303 p.setEC(param_3410);
9305 // Generate key pair
9306 AsymmetricKeyPair* kp = NULL;
9307 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9308 if (gost == NULL) return CKR_GENERAL_ERROR;
9309 if (!gost->generateKeyPair(&kp, &p))
9311 ERROR_MSG("Could not generate key pair");
9312 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9313 return CKR_GENERAL_ERROR;
9316 GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9317 GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9321 // Create a public key using C_CreateObject
9324 const CK_ULONG maxAttribs = 32;
9325 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9326 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9327 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9328 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9329 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9330 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9331 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9333 CK_ULONG publicKeyAttribsCount = 4;
9335 // Add the additional
9336 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9337 rv = CKR_TEMPLATE_INCONSISTENT;
9338 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9340 switch (pPublicKeyTemplate[i].type)
9348 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9353 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9355 // Store the attributes that are being supplied by the key generation to the object
9358 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9359 if (osobject == NULL_PTR || !osobject->isValid()) {
9360 rv = CKR_FUNCTION_FAILED;
9361 } else if (osobject->startTransaction()) {
9364 // Common Key Attributes
9365 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9366 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9367 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9369 // EC Public Key Attributes
9371 if (isPublicKeyPrivate)
9373 token->encrypt(pub->getQ(), point);
9377 point = pub->getQ();
9379 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9382 bOK = osobject->commitTransaction();
9384 osobject->abortTransaction();
9387 rv = CKR_FUNCTION_FAILED;
9389 rv = CKR_FUNCTION_FAILED;
9393 // Create a private key using C_CreateObject
9396 const CK_ULONG maxAttribs = 32;
9397 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9398 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9399 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9400 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9401 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9402 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9403 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9405 CK_ULONG privateKeyAttribsCount = 4;
9406 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9407 rv = CKR_TEMPLATE_INCONSISTENT;
9408 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9410 switch (pPrivateKeyTemplate[i].type)
9418 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9423 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9425 // Store the attributes that are being supplied by the key generation to the object
9428 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9429 if (osobject == NULL_PTR || !osobject->isValid()) {
9430 rv = CKR_FUNCTION_FAILED;
9431 } else if (osobject->startTransaction()) {
9434 // Common Key Attributes
9435 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9436 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9437 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9439 // Common Private Key Attributes
9440 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9441 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9442 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9443 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9445 // GOST Private Key Attributes
9450 if (isPrivateKeyPrivate)
9452 token->encrypt(priv->getD(), value);
9453 token->encrypt(priv->getEC(), param_a);
9454 token->encrypt(param_3411, param_b);
9455 token->encrypt(param_28147, param_c);
9459 value = priv->getD();
9460 param_a = priv->getEC();
9461 param_b = param_3411;
9462 param_c = param_28147;
9464 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9465 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9466 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9467 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9470 bOK = osobject->commitTransaction();
9472 osobject->abortTransaction();
9475 rv = CKR_FUNCTION_FAILED;
9477 rv = CKR_FUNCTION_FAILED;
9482 gost->recycleKeyPair(kp);
9483 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9485 // Remove keys that may have been created already when the function fails.
9488 if (*phPrivateKey != CK_INVALID_HANDLE)
9490 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9491 handleManager->destroyObject(*phPrivateKey);
9492 if (ospriv) ospriv->destroyObject();
9493 *phPrivateKey = CK_INVALID_HANDLE;
9496 if (*phPublicKey != CK_INVALID_HANDLE)
9498 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9499 handleManager->destroyObject(*phPublicKey);
9500 if (ospub) ospub->destroyObject();
9501 *phPublicKey = CK_INVALID_HANDLE;
9508 // Derive a DH secret
9509 CK_RV SoftHSM::deriveDH
9510 (CK_SESSION_HANDLE hSession,
9511 CK_MECHANISM_PTR pMechanism,
9512 CK_OBJECT_HANDLE hBaseKey,
9513 CK_ATTRIBUTE_PTR pTemplate,
9515 CK_OBJECT_HANDLE_PTR phKey,
9516 CK_KEY_TYPE keyType,
9520 *phKey = CK_INVALID_HANDLE;
9522 if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9523 if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9526 Session* session = (Session*)handleManager->getSession(hSession);
9527 if (session == NULL)
9528 return CKR_SESSION_HANDLE_INVALID;
9531 Token* token = session->getToken();
9533 return CKR_GENERAL_ERROR;
9535 // Extract desired parameter information
9537 bool checkValue = true;
9538 for (CK_ULONG i = 0; i < ulCount; i++)
9540 switch (pTemplate[i].type)
9543 INFO_MSG("CKA_VALUE must not be included");
9544 return CKR_ATTRIBUTE_READ_ONLY;
9546 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9548 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9549 return CKR_ATTRIBUTE_VALUE_INVALID;
9551 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9553 case CKA_CHECK_VALUE:
9554 if (pTemplate[i].ulValueLen > 0)
9556 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9557 return CKR_ATTRIBUTE_VALUE_INVALID;
9569 case CKK_GENERIC_SECRET:
9572 INFO_MSG("CKA_VALUE_LEN must be set");
9573 return CKR_TEMPLATE_INCOMPLETE;
9580 INFO_MSG("CKA_VALUE_LEN must not be set");
9581 return CKR_ATTRIBUTE_READ_ONLY;
9589 INFO_MSG("CKA_VALUE_LEN must not be set");
9590 return CKR_ATTRIBUTE_READ_ONLY;
9597 INFO_MSG("CKA_VALUE_LEN must not be set");
9598 return CKR_ATTRIBUTE_READ_ONLY;
9603 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9605 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9606 return CKR_ATTRIBUTE_VALUE_INVALID;
9610 return CKR_ATTRIBUTE_VALUE_INVALID;
9613 // Get the base key handle
9614 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9615 if (baseKey == NULL || !baseKey->isValid())
9616 return CKR_KEY_HANDLE_INVALID;
9618 // Get the DH algorithm handler
9619 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9621 return CKR_MECHANISM_INVALID;
9624 PrivateKey* privateKey = dh->newPrivateKey();
9625 if (privateKey == NULL)
9627 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9628 return CKR_HOST_MEMORY;
9630 if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9632 dh->recyclePrivateKey(privateKey);
9633 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9634 return CKR_GENERAL_ERROR;
9637 ByteString mechParameters;
9638 mechParameters.resize(pMechanism->ulParameterLen);
9639 memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9640 PublicKey* publicKey = dh->newPublicKey();
9641 if (publicKey == NULL)
9643 dh->recyclePrivateKey(privateKey);
9644 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9645 return CKR_HOST_MEMORY;
9647 if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9649 dh->recyclePrivateKey(privateKey);
9650 dh->recyclePublicKey(publicKey);
9651 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9652 return CKR_GENERAL_ERROR;
9655 // Derive the secret
9656 SymmetricKey* secret = NULL;
9658 if (!dh->deriveKey(&secret, publicKey, privateKey))
9659 rv = CKR_GENERAL_ERROR;
9660 dh->recyclePrivateKey(privateKey);
9661 dh->recyclePublicKey(publicKey);
9663 // Create the secret object using C_CreateObject
9664 const CK_ULONG maxAttribs = 32;
9665 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9666 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9667 { CKA_CLASS, &objClass, sizeof(objClass) },
9668 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9669 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9670 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9672 CK_ULONG secretAttribsCount = 4;
9674 // Add the additional
9675 if (ulCount > (maxAttribs - secretAttribsCount))
9676 rv = CKR_TEMPLATE_INCONSISTENT;
9677 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9679 switch (pTemplate[i].type)
9685 case CKA_CHECK_VALUE:
9688 secretAttribs[secretAttribsCount++] = pTemplate[i];
9693 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9695 // Store the attributes that are being supplied
9698 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9699 if (osobject == NULL_PTR || !osobject->isValid()) {
9700 rv = CKR_FUNCTION_FAILED;
9701 } else if (osobject->startTransaction()) {
9704 // Common Attributes
9705 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9707 // Common Secret Key Attributes
9708 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9710 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9711 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9715 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9717 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9719 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9720 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9724 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9727 // Secret Attributes
9728 ByteString secretValue = secret->getKeyBits();
9730 ByteString plainKCV;
9733 if (byteLen > secretValue.size())
9735 INFO_MSG("The derived secret is too short");
9740 // Truncate value when requested, remove from the leading end
9741 if (byteLen < secretValue.size())
9742 secretValue.split(secretValue.size() - byteLen);
9744 // Fix the odd parity for DES
9745 if (keyType == CKK_DES ||
9746 keyType == CKK_DES2 ||
9747 keyType == CKK_DES3)
9749 for (size_t i = 0; i < secretValue.size(); i++)
9751 secretValue[i] = odd_parity[secretValue[i]];
9758 case CKK_GENERIC_SECRET:
9759 secret->setBitLen(byteLen * 8);
9760 plainKCV = secret->getKeyCheckValue();
9765 secret->setBitLen(byteLen * 7);
9766 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9769 secret->setBitLen(byteLen * 8);
9770 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9779 token->encrypt(secretValue, value);
9780 token->encrypt(plainKCV, kcv);
9784 value = secretValue;
9788 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9790 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9793 bOK = osobject->commitTransaction();
9795 osobject->abortTransaction();
9798 rv = CKR_FUNCTION_FAILED;
9800 rv = CKR_FUNCTION_FAILED;
9804 dh->recycleSymmetricKey(secret);
9805 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9807 // Remove secret that may have been created already when the function fails.
9810 if (*phKey != CK_INVALID_HANDLE)
9812 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9813 handleManager->destroyObject(*phKey);
9814 if (ossecret) ossecret->destroyObject();
9815 *phKey = CK_INVALID_HANDLE;
9822 // Derive an ECDH secret
9823 CK_RV SoftHSM::deriveECDH
9824 (CK_SESSION_HANDLE hSession,
9825 CK_MECHANISM_PTR pMechanism,
9826 CK_OBJECT_HANDLE hBaseKey,
9827 CK_ATTRIBUTE_PTR pTemplate,
9829 CK_OBJECT_HANDLE_PTR phKey,
9830 CK_KEY_TYPE keyType,
9835 *phKey = CK_INVALID_HANDLE;
9837 if ((pMechanism->pParameter == NULL_PTR) ||
9838 (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9840 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9841 return CKR_MECHANISM_PARAM_INVALID;
9843 if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9845 DEBUG_MSG("kdf must be CKD_NULL");
9846 return CKR_MECHANISM_PARAM_INVALID;
9848 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9849 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9851 DEBUG_MSG("there must be no shared data");
9852 return CKR_MECHANISM_PARAM_INVALID;
9854 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9855 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9857 DEBUG_MSG("there must be a public data");
9858 return CKR_MECHANISM_PARAM_INVALID;
9862 Session* session = (Session*)handleManager->getSession(hSession);
9863 if (session == NULL)
9864 return CKR_SESSION_HANDLE_INVALID;
9867 Token* token = session->getToken();
9869 return CKR_GENERAL_ERROR;
9871 // Extract desired parameter information
9873 bool checkValue = true;
9874 for (CK_ULONG i = 0; i < ulCount; i++)
9876 switch (pTemplate[i].type)
9879 INFO_MSG("CKA_VALUE must not be included");
9880 return CKR_ATTRIBUTE_READ_ONLY;
9882 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9884 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9885 return CKR_ATTRIBUTE_VALUE_INVALID;
9887 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9889 case CKA_CHECK_VALUE:
9890 if (pTemplate[i].ulValueLen > 0)
9892 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9893 return CKR_ATTRIBUTE_VALUE_INVALID;
9903 // byteLen == 0 impiles return max size the ECC can derive
9906 case CKK_GENERIC_SECRET:
9910 if (byteLen != 0 && byteLen != 8)
9912 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9913 return CKR_ATTRIBUTE_VALUE_INVALID;
9919 if (byteLen != 0 && byteLen != 16)
9921 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9922 return CKR_ATTRIBUTE_VALUE_INVALID;
9927 if (byteLen != 0 && byteLen != 24)
9929 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9930 return CKR_ATTRIBUTE_VALUE_INVALID;
9935 if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9937 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9938 return CKR_ATTRIBUTE_VALUE_INVALID;
9942 return CKR_ATTRIBUTE_VALUE_INVALID;
9945 // Get the base key handle
9946 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9947 if (baseKey == NULL || !baseKey->isValid())
9948 return CKR_KEY_HANDLE_INVALID;
9950 // Get the ECDH algorithm handler
9951 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9953 return CKR_MECHANISM_INVALID;
9956 PrivateKey* privateKey = ecdh->newPrivateKey();
9957 if (privateKey == NULL)
9959 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9960 return CKR_HOST_MEMORY;
9962 if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9964 ecdh->recyclePrivateKey(privateKey);
9965 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9966 return CKR_GENERAL_ERROR;
9969 ByteString publicData;
9970 publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9971 memcpy(&publicData[0],
9972 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9973 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9974 PublicKey* publicKey = ecdh->newPublicKey();
9975 if (publicKey == NULL)
9977 ecdh->recyclePrivateKey(privateKey);
9978 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9979 return CKR_HOST_MEMORY;
9981 if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9983 ecdh->recyclePrivateKey(privateKey);
9984 ecdh->recyclePublicKey(publicKey);
9985 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9986 return CKR_GENERAL_ERROR;
9989 // Derive the secret
9990 SymmetricKey* secret = NULL;
9992 if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9993 rv = CKR_GENERAL_ERROR;
9994 ecdh->recyclePrivateKey(privateKey);
9995 ecdh->recyclePublicKey(publicKey);
9997 // Create the secret object using C_CreateObject
9998 const CK_ULONG maxAttribs = 32;
9999 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10000 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10001 { CKA_CLASS, &objClass, sizeof(objClass) },
10002 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10003 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10004 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10006 CK_ULONG secretAttribsCount = 4;
10008 // Add the additional
10009 if (ulCount > (maxAttribs - secretAttribsCount))
10010 rv = CKR_TEMPLATE_INCONSISTENT;
10011 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10013 switch (pTemplate[i].type)
10019 case CKA_CHECK_VALUE:
10022 secretAttribs[secretAttribsCount++] = pTemplate[i];
10027 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10029 // Store the attributes that are being supplied
10032 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10033 if (osobject == NULL_PTR || !osobject->isValid()) {
10034 rv = CKR_FUNCTION_FAILED;
10035 } else if (osobject->startTransaction()) {
10038 // Common Attributes
10039 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10041 // Common Secret Key Attributes
10042 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10044 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10045 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10049 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10051 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10053 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10054 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10058 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10061 // Secret Attributes
10062 ByteString secretValue = secret->getKeyBits();
10064 ByteString plainKCV;
10067 // For generic and AES keys:
10068 // default to return max size available.
10073 case CKK_GENERIC_SECRET:
10074 byteLen = secretValue.size();
10077 if (secretValue.size() >= 32)
10079 else if (secretValue.size() >= 24)
10086 if (byteLen > secretValue.size())
10088 INFO_MSG("The derived secret is too short");
10093 // Truncate value when requested, remove from the leading end
10094 if (byteLen < secretValue.size())
10095 secretValue.split(secretValue.size() - byteLen);
10097 // Fix the odd parity for DES
10098 if (keyType == CKK_DES ||
10099 keyType == CKK_DES2 ||
10100 keyType == CKK_DES3)
10102 for (size_t i = 0; i < secretValue.size(); i++)
10104 secretValue[i] = odd_parity[secretValue[i]];
10111 case CKK_GENERIC_SECRET:
10112 secret->setBitLen(byteLen * 8);
10113 plainKCV = secret->getKeyCheckValue();
10118 secret->setBitLen(byteLen * 7);
10119 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10122 secret->setBitLen(byteLen * 8);
10123 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10132 token->encrypt(secretValue, value);
10133 token->encrypt(plainKCV, kcv);
10137 value = secretValue;
10141 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10143 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10146 bOK = osobject->commitTransaction();
10148 osobject->abortTransaction();
10151 rv = CKR_FUNCTION_FAILED;
10153 rv = CKR_FUNCTION_FAILED;
10157 ecdh->recycleSymmetricKey(secret);
10158 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
10160 // Remove secret that may have been created already when the function fails.
10163 if (*phKey != CK_INVALID_HANDLE)
10165 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10166 handleManager->destroyObject(*phKey);
10167 if (ossecret) ossecret->destroyObject();
10168 *phKey = CK_INVALID_HANDLE;
10174 return CKR_MECHANISM_INVALID;
10178 // Derive an symmetric secret
10179 CK_RV SoftHSM::deriveSymmetric
10180 (CK_SESSION_HANDLE hSession,
10181 CK_MECHANISM_PTR pMechanism,
10182 CK_OBJECT_HANDLE hBaseKey,
10183 CK_ATTRIBUTE_PTR pTemplate,
10185 CK_OBJECT_HANDLE_PTR phKey,
10186 CK_KEY_TYPE keyType,
10187 CK_BBOOL isOnToken,
10188 CK_BBOOL isPrivate)
10190 *phKey = CK_INVALID_HANDLE;
10192 if (pMechanism->pParameter == NULL_PTR)
10194 DEBUG_MSG("pParameter must be supplied");
10195 return CKR_MECHANISM_PARAM_INVALID;
10200 if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
10201 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
10202 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10204 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10205 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10206 if (ulLen == 0 || pData == NULL_PTR)
10208 DEBUG_MSG("There must be data in the parameter");
10209 return CKR_MECHANISM_PARAM_INVALID;
10211 if (ulLen % 8 != 0)
10213 DEBUG_MSG("The data must be a multiple of 8 bytes long");
10214 return CKR_MECHANISM_PARAM_INVALID;
10216 data.resize(ulLen);
10221 else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
10222 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
10223 pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
10225 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10226 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10227 if (length == 0 || pData == NULL_PTR)
10229 DEBUG_MSG("There must be data in the parameter");
10230 return CKR_MECHANISM_PARAM_INVALID;
10232 if (length % 8 != 0)
10234 DEBUG_MSG("The data must be a multiple of 8 bytes long");
10235 return CKR_MECHANISM_PARAM_INVALID;
10237 data.resize(length);
10242 else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
10243 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10245 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10246 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10247 if (ulLen == 0 || pData == NULL_PTR)
10249 DEBUG_MSG("There must be data in the parameter");
10250 return CKR_MECHANISM_PARAM_INVALID;
10252 if (ulLen % 16 != 0)
10254 DEBUG_MSG("The data must be a multiple of 16 bytes long");
10255 return CKR_MECHANISM_PARAM_INVALID;
10257 data.resize(ulLen);
10262 else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
10263 pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
10265 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10266 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10267 if (length == 0 || pData == NULL_PTR)
10269 DEBUG_MSG("There must be data in the parameter");
10270 return CKR_MECHANISM_PARAM_INVALID;
10272 if (length % 16 != 0)
10274 DEBUG_MSG("The data must be a multiple of 16 bytes long");
10275 return CKR_MECHANISM_PARAM_INVALID;
10277 data.resize(length);
10284 DEBUG_MSG("pParameter is invalid");
10285 return CKR_MECHANISM_PARAM_INVALID;
10289 Session* session = (Session*)handleManager->getSession(hSession);
10290 if (session == NULL)
10291 return CKR_SESSION_HANDLE_INVALID;
10294 Token* token = session->getToken();
10296 return CKR_GENERAL_ERROR;
10298 // Extract desired parameter information
10299 size_t byteLen = 0;
10300 bool checkValue = true;
10301 for (CK_ULONG i = 0; i < ulCount; i++)
10303 switch (pTemplate[i].type)
10306 INFO_MSG("CKA_VALUE must not be included");
10307 return CKR_ATTRIBUTE_READ_ONLY;
10308 case CKA_VALUE_LEN:
10309 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10311 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10312 return CKR_ATTRIBUTE_VALUE_INVALID;
10314 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10316 case CKA_CHECK_VALUE:
10317 if (pTemplate[i].ulValueLen > 0)
10319 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10320 return CKR_ATTRIBUTE_VALUE_INVALID;
10322 checkValue = false;
10329 // Check the length
10332 case CKK_GENERIC_SECRET:
10335 INFO_MSG("CKA_VALUE_LEN must be set");
10336 return CKR_TEMPLATE_INCOMPLETE;
10343 INFO_MSG("CKA_VALUE_LEN must not be set");
10344 return CKR_ATTRIBUTE_READ_ONLY;
10352 INFO_MSG("CKA_VALUE_LEN must not be set");
10353 return CKR_ATTRIBUTE_READ_ONLY;
10360 INFO_MSG("CKA_VALUE_LEN must not be set");
10361 return CKR_ATTRIBUTE_READ_ONLY;
10366 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10368 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10369 return CKR_ATTRIBUTE_VALUE_INVALID;
10373 return CKR_ATTRIBUTE_VALUE_INVALID;
10376 // Get the symmetric algorithm matching the mechanism
10377 SymAlgo::Type algo = SymAlgo::Unknown;
10378 SymMode::Type mode = SymMode::Unknown;
10379 bool padding = false;
10382 switch(pMechanism->mechanism) {
10384 case CKM_DES_ECB_ENCRYPT_DATA:
10385 algo = SymAlgo::DES;
10386 mode = SymMode::ECB;
10389 case CKM_DES_CBC_ENCRYPT_DATA:
10390 algo = SymAlgo::DES;
10391 mode = SymMode::CBC;
10395 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10399 case CKM_DES3_ECB_ENCRYPT_DATA:
10400 algo = SymAlgo::DES3;
10401 mode = SymMode::ECB;
10404 case CKM_DES3_CBC_ENCRYPT_DATA:
10405 algo = SymAlgo::DES3;
10406 mode = SymMode::CBC;
10410 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10413 case CKM_AES_ECB_ENCRYPT_DATA:
10414 algo = SymAlgo::AES;
10415 mode = SymMode::ECB;
10417 case CKM_AES_CBC_ENCRYPT_DATA:
10418 algo = SymAlgo::AES;
10419 mode = SymMode::CBC;
10422 &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10426 return CKR_MECHANISM_INVALID;
10429 // Check the key handle
10430 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10431 if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10433 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10434 if (cipher == NULL) return CKR_MECHANISM_INVALID;
10436 SymmetricKey* secretkey = new SymmetricKey();
10438 if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10440 cipher->recycleKey(secretkey);
10441 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10442 return CKR_GENERAL_ERROR;
10445 // adjust key bit length
10446 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10448 // Initialize encryption
10449 if (!cipher->encryptInit(secretkey, mode, iv, padding))
10451 cipher->recycleKey(secretkey);
10452 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10453 return CKR_MECHANISM_INVALID;
10457 ByteString secretValue;
10459 // Encrypt the data
10460 if (!cipher->encryptUpdate(data, secretValue))
10462 cipher->recycleKey(secretkey);
10463 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10464 return CKR_GENERAL_ERROR;
10467 // Finalize encryption
10468 ByteString encryptedFinal;
10469 if (!cipher->encryptFinal(encryptedFinal))
10471 cipher->recycleKey(secretkey);
10472 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10473 return CKR_GENERAL_ERROR;
10475 cipher->recycleKey(secretkey);
10476 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10477 secretValue += encryptedFinal;
10479 // Create the secret object using C_CreateObject
10480 const CK_ULONG maxAttribs = 32;
10481 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10482 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10483 { CKA_CLASS, &objClass, sizeof(objClass) },
10484 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10485 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10486 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10488 CK_ULONG secretAttribsCount = 4;
10490 // Add the additional
10492 if (ulCount > (maxAttribs - secretAttribsCount))
10493 rv = CKR_TEMPLATE_INCONSISTENT;
10494 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10496 switch (pTemplate[i].type)
10502 case CKA_CHECK_VALUE:
10505 secretAttribs[secretAttribsCount++] = pTemplate[i];
10510 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10512 // Store the attributes that are being supplied
10515 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10516 if (osobject == NULL_PTR || !osobject->isValid()) {
10517 rv = CKR_FUNCTION_FAILED;
10518 } else if (osobject->startTransaction()) {
10521 // Common Attributes
10522 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10524 // Common Secret Key Attributes
10525 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10527 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10528 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10532 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10534 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10536 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10537 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10541 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10545 ByteString plainKCV;
10548 if (byteLen > secretValue.size())
10550 INFO_MSG("The derived secret is too short");
10555 // Truncate value when requested, remove from the trailing end
10556 if (byteLen < secretValue.size())
10557 secretValue.resize(byteLen);
10559 // Fix the odd parity for DES
10560 if (keyType == CKK_DES ||
10561 keyType == CKK_DES2 ||
10562 keyType == CKK_DES3)
10564 for (size_t i = 0; i < secretValue.size(); i++)
10566 secretValue[i] = odd_parity[secretValue[i]];
10571 SymmetricKey* secret = new SymmetricKey();
10572 secret->setKeyBits(secretValue);
10575 case CKK_GENERIC_SECRET:
10576 secret->setBitLen(byteLen * 8);
10577 plainKCV = secret->getKeyCheckValue();
10582 secret->setBitLen(byteLen * 7);
10583 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10586 secret->setBitLen(byteLen * 8);
10587 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10597 token->encrypt(secretValue, value);
10598 token->encrypt(plainKCV, kcv);
10602 value = secretValue;
10606 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10608 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10611 bOK = osobject->commitTransaction();
10613 osobject->abortTransaction();
10616 rv = CKR_FUNCTION_FAILED;
10618 rv = CKR_FUNCTION_FAILED;
10621 // Remove secret that may have been created already when the function fails.
10624 if (*phKey != CK_INVALID_HANDLE)
10626 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10627 handleManager->destroyObject(*phKey);
10628 if (ossecret) ossecret->destroyObject();
10629 *phKey = CK_INVALID_HANDLE;
10636 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10638 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10640 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10641 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10644 Session* session = (Session*)handleManager->getSession(hSession);
10645 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10648 Slot* slot = session->getSlot();
10649 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10652 Token* token = session->getToken();
10653 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10655 // Extract information from the template that is needed to create the object.
10656 CK_OBJECT_CLASS objClass = CKO_DATA;
10657 CK_KEY_TYPE keyType = CKK_RSA;
10658 CK_CERTIFICATE_TYPE certType = CKC_X_509;
10659 CK_BBOOL isOnToken = CK_FALSE;
10660 CK_BBOOL isPrivate = CK_TRUE;
10661 bool isImplicit = false;
10662 CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10665 ERROR_MSG("Mandatory attribute not present in template");
10669 // Check user credentials
10670 rv = haveWrite(session->getState(), isOnToken, isPrivate);
10673 if (rv == CKR_USER_NOT_LOGGED_IN)
10674 INFO_MSG("User is not authorized");
10675 if (rv == CKR_SESSION_READ_ONLY)
10676 INFO_MSG("Session is read-only");
10681 // Change order of attributes
10682 const CK_ULONG maxAttribs = 32;
10683 CK_ATTRIBUTE attribs[maxAttribs];
10684 CK_ATTRIBUTE saveAttribs[maxAttribs];
10685 CK_ULONG attribsCount = 0;
10686 CK_ULONG saveAttribsCount = 0;
10687 if (ulCount > maxAttribs)
10689 return CKR_TEMPLATE_INCONSISTENT;
10691 for (CK_ULONG i=0; i < ulCount; i++)
10693 switch (pTemplate[i].type)
10695 case CKA_CHECK_VALUE:
10696 saveAttribs[saveAttribsCount++] = pTemplate[i];
10699 attribs[attribsCount++] = pTemplate[i];
10702 for (CK_ULONG i=0; i < saveAttribsCount; i++)
10704 attribs[attribsCount++] = saveAttribs[i];
10707 P11Object* p11object = NULL;
10708 rv = newP11Object(objClass,keyType,certType,&p11object);
10712 // Create the object in session or on the token
10713 OSObject *object = NULL_PTR;
10716 object = (OSObject*) token->createObject();
10720 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10723 if (object == NULL || !p11object->init(object))
10726 return CKR_GENERAL_ERROR;
10729 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10734 if (op == OBJECT_OP_CREATE)
10736 if (objClass == CKO_PUBLIC_KEY &&
10737 (!object->startTransaction() ||
10738 !object->setAttribute(CKA_LOCAL, false) ||
10739 !object->commitTransaction()))
10741 return CKR_GENERAL_ERROR;
10744 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10745 (!object->startTransaction() ||
10746 !object->setAttribute(CKA_LOCAL, false) ||
10747 !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10748 !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10749 !object->commitTransaction()))
10751 return CKR_GENERAL_ERROR;
10757 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10759 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10765 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10767 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10768 if (token == NULL) return CKR_ARGUMENTS_BAD;
10769 if (key == NULL) return CKR_ARGUMENTS_BAD;
10771 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10772 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10774 // RSA Private Key Attributes
10775 ByteString modulus;
10776 ByteString publicExponent;
10777 ByteString privateExponent;
10780 ByteString exponent1;
10781 ByteString exponent2;
10782 ByteString coefficient;
10786 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10787 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10788 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10789 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10790 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10791 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10792 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10793 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10795 return CKR_GENERAL_ERROR;
10799 modulus = key->getByteStringValue(CKA_MODULUS);
10800 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10801 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10802 prime1 = key->getByteStringValue(CKA_PRIME_1);
10803 prime2 = key->getByteStringValue(CKA_PRIME_2);
10804 exponent1 = key->getByteStringValue(CKA_EXPONENT_1);
10805 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10806 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10809 privateKey->setN(modulus);
10810 privateKey->setE(publicExponent);
10811 privateKey->setD(privateExponent);
10812 privateKey->setP(prime1);
10813 privateKey->setQ(prime2);
10814 privateKey->setDP1(exponent1);
10815 privateKey->setDQ1(exponent2);
10816 privateKey->setPQ(coefficient);
10821 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10823 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10824 if (token == NULL) return CKR_ARGUMENTS_BAD;
10825 if (key == NULL) return CKR_ARGUMENTS_BAD;
10827 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10828 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10830 // RSA Public Key Attributes
10831 ByteString modulus;
10832 ByteString publicExponent;
10836 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10837 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10839 return CKR_GENERAL_ERROR;
10843 modulus = key->getByteStringValue(CKA_MODULUS);
10844 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10847 publicKey->setN(modulus);
10848 publicKey->setE(publicExponent);
10853 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10855 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10856 if (token == NULL) return CKR_ARGUMENTS_BAD;
10857 if (key == NULL) return CKR_ARGUMENTS_BAD;
10859 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10860 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10862 // DSA Private Key Attributes
10864 ByteString subprime;
10865 ByteString generator;
10870 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10871 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10872 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10873 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10875 return CKR_GENERAL_ERROR;
10879 prime = key->getByteStringValue(CKA_PRIME);
10880 subprime = key->getByteStringValue(CKA_SUBPRIME);
10881 generator = key->getByteStringValue(CKA_BASE);
10882 value = key->getByteStringValue(CKA_VALUE);
10885 privateKey->setP(prime);
10886 privateKey->setQ(subprime);
10887 privateKey->setG(generator);
10888 privateKey->setX(value);
10893 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10895 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10896 if (token == NULL) return CKR_ARGUMENTS_BAD;
10897 if (key == NULL) return CKR_ARGUMENTS_BAD;
10899 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10900 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10902 // DSA Public Key Attributes
10904 ByteString subprime;
10905 ByteString generator;
10910 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10911 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10912 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10913 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10915 return CKR_GENERAL_ERROR;
10919 prime = key->getByteStringValue(CKA_PRIME);
10920 subprime = key->getByteStringValue(CKA_SUBPRIME);
10921 generator = key->getByteStringValue(CKA_BASE);
10922 value = key->getByteStringValue(CKA_VALUE);
10925 publicKey->setP(prime);
10926 publicKey->setQ(subprime);
10927 publicKey->setG(generator);
10928 publicKey->setY(value);
10933 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10935 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10936 if (token == NULL) return CKR_ARGUMENTS_BAD;
10937 if (key == NULL) return CKR_ARGUMENTS_BAD;
10939 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10940 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10942 // EC Private Key Attributes
10948 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10949 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10951 return CKR_GENERAL_ERROR;
10955 group = key->getByteStringValue(CKA_EC_PARAMS);
10956 value = key->getByteStringValue(CKA_VALUE);
10959 privateKey->setEC(group);
10960 privateKey->setD(value);
10965 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10967 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10968 if (token == NULL) return CKR_ARGUMENTS_BAD;
10969 if (key == NULL) return CKR_ARGUMENTS_BAD;
10971 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10972 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10974 // EC Public Key Attributes
10980 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10981 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10983 return CKR_GENERAL_ERROR;
10987 group = key->getByteStringValue(CKA_EC_PARAMS);
10988 point = key->getByteStringValue(CKA_EC_POINT);
10991 publicKey->setEC(group);
10992 publicKey->setQ(point);
10997 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10999 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11000 if (token == NULL) return CKR_ARGUMENTS_BAD;
11001 if (key == NULL) return CKR_ARGUMENTS_BAD;
11003 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11004 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11006 // DH Private Key Attributes
11008 ByteString generator;
11013 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
11014 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
11015 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
11017 return CKR_GENERAL_ERROR;
11021 prime = key->getByteStringValue(CKA_PRIME);
11022 generator = key->getByteStringValue(CKA_BASE);
11023 value = key->getByteStringValue(CKA_VALUE);
11026 privateKey->setP(prime);
11027 privateKey->setG(generator);
11028 privateKey->setX(value);
11033 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
11035 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11036 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11038 // Copy Domain Parameters from Private Key
11039 publicKey->setP(privateKey->getP());
11040 publicKey->setG(privateKey->getG());
11043 publicKey->setY(pubParams);
11048 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
11050 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11051 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11053 // Copy Domain Parameters from Private Key
11054 publicKey->setEC(privateKey->getEC());
11057 ByteString data = getECDHPubData(pubData);
11058 publicKey->setQ(data);
11063 // ECDH pubData can be in RAW or DER format.
11064 // Need to convert RAW as SoftHSM uses DER.
11065 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
11067 size_t len = pubData.size();
11068 size_t controlOctets = 2;
11069 if (len == 65 || len == 97 || len == 133)
11071 // Raw: Length matches the public key size of P-256, P-384, or P-521
11074 else if (len < controlOctets || pubData[0] != 0x04)
11076 // Raw: Too short or does not start with 0x04
11079 else if (pubData[1] < 0x80)
11081 // Raw: Length octet does not match remaining data length
11082 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
11086 size_t lengthOctets = pubData[1] & 0x7F;
11087 controlOctets += lengthOctets;
11089 if (controlOctets >= len)
11096 ByteString length(&pubData[2], lengthOctets);
11098 if (length.long_val() != (len - controlOctets))
11100 // Raw: Length octets does not match remaining data length
11107 if (controlOctets != 0) return pubData;
11114 header[0] = (unsigned char)0x04;
11115 header[1] = (unsigned char)(len & 0x7F);
11119 // Count significate bytes
11120 size_t bytes = sizeof(size_t);
11121 for(; bytes > 0; bytes--)
11123 size_t value = len >> ((bytes - 1) * 8);
11124 if (value & 0xFF) break;
11128 header.resize(2 + bytes);
11129 header[0] = (unsigned char)0x04;
11130 header[1] = (unsigned char)(0x80 | bytes);
11131 for (size_t i = 1; i <= bytes; i++)
11133 header[2+bytes-i] = (unsigned char) (len & 0xFF);
11138 return header + pubData;
11141 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
11143 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11144 if (token == NULL) return CKR_ARGUMENTS_BAD;
11145 if (key == NULL) return CKR_ARGUMENTS_BAD;
11147 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11148 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11150 // GOST Private Key Attributes
11156 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
11157 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11159 return CKR_GENERAL_ERROR;
11163 value = key->getByteStringValue(CKA_VALUE);
11164 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11167 privateKey->setD(value);
11168 privateKey->setEC(param);
11173 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
11175 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11176 if (token == NULL) return CKR_ARGUMENTS_BAD;
11177 if (key == NULL) return CKR_ARGUMENTS_BAD;
11179 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11180 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11182 // GOST Public Key Attributes
11188 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
11189 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11191 return CKR_GENERAL_ERROR;
11195 point = key->getByteStringValue(CKA_VALUE);
11196 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11199 publicKey->setQ(point);
11200 publicKey->setEC(param);
11205 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
11207 if (skey == NULL) return CKR_ARGUMENTS_BAD;
11208 if (token == NULL) return CKR_ARGUMENTS_BAD;
11209 if (key == NULL) return CKR_ARGUMENTS_BAD;
11211 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11212 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11214 ByteString keybits;
11217 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
11218 return CKR_GENERAL_ERROR;
11222 keybits = key->getByteStringValue(CKA_VALUE);
11225 skey->setKeyBits(keybits);
11230 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11232 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
11235 PrivateKey* priv = rsa->newPrivateKey();
11238 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11241 if (!priv->PKCS8Decode(ber))
11243 rsa->recyclePrivateKey(priv);
11244 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11247 // RSA Private Key Attributes
11248 ByteString modulus;
11249 ByteString publicExponent;
11250 ByteString privateExponent;
11253 ByteString exponent1;
11254 ByteString exponent2;
11255 ByteString coefficient;
11258 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
11259 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
11260 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
11261 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
11262 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
11263 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
11264 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
11265 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
11269 modulus = ((RSAPrivateKey*)priv)->getN();
11270 publicExponent = ((RSAPrivateKey*)priv)->getE();
11271 privateExponent = ((RSAPrivateKey*)priv)->getD();
11272 prime1 = ((RSAPrivateKey*)priv)->getP();
11273 prime2 = ((RSAPrivateKey*)priv)->getQ();
11274 exponent1 = ((RSAPrivateKey*)priv)->getDP1();
11275 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
11276 coefficient = ((RSAPrivateKey*)priv)->getPQ();
11279 bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
11280 bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
11281 bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
11282 bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
11283 bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
11284 bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
11285 bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
11286 bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
11288 rsa->recyclePrivateKey(priv);
11289 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11294 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11296 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
11299 PrivateKey* priv = dsa->newPrivateKey();
11302 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11305 if (!priv->PKCS8Decode(ber))
11307 dsa->recyclePrivateKey(priv);
11308 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11311 // DSA Private Key Attributes
11313 ByteString subprime;
11314 ByteString generator;
11318 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11319 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11320 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11321 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11325 prime = ((DSAPrivateKey*)priv)->getP();
11326 subprime = ((DSAPrivateKey*)priv)->getQ();
11327 generator = ((DSAPrivateKey*)priv)->getG();
11328 value = ((DSAPrivateKey*)priv)->getX();
11331 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11332 bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11333 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11334 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11336 dsa->recyclePrivateKey(priv);
11337 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11342 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11344 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11347 PrivateKey* priv = dh->newPrivateKey();
11350 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11353 if (!priv->PKCS8Decode(ber))
11355 dh->recyclePrivateKey(priv);
11356 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11359 // DH Private Key Attributes
11361 ByteString generator;
11365 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11366 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11367 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11371 prime = ((DHPrivateKey*)priv)->getP();
11372 generator = ((DHPrivateKey*)priv)->getG();
11373 value = ((DHPrivateKey*)priv)->getX();
11376 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11377 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11378 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11380 dh->recyclePrivateKey(priv);
11381 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11386 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11388 AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11391 PrivateKey* priv = ecc->newPrivateKey();
11394 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11397 if (!priv->PKCS8Decode(ber))
11399 ecc->recyclePrivateKey(priv);
11400 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11403 // EC Private Key Attributes
11408 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11409 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11413 group = ((ECPrivateKey*)priv)->getEC();
11414 value = ((ECPrivateKey*)priv)->getD();
11417 bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11418 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11420 ecc->recyclePrivateKey(priv);
11421 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11426 bool SoftHSM::setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11428 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
11431 PrivateKey* priv = gost->newPrivateKey();
11434 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11437 if (!priv->PKCS8Decode(ber))
11439 gost->recyclePrivateKey(priv);
11440 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11443 // GOST Private Key Attributes
11445 ByteString param_a;
11448 token->encrypt(((GOSTPrivateKey*)priv)->getD(), value);
11449 token->encrypt(((GOSTPrivateKey*)priv)->getEC(), param_a);
11453 value = ((GOSTPrivateKey*)priv)->getD();
11454 param_a = ((GOSTPrivateKey*)priv)->getEC();
11457 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11458 bOK = bOK && key->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
11460 gost->recyclePrivateKey(priv);
11461 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11466 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11468 // This is a programming error
11469 if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11470 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11471 return CKR_GENERAL_ERROR;
11474 if (pMechanism->pParameter == NULL_PTR ||
11475 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11477 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11478 return CKR_ARGUMENTS_BAD;
11481 CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11482 if (params->hashAlg != CKM_SHA_1)
11484 ERROR_MSG("hashAlg must be CKM_SHA_1");
11485 return CKR_ARGUMENTS_BAD;
11487 if (params->mgf != CKG_MGF1_SHA1)
11489 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11490 return CKR_ARGUMENTS_BAD;
11492 if (params->source != CKZ_DATA_SPECIFIED)
11494 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11495 return CKR_ARGUMENTS_BAD;
11497 if (params->pSourceData != NULL)
11499 ERROR_MSG("pSourceData must be NULL");
11500 return CKR_ARGUMENTS_BAD;
11502 if (params->ulSourceDataLen != 0)
11504 ERROR_MSG("ulSourceDataLen must be 0");
11505 return CKR_ARGUMENTS_BAD;
11510 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11511 OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11512 std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11513 if (allowed.empty()) {
11517 return allowed.find(pMechanism->mechanism) != allowed.end();