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"
70 #if defined(WITH_OPENSSL)
71 #include "OSSLCryptoFactory.h"
73 #include "BotanCryptoFactory.h"
78 // Initialise the one-and-only instance
82 std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
83 std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
84 #if defined(WITH_OPENSSL)
85 std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
87 std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
89 std::unique_ptr<SoftHSM> SoftHSM::instance(nullptr);
93 std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
94 std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
95 #if defined(WITH_OPENSSL)
96 std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
98 std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
100 std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
104 static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
108 *p11object = new P11DataObj();
110 case CKO_CERTIFICATE:
111 if (certType == CKC_X_509)
112 *p11object = new P11X509CertificateObj();
113 else if (certType == CKC_OPENPGP)
114 *p11object = new P11OpenPGPPublicKeyObj();
116 return CKR_ATTRIBUTE_VALUE_INVALID;
119 if (keyType == CKK_RSA)
120 *p11object = new P11RSAPublicKeyObj();
121 else if (keyType == CKK_DSA)
122 *p11object = new P11DSAPublicKeyObj();
123 else if (keyType == CKK_EC)
124 *p11object = new P11ECPublicKeyObj();
125 else if (keyType == CKK_DH)
126 *p11object = new P11DHPublicKeyObj();
127 else if (keyType == CKK_GOSTR3410)
128 *p11object = new P11GOSTPublicKeyObj();
130 return CKR_ATTRIBUTE_VALUE_INVALID;
132 case CKO_PRIVATE_KEY:
133 // we need to know the type too
134 if (keyType == CKK_RSA)
135 *p11object = new P11RSAPrivateKeyObj();
136 else if (keyType == CKK_DSA)
137 *p11object = new P11DSAPrivateKeyObj();
138 else if (keyType == CKK_EC)
139 *p11object = new P11ECPrivateKeyObj();
140 else if (keyType == CKK_DH)
141 *p11object = new P11DHPrivateKeyObj();
142 else if (keyType == CKK_GOSTR3410)
143 *p11object = new P11GOSTPrivateKeyObj();
145 return CKR_ATTRIBUTE_VALUE_INVALID;
148 if ((keyType == CKK_GENERIC_SECRET) ||
149 (keyType == CKK_MD5_HMAC) ||
150 (keyType == CKK_SHA_1_HMAC) ||
151 (keyType == CKK_SHA224_HMAC) ||
152 (keyType == CKK_SHA256_HMAC) ||
153 (keyType == CKK_SHA384_HMAC) ||
154 (keyType == CKK_SHA512_HMAC))
156 P11GenericSecretKeyObj* key = new P11GenericSecretKeyObj();
158 key->setKeyType(keyType);
160 else if (keyType == CKK_AES)
162 *p11object = new P11AESSecretKeyObj();
164 else if ((keyType == CKK_DES) ||
165 (keyType == CKK_DES2) ||
166 (keyType == CKK_DES3))
168 P11DESSecretKeyObj* key = new P11DESSecretKeyObj();
170 key->setKeyType(keyType);
172 else if (keyType == CKK_GOST28147)
174 *p11object = new P11GOSTSecretKeyObj();
177 return CKR_ATTRIBUTE_VALUE_INVALID;
179 case CKO_DOMAIN_PARAMETERS:
180 if (keyType == CKK_DSA)
181 *p11object = new P11DSADomainObj();
182 else if (keyType == CKK_DH)
183 *p11object = new P11DHDomainObj();
185 return CKR_ATTRIBUTE_VALUE_INVALID;
188 return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
193 static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate,
195 CK_OBJECT_CLASS &objClass,
196 CK_KEY_TYPE &keyType,
197 CK_CERTIFICATE_TYPE &certType,
202 bool bHasClass = false;
203 bool bHasKeyType = false;
204 bool bHasCertType = false;
205 bool bHasPrivate = false;
207 // Extract object information
208 for (CK_ULONG i = 0; i < ulCount; ++i)
210 switch (pTemplate[i].type)
213 if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
215 objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
220 if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
222 keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
226 case CKA_CERTIFICATE_TYPE:
227 if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
229 certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
234 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
236 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
240 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
242 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
258 return CKR_TEMPLATE_INCOMPLETE;
261 bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
262 if (bKeyTypeRequired && !bHasKeyType)
264 return CKR_TEMPLATE_INCOMPLETE;
267 if (objClass == CKO_CERTIFICATE)
271 return CKR_TEMPLATE_INCOMPLETE;
275 // Change default value for certificates
276 isPrivate = CK_FALSE;
280 if (objClass == CKO_PUBLIC_KEY && !bHasPrivate)
282 // Change default value for public keys
283 isPrivate = CK_FALSE;
289 static CK_RV newP11Object(OSObject *object, P11Object **p11object)
291 CK_OBJECT_CLASS objClass = object->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
292 CK_KEY_TYPE keyType = CKK_RSA;
293 CK_CERTIFICATE_TYPE certType = CKC_X_509;
294 if (object->attributeExists(CKA_KEY_TYPE))
295 keyType = object->getUnsignedLongValue(CKA_KEY_TYPE, CKK_RSA);
296 if (object->attributeExists(CKA_CERTIFICATE_TYPE))
297 certType = object->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_X_509);
298 CK_RV rv = newP11Object(objClass,keyType,certType,p11object);
301 if (!(*p11object)->init(object))
302 return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
307 static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
309 CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
314 /*****************************************************************************
315 Implementation of SoftHSM class specific functions
316 *****************************************************************************/
318 // Return the one-and-only instance
319 SoftHSM* SoftHSM::i()
323 instance.reset(new SoftHSM());
326 return instance.get();
329 void SoftHSM::reset()
338 isInitialised = false;
340 sessionObjectStore = NULL;
343 sessionManager = NULL;
344 handleManager = NULL;
350 if (handleManager != NULL) delete handleManager;
351 if (sessionManager != NULL) delete sessionManager;
352 if (slotManager != NULL) delete slotManager;
353 if (objectStore != NULL) delete objectStore;
354 if (sessionObjectStore != NULL) delete sessionObjectStore;
357 /*****************************************************************************
358 Implementation of PKCS #11 functions
359 *****************************************************************************/
361 // PKCS #11 initialisation function
362 CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
364 CK_C_INITIALIZE_ARGS_PTR args;
366 // Check if PKCS#11 is already initialized
369 ERROR_MSG("SoftHSM is already initialized");
370 return CKR_CRYPTOKI_ALREADY_INITIALIZED;
373 // Do we have any arguments?
374 if (pInitArgs != NULL_PTR)
376 args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
378 // Must be set to NULL_PTR in this version of PKCS#11
379 if (args->pReserved != NULL_PTR)
381 ERROR_MSG("pReserved must be set to NULL_PTR");
382 return CKR_ARGUMENTS_BAD;
385 // Can we spawn our own threads?
386 // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
388 // DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
389 // return CKR_NEED_TO_CREATE_THREADS;
392 // Are we not supplied with mutex functions?
395 args->CreateMutex == NULL_PTR &&
396 args->DestroyMutex == NULL_PTR &&
397 args->LockMutex == NULL_PTR &&
398 args->UnlockMutex == NULL_PTR
401 // Can we use our own mutex functions?
402 if (args->flags & CKF_OS_LOCKING_OK)
404 // Use our own mutex functions.
405 MutexFactory::i()->setCreateMutex(OSCreateMutex);
406 MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
407 MutexFactory::i()->setLockMutex(OSLockMutex);
408 MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
409 MutexFactory::i()->enable();
413 // The external application is not using threading
414 MutexFactory::i()->disable();
419 // We must have all mutex functions
422 args->CreateMutex == NULL_PTR ||
423 args->DestroyMutex == NULL_PTR ||
424 args->LockMutex == NULL_PTR ||
425 args->UnlockMutex == NULL_PTR
428 ERROR_MSG("Not all mutex functions are supplied");
429 return CKR_ARGUMENTS_BAD;
432 // We could use our own mutex functions if the flag is set,
433 // but we use the external functions in both cases.
435 // Load the external mutex functions
436 MutexFactory::i()->setCreateMutex(args->CreateMutex);
437 MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
438 MutexFactory::i()->setLockMutex(args->LockMutex);
439 MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
440 MutexFactory::i()->enable();
445 // No concurrent access by multiple threads
446 MutexFactory::i()->disable();
449 // Initiate SecureMemoryRegistry
450 if (SecureMemoryRegistry::i() == NULL)
452 ERROR_MSG("Could not load the SecureMemoryRegistry");
453 return CKR_GENERAL_ERROR;
456 // Build the CryptoFactory
457 if (CryptoFactory::i() == NULL)
459 ERROR_MSG("Could not load the CryptoFactory");
460 return CKR_GENERAL_ERROR;
464 // Check the FIPS status
465 if (!CryptoFactory::i()->getFipsSelfTestStatus())
467 ERROR_MSG("The FIPS self test failed");
468 return CKR_FIPS_SELF_TEST_FAILED;
472 // (Re)load the configuration
473 if (!Configuration::i()->reload(SimpleConfigLoader::i()))
475 ERROR_MSG("Could not load the configuration");
476 return CKR_GENERAL_ERROR;
479 // Configure the log level
480 if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
482 ERROR_MSG("Could not set the log level");
483 return CKR_GENERAL_ERROR;
486 // Configure object store storage backend used by all tokens.
487 if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
489 ERROR_MSG("Could not set the storage backend");
490 return CKR_GENERAL_ERROR;
493 sessionObjectStore = new SessionObjectStore();
495 // Load the object store
496 objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
497 if (!objectStore->isValid())
499 WARNING_MSG("Could not load the object store");
502 delete sessionObjectStore;
503 sessionObjectStore = NULL;
504 return CKR_GENERAL_ERROR;
507 isRemovable = Configuration::i()->getBool("slots.removable", false);
509 // Load the slot manager
510 slotManager = new SlotManager(objectStore);
512 // Load the session manager
513 sessionManager = new SessionManager();
515 // Load the handle manager
516 handleManager = new HandleManager();
518 // Set the state to initialised
519 isInitialised = true;
524 // PKCS #11 finalisation function
525 CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
527 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
529 // Must be set to NULL_PTR in this version of PKCS#11
530 if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
532 if (handleManager != NULL) delete handleManager;
533 handleManager = NULL;
534 if (sessionManager != NULL) delete sessionManager;
535 sessionManager = NULL;
536 if (slotManager != NULL) delete slotManager;
538 if (objectStore != NULL) delete objectStore;
540 if (sessionObjectStore != NULL) delete sessionObjectStore;
541 sessionObjectStore = NULL;
542 CryptoFactory::reset();
543 SecureMemoryRegistry::reset();
545 isInitialised = false;
551 // Return information about the PKCS #11 module
552 CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
554 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
555 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
557 pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
558 pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
559 memset(pInfo->manufacturerID, ' ', 32);
560 memcpy(pInfo->manufacturerID, "SoftHSM", 7);
562 memset(pInfo->libraryDescription, ' ', 32);
564 memcpy(pInfo->libraryDescription, "Implementation of PKCS11+FIPS", 29);
566 memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
568 pInfo->libraryVersion.major = VERSION_MAJOR;
569 pInfo->libraryVersion.minor = VERSION_MINOR;
574 // Return a list of available slots
575 CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
577 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
579 return slotManager->getSlotList(objectStore, tokenPresent, pSlotList, pulCount);
582 // Return information about a slot
583 CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
586 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
588 Slot* slot = slotManager->getSlot(slotID);
591 return CKR_SLOT_ID_INVALID;
594 rv = slot->getSlotInfo(pInfo);
600 pInfo->flags |= CKF_REMOVABLE_DEVICE;
606 // Return information about a token in a slot
607 CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
609 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
611 Slot* slot = slotManager->getSlot(slotID);
614 return CKR_SLOT_ID_INVALID;
617 Token* token = slot->getToken();
620 return CKR_TOKEN_NOT_PRESENT;
623 return token->getTokenInfo(pInfo);
626 // Return the list of supported mechanisms for a given slot
627 CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
629 // A list with the supported mechanisms
630 CK_ULONG nrSupportedMechanisms = 61;
632 nrSupportedMechanisms += 3;
635 nrSupportedMechanisms -= 9;
638 nrSupportedMechanisms += 5;
640 #ifdef HAVE_AES_KEY_WRAP_PAD
641 nrSupportedMechanisms += 1;
644 nrSupportedMechanisms += 1; // CKM_RSA_PKCS_PSS
647 nrSupportedMechanisms += 1;
650 CK_MECHANISM_TYPE supportedMechanisms[] =
668 CKM_RSA_PKCS_KEY_PAIR_GEN,
683 CKM_SHA1_RSA_PKCS_PSS,
684 CKM_SHA224_RSA_PKCS_PSS,
685 CKM_SHA256_RSA_PKCS_PSS,
686 CKM_SHA384_RSA_PKCS_PSS,
687 CKM_SHA512_RSA_PKCS_PSS,
697 CKM_DES_ECB_ENCRYPT_DATA,
698 CKM_DES_CBC_ENCRYPT_DATA,
703 CKM_DES3_ECB_ENCRYPT_DATA,
704 CKM_DES3_CBC_ENCRYPT_DATA,
715 #ifdef HAVE_AES_KEY_WRAP_PAD
716 CKM_AES_KEY_WRAP_PAD,
718 CKM_AES_ECB_ENCRYPT_DATA,
719 CKM_AES_CBC_ENCRYPT_DATA,
721 CKM_DSA_PARAMETER_GEN,
722 CKM_DSA_KEY_PAIR_GEN,
729 CKM_DH_PKCS_KEY_PAIR_GEN,
730 CKM_DH_PKCS_PARAMETER_GEN,
740 CKM_GOSTR3410_KEY_PAIR_GEN,
742 CKM_GOSTR3410_WITH_GOSTR3411
746 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
747 if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
749 Slot* slot = slotManager->getSlot(slotID);
752 return CKR_SLOT_ID_INVALID;
755 if (pMechanismList == NULL_PTR)
757 *pulCount = nrSupportedMechanisms;
762 if (*pulCount < nrSupportedMechanisms)
764 *pulCount = nrSupportedMechanisms;
766 return CKR_BUFFER_TOO_SMALL;
769 *pulCount = nrSupportedMechanisms;
771 for (CK_ULONG i = 0; i < nrSupportedMechanisms; i ++)
773 pMechanismList[i] = supportedMechanisms[i];
779 // Return more information about a mechanism for a given slot
780 CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
782 unsigned long rsaMinSize, rsaMaxSize;
783 unsigned long dsaMinSize, dsaMaxSize;
784 unsigned long dhMinSize, dhMaxSize;
786 unsigned long ecdsaMinSize, ecdsaMaxSize;
787 unsigned long ecdhMinSize, ecdhMaxSize;
790 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
791 if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
793 Slot* slot = slotManager->getSlot(slotID);
796 return CKR_SLOT_ID_INVALID;
799 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
802 rsaMinSize = rsa->getMinKeySize();
803 rsaMaxSize = rsa->getMaxKeySize();
807 return CKR_GENERAL_ERROR;
809 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
811 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
814 dsaMinSize = dsa->getMinKeySize();
815 // Limitation in PKCS#11
816 if (dsaMinSize < 512)
821 dsaMaxSize = dsa->getMaxKeySize();
822 // Limitation in PKCS#11
823 if (dsaMaxSize > 1024)
830 return CKR_GENERAL_ERROR;
832 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
834 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
837 dhMinSize = dh->getMinKeySize();
838 dhMaxSize = dh->getMaxKeySize();
842 return CKR_GENERAL_ERROR;
844 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
847 AsymmetricAlgorithm* ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
850 ecdsaMinSize = ecdsa->getMinKeySize();
851 ecdsaMaxSize = ecdsa->getMaxKeySize();
855 return CKR_GENERAL_ERROR;
857 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
859 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
862 ecdhMinSize = ecdh->getMinKeySize();
863 ecdhMaxSize = ecdh->getMaxKeySize();
867 return CKR_GENERAL_ERROR;
869 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
882 // Key size is not in use
883 pInfo->ulMinKeySize = 0;
884 pInfo->ulMaxKeySize = 0;
885 pInfo->flags = CKF_DIGEST;
889 pInfo->ulMinKeySize = 16;
890 pInfo->ulMaxKeySize = 512;
891 pInfo->flags = CKF_SIGN | CKF_VERIFY;
895 pInfo->ulMinKeySize = 20;
896 pInfo->ulMaxKeySize = 512;
897 pInfo->flags = CKF_SIGN | CKF_VERIFY;
899 case CKM_SHA224_HMAC:
900 pInfo->ulMinKeySize = 28;
901 pInfo->ulMaxKeySize = 512;
902 pInfo->flags = CKF_SIGN | CKF_VERIFY;
904 case CKM_SHA256_HMAC:
905 pInfo->ulMinKeySize = 32;
906 pInfo->ulMaxKeySize = 512;
907 pInfo->flags = CKF_SIGN | CKF_VERIFY;
909 case CKM_SHA384_HMAC:
910 pInfo->ulMinKeySize = 48;
911 pInfo->ulMaxKeySize = 512;
912 pInfo->flags = CKF_SIGN | CKF_VERIFY;
914 case CKM_SHA512_HMAC:
915 pInfo->ulMinKeySize = 64;
916 pInfo->ulMaxKeySize = 512;
917 pInfo->flags = CKF_SIGN | CKF_VERIFY;
919 case CKM_RSA_PKCS_KEY_PAIR_GEN:
920 pInfo->ulMinKeySize = rsaMinSize;
921 pInfo->ulMaxKeySize = rsaMaxSize;
922 pInfo->flags = CKF_GENERATE_KEY_PAIR;
925 pInfo->ulMinKeySize = rsaMinSize;
926 pInfo->ulMaxKeySize = rsaMaxSize;
927 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
930 pInfo->ulMinKeySize = rsaMinSize;
931 pInfo->ulMaxKeySize = rsaMaxSize;
932 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
935 case CKM_MD5_RSA_PKCS:
937 case CKM_SHA1_RSA_PKCS:
938 case CKM_SHA224_RSA_PKCS:
939 case CKM_SHA256_RSA_PKCS:
940 case CKM_SHA384_RSA_PKCS:
941 case CKM_SHA512_RSA_PKCS:
943 case CKM_RSA_PKCS_PSS:
945 case CKM_SHA1_RSA_PKCS_PSS:
946 case CKM_SHA224_RSA_PKCS_PSS:
947 case CKM_SHA256_RSA_PKCS_PSS:
948 case CKM_SHA384_RSA_PKCS_PSS:
949 case CKM_SHA512_RSA_PKCS_PSS:
950 pInfo->ulMinKeySize = rsaMinSize;
951 pInfo->ulMaxKeySize = rsaMaxSize;
952 pInfo->flags = CKF_SIGN | CKF_VERIFY;
954 case CKM_RSA_PKCS_OAEP:
955 pInfo->ulMinKeySize = rsaMinSize;
956 pInfo->ulMaxKeySize = rsaMaxSize;
957 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
960 case CKM_DES_KEY_GEN:
962 case CKM_DES2_KEY_GEN:
963 case CKM_DES3_KEY_GEN:
964 // Key size is not in use
965 pInfo->ulMinKeySize = 0;
966 pInfo->ulMaxKeySize = 0;
967 pInfo->flags = CKF_GENERATE;
972 case CKM_DES_CBC_PAD:
976 case CKM_DES3_CBC_PAD:
977 // Key size is not in use
978 pInfo->ulMinKeySize = 0;
979 pInfo->ulMaxKeySize = 0;
980 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
983 // Key size is not in use
984 pInfo->ulMinKeySize = 0;
985 pInfo->ulMaxKeySize = 0;
986 pInfo->flags = CKF_SIGN | CKF_VERIFY;
988 case CKM_AES_KEY_GEN:
989 pInfo->ulMinKeySize = 16;
990 pInfo->ulMaxKeySize = 32;
991 pInfo->flags = CKF_GENERATE;
995 case CKM_AES_CBC_PAD:
1000 pInfo->ulMinKeySize = 16;
1001 pInfo->ulMaxKeySize = 32;
1002 pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1004 case CKM_AES_KEY_WRAP:
1005 pInfo->ulMinKeySize = 16;
1006 pInfo->ulMaxKeySize = 0x80000000;
1007 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1009 #ifdef HAVE_AES_KEY_WRAP_PAD
1010 case CKM_AES_KEY_WRAP_PAD:
1011 pInfo->ulMinKeySize = 1;
1012 pInfo->ulMaxKeySize = 0x80000000;
1013 pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1017 case CKM_DES_ECB_ENCRYPT_DATA:
1018 case CKM_DES_CBC_ENCRYPT_DATA:
1020 case CKM_DES3_ECB_ENCRYPT_DATA:
1021 case CKM_DES3_CBC_ENCRYPT_DATA:
1022 case CKM_AES_ECB_ENCRYPT_DATA:
1023 case CKM_AES_CBC_ENCRYPT_DATA:
1024 // Key size is not in use
1025 pInfo->ulMinKeySize = 0;
1026 pInfo->ulMaxKeySize = 0;
1027 pInfo->flags = CKF_DERIVE;
1030 pInfo->ulMinKeySize = 16;
1031 pInfo->ulMaxKeySize = 32;
1032 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1034 case CKM_DSA_PARAMETER_GEN:
1035 pInfo->ulMinKeySize = dsaMinSize;
1036 pInfo->ulMaxKeySize = dsaMaxSize;
1037 pInfo->flags = CKF_GENERATE;
1039 case CKM_DSA_KEY_PAIR_GEN:
1040 pInfo->ulMinKeySize = dsaMinSize;
1041 pInfo->ulMaxKeySize = dsaMaxSize;
1042 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1046 case CKM_DSA_SHA224:
1047 case CKM_DSA_SHA256:
1048 case CKM_DSA_SHA384:
1049 case CKM_DSA_SHA512:
1050 pInfo->ulMinKeySize = dsaMinSize;
1051 pInfo->ulMaxKeySize = dsaMaxSize;
1052 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1054 case CKM_DH_PKCS_KEY_PAIR_GEN:
1055 pInfo->ulMinKeySize = dhMinSize;
1056 pInfo->ulMaxKeySize = dhMaxSize;
1057 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1059 case CKM_DH_PKCS_PARAMETER_GEN:
1060 pInfo->ulMinKeySize = dhMinSize;
1061 pInfo->ulMaxKeySize = dhMaxSize;
1062 pInfo->flags = CKF_GENERATE;
1064 case CKM_DH_PKCS_DERIVE:
1065 pInfo->ulMinKeySize = dhMinSize;
1066 pInfo->ulMaxKeySize = dhMaxSize;
1067 pInfo->flags = CKF_DERIVE;
1070 case CKM_EC_KEY_PAIR_GEN:
1071 pInfo->ulMinKeySize = ecdsaMinSize;
1072 pInfo->ulMaxKeySize = ecdsaMaxSize;
1073 #define CKF_EC_COMMOM (CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS)
1074 pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
1077 pInfo->ulMinKeySize = ecdsaMinSize;
1078 pInfo->ulMaxKeySize = ecdsaMaxSize;
1079 pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
1081 case CKM_ECDH1_DERIVE:
1082 pInfo->ulMinKeySize = ecdhMinSize;
1083 pInfo->ulMaxKeySize = ecdhMaxSize;
1084 pInfo->flags = CKF_DERIVE;
1089 // Key size is not in use
1090 pInfo->ulMinKeySize = 0;
1091 pInfo->ulMaxKeySize = 0;
1092 pInfo->flags = CKF_DIGEST;
1094 case CKM_GOSTR3411_HMAC:
1095 // Key size is not in use
1096 pInfo->ulMinKeySize = 32;
1097 pInfo->ulMaxKeySize = 512;
1098 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1100 case CKM_GOSTR3410_KEY_PAIR_GEN:
1101 // Key size is not in use
1102 pInfo->ulMinKeySize = 0;
1103 pInfo->ulMaxKeySize = 0;
1104 pInfo->flags = CKF_GENERATE_KEY_PAIR;
1107 // Key size is not in use
1108 pInfo->ulMinKeySize = 0;
1109 pInfo->ulMaxKeySize = 0;
1110 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1112 case CKM_GOSTR3410_WITH_GOSTR3411:
1113 // Key size is not in use
1114 pInfo->ulMinKeySize = 0;
1115 pInfo->ulMaxKeySize = 0;
1116 pInfo->flags = CKF_SIGN | CKF_VERIFY;
1120 DEBUG_MSG("The selected mechanism is not supported");
1121 return CKR_MECHANISM_INVALID;
1128 // Initialise the token in the specified slot
1129 CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
1131 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1133 Slot* slot = slotManager->getSlot(slotID);
1136 return CKR_SLOT_ID_INVALID;
1139 // Check if any session is open with this token.
1140 if (sessionManager->haveSession(slotID))
1142 return CKR_SESSION_EXISTS;
1146 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1147 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
1149 ByteString soPIN(pPin, ulPinLen);
1151 return slot->initToken(soPIN, pLabel);
1154 // Initialise the user PIN
1155 CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1157 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1160 Session* session = (Session*)handleManager->getSession(hSession);
1161 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1163 // The SO must be logged in
1164 if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
1167 Token* token = session->getToken();
1168 if (token == NULL) return CKR_GENERAL_ERROR;
1171 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1172 if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1174 ByteString userPIN(pPin, ulPinLen);
1176 return token->initUserPIN(userPIN);
1180 CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
1184 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1187 Session* session = (Session*)handleManager->getSession(hSession);
1188 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1190 // Check the new PINs
1191 if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1192 if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1193 if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1195 ByteString oldPIN(pOldPin, ulOldLen);
1196 ByteString newPIN(pNewPin, ulNewLen);
1199 Token* token = session->getToken();
1200 if (token == NULL) return CKR_GENERAL_ERROR;
1202 switch (session->getState())
1204 case CKS_RW_PUBLIC_SESSION:
1205 case CKS_RW_USER_FUNCTIONS:
1206 rv = token->setUserPIN(oldPIN, newPIN);
1208 case CKS_RW_SO_FUNCTIONS:
1209 rv = token->setSOPIN(oldPIN, newPIN);
1212 return CKR_SESSION_READ_ONLY;
1218 // Open a new session to the specified slot
1219 CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
1221 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1223 Slot* slot = slotManager->getSlot(slotID);
1225 CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
1229 // Get a pointer to the session object and store it in the handle manager.
1230 Session* session = sessionManager->getSession(*phSession);
1231 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1232 *phSession = handleManager->addSession(slotID,session);
1237 // Close the given session
1238 CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
1240 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1243 Session* session = (Session*)handleManager->getSession(hSession);
1244 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1246 // Tell the handle manager the session has been closed.
1247 handleManager->sessionClosed(hSession);
1250 // Tell the session object store that the session has closed.
1251 sessionObjectStore->sessionClosed(hSession);
1253 // Tell the session manager the session has been closed.
1254 return sessionManager->closeSession(session->getHandle());
1257 // Close all open sessions
1258 CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
1260 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1263 Slot* slot = slotManager->getSlot(slotID);
1264 if (slot == NULL) return CKR_SLOT_ID_INVALID;
1267 Token* token = slot->getToken();
1268 if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
1270 // Tell the handle manager all sessions were closed for the given slotID.
1271 // The handle manager should then remove all session and object handles for this slot.
1272 handleManager->allSessionsClosed(slotID);
1274 // Tell the session object store that all sessions were closed for the given slotID.
1275 // The session object store should then remove all session objects for this slot.
1276 sessionObjectStore->allSessionsClosed(slotID);
1278 // Finally tell the session manager tho close all sessions for the given slot.
1279 // This will also trigger a logout on the associated token to occur.
1280 return sessionManager->closeAllSessions(slot);
1283 // Retrieve information about the specified session
1284 CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
1286 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1289 Session* session = (Session*)handleManager->getSession(hSession);
1290 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1292 return session->getInfo(pInfo);
1295 // Determine the state of a running operation in a session
1296 CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG_PTR /*pulOperationStateLen*/)
1298 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1301 Session* session = (Session*)handleManager->getSession(hSession);
1302 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1304 return CKR_FUNCTION_NOT_SUPPORTED;
1307 // Set the operation sate in a session
1308 CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG /*ulOperationStateLen*/, CK_OBJECT_HANDLE /*hEncryptionKey*/, CK_OBJECT_HANDLE /*hAuthenticationKey*/)
1310 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1313 Session* session = (Session*)handleManager->getSession(hSession);
1314 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1316 return CKR_FUNCTION_NOT_SUPPORTED;
1319 // Login on the token in the specified session
1320 CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1324 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1327 Session* session = (Session*)handleManager->getSession(hSession);
1328 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1331 if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1332 ByteString pin(pPin, ulPinLen);
1335 Token* token = session->getToken();
1336 if (token == NULL) return CKR_GENERAL_ERROR;
1341 // There cannot exist a R/O session on this slot
1342 if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
1345 rv = token->loginSO(pin);
1349 rv = token->loginUser(pin);
1351 case CKU_CONTEXT_SPECIFIC:
1352 // Check if re-authentication is required
1353 if (!session->getReAuthentication()) return CKR_OPERATION_NOT_INITIALIZED;
1356 rv = token->reAuthenticate(pin);
1357 if (rv == CKR_OK) session->setReAuthentication(false);
1360 return CKR_USER_TYPE_INVALID;
1366 // Log out of the token in the specified session
1367 CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
1369 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1372 Session* session = (Session*)handleManager->getSession(hSession);
1373 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1376 Token* token = session->getToken();
1377 if (token == NULL) return CKR_GENERAL_ERROR;
1382 // [PKCS#11 v2.40, C_Logout] When logout is successful...
1383 // a. Any of the application's handles to private objects become invalid.
1384 // b. Even if a user is later logged back into the token those handles remain invalid.
1385 // c. All private session objects from sessions belonging to the application are destroyed.
1387 // Have the handle manager remove all handles pointing to private objects for this slot.
1388 CK_SLOT_ID slotID = session->getSlot()->getSlotID();
1389 handleManager->tokenLoggedOut(slotID);
1390 sessionObjectStore->tokenLoggedOut(slotID);
1395 // Create a new object on the token in the specified session using the given attribute template
1396 CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
1398 return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
1401 // Create a copy of the object with the specified handle
1402 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)
1404 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1406 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
1407 if (phNewObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1408 *phNewObject = CK_INVALID_HANDLE;
1411 Session* session = (Session*)handleManager->getSession(hSession);
1412 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1415 Slot* slot = session->getSlot();
1416 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1419 Token* token = session->getToken();
1420 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1422 // Check the object handle.
1423 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1424 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1426 CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
1427 CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1429 // Check read user credentials
1430 CK_RV rv = haveRead(session->getState(), wasOnToken, wasPrivate);
1433 if (rv == CKR_USER_NOT_LOGGED_IN)
1434 INFO_MSG("User is not authorized");
1439 // Check if the object is copyable
1440 CK_BBOOL isCopyable = object->getBooleanValue(CKA_COPYABLE, true);
1441 if (!isCopyable) return CKR_ACTION_PROHIBITED;
1443 // Extract critical information from the template
1444 CK_BBOOL isOnToken = wasOnToken;
1445 CK_BBOOL isPrivate = wasPrivate;
1447 for (CK_ULONG i = 0; i < ulCount; i++)
1449 if ((pTemplate[i].type == CKA_TOKEN) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1451 isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
1454 if ((pTemplate[i].type == CKA_PRIVATE) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1456 isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
1461 // Check privacy does not downgrade
1462 if (wasPrivate && !isPrivate) return CKR_TEMPLATE_INCONSISTENT;
1464 // Check write user credentials
1465 rv = haveWrite(session->getState(), isOnToken, isPrivate);
1468 if (rv == CKR_USER_NOT_LOGGED_IN)
1469 INFO_MSG("User is not authorized");
1470 if (rv == CKR_SESSION_READ_ONLY)
1471 INFO_MSG("Session is read-only");
1476 // Create the object in session or on the token
1477 OSObject *newobject = NULL_PTR;
1480 newobject = (OSObject*) token->createObject();
1484 newobject = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
1486 if (newobject == NULL) return CKR_GENERAL_ERROR;
1488 // Copy attributes from object class (CKA_CLASS=0 so the first)
1489 if (!newobject->startTransaction())
1491 newobject->destroyObject();
1492 return CKR_FUNCTION_FAILED;
1495 CK_ATTRIBUTE_TYPE attrType = CKA_CLASS;
1498 if (!object->attributeExists(attrType))
1500 rv = CKR_FUNCTION_FAILED;
1504 OSAttribute attr = object->getAttribute(attrType);
1506 // Upgrade privacy has to encrypt byte strings
1507 if (!wasPrivate && isPrivate &&
1508 attr.isByteStringAttribute() &&
1509 attr.getByteStringValue().size() != 0)
1512 if (!token->encrypt(attr.getByteStringValue(), value) ||
1513 !newobject->setAttribute(attrType, value))
1515 rv = CKR_FUNCTION_FAILED;
1521 if (!newobject->setAttribute(attrType, attr))
1523 rv = CKR_FUNCTION_FAILED;
1527 attrType = object->nextAttributeType(attrType);
1529 while (attrType != CKA_CLASS);
1533 newobject->abortTransaction();
1535 else if (!newobject->commitTransaction())
1537 rv = CKR_FUNCTION_FAILED;
1542 newobject->destroyObject();
1546 // Get the new P11 object
1547 P11Object* newp11object = NULL;
1548 rv = newP11Object(newobject,&newp11object);
1551 newobject->destroyObject();
1555 // Apply the template
1556 rv = newp11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate, ulCount, OBJECT_OP_COPY);
1557 delete newp11object;
1561 newobject->destroyObject();
1568 *phNewObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, newobject);
1572 *phNewObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, newobject);
1578 // Destroy the specified object
1579 CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
1581 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1584 Session* session = (Session*)handleManager->getSession(hSession);
1585 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1588 Token* token = session->getToken();
1589 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1591 // Check the object handle.
1592 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1593 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1595 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1596 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1598 // Check user credentials
1599 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1602 if (rv == CKR_USER_NOT_LOGGED_IN)
1603 INFO_MSG("User is not authorized");
1604 if (rv == CKR_SESSION_READ_ONLY)
1605 INFO_MSG("Session is read-only");
1610 // Check if the object is destroyable
1611 CK_BBOOL isDestroyable = object->getBooleanValue(CKA_DESTROYABLE, true);
1612 if (!isDestroyable) return CKR_ACTION_PROHIBITED;
1614 // Tell the handleManager to forget about the object.
1615 handleManager->destroyObject(hObject);
1617 // Destroy the object
1618 if (!object->destroyObject())
1619 return CKR_FUNCTION_FAILED;
1624 // Determine the size of the specified object
1625 CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
1627 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1629 if (pulSize == NULL) return CKR_ARGUMENTS_BAD;
1632 Session* session = (Session*)handleManager->getSession(hSession);
1633 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1636 Token* token = session->getToken();
1637 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1639 // Check the object handle.
1640 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1641 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1643 *pulSize = CK_UNAVAILABLE_INFORMATION;
1648 // Retrieve the specified attributes for the given object
1649 CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1651 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1653 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1656 Session* session = (Session*)handleManager->getSession(hSession);
1657 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1660 Token* token = session->getToken();
1661 if (token == NULL) return CKR_GENERAL_ERROR;
1663 // Check the object handle.
1664 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1665 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1667 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1668 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1670 // Check read user credentials
1671 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
1674 if (rv == CKR_USER_NOT_LOGGED_IN)
1675 INFO_MSG("User is not authorized");
1677 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
1678 // so we use CKR_GENERAL_ERROR.
1679 return CKR_GENERAL_ERROR;
1682 // Wrap a P11Object around the OSObject so we can access the attributes in the
1683 // context of the object in which it is defined.
1684 P11Object* p11object = NULL;
1685 rv = newP11Object(object,&p11object);
1689 // Ask the P11Object to fill the template with attribute values.
1690 rv = p11object->loadTemplate(token, pTemplate,ulCount);
1695 // Change or set the value of the specified attributes on the specified object
1696 CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1698 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1700 if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1703 Session* session = (Session*)handleManager->getSession(hSession);
1704 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1707 Token* token = session->getToken();
1708 if (token == NULL) return CKR_GENERAL_ERROR;
1710 // Check the object handle.
1711 OSObject *object = (OSObject *)handleManager->getObject(hObject);
1712 if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1714 CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1715 CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1717 // Check user credentials
1718 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1721 if (rv == CKR_USER_NOT_LOGGED_IN)
1722 INFO_MSG("User is not authorized");
1723 if (rv == CKR_SESSION_READ_ONLY)
1724 INFO_MSG("Session is read-only");
1729 // Check if the object is modifiable
1730 CK_BBOOL isModifiable = object->getBooleanValue(CKA_MODIFIABLE, true);
1731 if (!isModifiable) return CKR_ACTION_PROHIBITED;
1733 // Wrap a P11Object around the OSObject so we can access the attributes in the
1734 // context of the object in which it is defined.
1735 P11Object* p11object = NULL;
1736 rv = newP11Object(object,&p11object);
1740 // Ask the P11Object to save the template with attribute values.
1741 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate,ulCount,OBJECT_OP_SET);
1746 // Initialise object search in the specified session using the specified attribute template as search parameters
1747 CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1749 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1752 Session* session = (Session*)handleManager->getSession(hSession);
1753 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1756 Slot* slot = session->getSlot();
1757 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1759 // Determine whether we have a public session or not.
1760 bool isPublicSession;
1761 switch (session->getState()) {
1762 case CKS_RO_USER_FUNCTIONS:
1763 case CKS_RW_USER_FUNCTIONS:
1764 isPublicSession = false;
1767 isPublicSession = true;
1771 Token* token = session->getToken();
1772 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1774 // Check if we have another operation
1775 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
1777 session->setOpType(SESSION_OP_FIND);
1778 FindOperation *findOp = FindOperation::create();
1780 // Check if we are out of memory
1781 if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
1783 std::set<OSObject*> allObjects;
1784 token->getObjects(allObjects);
1785 sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
1787 std::set<CK_OBJECT_HANDLE> handles;
1788 std::set<OSObject*>::iterator it;
1789 for (it=allObjects.begin(); it != allObjects.end(); ++it)
1791 // Refresh object and check if it is valid
1792 if (!(*it)->isValid()) {
1793 DEBUG_MSG("Object is not valid, skipping");
1797 // Determine if the object has CKA_PRIVATE set to CK_TRUE
1798 bool isPrivateObject = (*it)->getBooleanValue(CKA_PRIVATE, true);
1800 // If the object is private, and we are in a public session then skip it !
1801 if (isPublicSession && isPrivateObject)
1802 continue; // skip object
1804 // Perform the actual attribute matching.
1805 bool bAttrMatch = true; // We let an empty template match everything.
1806 for (CK_ULONG i=0; i<ulCount; ++i)
1810 if (!(*it)->attributeExists(pTemplate[i].type))
1813 OSAttribute attr = (*it)->getAttribute(pTemplate[i].type);
1815 if (attr.isBooleanAttribute())
1817 if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
1819 bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
1820 if (attr.getBooleanValue() != bTemplateValue)
1825 if (attr.isUnsignedLongAttribute())
1827 if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
1829 CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
1830 if (attr.getUnsignedLongValue() != ulTemplateValue)
1835 if (attr.isByteStringAttribute())
1837 ByteString bsAttrValue;
1838 if (isPrivateObject && attr.getByteStringValue().size() != 0)
1840 if (!token->decrypt(attr.getByteStringValue(), bsAttrValue))
1843 return CKR_GENERAL_ERROR;
1847 bsAttrValue = attr.getByteStringValue();
1849 if (bsAttrValue.size() != pTemplate[i].ulValueLen)
1851 if (pTemplate[i].ulValueLen != 0)
1853 ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
1854 if (bsAttrValue != bsTemplateValue)
1862 // The attribute matched !
1868 CK_SLOT_ID slotID = slot->getSlotID();
1869 bool isOnToken = (*it)->getBooleanValue(CKA_TOKEN, false);
1870 bool isPrivate = (*it)->getBooleanValue(CKA_PRIVATE, true);
1871 // Create an object handle for every returned object.
1872 CK_OBJECT_HANDLE hObject;
1874 hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
1876 hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
1877 if (hObject == CK_INVALID_HANDLE)
1880 return CKR_GENERAL_ERROR;
1882 handles.insert(hObject);
1886 // Storing the object handles for the find will protect the library
1887 // whenever a stale object handle is used to access the library.
1888 findOp->setHandles(handles);
1890 session->setFindOp(findOp);
1895 // Continue the search for objects in the specified session
1896 CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
1898 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1899 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1900 if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
1903 Session* session = (Session*)handleManager->getSession(hSession);
1904 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1906 // Check if we are doing the correct operation
1907 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1909 // return the object handles that have been added to the find operation.
1910 FindOperation *findOp = session->getFindOp();
1911 if (findOp == NULL) return CKR_GENERAL_ERROR;
1913 // Ask the find operation to retrieve the object handles
1914 *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
1916 // Erase the object handles from the find operation.
1917 findOp->eraseHandles(0,*pulObjectCount);
1922 // Finish searching for objects
1923 CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1925 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1928 Session* session = (Session*)handleManager->getSession(hSession);
1929 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1931 // Check if we are doing the correct operation
1932 if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1938 // Encrypt*/Decrypt*() is for Symmetrical ciphers too
1939 static bool isSymMechanism(CK_MECHANISM_PTR pMechanism)
1941 if (pMechanism == NULL_PTR) return false;
1943 switch(pMechanism->mechanism) {
1946 case CKM_DES_CBC_PAD:
1949 case CKM_DES3_CBC_PAD:
1952 case CKM_AES_CBC_PAD:
1961 // SymAlgorithm version of C_EncryptInit
1962 CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1964 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1966 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
1969 Session* session = (Session*)handleManager->getSession(hSession);
1970 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1972 // Check if we have another operation
1973 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
1976 Token* token = session->getToken();
1977 if (token == NULL) return CKR_GENERAL_ERROR;
1979 // Check the key handle.
1980 OSObject *key = (OSObject *)handleManager->getObject(hKey);
1981 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1983 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
1984 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
1986 // Check read user credentials
1987 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
1990 if (rv == CKR_USER_NOT_LOGGED_IN)
1991 INFO_MSG("User is not authorized");
1996 // Check if key can be used for encryption
1997 if (!key->getBooleanValue(CKA_ENCRYPT, false))
1998 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2000 // Check if the specified mechanism is allowed for the key
2001 if (!isMechanismPermitted(key, pMechanism))
2002 return CKR_MECHANISM_INVALID;
2004 // Get the symmetric algorithm matching the mechanism
2005 SymAlgo::Type algo = SymAlgo::Unknown;
2006 SymMode::Type mode = SymMode::Unknown;
2007 bool padding = false;
2010 size_t counterBits = 0;
2012 size_t tagBytes = 0;
2013 switch(pMechanism->mechanism) {
2016 algo = SymAlgo::DES;
2017 mode = SymMode::ECB;
2021 algo = SymAlgo::DES;
2022 mode = SymMode::CBC;
2023 if (pMechanism->pParameter == NULL_PTR ||
2024 pMechanism->ulParameterLen == 0)
2026 DEBUG_MSG("CBC mode requires an init vector");
2027 return CKR_ARGUMENTS_BAD;
2029 iv.resize(pMechanism->ulParameterLen);
2030 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2033 case CKM_DES_CBC_PAD:
2034 algo = SymAlgo::DES;
2035 mode = SymMode::CBC;
2037 if (pMechanism->pParameter == NULL_PTR ||
2038 pMechanism->ulParameterLen == 0)
2040 DEBUG_MSG("CBC mode requires an init vector");
2041 return CKR_ARGUMENTS_BAD;
2043 iv.resize(pMechanism->ulParameterLen);
2044 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2049 algo = SymAlgo::DES3;
2050 mode = SymMode::ECB;
2054 algo = SymAlgo::DES3;
2055 mode = SymMode::CBC;
2056 if (pMechanism->pParameter == NULL_PTR ||
2057 pMechanism->ulParameterLen == 0)
2059 DEBUG_MSG("CBC mode requires an init vector");
2060 return CKR_ARGUMENTS_BAD;
2062 iv.resize(pMechanism->ulParameterLen);
2063 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2066 case CKM_DES3_CBC_PAD:
2067 algo = SymAlgo::DES3;
2068 mode = SymMode::CBC;
2070 if (pMechanism->pParameter == NULL_PTR ||
2071 pMechanism->ulParameterLen == 0)
2073 DEBUG_MSG("CBC mode requires an init vector");
2074 return CKR_ARGUMENTS_BAD;
2076 iv.resize(pMechanism->ulParameterLen);
2077 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2081 algo = SymAlgo::AES;
2082 mode = SymMode::ECB;
2085 algo = SymAlgo::AES;
2086 mode = SymMode::CBC;
2087 if (pMechanism->pParameter == NULL_PTR ||
2088 pMechanism->ulParameterLen == 0)
2090 DEBUG_MSG("CBC mode requires an init vector");
2091 return CKR_ARGUMENTS_BAD;
2093 iv.resize(pMechanism->ulParameterLen);
2094 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2096 case CKM_AES_CBC_PAD:
2097 algo = SymAlgo::AES;
2098 mode = SymMode::CBC;
2100 if (pMechanism->pParameter == NULL_PTR ||
2101 pMechanism->ulParameterLen == 0)
2103 DEBUG_MSG("CBC mode requires an init vector");
2104 return CKR_ARGUMENTS_BAD;
2106 iv.resize(pMechanism->ulParameterLen);
2107 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2110 algo = SymAlgo::AES;
2111 mode = SymMode::CTR;
2112 if (pMechanism->pParameter == NULL_PTR ||
2113 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2115 DEBUG_MSG("CTR mode requires a counter block");
2116 return CKR_ARGUMENTS_BAD;
2118 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2119 if (counterBits == 0 || counterBits > 128)
2121 DEBUG_MSG("Invalid ulCounterBits");
2122 return CKR_MECHANISM_PARAM_INVALID;
2125 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2129 algo = SymAlgo::AES;
2130 mode = SymMode::GCM;
2131 if (pMechanism->pParameter == NULL_PTR ||
2132 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2134 DEBUG_MSG("GCM mode requires parameters");
2135 return CKR_ARGUMENTS_BAD;
2137 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2138 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2139 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2140 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2141 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2142 if (tagBytes > 128 || tagBytes % 8 != 0)
2144 DEBUG_MSG("Invalid ulTagBits value");
2145 return CKR_ARGUMENTS_BAD;
2147 tagBytes = tagBytes / 8;
2151 return CKR_MECHANISM_INVALID;
2153 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2154 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2156 SymmetricKey* secretkey = new SymmetricKey();
2158 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2160 cipher->recycleKey(secretkey);
2161 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2162 return CKR_GENERAL_ERROR;
2165 // adjust key bit length
2166 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2168 // Initialize encryption
2169 if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2171 cipher->recycleKey(secretkey);
2172 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2173 return CKR_MECHANISM_INVALID;
2176 session->setOpType(SESSION_OP_ENCRYPT);
2177 session->setSymmetricCryptoOp(cipher);
2178 session->setAllowMultiPartOp(true);
2179 session->setAllowSinglePartOp(true);
2180 session->setSymmetricKey(secretkey);
2185 // AsymAlgorithm version of C_EncryptInit
2186 CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2188 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2190 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2193 Session* session = (Session*)handleManager->getSession(hSession);
2194 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2196 // Check if we have another operation
2197 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2200 Token* token = session->getToken();
2201 if (token == NULL) return CKR_GENERAL_ERROR;
2203 // Check the key handle.
2204 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2205 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2207 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2208 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2210 // Check read user credentials
2211 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2214 if (rv == CKR_USER_NOT_LOGGED_IN)
2215 INFO_MSG("User is not authorized");
2220 // Check if key can be used for encryption
2221 if (!key->getBooleanValue(CKA_ENCRYPT, false))
2222 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2224 // Get the asymmetric algorithm matching the mechanism
2225 AsymMech::Type mechanism;
2227 switch(pMechanism->mechanism) {
2229 mechanism = AsymMech::RSA_PKCS;
2233 mechanism = AsymMech::RSA;
2236 case CKM_RSA_PKCS_OAEP:
2237 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
2241 mechanism = AsymMech::RSA_PKCS_OAEP;
2245 return CKR_MECHANISM_INVALID;
2248 AsymmetricAlgorithm* asymCrypto = NULL;
2249 PublicKey* publicKey = NULL;
2252 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2253 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2255 publicKey = asymCrypto->newPublicKey();
2256 if (publicKey == NULL)
2258 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2259 return CKR_HOST_MEMORY;
2262 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
2264 asymCrypto->recyclePublicKey(publicKey);
2265 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2266 return CKR_GENERAL_ERROR;
2271 return CKR_MECHANISM_INVALID;
2274 session->setOpType(SESSION_OP_ENCRYPT);
2275 session->setAsymmetricCryptoOp(asymCrypto);
2276 session->setMechanism(mechanism);
2277 session->setAllowMultiPartOp(false);
2278 session->setAllowSinglePartOp(true);
2279 session->setPublicKey(publicKey);
2284 // Initialise encryption using the specified object and mechanism
2285 CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2287 if (isSymMechanism(pMechanism))
2288 return SymEncryptInit(hSession, pMechanism, hKey);
2290 return AsymEncryptInit(hSession, pMechanism, hKey);
2293 // SymAlgorithm version of C_Encrypt
2294 static CK_RV SymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2296 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2297 if (cipher == NULL || !session->getAllowSinglePartOp())
2300 return CKR_OPERATION_NOT_INITIALIZED;
2304 CK_ULONG maxSize = ulDataLen + cipher->getTagBytes();
2305 if (cipher->isBlockCipher())
2307 CK_ULONG remainder = ulDataLen % cipher->getBlockSize();
2308 if (cipher->getPaddingMode() == false && remainder != 0)
2311 return CKR_DATA_LEN_RANGE;
2314 // Round up to block size
2317 maxSize = ulDataLen + cipher->getBlockSize() - remainder;
2319 else if (cipher->getPaddingMode() == true)
2321 maxSize = ulDataLen + cipher->getBlockSize();
2324 if (!cipher->checkMaximumBytes(ulDataLen))
2327 return CKR_DATA_LEN_RANGE;
2330 if (pEncryptedData == NULL_PTR)
2332 *pulEncryptedDataLen = maxSize;
2336 // Check buffer size
2337 if (*pulEncryptedDataLen < maxSize)
2339 *pulEncryptedDataLen = maxSize;
2340 return CKR_BUFFER_TOO_SMALL;
2344 ByteString data(pData, ulDataLen);
2345 ByteString encryptedData;
2348 if (!cipher->encryptUpdate(data, encryptedData))
2351 return CKR_GENERAL_ERROR;
2354 // Finalize encryption
2355 ByteString encryptedFinal;
2356 if (!cipher->encryptFinal(encryptedFinal))
2359 return CKR_GENERAL_ERROR;
2361 encryptedData += encryptedFinal;
2362 encryptedData.resize(maxSize);
2364 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2365 *pulEncryptedDataLen = encryptedData.size();
2371 // AsymAlgorithm version of C_Encrypt
2372 static CK_RV AsymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2374 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
2375 AsymMech::Type mechanism = session->getMechanism();
2376 PublicKey* publicKey = session->getPublicKey();
2377 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
2380 return CKR_OPERATION_NOT_INITIALIZED;
2383 // Size of the encrypted data
2384 CK_ULONG size = publicKey->getOutputLength();
2386 if (pEncryptedData == NULL_PTR)
2388 *pulEncryptedDataLen = size;
2392 // Check buffer size
2393 if (*pulEncryptedDataLen < size)
2395 *pulEncryptedDataLen = size;
2396 return CKR_BUFFER_TOO_SMALL;
2401 ByteString encryptedData;
2403 // We must allow input length <= k and therfore need to prepend the data with zeroes.
2404 if (mechanism == AsymMech::RSA) {
2405 data.wipe(size-ulDataLen);
2408 data += ByteString(pData, ulDataLen);
2411 if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
2414 return CKR_GENERAL_ERROR;
2418 if (encryptedData.size() != size)
2420 ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
2422 return CKR_GENERAL_ERROR;
2424 memcpy(pEncryptedData, encryptedData.byte_str(), size);
2425 *pulEncryptedDataLen = size;
2431 // Perform a single operation encryption operation in the specified session
2432 CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2434 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2436 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2437 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2440 Session* session = (Session*)handleManager->getSession(hSession);
2441 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2443 // Check if we are doing the correct operation
2444 if (session->getOpType() != SESSION_OP_ENCRYPT)
2445 return CKR_OPERATION_NOT_INITIALIZED;
2447 if (session->getSymmetricCryptoOp() != NULL)
2448 return SymEncrypt(session, pData, ulDataLen,
2449 pEncryptedData, pulEncryptedDataLen);
2451 return AsymEncrypt(session, pData, ulDataLen,
2452 pEncryptedData, pulEncryptedDataLen);
2455 // SymAlgorithm version of C_EncryptUpdate
2456 static CK_RV SymEncryptUpdate(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2458 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2459 if (cipher == NULL || !session->getAllowMultiPartOp())
2462 return CKR_OPERATION_NOT_INITIALIZED;
2466 size_t blockSize = cipher->getBlockSize();
2467 size_t remainingSize = cipher->getBufferSize();
2468 CK_ULONG maxSize = ulDataLen + remainingSize;
2469 if (cipher->isBlockCipher())
2471 int nrOfBlocks = (ulDataLen + remainingSize) / blockSize;
2472 maxSize = nrOfBlocks * blockSize;
2474 if (!cipher->checkMaximumBytes(ulDataLen))
2477 return CKR_DATA_LEN_RANGE;
2481 if (pEncryptedData == NULL_PTR)
2483 *pulEncryptedDataLen = maxSize;
2487 // Check output buffer size
2488 if (*pulEncryptedDataLen < maxSize)
2490 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
2491 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize);
2492 *pulEncryptedDataLen = maxSize;
2493 return CKR_BUFFER_TOO_SMALL;
2497 ByteString data(pData, ulDataLen);
2498 ByteString encryptedData;
2501 if (!cipher->encryptUpdate(data, encryptedData))
2504 return CKR_GENERAL_ERROR;
2506 DEBUG_MSG("ulDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x encryptedData.size(): %#5x",
2507 ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize, encryptedData.size());
2509 // Check output size from crypto. Unrecoverable error if to large.
2510 if (*pulEncryptedDataLen < encryptedData.size())
2513 ERROR_MSG("EncryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2514 *pulEncryptedDataLen, encryptedData.size());
2515 return CKR_GENERAL_ERROR;
2518 if (encryptedData.size() > 0)
2520 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2522 *pulEncryptedDataLen = encryptedData.size();
2527 // Feed data to the running encryption operation in a session
2528 CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2530 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2532 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2533 if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2536 Session* session = (Session*)handleManager->getSession(hSession);
2537 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2539 // Check if we are doing the correct operation
2540 if (session->getOpType() != SESSION_OP_ENCRYPT)
2541 return CKR_OPERATION_NOT_INITIALIZED;
2543 if (session->getSymmetricCryptoOp() != NULL)
2544 return SymEncryptUpdate(session, pData, ulDataLen,
2545 pEncryptedData, pulEncryptedDataLen);
2547 return CKR_FUNCTION_NOT_SUPPORTED;
2550 // SymAlgorithm version of C_EncryptFinal
2551 static CK_RV SymEncryptFinal(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2553 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2554 if (cipher == NULL || !session->getAllowMultiPartOp())
2557 return CKR_OPERATION_NOT_INITIALIZED;
2561 size_t remainingSize = cipher->getBufferSize() + cipher->getTagBytes();
2562 CK_ULONG size = remainingSize;
2563 if (cipher->isBlockCipher())
2565 size_t blockSize = cipher->getBlockSize();
2566 bool isPadding = cipher->getPaddingMode();
2567 if ((remainingSize % blockSize) != 0 && !isPadding)
2570 DEBUG_MSG("Remaining buffer size is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
2571 blockSize, remainingSize);
2572 return CKR_DATA_LEN_RANGE;
2574 // when padding: an integral of the block size that is longer than the remaining data.
2575 size = isPadding ? ((remainingSize + blockSize) / blockSize) * blockSize : remainingSize;
2578 // Give required output buffer size.
2579 if (pEncryptedData == NULL_PTR)
2581 *pulEncryptedDataLen = size;
2585 // Check output buffer size
2586 if (*pulEncryptedDataLen < size)
2588 DEBUG_MSG("output buffer size: %#5x size: %#5x",
2589 *pulEncryptedDataLen, size);
2590 *pulEncryptedDataLen = size;
2591 return CKR_BUFFER_TOO_SMALL;
2594 // Finalize encryption
2595 ByteString encryptedFinal;
2596 if (!cipher->encryptFinal(encryptedFinal))
2599 return CKR_GENERAL_ERROR;
2601 DEBUG_MSG("output buffer size: %#2x size: %#2x encryptedFinal.size(): %#2x",
2602 *pulEncryptedDataLen, size, encryptedFinal.size());
2604 // Check output size from crypto. Unrecoverable error if to large.
2605 if (*pulEncryptedDataLen < encryptedFinal.size())
2608 ERROR_MSG("EncryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2609 *pulEncryptedDataLen, encryptedFinal.size());
2610 return CKR_GENERAL_ERROR;
2613 if (encryptedFinal.size() > 0)
2615 memcpy(pEncryptedData, encryptedFinal.byte_str(), encryptedFinal.size());
2617 *pulEncryptedDataLen = encryptedFinal.size();
2623 // Finalise the encryption operation
2624 CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2626 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2629 Session* session = (Session*)handleManager->getSession(hSession);
2630 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2632 // Check if we are doing the correct operation
2633 if (session->getOpType() != SESSION_OP_ENCRYPT) return CKR_OPERATION_NOT_INITIALIZED;
2635 if (session->getSymmetricCryptoOp() != NULL)
2636 return SymEncryptFinal(session, pEncryptedData, pulEncryptedDataLen);
2638 return CKR_FUNCTION_NOT_SUPPORTED;
2641 // SymAlgorithm version of C_DecryptInit
2642 CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2644 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2646 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2649 Session* session = (Session*)handleManager->getSession(hSession);
2650 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2653 Token* token = session->getToken();
2654 if (token == NULL) return CKR_GENERAL_ERROR;
2656 // Check if we have another operation
2657 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2659 // Check the key handle.
2660 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2661 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2663 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2664 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2666 // Check read user credentials
2667 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2670 if (rv == CKR_USER_NOT_LOGGED_IN)
2671 INFO_MSG("User is not authorized");
2676 // Check if key can be used for decryption
2677 if (!key->getBooleanValue(CKA_DECRYPT, false))
2678 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2681 // Check if the specified mechanism is allowed for the key
2682 if (!isMechanismPermitted(key, pMechanism))
2683 return CKR_MECHANISM_INVALID;
2685 // Get the symmetric algorithm matching the mechanism
2686 SymAlgo::Type algo = SymAlgo::Unknown;
2687 SymMode::Type mode = SymMode::Unknown;
2688 bool padding = false;
2691 size_t counterBits = 0;
2693 size_t tagBytes = 0;
2694 switch(pMechanism->mechanism) {
2697 algo = SymAlgo::DES;
2698 mode = SymMode::ECB;
2702 algo = SymAlgo::DES;
2703 mode = SymMode::CBC;
2704 if (pMechanism->pParameter == NULL_PTR ||
2705 pMechanism->ulParameterLen == 0)
2707 DEBUG_MSG("CBC mode requires an init vector");
2708 return CKR_ARGUMENTS_BAD;
2710 iv.resize(pMechanism->ulParameterLen);
2711 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2714 case CKM_DES_CBC_PAD:
2715 algo = SymAlgo::DES;
2716 mode = SymMode::CBC;
2718 if (pMechanism->pParameter == NULL_PTR ||
2719 pMechanism->ulParameterLen == 0)
2721 DEBUG_MSG("CBC mode requires an init vector");
2722 return CKR_ARGUMENTS_BAD;
2724 iv.resize(pMechanism->ulParameterLen);
2725 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2730 algo = SymAlgo::DES3;
2731 mode = SymMode::ECB;
2735 algo = SymAlgo::DES3;
2736 mode = SymMode::CBC;
2737 if (pMechanism->pParameter == NULL_PTR ||
2738 pMechanism->ulParameterLen == 0)
2740 DEBUG_MSG("CBC mode requires an init vector");
2741 return CKR_ARGUMENTS_BAD;
2743 iv.resize(pMechanism->ulParameterLen);
2744 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2747 case CKM_DES3_CBC_PAD:
2748 algo = SymAlgo::DES3;
2749 mode = SymMode::CBC;
2751 if (pMechanism->pParameter == NULL_PTR ||
2752 pMechanism->ulParameterLen == 0)
2754 DEBUG_MSG("CBC mode requires an init vector");
2755 return CKR_ARGUMENTS_BAD;
2757 iv.resize(pMechanism->ulParameterLen);
2758 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2762 algo = SymAlgo::AES;
2763 mode = SymMode::ECB;
2766 algo = SymAlgo::AES;
2767 mode = SymMode::CBC;
2768 if (pMechanism->pParameter == NULL_PTR ||
2769 pMechanism->ulParameterLen == 0)
2771 DEBUG_MSG("CBC mode requires an init vector");
2772 return CKR_ARGUMENTS_BAD;
2774 iv.resize(pMechanism->ulParameterLen);
2775 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2777 case CKM_AES_CBC_PAD:
2778 algo = SymAlgo::AES;
2779 mode = SymMode::CBC;
2781 if (pMechanism->pParameter == NULL_PTR ||
2782 pMechanism->ulParameterLen == 0)
2784 DEBUG_MSG("CBC mode requires an init vector");
2785 return CKR_ARGUMENTS_BAD;
2787 iv.resize(pMechanism->ulParameterLen);
2788 memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2791 algo = SymAlgo::AES;
2792 mode = SymMode::CTR;
2793 if (pMechanism->pParameter == NULL_PTR ||
2794 pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2796 DEBUG_MSG("CTR mode requires a counter block");
2797 return CKR_ARGUMENTS_BAD;
2799 counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2800 if (counterBits == 0 || counterBits > 128)
2802 DEBUG_MSG("Invalid ulCounterBits");
2803 return CKR_MECHANISM_PARAM_INVALID;
2806 memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2810 algo = SymAlgo::AES;
2811 mode = SymMode::GCM;
2812 if (pMechanism->pParameter == NULL_PTR ||
2813 pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2815 DEBUG_MSG("GCM mode requires parameters");
2816 return CKR_ARGUMENTS_BAD;
2818 iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2819 memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2820 aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2821 memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2822 tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2823 if (tagBytes > 128 || tagBytes % 8 != 0)
2825 DEBUG_MSG("Invalid ulTagBits value");
2826 return CKR_ARGUMENTS_BAD;
2828 tagBytes = tagBytes / 8;
2832 return CKR_MECHANISM_INVALID;
2834 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2835 if (cipher == NULL) return CKR_MECHANISM_INVALID;
2837 SymmetricKey* secretkey = new SymmetricKey();
2839 if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2841 cipher->recycleKey(secretkey);
2842 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2843 return CKR_GENERAL_ERROR;
2846 // adjust key bit length
2847 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2849 // Initialize decryption
2850 if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2852 cipher->recycleKey(secretkey);
2853 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2854 return CKR_MECHANISM_INVALID;
2857 session->setOpType(SESSION_OP_DECRYPT);
2858 session->setSymmetricCryptoOp(cipher);
2859 session->setAllowMultiPartOp(true);
2860 session->setAllowSinglePartOp(true);
2861 session->setSymmetricKey(secretkey);
2866 // AsymAlgorithm version of C_DecryptInit
2867 CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2869 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2871 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2874 Session* session = (Session*)handleManager->getSession(hSession);
2875 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2878 Token* token = session->getToken();
2879 if (token == NULL) return CKR_GENERAL_ERROR;
2881 // Check if we have another operation
2882 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2884 // Check the key handle.
2885 OSObject *key = (OSObject *)handleManager->getObject(hKey);
2886 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2888 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2889 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2891 // Check read user credentials
2892 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2895 if (rv == CKR_USER_NOT_LOGGED_IN)
2896 INFO_MSG("User is not authorized");
2901 // Check if key can be used for decryption
2902 if (!key->getBooleanValue(CKA_DECRYPT, false))
2903 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2905 // Check if the specified mechanism is allowed for the key
2906 if (!isMechanismPermitted(key, pMechanism))
2907 return CKR_MECHANISM_INVALID;
2909 // Get the asymmetric algorithm matching the mechanism
2910 AsymMech::Type mechanism = AsymMech::Unknown;
2912 switch(pMechanism->mechanism) {
2914 mechanism = AsymMech::RSA_PKCS;
2918 mechanism = AsymMech::RSA;
2921 case CKM_RSA_PKCS_OAEP:
2922 if (pMechanism->pParameter == NULL_PTR ||
2923 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
2925 DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
2926 return CKR_ARGUMENTS_BAD;
2928 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
2930 DEBUG_MSG("hashAlg must be CKM_SHA_1");
2931 return CKR_ARGUMENTS_BAD;
2933 if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
2935 DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
2936 return CKR_ARGUMENTS_BAD;
2939 mechanism = AsymMech::RSA_PKCS_OAEP;
2943 return CKR_MECHANISM_INVALID;
2946 AsymmetricAlgorithm* asymCrypto = NULL;
2947 PrivateKey* privateKey = NULL;
2950 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2951 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2953 privateKey = asymCrypto->newPrivateKey();
2954 if (privateKey == NULL)
2956 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2957 return CKR_HOST_MEMORY;
2960 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
2962 asymCrypto->recyclePrivateKey(privateKey);
2963 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2964 return CKR_GENERAL_ERROR;
2969 return CKR_MECHANISM_INVALID;
2972 // Check if re-authentication is required
2973 if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
2975 session->setReAuthentication(true);
2978 session->setOpType(SESSION_OP_DECRYPT);
2979 session->setAsymmetricCryptoOp(asymCrypto);
2980 session->setMechanism(mechanism);
2981 session->setAllowMultiPartOp(false);
2982 session->setAllowSinglePartOp(true);
2983 session->setPrivateKey(privateKey);
2988 // Initialise decryption using the specified object
2989 CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2991 if (isSymMechanism(pMechanism))
2992 return SymDecryptInit(hSession, pMechanism, hKey);
2994 return AsymDecryptInit(hSession, pMechanism, hKey);
2997 // SymAlgorithm version of C_Decrypt
2998 static CK_RV SymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3000 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3001 if (cipher == NULL || !session->getAllowSinglePartOp())
3004 return CKR_OPERATION_NOT_INITIALIZED;
3007 // Check encrypted data size
3008 if (cipher->isBlockCipher() && ulEncryptedDataLen % cipher->getBlockSize() != 0)
3011 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3013 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3016 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3019 if (pData == NULL_PTR)
3021 *pulDataLen = ulEncryptedDataLen;
3025 // Check buffer size
3026 if (*pulDataLen < ulEncryptedDataLen)
3028 *pulDataLen = ulEncryptedDataLen;
3029 return CKR_BUFFER_TOO_SMALL;
3033 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3037 if (!cipher->decryptUpdate(encryptedData,data))
3040 return CKR_GENERAL_ERROR;
3043 // Finalize decryption
3044 ByteString dataFinal;
3045 if (!cipher->decryptFinal(dataFinal))
3048 return CKR_GENERAL_ERROR;
3051 if (data.size() > ulEncryptedDataLen)
3053 data.resize(ulEncryptedDataLen);
3056 if (data.size() != 0)
3058 memcpy(pData, data.byte_str(), data.size());
3060 *pulDataLen = data.size();
3067 // AsymAlgorithm version of C_Decrypt
3068 static CK_RV AsymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3070 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
3071 AsymMech::Type mechanism = session->getMechanism();
3072 PrivateKey* privateKey = session->getPrivateKey();
3073 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
3076 return CKR_OPERATION_NOT_INITIALIZED;
3079 // Check if re-authentication is required
3080 if (session->getReAuthentication())
3083 return CKR_USER_NOT_LOGGED_IN;
3087 CK_ULONG size = privateKey->getOutputLength();
3088 if (pData == NULL_PTR)
3094 // Check buffer size
3095 if (*pulDataLen < size)
3098 return CKR_BUFFER_TOO_SMALL;
3102 ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3106 if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
3109 return CKR_GENERAL_ERROR;
3113 if (data.size() > size)
3115 ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
3117 return CKR_GENERAL_ERROR;
3119 if (data.size() != 0)
3121 memcpy(pData, data.byte_str(), data.size());
3123 *pulDataLen = data.size();
3130 // Perform a single operation decryption in the given session
3131 CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3133 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3135 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3136 if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3139 Session* session = (Session*)handleManager->getSession(hSession);
3140 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3142 // Check if we are doing the correct operation
3143 if (session->getOpType() != SESSION_OP_DECRYPT)
3144 return CKR_OPERATION_NOT_INITIALIZED;
3146 if (session->getSymmetricCryptoOp() != NULL)
3147 return SymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3150 return AsymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3154 // SymAlgorithm version of C_DecryptUpdate
3155 static CK_RV SymDecryptUpdate(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3157 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3158 if (cipher == NULL || !session->getAllowMultiPartOp())
3161 return CKR_OPERATION_NOT_INITIALIZED;
3164 // Check encrypted data size
3165 size_t blockSize = cipher->getBlockSize();
3166 size_t remainingSize = cipher->getBufferSize();
3167 CK_ULONG maxSize = ulEncryptedDataLen + remainingSize;
3168 if (cipher->isBlockCipher())
3170 // There must always be one block left in padding mode if next operation is DecryptFinal.
3171 // To guarantee that one byte is removed in padding mode when the number of blocks is calculated.
3172 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3173 int nrOfBlocks = (ulEncryptedDataLen + remainingSize - paddingAdjustByte) / blockSize;
3174 maxSize = nrOfBlocks * blockSize;
3176 if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3179 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3182 // Give required output buffer size.
3183 if (pData == NULL_PTR)
3185 *pDataLen = maxSize;
3189 // Check output buffer size
3190 if (*pDataLen < maxSize)
3192 DEBUG_MSG("Output buffer too short ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x",
3193 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize);
3194 *pDataLen = maxSize;
3195 return CKR_BUFFER_TOO_SMALL;
3199 ByteString data(pEncryptedData, ulEncryptedDataLen);
3200 ByteString decryptedData;
3203 if (!cipher->decryptUpdate(data, decryptedData))
3206 return CKR_GENERAL_ERROR;
3208 DEBUG_MSG("ulEncryptedDataLen: %#5x output buffer size: %#5x blockSize: %#3x remainingSize: %#4x maxSize: %#5x decryptedData.size(): %#5x",
3209 ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize, decryptedData.size());
3211 // Check output size from crypto. Unrecoverable error if to large.
3212 if (*pDataLen < decryptedData.size())
3215 ERROR_MSG("DecryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the decrypt.",
3216 *pDataLen, decryptedData.size());
3217 return CKR_GENERAL_ERROR;
3220 if (decryptedData.size() > 0)
3222 memcpy(pData, decryptedData.byte_str(), decryptedData.size());
3224 *pDataLen = decryptedData.size();
3230 // Feed data to the running decryption operation in a session
3231 CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3233 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3235 if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3236 if (pDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3239 Session* session = (Session*)handleManager->getSession(hSession);
3240 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3242 // Check if we are doing the correct operation
3243 if (session->getOpType() != SESSION_OP_DECRYPT)
3244 return CKR_OPERATION_NOT_INITIALIZED;
3246 if (session->getSymmetricCryptoOp() != NULL)
3247 return SymDecryptUpdate(session, pEncryptedData, ulEncryptedDataLen,
3250 return CKR_FUNCTION_NOT_SUPPORTED;
3253 static CK_RV SymDecryptFinal(Session* session, CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen)
3255 SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3256 if (cipher == NULL || !session->getAllowMultiPartOp())
3259 return CKR_OPERATION_NOT_INITIALIZED;
3262 // Check encrypted data size
3263 size_t remainingSize = cipher->getBufferSize();
3264 CK_ULONG size = remainingSize;
3265 if (cipher->isBlockCipher())
3267 size_t blockSize = cipher->getBlockSize();
3268 if (remainingSize % blockSize != 0)
3271 DEBUG_MSG("Remaining data length is not an integral of the block size. Block size: %#2x Remaining size: %#2x",
3272 blockSize, remainingSize);
3273 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3275 // It is at least one padding byte. If no padding the all remains will be returned.
3276 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3277 size = remainingSize - paddingAdjustByte;
3280 // Give required output buffer size.
3281 if (pDecryptedData == NULL_PTR)
3283 *pulDecryptedDataLen = size;
3287 // Check output buffer size
3288 if (*pulDecryptedDataLen < size)
3290 DEBUG_MSG("output buffer size: %#5x size: %#5x",
3291 *pulDecryptedDataLen, size);
3292 *pulDecryptedDataLen = size;
3293 return CKR_BUFFER_TOO_SMALL;
3296 // Finalize decryption
3297 ByteString decryptedFinal;
3298 if (!cipher->decryptFinal(decryptedFinal))
3301 return CKR_GENERAL_ERROR;
3303 DEBUG_MSG("output buffer size: %#2x size: %#2x decryptedFinal.size(): %#2x",
3304 *pulDecryptedDataLen, size, decryptedFinal.size());
3306 // Check output size from crypto. Unrecoverable error if to large.
3307 if (*pulDecryptedDataLen < decryptedFinal.size())
3310 ERROR_MSG("DecryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
3311 *pulDecryptedDataLen, decryptedFinal.size());
3312 return CKR_GENERAL_ERROR;
3315 if (decryptedFinal.size() > 0)
3317 memcpy(pDecryptedData, decryptedFinal.byte_str(), decryptedFinal.size());
3319 *pulDecryptedDataLen = decryptedFinal.size();
3325 // Finalise the decryption operation
3326 CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3328 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3331 Session* session = (Session*)handleManager->getSession(hSession);
3332 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3334 // Check if we are doing the correct operation
3335 if (session->getOpType() != SESSION_OP_DECRYPT) return CKR_OPERATION_NOT_INITIALIZED;
3337 if (session->getSymmetricCryptoOp() != NULL)
3338 return SymDecryptFinal(session, pData, pDataLen);
3340 return CKR_FUNCTION_NOT_SUPPORTED;
3343 // Initialise digesting using the specified mechanism in the specified session
3344 CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
3346 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3348 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3351 Session* session = (Session*)handleManager->getSession(hSession);
3352 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3354 // Check if we have another operation
3355 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3357 // Get the mechanism
3358 HashAlgo::Type algo = HashAlgo::Unknown;
3359 switch(pMechanism->mechanism) {
3362 algo = HashAlgo::MD5;
3366 algo = HashAlgo::SHA1;
3369 algo = HashAlgo::SHA224;
3372 algo = HashAlgo::SHA256;
3375 algo = HashAlgo::SHA384;
3378 algo = HashAlgo::SHA512;
3382 algo = HashAlgo::GOST;
3386 return CKR_MECHANISM_INVALID;
3388 HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(algo);
3389 if (hash == NULL) return CKR_MECHANISM_INVALID;
3391 // Initialize hashing
3392 if (hash->hashInit() == false)
3394 CryptoFactory::i()->recycleHashAlgorithm(hash);
3395 return CKR_GENERAL_ERROR;
3398 session->setOpType(SESSION_OP_DIGEST);
3399 session->setDigestOp(hash);
3400 session->setHashAlgo(algo);
3405 // Digest the specified data in a one-pass operation and return the resulting digest
3406 CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3408 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3410 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3411 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3414 Session* session = (Session*)handleManager->getSession(hSession);
3415 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3417 // Check if we are doing the correct operation
3418 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3421 CK_ULONG size = session->getDigestOp()->getHashSize();
3422 if (pDigest == NULL_PTR)
3424 *pulDigestLen = size;
3428 // Check buffer size
3429 if (*pulDigestLen < size)
3431 *pulDigestLen = size;
3432 return CKR_BUFFER_TOO_SMALL;
3436 ByteString data(pData, ulDataLen);
3439 if (session->getDigestOp()->hashUpdate(data) == false)
3442 return CKR_GENERAL_ERROR;
3447 if (session->getDigestOp()->hashFinal(digest) == false)
3450 return CKR_GENERAL_ERROR;
3454 if (digest.size() != size)
3456 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3458 return CKR_GENERAL_ERROR;
3460 memcpy(pDigest, digest.byte_str(), size);
3461 *pulDigestLen = size;
3468 // Update a running digest operation
3469 CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
3471 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3473 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
3476 Session* session = (Session*)handleManager->getSession(hSession);
3477 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3479 // Check if we are doing the correct operation
3480 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3483 ByteString data(pPart, ulPartLen);
3486 if (session->getDigestOp()->hashUpdate(data) == false)
3489 return CKR_GENERAL_ERROR;
3495 // Update a running digest operation by digesting a secret key with the specified handle
3496 CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3498 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3501 Session* session = (Session*)handleManager->getSession(hSession);
3502 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3504 // Check if we are doing the correct operation
3505 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3508 Token* token = session->getToken();
3509 if (token == NULL) return CKR_GENERAL_ERROR;
3511 // Check the key handle.
3512 OSObject *key = (OSObject *)handleManager->getObject(hObject);
3513 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
3515 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3516 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3518 // Check read user credentials
3519 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3522 if (rv == CKR_USER_NOT_LOGGED_IN)
3523 INFO_MSG("User is not authorized");
3525 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
3526 // so we use CKR_GENERAL_ERROR.
3527 return CKR_GENERAL_ERROR;
3531 HashAlgo::Type algo = session->getHashAlgo();
3532 if (algo != HashAlgo::SHA1 &&
3533 algo != HashAlgo::SHA224 &&
3534 algo != HashAlgo::SHA256 &&
3535 algo != HashAlgo::SHA384 &&
3536 algo != HashAlgo::SHA512)
3539 if (!key->getBooleanValue(CKA_EXTRACTABLE, false))
3540 return CKR_KEY_INDIGESTIBLE;
3541 if (key->getBooleanValue(CKA_SENSITIVE, false))
3542 return CKR_KEY_INDIGESTIBLE;
3546 if (!key->attributeExists(CKA_VALUE))
3547 return CKR_KEY_INDIGESTIBLE;
3551 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
3552 return CKR_GENERAL_ERROR;
3556 keybits = key->getByteStringValue(CKA_VALUE);
3560 if (session->getDigestOp()->hashUpdate(keybits) == false)
3563 return CKR_GENERAL_ERROR;
3569 // Finalise the digest operation in the specified session and return the digest
3570 CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3572 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3574 if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3577 Session* session = (Session*)handleManager->getSession(hSession);
3578 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3580 // Check if we are doing the correct operation
3581 if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3584 CK_ULONG size = session->getDigestOp()->getHashSize();
3585 if (pDigest == NULL_PTR)
3587 *pulDigestLen = size;
3591 // Check buffer size
3592 if (*pulDigestLen < size)
3594 *pulDigestLen = size;
3595 return CKR_BUFFER_TOO_SMALL;
3600 if (session->getDigestOp()->hashFinal(digest) == false)
3603 return CKR_GENERAL_ERROR;
3607 if (digest.size() != size)
3609 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3611 return CKR_GENERAL_ERROR;
3613 memcpy(pDigest, digest.byte_str(), size);
3614 *pulDigestLen = size;
3621 // Sign*/Verify*() is for MACs too
3622 static bool isMacMechanism(CK_MECHANISM_PTR pMechanism)
3624 if (pMechanism == NULL_PTR) return false;
3626 switch(pMechanism->mechanism) {
3628 case CKM_SHA_1_HMAC:
3629 case CKM_SHA224_HMAC:
3630 case CKM_SHA256_HMAC:
3631 case CKM_SHA384_HMAC:
3632 case CKM_SHA512_HMAC:
3634 case CKM_GOSTR3411_HMAC:
3644 // MacAlgorithm version of C_SignInit
3645 CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3647 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3649 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3652 Session* session = (Session*)handleManager->getSession(hSession);
3653 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3655 // Check if we have another operation
3656 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3659 Token* token = session->getToken();
3660 if (token == NULL) return CKR_GENERAL_ERROR;
3662 // Check the key handle.
3663 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3664 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3666 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3667 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3669 // Check read user credentials
3670 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3673 if (rv == CKR_USER_NOT_LOGGED_IN)
3674 INFO_MSG("User is not authorized");
3679 // Check if key can be used for signing
3680 if (!key->getBooleanValue(CKA_SIGN, false))
3681 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3683 // Check if the specified mechanism is allowed for the key
3684 if (!isMechanismPermitted(key, pMechanism))
3685 return CKR_MECHANISM_INVALID;
3688 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
3690 // Get the MAC algorithm matching the mechanism
3691 // Also check mechanism constraints
3692 MacAlgo::Type algo = MacAlgo::Unknown;
3695 switch(pMechanism->mechanism) {
3698 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
3699 return CKR_KEY_TYPE_INCONSISTENT;
3701 algo = MacAlgo::HMAC_MD5;
3704 case CKM_SHA_1_HMAC:
3705 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
3706 return CKR_KEY_TYPE_INCONSISTENT;
3708 algo = MacAlgo::HMAC_SHA1;
3710 case CKM_SHA224_HMAC:
3711 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
3712 return CKR_KEY_TYPE_INCONSISTENT;
3714 algo = MacAlgo::HMAC_SHA224;
3716 case CKM_SHA256_HMAC:
3717 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
3718 return CKR_KEY_TYPE_INCONSISTENT;
3720 algo = MacAlgo::HMAC_SHA256;
3722 case CKM_SHA384_HMAC:
3723 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
3724 return CKR_KEY_TYPE_INCONSISTENT;
3726 algo = MacAlgo::HMAC_SHA384;
3728 case CKM_SHA512_HMAC:
3729 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
3730 return CKR_KEY_TYPE_INCONSISTENT;
3732 algo = MacAlgo::HMAC_SHA512;
3735 case CKM_GOSTR3411_HMAC:
3736 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
3737 return CKR_KEY_TYPE_INCONSISTENT;
3739 algo = MacAlgo::HMAC_GOST;
3743 if (keyType != CKK_DES2 && keyType != CKK_DES3)
3744 return CKR_KEY_TYPE_INCONSISTENT;
3745 algo = MacAlgo::CMAC_DES;
3749 if (keyType != CKK_AES)
3750 return CKR_KEY_TYPE_INCONSISTENT;
3751 algo = MacAlgo::CMAC_AES;
3754 return CKR_MECHANISM_INVALID;
3756 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
3757 if (mac == NULL) return CKR_MECHANISM_INVALID;
3759 SymmetricKey* privkey = new SymmetricKey();
3761 if (getSymmetricKey(privkey, token, key) != CKR_OK)
3763 mac->recycleKey(privkey);
3764 CryptoFactory::i()->recycleMacAlgorithm(mac);
3765 return CKR_GENERAL_ERROR;
3768 // Adjust key bit length
3769 privkey->setBitLen(privkey->getKeyBits().size() * bb);
3772 if (privkey->getBitLen() < (minSize*8))
3774 mac->recycleKey(privkey);
3775 CryptoFactory::i()->recycleMacAlgorithm(mac);
3776 return CKR_KEY_SIZE_RANGE;
3779 // Initialize signing
3780 if (!mac->signInit(privkey))
3782 mac->recycleKey(privkey);
3783 CryptoFactory::i()->recycleMacAlgorithm(mac);
3784 return CKR_MECHANISM_INVALID;
3787 session->setOpType(SESSION_OP_SIGN);
3788 session->setMacOp(mac);
3789 session->setAllowMultiPartOp(true);
3790 session->setAllowSinglePartOp(true);
3791 session->setSymmetricKey(privkey);
3796 // AsymmetricAlgorithm version of C_SignInit
3797 CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3799 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3801 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3804 Session* session = (Session*)handleManager->getSession(hSession);
3805 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3807 // Check if we have another operation
3808 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3811 Token* token = session->getToken();
3812 if (token == NULL) return CKR_GENERAL_ERROR;
3814 // Check the key handle.
3815 OSObject *key = (OSObject *)handleManager->getObject(hKey);
3816 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3818 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3819 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3821 // Check read user credentials
3822 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3825 if (rv == CKR_USER_NOT_LOGGED_IN)
3826 INFO_MSG("User is not authorized");
3831 // Check if key can be used for signing
3832 if (!key->getBooleanValue(CKA_SIGN, false))
3833 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3835 // Check if the specified mechanism is allowed for the key
3836 if (!isMechanismPermitted(key, pMechanism))
3837 return CKR_MECHANISM_INVALID;
3839 // Get the asymmetric algorithm matching the mechanism
3840 AsymMech::Type mechanism = AsymMech::Unknown;
3842 size_t paramLen = 0;
3843 RSA_PKCS_PSS_PARAMS pssParam;
3844 bool bAllowMultiPartOp;
3847 bool isECDSA = false;
3848 switch(pMechanism->mechanism) {
3850 mechanism = AsymMech::RSA_PKCS;
3851 bAllowMultiPartOp = false;
3855 mechanism = AsymMech::RSA;
3856 bAllowMultiPartOp = false;
3860 case CKM_MD5_RSA_PKCS:
3861 mechanism = AsymMech::RSA_MD5_PKCS;
3862 bAllowMultiPartOp = true;
3866 case CKM_SHA1_RSA_PKCS:
3867 mechanism = AsymMech::RSA_SHA1_PKCS;
3868 bAllowMultiPartOp = true;
3871 case CKM_SHA224_RSA_PKCS:
3872 mechanism = AsymMech::RSA_SHA224_PKCS;
3873 bAllowMultiPartOp = true;
3876 case CKM_SHA256_RSA_PKCS:
3877 mechanism = AsymMech::RSA_SHA256_PKCS;
3878 bAllowMultiPartOp = true;
3881 case CKM_SHA384_RSA_PKCS:
3882 mechanism = AsymMech::RSA_SHA384_PKCS;
3883 bAllowMultiPartOp = true;
3886 case CKM_SHA512_RSA_PKCS:
3887 mechanism = AsymMech::RSA_SHA512_PKCS;
3888 bAllowMultiPartOp = true;
3892 case CKM_RSA_PKCS_PSS:
3893 if (pMechanism->pParameter == NULL_PTR ||
3894 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3896 ERROR_MSG("Invalid RSA-PSS parameters");
3897 return CKR_ARGUMENTS_BAD;
3899 mechanism = AsymMech::RSA_PKCS_PSS;
3900 unsigned long allowedMgf;
3902 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
3904 pssParam.hashAlg = HashAlgo::SHA1;
3905 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3906 allowedMgf = CKG_MGF1_SHA1;
3909 pssParam.hashAlg = HashAlgo::SHA224;
3910 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
3911 allowedMgf = CKG_MGF1_SHA224;
3914 pssParam.hashAlg = HashAlgo::SHA256;
3915 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
3916 allowedMgf = CKG_MGF1_SHA256;
3919 pssParam.hashAlg = HashAlgo::SHA384;
3920 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
3921 allowedMgf = CKG_MGF1_SHA384;
3924 pssParam.hashAlg = HashAlgo::SHA512;
3925 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
3926 allowedMgf = CKG_MGF1_SHA512;
3929 ERROR_MSG("Invalid RSA-PSS hash");
3930 return CKR_ARGUMENTS_BAD;
3933 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != allowedMgf) {
3934 ERROR_MSG("Hash and MGF don't match");
3935 return CKR_ARGUMENTS_BAD;
3938 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3940 paramLen = sizeof(pssParam);
3941 bAllowMultiPartOp = false;
3945 case CKM_SHA1_RSA_PKCS_PSS:
3946 if (pMechanism->pParameter == NULL_PTR ||
3947 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3948 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
3949 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
3951 ERROR_MSG("Invalid parameters");
3952 return CKR_ARGUMENTS_BAD;
3954 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
3955 pssParam.hashAlg = HashAlgo::SHA1;
3956 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3957 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3959 paramLen = sizeof(pssParam);
3960 bAllowMultiPartOp = true;
3963 case CKM_SHA224_RSA_PKCS_PSS:
3964 if (pMechanism->pParameter == NULL_PTR ||
3965 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3966 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
3967 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
3969 ERROR_MSG("Invalid parameters");
3970 return CKR_ARGUMENTS_BAD;
3972 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
3973 pssParam.hashAlg = HashAlgo::SHA224;
3974 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
3975 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3977 paramLen = sizeof(pssParam);
3978 bAllowMultiPartOp = true;
3981 case CKM_SHA256_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_SHA256 ||
3985 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
3987 ERROR_MSG("Invalid parameters");
3988 return CKR_ARGUMENTS_BAD;
3990 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
3991 pssParam.hashAlg = HashAlgo::SHA256;
3992 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
3993 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3995 paramLen = sizeof(pssParam);
3996 bAllowMultiPartOp = true;
3999 case CKM_SHA384_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_SHA384 ||
4003 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
4005 ERROR_MSG("Invalid parameters");
4006 return CKR_ARGUMENTS_BAD;
4008 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
4009 pssParam.hashAlg = HashAlgo::SHA384;
4010 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4011 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4013 paramLen = sizeof(pssParam);
4014 bAllowMultiPartOp = true;
4017 case CKM_SHA512_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_SHA512 ||
4021 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
4023 ERROR_MSG("Invalid parameters");
4024 return CKR_ARGUMENTS_BAD;
4026 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
4027 pssParam.hashAlg = HashAlgo::SHA512;
4028 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4029 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4031 paramLen = sizeof(pssParam);
4032 bAllowMultiPartOp = true;
4036 mechanism = AsymMech::DSA;
4037 bAllowMultiPartOp = false;
4041 mechanism = AsymMech::DSA_SHA1;
4042 bAllowMultiPartOp = true;
4045 case CKM_DSA_SHA224:
4046 mechanism = AsymMech::DSA_SHA224;
4047 bAllowMultiPartOp = true;
4050 case CKM_DSA_SHA256:
4051 mechanism = AsymMech::DSA_SHA256;
4052 bAllowMultiPartOp = true;
4055 case CKM_DSA_SHA384:
4056 mechanism = AsymMech::DSA_SHA384;
4057 bAllowMultiPartOp = true;
4060 case CKM_DSA_SHA512:
4061 mechanism = AsymMech::DSA_SHA512;
4062 bAllowMultiPartOp = true;
4067 mechanism = AsymMech::ECDSA;
4068 bAllowMultiPartOp = false;
4074 mechanism = AsymMech::GOST;
4075 bAllowMultiPartOp = false;
4077 case CKM_GOSTR3410_WITH_GOSTR3411:
4078 mechanism = AsymMech::GOST_GOST;
4079 bAllowMultiPartOp = true;
4083 return CKR_MECHANISM_INVALID;
4086 AsymmetricAlgorithm* asymCrypto = NULL;
4087 PrivateKey* privateKey = NULL;
4090 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
4091 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4093 privateKey = asymCrypto->newPrivateKey();
4094 if (privateKey == NULL)
4096 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4097 return CKR_HOST_MEMORY;
4100 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
4102 asymCrypto->recyclePrivateKey(privateKey);
4103 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4104 return CKR_GENERAL_ERROR;
4109 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
4110 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4112 privateKey = asymCrypto->newPrivateKey();
4113 if (privateKey == NULL)
4115 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4116 return CKR_HOST_MEMORY;
4119 if (getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key) != CKR_OK)
4121 asymCrypto->recyclePrivateKey(privateKey);
4122 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4123 return CKR_GENERAL_ERROR;
4129 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
4130 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4132 privateKey = asymCrypto->newPrivateKey();
4133 if (privateKey == NULL)
4135 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4136 return CKR_HOST_MEMORY;
4139 if (getECPrivateKey((ECPrivateKey*)privateKey, token, key) != CKR_OK)
4141 asymCrypto->recyclePrivateKey(privateKey);
4142 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4143 return CKR_GENERAL_ERROR;
4150 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
4151 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4153 privateKey = asymCrypto->newPrivateKey();
4154 if (privateKey == NULL)
4156 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4157 return CKR_HOST_MEMORY;
4160 if (getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key) != CKR_OK)
4162 asymCrypto->recyclePrivateKey(privateKey);
4163 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4164 return CKR_GENERAL_ERROR;
4167 return CKR_MECHANISM_INVALID;
4171 // Initialize signing
4172 if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
4174 asymCrypto->recyclePrivateKey(privateKey);
4175 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4176 return CKR_MECHANISM_INVALID;
4179 // Check if re-authentication is required
4180 if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
4182 session->setReAuthentication(true);
4185 session->setOpType(SESSION_OP_SIGN);
4186 session->setAsymmetricCryptoOp(asymCrypto);
4187 session->setMechanism(mechanism);
4188 session->setParameters(param, paramLen);
4189 session->setAllowMultiPartOp(bAllowMultiPartOp);
4190 session->setAllowSinglePartOp(true);
4191 session->setPrivateKey(privateKey);
4196 // Initialise a signing operation using the specified key and mechanism
4197 CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4199 if (isMacMechanism(pMechanism))
4200 return MacSignInit(hSession, pMechanism, hKey);
4202 return AsymSignInit(hSession, pMechanism, hKey);
4205 // MacAlgorithm version of C_Sign
4206 static CK_RV MacSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4208 MacAlgorithm* mac = session->getMacOp();
4209 if (mac == NULL || !session->getAllowSinglePartOp())
4212 return CKR_OPERATION_NOT_INITIALIZED;
4215 // Size of the signature
4216 CK_ULONG size = mac->getMacSize();
4217 if (pSignature == NULL_PTR)
4219 *pulSignatureLen = size;
4223 // Check buffer size
4224 if (*pulSignatureLen < size)
4226 *pulSignatureLen = size;
4227 return CKR_BUFFER_TOO_SMALL;
4231 ByteString data(pData, ulDataLen);
4234 if (!mac->signUpdate(data))
4237 return CKR_GENERAL_ERROR;
4240 // Get the signature
4241 ByteString signature;
4242 if (!mac->signFinal(signature))
4245 return CKR_GENERAL_ERROR;
4249 if (signature.size() != size)
4251 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4253 return CKR_GENERAL_ERROR;
4255 memcpy(pSignature, signature.byte_str(), size);
4256 *pulSignatureLen = size;
4262 // AsymmetricAlgorithm version of C_Sign
4263 static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4265 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4266 AsymMech::Type mechanism = session->getMechanism();
4267 PrivateKey* privateKey = session->getPrivateKey();
4269 void* param = session->getParameters(paramLen);
4270 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4273 return CKR_OPERATION_NOT_INITIALIZED;
4276 // Check if re-authentication is required
4277 if (session->getReAuthentication())
4280 return CKR_USER_NOT_LOGGED_IN;
4283 // Size of the signature
4284 CK_ULONG size = privateKey->getOutputLength();
4285 if (pSignature == NULL_PTR)
4287 *pulSignatureLen = size;
4291 // Check buffer size
4292 if (*pulSignatureLen < size)
4294 *pulSignatureLen = size;
4295 return CKR_BUFFER_TOO_SMALL;
4301 // We must allow input length <= k and therfore need to prepend the data with zeroes.
4302 if (mechanism == AsymMech::RSA) {
4303 data.wipe(size-ulDataLen);
4306 data += ByteString(pData, ulDataLen);
4307 ByteString signature;
4310 if (session->getAllowMultiPartOp())
4312 if (!asymCrypto->signUpdate(data) ||
4313 !asymCrypto->signFinal(signature))
4316 return CKR_GENERAL_ERROR;
4319 else if (!asymCrypto->sign(privateKey,data,signature,mechanism,param,paramLen))
4322 return CKR_GENERAL_ERROR;
4326 if (signature.size() != size)
4328 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4330 return CKR_GENERAL_ERROR;
4332 memcpy(pSignature, signature.byte_str(), size);
4333 *pulSignatureLen = size;
4339 // Sign the data in a single pass operation
4340 CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4342 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4344 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
4345 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4348 Session* session = (Session*)handleManager->getSession(hSession);
4349 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4351 // Check if we are doing the correct operation
4352 if (session->getOpType() != SESSION_OP_SIGN)
4353 return CKR_OPERATION_NOT_INITIALIZED;
4355 if (session->getMacOp() != NULL)
4356 return MacSign(session, pData, ulDataLen,
4357 pSignature, pulSignatureLen);
4359 return AsymSign(session, pData, ulDataLen,
4360 pSignature, pulSignatureLen);
4363 // MacAlgorithm version of C_SignUpdate
4364 static CK_RV MacSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4366 MacAlgorithm* mac = session->getMacOp();
4367 if (mac == NULL || !session->getAllowMultiPartOp())
4370 return CKR_OPERATION_NOT_INITIALIZED;
4374 ByteString part(pPart, ulPartLen);
4377 if (!mac->signUpdate(part))
4380 return CKR_GENERAL_ERROR;
4383 session->setAllowSinglePartOp(false);
4387 // AsymmetricAlgorithm version of C_SignUpdate
4388 static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4390 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4391 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4394 return CKR_OPERATION_NOT_INITIALIZED;
4397 // Check if re-authentication is required
4398 if (session->getReAuthentication())
4401 return CKR_USER_NOT_LOGGED_IN;
4405 ByteString part(pPart, ulPartLen);
4408 if (!asymCrypto->signUpdate(part))
4411 return CKR_GENERAL_ERROR;
4414 session->setAllowSinglePartOp(false);
4418 // Update a running signing operation with additional data
4419 CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4421 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4423 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
4426 Session* session = (Session*)handleManager->getSession(hSession);
4427 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4429 // Check if we are doing the correct operation
4430 if (session->getOpType() != SESSION_OP_SIGN)
4431 return CKR_OPERATION_NOT_INITIALIZED;
4433 if (session->getMacOp() != NULL)
4434 return MacSignUpdate(session, pPart, ulPartLen);
4436 return AsymSignUpdate(session, pPart, ulPartLen);
4439 // MacAlgorithm version of C_SignFinal
4440 static CK_RV MacSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4442 MacAlgorithm* mac = session->getMacOp();
4446 return CKR_OPERATION_NOT_INITIALIZED;
4449 // Size of the signature
4450 CK_ULONG size = mac->getMacSize();
4451 if (pSignature == NULL_PTR)
4453 *pulSignatureLen = size;
4457 // Check buffer size
4458 if (*pulSignatureLen < size)
4460 *pulSignatureLen = size;
4461 return CKR_BUFFER_TOO_SMALL;
4464 // Get the signature
4465 ByteString signature;
4466 if (!mac->signFinal(signature))
4469 return CKR_GENERAL_ERROR;
4473 if (signature.size() != size)
4475 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4477 return CKR_GENERAL_ERROR;
4479 memcpy(pSignature, signature.byte_str(), size);
4480 *pulSignatureLen = size;
4486 // AsymmetricAlgorithm version of C_SignFinal
4487 static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4489 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4490 PrivateKey* privateKey = session->getPrivateKey();
4491 if (asymCrypto == NULL || privateKey == NULL)
4494 return CKR_OPERATION_NOT_INITIALIZED;
4497 // Check if re-authentication is required
4498 if (session->getReAuthentication())
4501 return CKR_USER_NOT_LOGGED_IN;
4504 // Size of the signature
4505 CK_ULONG size = privateKey->getOutputLength();
4506 if (pSignature == NULL_PTR)
4508 *pulSignatureLen = size;
4512 // Check buffer size
4513 if (*pulSignatureLen < size)
4515 *pulSignatureLen = size;
4516 return CKR_BUFFER_TOO_SMALL;
4519 // Get the signature
4520 ByteString signature;
4521 if (!asymCrypto->signFinal(signature))
4524 return CKR_GENERAL_ERROR;
4528 if (signature.size() != size)
4530 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4532 return CKR_GENERAL_ERROR;
4534 memcpy(pSignature, signature.byte_str(), size);
4535 *pulSignatureLen = size;
4541 // Finalise a running signing operation and return the signature
4542 CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4544 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4546 if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4549 Session* session = (Session*)handleManager->getSession(hSession);
4550 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4552 // Check if we are doing the correct operation
4553 if (session->getOpType() != SESSION_OP_SIGN || !session->getAllowMultiPartOp())
4554 return CKR_OPERATION_NOT_INITIALIZED;
4556 if (session->getMacOp() != NULL)
4557 return MacSignFinal(session, pSignature, pulSignatureLen);
4559 return AsymSignFinal(session, pSignature, pulSignatureLen);
4562 // Initialise a signing operation that allows recovery of the signed data
4563 CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
4565 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4568 Session* session = (Session*)handleManager->getSession(hSession);
4569 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4571 // Check if we have another operation
4572 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4574 return CKR_FUNCTION_NOT_SUPPORTED;
4577 // Perform a single part signing operation that allows recovery of the signed data
4578 CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pData*/, CK_ULONG /*ulDataLen*/, CK_BYTE_PTR /*pSignature*/, CK_ULONG_PTR /*pulSignatureLen*/)
4580 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4583 Session* session = (Session*)handleManager->getSession(hSession);
4584 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4586 return CKR_FUNCTION_NOT_SUPPORTED;
4589 // MacAlgorithm version of C_VerifyInit
4590 CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4592 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4594 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4597 Session* session = (Session*)handleManager->getSession(hSession);
4598 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4600 // Check if we have another operation
4601 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4604 Token* token = session->getToken();
4605 if (token == NULL) return CKR_GENERAL_ERROR;
4607 // Check the key handle.
4608 OSObject *key = (OSObject *)handleManager->getObject(hKey);
4609 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4611 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4612 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4614 // Check read user credentials
4615 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4618 if (rv == CKR_USER_NOT_LOGGED_IN)
4619 INFO_MSG("User is not authorized");
4624 // Check if key can be used for verifying
4625 if (!key->getBooleanValue(CKA_VERIFY, false))
4626 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4628 // Check if the specified mechanism is allowed for the key
4629 if (!isMechanismPermitted(key, pMechanism))
4630 return CKR_MECHANISM_INVALID;
4633 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
4635 // Get the MAC algorithm matching the mechanism
4636 // Also check mechanism constraints
4637 MacAlgo::Type algo = MacAlgo::Unknown;
4640 switch(pMechanism->mechanism) {
4643 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
4644 return CKR_KEY_TYPE_INCONSISTENT;
4646 algo = MacAlgo::HMAC_MD5;
4649 case CKM_SHA_1_HMAC:
4650 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
4651 return CKR_KEY_TYPE_INCONSISTENT;
4653 algo = MacAlgo::HMAC_SHA1;
4655 case CKM_SHA224_HMAC:
4656 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
4657 return CKR_KEY_TYPE_INCONSISTENT;
4659 algo = MacAlgo::HMAC_SHA224;
4661 case CKM_SHA256_HMAC:
4662 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
4663 return CKR_KEY_TYPE_INCONSISTENT;
4665 algo = MacAlgo::HMAC_SHA256;
4667 case CKM_SHA384_HMAC:
4668 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
4669 return CKR_KEY_TYPE_INCONSISTENT;
4671 algo = MacAlgo::HMAC_SHA384;
4673 case CKM_SHA512_HMAC:
4674 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
4675 return CKR_KEY_TYPE_INCONSISTENT;
4677 algo = MacAlgo::HMAC_SHA512;
4680 case CKM_GOSTR3411_HMAC:
4681 if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
4682 return CKR_KEY_TYPE_INCONSISTENT;
4684 algo = MacAlgo::HMAC_GOST;
4688 if (keyType != CKK_DES2 && keyType != CKK_DES3)
4689 return CKR_KEY_TYPE_INCONSISTENT;
4690 algo = MacAlgo::CMAC_DES;
4694 if (keyType != CKK_AES)
4695 return CKR_KEY_TYPE_INCONSISTENT;
4696 algo = MacAlgo::CMAC_AES;
4699 return CKR_MECHANISM_INVALID;
4701 MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
4702 if (mac == NULL) return CKR_MECHANISM_INVALID;
4704 SymmetricKey* pubkey = new SymmetricKey();
4706 if (getSymmetricKey(pubkey, token, key) != CKR_OK)
4708 mac->recycleKey(pubkey);
4709 CryptoFactory::i()->recycleMacAlgorithm(mac);
4710 return CKR_GENERAL_ERROR;
4713 // Adjust key bit length
4714 pubkey->setBitLen(pubkey->getKeyBits().size() * bb);
4717 if (pubkey->getBitLen() < (minSize*8))
4719 mac->recycleKey(pubkey);
4720 CryptoFactory::i()->recycleMacAlgorithm(mac);
4721 return CKR_KEY_SIZE_RANGE;
4724 // Initialize verifying
4725 if (!mac->verifyInit(pubkey))
4727 mac->recycleKey(pubkey);
4728 CryptoFactory::i()->recycleMacAlgorithm(mac);
4729 return CKR_MECHANISM_INVALID;
4732 session->setOpType(SESSION_OP_VERIFY);
4733 session->setMacOp(mac);
4734 session->setAllowMultiPartOp(true);
4735 session->setAllowSinglePartOp(true);
4736 session->setSymmetricKey(pubkey);
4741 // AsymmetricAlgorithm version of C_VerifyInit
4742 CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4744 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4746 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4749 Session* session = (Session*)handleManager->getSession(hSession);
4750 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4752 // Check if we have another operation
4753 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4756 Token* token = session->getToken();
4757 if (token == NULL) return CKR_GENERAL_ERROR;
4759 // Check the key handle.
4760 OSObject *key = (OSObject *)handleManager->getObject(hKey);
4761 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4763 CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4764 CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4766 // Check read user credentials
4767 CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4770 if (rv == CKR_USER_NOT_LOGGED_IN)
4771 INFO_MSG("User is not authorized");
4776 // Check if key can be used for verifying
4777 if (!key->getBooleanValue(CKA_VERIFY, false))
4778 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4780 // Check if the specified mechanism is allowed for the key
4781 if (!isMechanismPermitted(key, pMechanism))
4782 return CKR_MECHANISM_INVALID;
4784 // Get the asymmetric algorithm matching the mechanism
4785 AsymMech::Type mechanism = AsymMech::Unknown;
4787 size_t paramLen = 0;
4788 RSA_PKCS_PSS_PARAMS pssParam;
4789 bool bAllowMultiPartOp;
4792 bool isECDSA = false;
4793 switch(pMechanism->mechanism) {
4795 mechanism = AsymMech::RSA_PKCS;
4796 bAllowMultiPartOp = false;
4800 mechanism = AsymMech::RSA;
4801 bAllowMultiPartOp = false;
4805 case CKM_MD5_RSA_PKCS:
4806 mechanism = AsymMech::RSA_MD5_PKCS;
4807 bAllowMultiPartOp = true;
4811 case CKM_SHA1_RSA_PKCS:
4812 mechanism = AsymMech::RSA_SHA1_PKCS;
4813 bAllowMultiPartOp = true;
4816 case CKM_SHA224_RSA_PKCS:
4817 mechanism = AsymMech::RSA_SHA224_PKCS;
4818 bAllowMultiPartOp = true;
4821 case CKM_SHA256_RSA_PKCS:
4822 mechanism = AsymMech::RSA_SHA256_PKCS;
4823 bAllowMultiPartOp = true;
4826 case CKM_SHA384_RSA_PKCS:
4827 mechanism = AsymMech::RSA_SHA384_PKCS;
4828 bAllowMultiPartOp = true;
4831 case CKM_SHA512_RSA_PKCS:
4832 mechanism = AsymMech::RSA_SHA512_PKCS;
4833 bAllowMultiPartOp = true;
4837 case CKM_RSA_PKCS_PSS:
4838 if (pMechanism->pParameter == NULL_PTR ||
4839 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
4841 ERROR_MSG("Invalid parameters");
4842 return CKR_ARGUMENTS_BAD;
4844 mechanism = AsymMech::RSA_PKCS_PSS;
4846 unsigned long expectedMgf;
4847 switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
4849 pssParam.hashAlg = HashAlgo::SHA1;
4850 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
4851 expectedMgf = CKG_MGF1_SHA1;
4854 pssParam.hashAlg = HashAlgo::SHA224;
4855 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
4856 expectedMgf = CKG_MGF1_SHA224;
4859 pssParam.hashAlg = HashAlgo::SHA256;
4860 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
4861 expectedMgf = CKG_MGF1_SHA256;
4864 pssParam.hashAlg = HashAlgo::SHA384;
4865 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4866 expectedMgf = CKG_MGF1_SHA384;
4869 pssParam.hashAlg = HashAlgo::SHA512;
4870 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4871 expectedMgf = CKG_MGF1_SHA512;
4874 return CKR_ARGUMENTS_BAD;
4877 if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != expectedMgf) {
4878 return CKR_ARGUMENTS_BAD;
4881 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4883 paramLen = sizeof(pssParam);
4884 bAllowMultiPartOp = false;
4888 case CKM_SHA1_RSA_PKCS_PSS:
4889 if (pMechanism->pParameter == NULL_PTR ||
4890 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4891 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
4892 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
4894 ERROR_MSG("Invalid parameters");
4895 return CKR_ARGUMENTS_BAD;
4897 mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
4898 pssParam.hashAlg = HashAlgo::SHA1;
4899 pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
4900 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4902 paramLen = sizeof(pssParam);
4903 bAllowMultiPartOp = true;
4906 case CKM_SHA224_RSA_PKCS_PSS:
4907 if (pMechanism->pParameter == NULL_PTR ||
4908 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4909 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
4910 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
4912 ERROR_MSG("Invalid parameters");
4913 return CKR_ARGUMENTS_BAD;
4915 mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
4916 pssParam.hashAlg = HashAlgo::SHA224;
4917 pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
4918 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4920 paramLen = sizeof(pssParam);
4921 bAllowMultiPartOp = true;
4924 case CKM_SHA256_RSA_PKCS_PSS:
4925 if (pMechanism->pParameter == NULL_PTR ||
4926 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4927 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
4928 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
4930 ERROR_MSG("Invalid parameters");
4931 return CKR_ARGUMENTS_BAD;
4933 mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
4934 pssParam.hashAlg = HashAlgo::SHA256;
4935 pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
4936 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4938 paramLen = sizeof(pssParam);
4939 bAllowMultiPartOp = true;
4942 case CKM_SHA384_RSA_PKCS_PSS:
4943 if (pMechanism->pParameter == NULL_PTR ||
4944 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4945 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
4946 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
4948 ERROR_MSG("Invalid parameters");
4949 return CKR_ARGUMENTS_BAD;
4951 mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
4952 pssParam.hashAlg = HashAlgo::SHA384;
4953 pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4954 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4956 paramLen = sizeof(pssParam);
4957 bAllowMultiPartOp = true;
4960 case CKM_SHA512_RSA_PKCS_PSS:
4961 if (pMechanism->pParameter == NULL_PTR ||
4962 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4963 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
4964 CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
4966 ERROR_MSG("Invalid parameters");
4967 return CKR_ARGUMENTS_BAD;
4969 mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
4970 pssParam.hashAlg = HashAlgo::SHA512;
4971 pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4972 pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4974 paramLen = sizeof(pssParam);
4975 bAllowMultiPartOp = true;
4979 mechanism = AsymMech::DSA;
4980 bAllowMultiPartOp = false;
4984 mechanism = AsymMech::DSA_SHA1;
4985 bAllowMultiPartOp = true;
4988 case CKM_DSA_SHA224:
4989 mechanism = AsymMech::DSA_SHA224;
4990 bAllowMultiPartOp = true;
4993 case CKM_DSA_SHA256:
4994 mechanism = AsymMech::DSA_SHA256;
4995 bAllowMultiPartOp = true;
4998 case CKM_DSA_SHA384:
4999 mechanism = AsymMech::DSA_SHA384;
5000 bAllowMultiPartOp = true;
5003 case CKM_DSA_SHA512:
5004 mechanism = AsymMech::DSA_SHA512;
5005 bAllowMultiPartOp = true;
5010 mechanism = AsymMech::ECDSA;
5011 bAllowMultiPartOp = false;
5017 mechanism = AsymMech::GOST;
5018 bAllowMultiPartOp = false;
5020 case CKM_GOSTR3410_WITH_GOSTR3411:
5021 mechanism = AsymMech::GOST_GOST;
5022 bAllowMultiPartOp = true;
5026 return CKR_MECHANISM_INVALID;
5029 AsymmetricAlgorithm* asymCrypto = NULL;
5030 PublicKey* publicKey = NULL;
5033 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
5034 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5036 publicKey = asymCrypto->newPublicKey();
5037 if (publicKey == NULL)
5039 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5040 return CKR_HOST_MEMORY;
5043 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
5045 asymCrypto->recyclePublicKey(publicKey);
5046 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5047 return CKR_GENERAL_ERROR;
5052 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
5053 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5055 publicKey = asymCrypto->newPublicKey();
5056 if (publicKey == NULL)
5058 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5059 return CKR_HOST_MEMORY;
5062 if (getDSAPublicKey((DSAPublicKey*)publicKey, token, key) != CKR_OK)
5064 asymCrypto->recyclePublicKey(publicKey);
5065 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5066 return CKR_GENERAL_ERROR;
5072 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
5073 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5075 publicKey = asymCrypto->newPublicKey();
5076 if (publicKey == NULL)
5078 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5079 return CKR_HOST_MEMORY;
5082 if (getECPublicKey((ECPublicKey*)publicKey, token, key) != CKR_OK)
5084 asymCrypto->recyclePublicKey(publicKey);
5085 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5086 return CKR_GENERAL_ERROR;
5093 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
5094 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5096 publicKey = asymCrypto->newPublicKey();
5097 if (publicKey == NULL)
5099 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5100 return CKR_HOST_MEMORY;
5103 if (getGOSTPublicKey((GOSTPublicKey*)publicKey, token, key) != CKR_OK)
5105 asymCrypto->recyclePublicKey(publicKey);
5106 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5107 return CKR_GENERAL_ERROR;
5110 return CKR_MECHANISM_INVALID;
5114 // Initialize verifying
5115 if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))
5117 asymCrypto->recyclePublicKey(publicKey);
5118 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5119 return CKR_MECHANISM_INVALID;
5122 session->setOpType(SESSION_OP_VERIFY);
5123 session->setAsymmetricCryptoOp(asymCrypto);
5124 session->setMechanism(mechanism);
5125 session->setParameters(param, paramLen);
5126 session->setAllowMultiPartOp(bAllowMultiPartOp);
5127 session->setAllowSinglePartOp(true);
5128 session->setPublicKey(publicKey);
5133 // Initialise a verification operation using the specified key and mechanism
5134 CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5136 if (isMacMechanism(pMechanism))
5137 return MacVerifyInit(hSession, pMechanism, hKey);
5139 return AsymVerifyInit(hSession, pMechanism, hKey);
5142 // MacAlgorithm version of C_Verify
5143 static CK_RV MacVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5145 MacAlgorithm* mac = session->getMacOp();
5146 if (mac == NULL || !session->getAllowSinglePartOp())
5149 return CKR_OPERATION_NOT_INITIALIZED;
5152 // Size of the signature
5153 CK_ULONG size = mac->getMacSize();
5155 // Check buffer size
5156 if (ulSignatureLen != size)
5158 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5160 return CKR_SIGNATURE_LEN_RANGE;
5164 ByteString data(pData, ulDataLen);
5167 if (!mac->verifyUpdate(data))
5170 return CKR_GENERAL_ERROR;
5173 // Get the signature
5174 ByteString signature(pSignature, ulSignatureLen);
5176 // Verify the signature
5177 if (!mac->verifyFinal(signature))
5180 return CKR_SIGNATURE_INVALID;
5187 // AsymmetricAlgorithm version of C_Verify
5188 static CK_RV AsymVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5190 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5191 AsymMech::Type mechanism = session->getMechanism();
5192 PublicKey* publicKey = session->getPublicKey();
5194 void* param = session->getParameters(paramLen);
5195 if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
5198 return CKR_OPERATION_NOT_INITIALIZED;
5201 // Size of the signature
5202 CK_ULONG size = publicKey->getOutputLength();
5204 // Check buffer size
5205 if (ulSignatureLen != size)
5207 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5209 return CKR_SIGNATURE_LEN_RANGE;
5215 // We must allow input length <= k and therfore need to prepend the data with zeroes.
5216 if (mechanism == AsymMech::RSA) {
5217 data.wipe(size-ulDataLen);
5220 data += ByteString(pData, ulDataLen);
5221 ByteString signature(pSignature, ulSignatureLen);
5224 if (session->getAllowMultiPartOp())
5226 if (!asymCrypto->verifyUpdate(data) ||
5227 !asymCrypto->verifyFinal(signature))
5230 return CKR_SIGNATURE_INVALID;
5233 else if (!asymCrypto->verify(publicKey,data,signature,mechanism,param,paramLen))
5236 return CKR_SIGNATURE_INVALID;
5243 // Perform a single pass verification operation
5244 CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5246 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5248 if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
5249 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5252 Session* session = (Session*)handleManager->getSession(hSession);
5253 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5255 // Check if we are doing the correct operation
5256 if (session->getOpType() != SESSION_OP_VERIFY)
5257 return CKR_OPERATION_NOT_INITIALIZED;
5259 if (session->getMacOp() != NULL)
5260 return MacVerify(session, pData, ulDataLen,
5261 pSignature, ulSignatureLen);
5263 return AsymVerify(session, pData, ulDataLen,
5264 pSignature, ulSignatureLen);
5267 // MacAlgorithm version of C_VerifyUpdate
5268 static CK_RV MacVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5270 MacAlgorithm* mac = session->getMacOp();
5271 if (mac == NULL || !session->getAllowMultiPartOp())
5274 return CKR_OPERATION_NOT_INITIALIZED;
5278 ByteString part(pPart, ulPartLen);
5281 if (!mac->verifyUpdate(part))
5283 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5285 return CKR_GENERAL_ERROR;
5288 session->setAllowSinglePartOp(false);
5292 // AsymmetricAlgorithm version of C_VerifyUpdate
5293 static CK_RV AsymVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5295 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5296 if (asymCrypto == NULL || !session->getAllowMultiPartOp())
5299 return CKR_OPERATION_NOT_INITIALIZED;
5303 ByteString part(pPart, ulPartLen);
5306 if (!asymCrypto->verifyUpdate(part))
5308 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5310 return CKR_GENERAL_ERROR;
5313 session->setAllowSinglePartOp(false);
5317 // Update a running verification operation with additional data
5318 CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5320 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5322 if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
5325 Session* session = (Session*)handleManager->getSession(hSession);
5326 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5328 // Check if we are doing the correct operation
5329 if (session->getOpType() != SESSION_OP_VERIFY)
5330 return CKR_OPERATION_NOT_INITIALIZED;
5332 if (session->getMacOp() != NULL)
5333 return MacVerifyUpdate(session, pPart, ulPartLen);
5335 return AsymVerifyUpdate(session, pPart, ulPartLen);
5338 // MacAlgorithm version of C_SignFinal
5339 static CK_RV MacVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5341 MacAlgorithm* mac = session->getMacOp();
5345 return CKR_OPERATION_NOT_INITIALIZED;
5348 // Size of the signature
5349 CK_ULONG size = mac->getMacSize();
5351 // Check buffer size
5352 if (ulSignatureLen != size)
5354 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5356 return CKR_SIGNATURE_LEN_RANGE;
5359 // Get the signature
5360 ByteString signature(pSignature, ulSignatureLen);
5363 if (!mac->verifyFinal(signature))
5366 return CKR_SIGNATURE_INVALID;
5373 // AsymmetricAlgorithm version of C_VerifyFinal
5374 static CK_RV AsymVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5376 AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5377 PublicKey* publicKey = session->getPublicKey();
5378 if (asymCrypto == NULL || publicKey == NULL)
5381 return CKR_OPERATION_NOT_INITIALIZED;
5384 // Size of the signature
5385 CK_ULONG size = publicKey->getOutputLength();
5387 // Check buffer size
5388 if (ulSignatureLen != size)
5390 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5392 return CKR_SIGNATURE_LEN_RANGE;
5396 ByteString signature(pSignature, ulSignatureLen);
5399 if (!asymCrypto->verifyFinal(signature))
5402 return CKR_SIGNATURE_INVALID;
5409 // Finalise the verification operation and check the signature
5410 CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5412 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5414 if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5417 Session* session = (Session*)handleManager->getSession(hSession);
5418 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5420 // Check if we are doing the correct operation
5421 if (session->getOpType() != SESSION_OP_VERIFY || !session->getAllowMultiPartOp())
5422 return CKR_OPERATION_NOT_INITIALIZED;
5424 if (session->getMacOp() != NULL)
5425 return MacVerifyFinal(session, pSignature, ulSignatureLen);
5427 return AsymVerifyFinal(session, pSignature, ulSignatureLen);
5430 // Initialise a verification operation the allows recovery of the signed data from the signature
5431 CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
5433 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5436 Session* session = (Session*)handleManager->getSession(hSession);
5437 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5439 // Check if we have another operation
5440 if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5442 return CKR_FUNCTION_NOT_SUPPORTED;
5445 // Perform a single part verification operation and recover the signed data
5446 CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pSignature*/, CK_ULONG /*ulSignatureLen*/, CK_BYTE_PTR /*pData*/, CK_ULONG_PTR /*pulDataLen*/)
5448 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5451 Session* session = (Session*)handleManager->getSession(hSession);
5452 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5454 return CKR_FUNCTION_NOT_SUPPORTED;
5457 // Update a running multi-part encryption and digesting operation
5458 CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5460 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5463 Session* session = (Session*)handleManager->getSession(hSession);
5464 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5466 return CKR_FUNCTION_NOT_SUPPORTED;
5469 // Update a running multi-part decryption and digesting operation
5470 CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pDecryptedPart*/, CK_ULONG_PTR /*pulDecryptedPartLen*/)
5472 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5475 Session* session = (Session*)handleManager->getSession(hSession);
5476 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5478 return CKR_FUNCTION_NOT_SUPPORTED;
5481 // Update a running multi-part signing and encryption operation
5482 CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5484 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5487 Session* session = (Session*)handleManager->getSession(hSession);
5488 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5490 return CKR_FUNCTION_NOT_SUPPORTED;
5493 // Update a running multi-part decryption and verification operation
5494 CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG /*ulEncryptedPartLen*/, CK_BYTE_PTR /*pPart*/, CK_ULONG_PTR /*pulPartLen*/)
5496 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5499 Session* session = (Session*)handleManager->getSession(hSession);
5500 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5502 return CKR_FUNCTION_NOT_SUPPORTED;
5505 // Generate a secret key or a domain parameter set using the specified mechanism
5506 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)
5508 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5510 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5511 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5514 Session* session = (Session*)handleManager->getSession(hSession);
5515 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5517 // Check the mechanism, only accept DSA and DH parameters
5518 // and symmetric ciphers
5519 CK_OBJECT_CLASS objClass;
5520 CK_KEY_TYPE keyType;
5521 switch (pMechanism->mechanism)
5523 case CKM_DSA_PARAMETER_GEN:
5524 objClass = CKO_DOMAIN_PARAMETERS;
5527 case CKM_DH_PKCS_PARAMETER_GEN:
5528 objClass = CKO_DOMAIN_PARAMETERS;
5532 case CKM_DES_KEY_GEN:
5533 objClass = CKO_SECRET_KEY;
5537 case CKM_DES2_KEY_GEN:
5538 objClass = CKO_SECRET_KEY;
5541 case CKM_DES3_KEY_GEN:
5542 objClass = CKO_SECRET_KEY;
5545 case CKM_AES_KEY_GEN:
5546 objClass = CKO_SECRET_KEY;
5550 return CKR_MECHANISM_INVALID;
5553 // Extract information from the template that is needed to create the object.
5554 CK_BBOOL isOnToken = CK_FALSE;
5555 CK_BBOOL isPrivate = CK_TRUE;
5556 CK_CERTIFICATE_TYPE dummy;
5557 bool isImplicit = true;
5558 extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
5560 // Report errors and/or unexpected usage.
5561 if (objClass != CKO_SECRET_KEY && objClass != CKO_DOMAIN_PARAMETERS)
5562 return CKR_ATTRIBUTE_VALUE_INVALID;
5563 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN &&
5564 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DSA))
5565 return CKR_TEMPLATE_INCONSISTENT;
5566 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN &&
5567 (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DH))
5568 return CKR_TEMPLATE_INCONSISTENT;
5569 if (pMechanism->mechanism == CKM_DES_KEY_GEN &&
5570 (objClass != CKO_SECRET_KEY || keyType != CKK_DES))
5571 return CKR_TEMPLATE_INCONSISTENT;
5572 if (pMechanism->mechanism == CKM_DES2_KEY_GEN &&
5573 (objClass != CKO_SECRET_KEY || keyType != CKK_DES2))
5574 return CKR_TEMPLATE_INCONSISTENT;
5575 if (pMechanism->mechanism == CKM_DES3_KEY_GEN &&
5576 (objClass != CKO_SECRET_KEY || keyType != CKK_DES3))
5577 return CKR_TEMPLATE_INCONSISTENT;
5578 if (pMechanism->mechanism == CKM_AES_KEY_GEN &&
5579 (objClass != CKO_SECRET_KEY || keyType != CKK_AES))
5580 return CKR_TEMPLATE_INCONSISTENT;
5582 // Check authorization
5583 CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
5586 if (rv == CKR_USER_NOT_LOGGED_IN)
5587 INFO_MSG("User is not authorized");
5588 if (rv == CKR_SESSION_READ_ONLY)
5589 INFO_MSG("Session is read-only");
5594 // Generate DSA domain parameters
5595 if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN)
5597 return this->generateDSAParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5600 // Generate DH domain parameters
5601 if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN)
5603 return this->generateDHParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5606 // Generate DES secret key
5607 if (pMechanism->mechanism == CKM_DES_KEY_GEN)
5609 return this->generateDES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5612 // Generate DES2 secret key
5613 if (pMechanism->mechanism == CKM_DES2_KEY_GEN)
5615 return this->generateDES2(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5618 // Generate DES3 secret key
5619 if (pMechanism->mechanism == CKM_DES3_KEY_GEN)
5621 return this->generateDES3(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5624 // Generate AES secret key
5625 if (pMechanism->mechanism == CKM_AES_KEY_GEN)
5627 return this->generateAES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5630 return CKR_GENERAL_ERROR;
5633 // Generate a key-pair using the specified mechanism
5634 CK_RV SoftHSM::C_GenerateKeyPair
5636 CK_SESSION_HANDLE hSession,
5637 CK_MECHANISM_PTR pMechanism,
5638 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5639 CK_ULONG ulPublicKeyAttributeCount,
5640 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5641 CK_ULONG ulPrivateKeyAttributeCount,
5642 CK_OBJECT_HANDLE_PTR phPublicKey,
5643 CK_OBJECT_HANDLE_PTR phPrivateKey
5646 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5648 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5649 if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5650 if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5653 Session* session = (Session*)handleManager->getSession(hSession);
5654 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5656 // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation.
5657 CK_KEY_TYPE keyType;
5658 switch (pMechanism->mechanism)
5660 case CKM_RSA_PKCS_KEY_PAIR_GEN:
5663 case CKM_DSA_KEY_PAIR_GEN:
5666 case CKM_DH_PKCS_KEY_PAIR_GEN:
5670 case CKM_EC_KEY_PAIR_GEN:
5675 case CKM_GOSTR3410_KEY_PAIR_GEN:
5676 keyType = CKK_GOSTR3410;
5680 return CKR_MECHANISM_INVALID;
5682 CK_CERTIFICATE_TYPE dummy;
5684 // Extract information from the public key template that is needed to create the object.
5685 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
5686 CK_BBOOL ispublicKeyToken = CK_FALSE;
5687 CK_BBOOL ispublicKeyPrivate = CK_FALSE;
5688 bool isPublicKeyImplicit = true;
5689 extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate, isPublicKeyImplicit);
5691 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5692 if (publicKeyClass != CKO_PUBLIC_KEY)
5693 return CKR_ATTRIBUTE_VALUE_INVALID;
5694 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5695 return CKR_TEMPLATE_INCONSISTENT;
5696 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5697 return CKR_TEMPLATE_INCONSISTENT;
5698 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5699 return CKR_TEMPLATE_INCONSISTENT;
5700 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5701 return CKR_TEMPLATE_INCONSISTENT;
5702 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5703 return CKR_TEMPLATE_INCONSISTENT;
5705 // Extract information from the private key template that is needed to create the object.
5706 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
5707 CK_BBOOL isprivateKeyToken = CK_FALSE;
5708 CK_BBOOL isprivateKeyPrivate = CK_TRUE;
5709 bool isPrivateKeyImplicit = true;
5710 extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit);
5712 // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5713 if (privateKeyClass != CKO_PRIVATE_KEY)
5714 return CKR_ATTRIBUTE_VALUE_INVALID;
5715 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5716 return CKR_TEMPLATE_INCONSISTENT;
5717 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5718 return CKR_TEMPLATE_INCONSISTENT;
5719 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5720 return CKR_TEMPLATE_INCONSISTENT;
5721 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5722 return CKR_TEMPLATE_INCONSISTENT;
5723 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5724 return CKR_TEMPLATE_INCONSISTENT;
5726 // Check user credentials
5727 CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
5730 if (rv == CKR_USER_NOT_LOGGED_IN)
5731 INFO_MSG("User is not authorized");
5732 if (rv == CKR_SESSION_READ_ONLY)
5733 INFO_MSG("Session is read-only");
5738 // Generate RSA keys
5739 if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
5741 return this->generateRSA(hSession,
5742 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5743 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5744 phPublicKey, phPrivateKey,
5745 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5748 // Generate DSA keys
5749 if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
5751 return this->generateDSA(hSession,
5752 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5753 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5754 phPublicKey, phPrivateKey,
5755 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5759 if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
5761 return this->generateEC(hSession,
5762 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5763 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5764 phPublicKey, phPrivateKey,
5765 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5769 if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN)
5771 return this->generateDH(hSession,
5772 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5773 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5774 phPublicKey, phPrivateKey,
5775 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5778 // Generate GOST keys
5779 if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
5781 return this->generateGOST(hSession,
5782 pPublicKeyTemplate, ulPublicKeyAttributeCount,
5783 pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
5784 phPublicKey, phPrivateKey,
5785 ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
5788 return CKR_GENERAL_ERROR;
5791 // Internal: Wrap blob using symmetric key
5792 CK_RV SoftHSM::WrapKeySym
5794 CK_MECHANISM_PTR pMechanism,
5797 ByteString& keydata,
5801 // Get the symmetric algorithm matching the mechanism
5802 SymAlgo::Type algo = SymAlgo::Unknown;
5803 SymWrap::Type mode = SymWrap::Unknown;
5805 #ifdef HAVE_AES_KEY_WRAP
5806 CK_ULONG wrappedlen = keydata.size();
5808 // [PKCS#11 v2.40, 2.14.3 AES Key Wrap]
5809 // A key whose length is not a multiple of the AES Key Wrap block
5810 // size (8 bytes) will be zero padded to fit.
5811 CK_ULONG alignment = wrappedlen % 8;
5814 keydata.resize(wrappedlen + 8 - alignment);
5815 memset(&keydata[wrappedlen], 0, 8 - alignment);
5816 wrappedlen = keydata.size();
5819 switch(pMechanism->mechanism) {
5820 #ifdef HAVE_AES_KEY_WRAP
5821 case CKM_AES_KEY_WRAP:
5822 if ((wrappedlen < 16) || ((wrappedlen % 8) != 0))
5823 return CKR_KEY_SIZE_RANGE;
5824 algo = SymAlgo::AES;
5825 mode = SymWrap::AES_KEYWRAP;
5828 #ifdef HAVE_AES_KEY_WRAP_PAD
5829 case CKM_AES_KEY_WRAP_PAD:
5830 algo = SymAlgo::AES;
5831 mode = SymWrap::AES_KEYWRAP_PAD;
5835 return CKR_MECHANISM_INVALID;
5837 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
5838 if (cipher == NULL) return CKR_MECHANISM_INVALID;
5840 SymmetricKey* wrappingkey = new SymmetricKey();
5842 if (getSymmetricKey(wrappingkey, token, wrapKey) != CKR_OK)
5844 cipher->recycleKey(wrappingkey);
5845 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
5846 return CKR_GENERAL_ERROR;
5849 // adjust key bit length
5850 wrappingkey->setBitLen(wrappingkey->getKeyBits().size() * bb);
5853 if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped))
5855 cipher->recycleKey(wrappingkey);
5856 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
5857 return CKR_GENERAL_ERROR;
5860 cipher->recycleKey(wrappingkey);
5861 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
5865 // Internal: Wrap blob using asymmetric key
5866 CK_RV SoftHSM::WrapKeyAsym
5868 CK_MECHANISM_PTR pMechanism,
5871 ByteString& keydata,
5875 const size_t bb = 8;
5876 AsymAlgo::Type algo = AsymAlgo::Unknown;
5877 AsymMech::Type mech = AsymMech::Unknown;
5879 CK_ULONG modulus_length;
5880 switch(pMechanism->mechanism) {
5882 case CKM_RSA_PKCS_OAEP:
5883 algo = AsymAlgo::RSA;
5884 if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
5885 return CKR_GENERAL_ERROR;
5886 modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
5887 // adjust key bit length
5888 modulus_length /= bb;
5892 return CKR_MECHANISM_INVALID;
5895 switch(pMechanism->mechanism) {
5897 mech = AsymMech::RSA_PKCS;
5898 // RFC 3447 section 7.2.1
5899 if (keydata.size() > modulus_length - 11)
5900 return CKR_KEY_SIZE_RANGE;
5903 case CKM_RSA_PKCS_OAEP:
5904 mech = AsymMech::RSA_PKCS_OAEP;
5905 // SHA-1 is the only supported option
5906 // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
5907 if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
5908 return CKR_KEY_SIZE_RANGE;
5912 return CKR_MECHANISM_INVALID;
5915 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
5916 if (cipher == NULL) return CKR_MECHANISM_INVALID;
5918 PublicKey* publicKey = cipher->newPublicKey();
5919 if (publicKey == NULL)
5921 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
5922 return CKR_HOST_MEMORY;
5925 switch(pMechanism->mechanism) {
5927 case CKM_RSA_PKCS_OAEP:
5928 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
5930 cipher->recyclePublicKey(publicKey);
5931 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
5932 return CKR_GENERAL_ERROR;
5937 return CKR_MECHANISM_INVALID;
5940 if (!cipher->wrapKey(publicKey, keydata, wrapped, mech))
5942 cipher->recyclePublicKey(publicKey);
5943 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
5944 return CKR_GENERAL_ERROR;
5947 cipher->recyclePublicKey(publicKey);
5948 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
5954 // Wrap the specified key using the specified wrapping key and mechanism
5955 CK_RV SoftHSM::C_WrapKey
5957 CK_SESSION_HANDLE hSession,
5958 CK_MECHANISM_PTR pMechanism,
5959 CK_OBJECT_HANDLE hWrappingKey,
5960 CK_OBJECT_HANDLE hKey,
5961 CK_BYTE_PTR pWrappedKey,
5962 CK_ULONG_PTR pulWrappedKeyLen
5965 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5967 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5968 if (pulWrappedKeyLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
5971 Session* session = (Session*)handleManager->getSession(hSession);
5972 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5975 // Check the mechanism, only accept advanced AES key wrapping and RSA
5976 switch(pMechanism->mechanism)
5978 #ifdef HAVE_AES_KEY_WRAP
5979 case CKM_AES_KEY_WRAP:
5981 #ifdef HAVE_AES_KEY_WRAP_PAD
5982 case CKM_AES_KEY_WRAP_PAD:
5985 // Does not handle optional init vector
5986 if (pMechanism->pParameter != NULL_PTR ||
5987 pMechanism->ulParameterLen != 0)
5988 return CKR_ARGUMENTS_BAD;
5990 case CKM_RSA_PKCS_OAEP:
5991 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
5997 return CKR_MECHANISM_INVALID;
6001 Token* token = session->getToken();
6002 if (token == NULL) return CKR_GENERAL_ERROR;
6004 // Check the wrapping key handle.
6005 OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
6006 if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
6008 CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
6009 CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
6011 // Check user credentials for the wrapping key
6012 rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
6015 if (rv == CKR_USER_NOT_LOGGED_IN)
6016 INFO_MSG("User is not authorized");
6021 // Check wrapping key class and type
6022 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6023 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6024 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
6025 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6026 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6027 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6028 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6029 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6030 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6031 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6033 // Check if the wrapping key can be used for wrapping
6034 if (wrapKey->getBooleanValue(CKA_WRAP, false) == false)
6035 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6037 // Check if the specified mechanism is allowed for the wrapping key
6038 if (!isMechanismPermitted(wrapKey, pMechanism))
6039 return CKR_MECHANISM_INVALID;
6041 // Check the to be wrapped key handle.
6042 OSObject *key = (OSObject *)handleManager->getObject(hKey);
6043 if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
6045 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6046 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6048 // Check user credentials for the to be wrapped key
6049 rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6052 if (rv == CKR_USER_NOT_LOGGED_IN)
6053 INFO_MSG("User is not authorized");
6058 // Check if the to be wrapped key can be wrapped
6059 if (key->getBooleanValue(CKA_EXTRACTABLE, false) == false)
6060 return CKR_KEY_UNEXTRACTABLE;
6061 if (key->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false) && wrapKey->getBooleanValue(CKA_TRUSTED, false) == false)
6062 return CKR_KEY_NOT_WRAPPABLE;
6065 CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6066 if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
6067 return CKR_KEY_NOT_WRAPPABLE;
6068 // 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
6069 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
6070 return CKR_KEY_NOT_WRAPPABLE;
6072 // Verify the wrap template attribute
6073 if (wrapKey->attributeExists(CKA_WRAP_TEMPLATE))
6075 OSAttribute attr = wrapKey->getAttribute(CKA_WRAP_TEMPLATE);
6077 if (attr.isAttributeMapAttribute())
6079 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6081 const attrmap_type& map = attr.getAttributeMapValue();
6083 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6085 if (!key->attributeExists(it->first))
6087 return CKR_KEY_NOT_WRAPPABLE;
6090 OSAttribute keyAttr = key->getAttribute(it->first);
6092 if (!keyAttr.peekValue(v1) || !it->second.peekValue(v2) || (v1 != v2))
6094 return CKR_KEY_NOT_WRAPPABLE;
6100 // Get the key data to encrypt
6102 if (keyClass == CKO_SECRET_KEY)
6106 bool bOK = token->decrypt(key->getByteStringValue(CKA_VALUE), keydata);
6107 if (!bOK) return CKR_GENERAL_ERROR;
6111 keydata = key->getByteStringValue(CKA_VALUE);
6116 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6117 AsymAlgo::Type alg = AsymAlgo::Unknown;
6120 alg = AsymAlgo::RSA;
6123 alg = AsymAlgo::DSA;
6130 // can be ecdh too but it doesn't matter
6131 alg = AsymAlgo::ECDSA;
6135 return CKR_KEY_NOT_WRAPPABLE;
6137 AsymmetricAlgorithm* asymCrypto = NULL;
6138 PrivateKey* privateKey = NULL;
6139 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6140 if (asymCrypto == NULL)
6141 return CKR_GENERAL_ERROR;
6142 privateKey = asymCrypto->newPrivateKey();
6143 if (privateKey == NULL)
6145 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6146 return CKR_HOST_MEMORY;
6150 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6153 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6156 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6160 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6166 asymCrypto->recyclePrivateKey(privateKey);
6167 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6168 return CKR_GENERAL_ERROR;
6170 keydata = privateKey->PKCS8Encode();
6171 asymCrypto->recyclePrivateKey(privateKey);
6172 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6174 if (keydata.size() == 0)
6175 return CKR_KEY_NOT_WRAPPABLE;
6177 keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6179 if (keyClass == CKO_SECRET_KEY)
6180 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6182 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6186 if (pWrappedKey != NULL) {
6187 if (*pulWrappedKeyLen >= wrapped.size())
6188 memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6190 rv = CKR_BUFFER_TOO_SMALL;
6193 *pulWrappedKeyLen = wrapped.size();
6197 // Internal: Unwrap blob using symmetric key
6198 CK_RV SoftHSM::UnwrapKeySym
6200 CK_MECHANISM_PTR pMechanism,
6201 ByteString& wrapped,
6203 OSObject* unwrapKey,
6207 // Get the symmetric algorithm matching the mechanism
6208 SymAlgo::Type algo = SymAlgo::Unknown;
6209 SymWrap::Type mode = SymWrap::Unknown;
6211 switch(pMechanism->mechanism) {
6212 #ifdef HAVE_AES_KEY_WRAP
6213 case CKM_AES_KEY_WRAP:
6214 algo = SymAlgo::AES;
6215 mode = SymWrap::AES_KEYWRAP;
6218 #ifdef HAVE_AES_KEY_WRAP_PAD
6219 case CKM_AES_KEY_WRAP_PAD:
6220 algo = SymAlgo::AES;
6221 mode = SymWrap::AES_KEYWRAP_PAD;
6225 return CKR_MECHANISM_INVALID;
6227 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6228 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6230 SymmetricKey* unwrappingkey = new SymmetricKey();
6232 if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6234 cipher->recycleKey(unwrappingkey);
6235 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6236 return CKR_GENERAL_ERROR;
6239 // adjust key bit length
6240 unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6244 if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6245 rv = CKR_GENERAL_ERROR;
6246 cipher->recycleKey(unwrappingkey);
6247 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6251 // Internal: Unwrap blob using asymmetric key
6252 CK_RV SoftHSM::UnwrapKeyAsym
6254 CK_MECHANISM_PTR pMechanism,
6255 ByteString& wrapped,
6257 OSObject* unwrapKey,
6261 // Get the symmetric algorithm matching the mechanism
6262 AsymAlgo::Type algo = AsymAlgo::Unknown;
6263 AsymMech::Type mode = AsymMech::Unknown;
6264 switch(pMechanism->mechanism) {
6266 algo = AsymAlgo::RSA;
6267 mode = AsymMech::RSA_PKCS;
6270 case CKM_RSA_PKCS_OAEP:
6271 algo = AsymAlgo::RSA;
6272 mode = AsymMech::RSA_PKCS_OAEP;
6276 return CKR_MECHANISM_INVALID;
6278 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6279 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6281 PrivateKey* unwrappingkey = cipher->newPrivateKey();
6282 if (unwrappingkey == NULL)
6284 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6285 return CKR_HOST_MEMORY;
6288 switch(pMechanism->mechanism) {
6290 case CKM_RSA_PKCS_OAEP:
6291 if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6293 cipher->recyclePrivateKey(unwrappingkey);
6294 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6295 return CKR_GENERAL_ERROR;
6300 return CKR_MECHANISM_INVALID;
6305 if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6306 rv = CKR_GENERAL_ERROR;
6307 cipher->recyclePrivateKey(unwrappingkey);
6308 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6312 // Unwrap the specified key using the specified unwrapping key
6313 CK_RV SoftHSM::C_UnwrapKey
6315 CK_SESSION_HANDLE hSession,
6316 CK_MECHANISM_PTR pMechanism,
6317 CK_OBJECT_HANDLE hUnwrappingKey,
6318 CK_BYTE_PTR pWrappedKey,
6319 CK_ULONG ulWrappedKeyLen,
6320 CK_ATTRIBUTE_PTR pTemplate,
6322 CK_OBJECT_HANDLE_PTR hKey
6325 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6327 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6328 if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6329 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6330 if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6333 Session* session = (Session*)handleManager->getSession(hSession);
6334 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6337 // Check the mechanism
6338 switch(pMechanism->mechanism)
6340 #ifdef HAVE_AES_KEY_WRAP
6341 case CKM_AES_KEY_WRAP:
6342 if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
6343 return CKR_WRAPPED_KEY_LEN_RANGE;
6344 // Does not handle optional init vector
6345 if (pMechanism->pParameter != NULL_PTR ||
6346 pMechanism->ulParameterLen != 0)
6347 return CKR_ARGUMENTS_BAD;
6350 #ifdef HAVE_AES_KEY_WRAP_PAD
6351 case CKM_AES_KEY_WRAP_PAD:
6352 if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6353 return CKR_WRAPPED_KEY_LEN_RANGE;
6354 // Does not handle optional init vector
6355 if (pMechanism->pParameter != NULL_PTR ||
6356 pMechanism->ulParameterLen != 0)
6357 return CKR_ARGUMENTS_BAD;
6361 // Input length checks needs to be done later when unwrapping key is known
6363 case CKM_RSA_PKCS_OAEP:
6364 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6370 return CKR_MECHANISM_INVALID;
6374 Token* token = session->getToken();
6375 if (token == NULL) return CKR_GENERAL_ERROR;
6377 // Check the unwrapping key handle.
6378 OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6379 if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6381 CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6382 CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6384 // Check user credentials
6385 rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6388 if (rv == CKR_USER_NOT_LOGGED_IN)
6389 INFO_MSG("User is not authorized");
6394 // Check unwrapping key class and type
6395 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6396 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6397 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6398 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6399 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6400 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6401 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6402 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6403 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6404 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6406 // Check if the unwrapping key can be used for unwrapping
6407 if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6408 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6410 // Check if the specified mechanism is allowed for the unwrap key
6411 if (!isMechanismPermitted(unwrapKey, pMechanism))
6412 return CKR_MECHANISM_INVALID;
6414 // Extract information from the template that is needed to create the object.
6415 CK_OBJECT_CLASS objClass;
6416 CK_KEY_TYPE keyType;
6417 CK_BBOOL isOnToken = CK_FALSE;
6418 CK_BBOOL isPrivate = CK_TRUE;
6419 CK_CERTIFICATE_TYPE dummy;
6420 bool isImplicit = false;
6421 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6424 ERROR_MSG("Mandatory attribute not present in template");
6428 // Report errors and/or unexpected usage.
6429 if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6430 return CKR_ATTRIBUTE_VALUE_INVALID;
6431 // Key type will be handled at object creation
6433 // Check authorization
6434 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6437 if (rv == CKR_USER_NOT_LOGGED_IN)
6438 INFO_MSG("User is not authorized");
6439 if (rv == CKR_SESSION_READ_ONLY)
6440 INFO_MSG("Session is read-only");
6445 // Build unwrapped key template
6446 const CK_ULONG maxAttribs = 32;
6447 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6448 { CKA_CLASS, &objClass, sizeof(objClass) },
6449 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6450 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6451 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6453 CK_ULONG secretAttribsCount = 4;
6455 // Add the additional
6456 if (ulCount > (maxAttribs - secretAttribsCount))
6457 return CKR_TEMPLATE_INCONSISTENT;
6458 for (CK_ULONG i = 0; i < ulCount; ++i)
6460 switch (pTemplate[i].type)
6468 secretAttribs[secretAttribsCount++] = pTemplate[i];
6472 // Apply the unwrap template
6473 if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6475 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6477 if (unwrapAttr.isAttributeMapAttribute())
6479 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6481 const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6483 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6485 CK_ATTRIBUTE* attr = NULL;
6486 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6488 if (it->first == secretAttribs[i].type)
6492 return CKR_TEMPLATE_INCONSISTENT;
6494 attr = &secretAttribs[i];
6496 it->second.peekValue(value);
6497 if (attr->ulValueLen != value.size())
6499 return CKR_TEMPLATE_INCONSISTENT;
6501 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6503 return CKR_TEMPLATE_INCONSISTENT;
6509 return CKR_TEMPLATE_INCONSISTENT;
6515 *hKey = CK_INVALID_HANDLE;
6518 ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6520 if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6521 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6522 else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6523 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6525 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6529 // Create the secret object using C_CreateObject
6530 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6532 // Store the attributes that are being supplied
6535 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6536 if (osobject == NULL_PTR || !osobject->isValid())
6537 rv = CKR_FUNCTION_FAILED;
6538 if (osobject->startTransaction())
6542 // Common Attributes
6543 bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6545 // Common Secret Key Attributes
6546 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6547 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6549 // Secret Attributes
6550 if (objClass == CKO_SECRET_KEY)
6554 token->encrypt(keydata, value);
6557 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6559 else if (keyType == CKK_RSA)
6561 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6563 else if (keyType == CKK_DSA)
6565 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6567 else if (keyType == CKK_DH)
6569 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6571 else if (keyType == CKK_EC)
6573 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6579 bOK = osobject->commitTransaction();
6581 osobject->abortTransaction();
6584 rv = CKR_FUNCTION_FAILED;
6587 rv = CKR_FUNCTION_FAILED;
6590 // Remove secret that may have been created already when the function fails.
6593 if (*hKey != CK_INVALID_HANDLE)
6595 OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6596 handleManager->destroyObject(*hKey);
6597 if (obj) obj->destroyObject();
6598 *hKey = CK_INVALID_HANDLE;
6606 // Derive a key from the specified base key
6607 CK_RV SoftHSM::C_DeriveKey
6609 CK_SESSION_HANDLE hSession,
6610 CK_MECHANISM_PTR pMechanism,
6611 CK_OBJECT_HANDLE hBaseKey,
6612 CK_ATTRIBUTE_PTR pTemplate,
6614 CK_OBJECT_HANDLE_PTR phKey
6617 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6619 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6620 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6621 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6624 Session* session = (Session*)handleManager->getSession(hSession);
6625 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6627 // Check the mechanism, only accept DH and ECDH derive
6628 switch (pMechanism->mechanism)
6630 case CKM_DH_PKCS_DERIVE:
6632 case CKM_ECDH1_DERIVE:
6635 case CKM_DES_ECB_ENCRYPT_DATA:
6636 case CKM_DES_CBC_ENCRYPT_DATA:
6638 case CKM_DES3_ECB_ENCRYPT_DATA:
6639 case CKM_DES3_CBC_ENCRYPT_DATA:
6640 case CKM_AES_ECB_ENCRYPT_DATA:
6641 case CKM_AES_CBC_ENCRYPT_DATA:
6644 ERROR_MSG("Invalid mechanism");
6645 return CKR_MECHANISM_INVALID;
6649 Token* token = session->getToken();
6650 if (token == NULL) return CKR_GENERAL_ERROR;
6652 // Check the key handle.
6653 OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6654 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6656 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6657 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6659 // Check user credentials
6660 CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6663 if (rv == CKR_USER_NOT_LOGGED_IN)
6664 INFO_MSG("User is not authorized");
6669 // Check if key can be used for derive
6670 if (!key->getBooleanValue(CKA_DERIVE, false))
6671 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6673 // Check if the specified mechanism is allowed for the key
6674 if (!isMechanismPermitted(key, pMechanism))
6675 return CKR_MECHANISM_INVALID;
6677 // Extract information from the template that is needed to create the object.
6678 CK_OBJECT_CLASS objClass;
6679 CK_KEY_TYPE keyType;
6680 CK_BBOOL isOnToken = CK_FALSE;
6681 CK_BBOOL isPrivate = CK_TRUE;
6682 CK_CERTIFICATE_TYPE dummy;
6683 bool isImplicit = false;
6684 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6687 ERROR_MSG("Mandatory attribute not present in template");
6691 // Report errors and/or unexpected usage.
6692 if (objClass != CKO_SECRET_KEY)
6693 return CKR_ATTRIBUTE_VALUE_INVALID;
6694 if (keyType != CKK_GENERIC_SECRET &&
6695 keyType != CKK_DES &&
6696 keyType != CKK_DES2 &&
6697 keyType != CKK_DES3 &&
6699 return CKR_TEMPLATE_INCONSISTENT;
6701 // Check authorization
6702 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6705 if (rv == CKR_USER_NOT_LOGGED_IN)
6706 INFO_MSG("User is not authorized");
6707 if (rv == CKR_SESSION_READ_ONLY)
6708 INFO_MSG("Session is read-only");
6714 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
6716 // Check key class and type
6717 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6718 return CKR_KEY_TYPE_INCONSISTENT;
6719 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
6720 return CKR_KEY_TYPE_INCONSISTENT;
6722 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6726 // Derive ECDH secret
6727 if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
6729 // Check key class and type
6730 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6731 return CKR_KEY_TYPE_INCONSISTENT;
6732 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
6733 return CKR_KEY_TYPE_INCONSISTENT;
6735 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6739 // Derive symmetric secret
6740 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
6741 pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
6742 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
6743 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
6744 pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
6745 pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
6747 // Check key class and type
6748 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6749 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6750 return CKR_KEY_TYPE_INCONSISTENT;
6751 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
6752 baseKeyType != CKK_DES)
6753 return CKR_KEY_TYPE_INCONSISTENT;
6754 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
6755 baseKeyType != CKK_DES)
6756 return CKR_KEY_TYPE_INCONSISTENT;
6757 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
6758 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6759 return CKR_KEY_TYPE_INCONSISTENT;
6760 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
6761 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6762 return CKR_KEY_TYPE_INCONSISTENT;
6763 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
6764 baseKeyType != CKK_AES)
6765 return CKR_KEY_TYPE_INCONSISTENT;
6766 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
6767 baseKeyType != CKK_AES)
6768 return CKR_KEY_TYPE_INCONSISTENT;
6770 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6773 return CKR_MECHANISM_INVALID;
6776 // Seed the random number generator with new data
6777 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
6779 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6781 if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
6784 Session* session = (Session*)handleManager->getSession(hSession);
6785 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6788 RNG* rng = CryptoFactory::i()->getRNG();
6789 if (rng == NULL) return CKR_GENERAL_ERROR;
6792 ByteString seed(pSeed, ulSeedLen);
6798 // Generate the specified amount of random data
6799 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
6801 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6803 if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
6806 Session* session = (Session*)handleManager->getSession(hSession);
6807 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6810 RNG* rng = CryptoFactory::i()->getRNG();
6811 if (rng == NULL) return CKR_GENERAL_ERROR;
6813 // Generate random data
6814 ByteString randomData;
6815 if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
6817 // Return random data
6818 if (ulRandomLen != 0)
6820 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
6827 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
6829 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6832 Session* session = (Session*)handleManager->getSession(hSession);
6833 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6835 return CKR_FUNCTION_NOT_PARALLEL;
6839 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
6841 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6844 Session* session = (Session*)handleManager->getSession(hSession);
6845 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6847 return CKR_FUNCTION_NOT_PARALLEL;
6850 // Wait or poll for a slot event on the specified slot
6851 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
6853 return CKR_FUNCTION_NOT_SUPPORTED;
6856 // Generate an AES secret key
6857 CK_RV SoftHSM::generateAES
6858 (CK_SESSION_HANDLE hSession,
6859 CK_ATTRIBUTE_PTR pTemplate,
6861 CK_OBJECT_HANDLE_PTR phKey,
6865 *phKey = CK_INVALID_HANDLE;
6868 Session* session = (Session*)handleManager->getSession(hSession);
6869 if (session == NULL)
6870 return CKR_SESSION_HANDLE_INVALID;
6873 Token* token = session->getToken();
6875 return CKR_GENERAL_ERROR;
6877 // Extract desired parameter information
6879 bool checkValue = true;
6880 for (CK_ULONG i = 0; i < ulCount; i++)
6882 switch (pTemplate[i].type)
6885 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
6887 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
6888 return CKR_ATTRIBUTE_VALUE_INVALID;
6890 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
6892 case CKA_CHECK_VALUE:
6893 if (pTemplate[i].ulValueLen > 0)
6895 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
6896 return CKR_ATTRIBUTE_VALUE_INVALID;
6905 // CKA_VALUE_LEN must be specified
6908 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
6909 return CKR_TEMPLATE_INCOMPLETE;
6912 // keyLen must be 16, 24, or 32
6913 if (keyLen != 16 && keyLen != 24 && keyLen != 32)
6915 INFO_MSG("bad AES key length");
6916 return CKR_ATTRIBUTE_VALUE_INVALID;
6919 // Generate the secret key
6920 AESKey* key = new AESKey(keyLen * 8);
6921 SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
6924 ERROR_MSG("Could not get SymmetricAlgorithm");
6926 return CKR_GENERAL_ERROR;
6928 RNG* rng = CryptoFactory::i()->getRNG();
6931 ERROR_MSG("Could not get RNG");
6932 aes->recycleKey(key);
6933 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6934 return CKR_GENERAL_ERROR;
6936 if (!aes->generateKey(*key, rng))
6938 ERROR_MSG("Could not generate AES secret key");
6939 aes->recycleKey(key);
6940 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6941 return CKR_GENERAL_ERROR;
6946 // Create the secret key object using C_CreateObject
6947 const CK_ULONG maxAttribs = 32;
6948 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
6949 CK_KEY_TYPE keyType = CKK_AES;
6950 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
6951 { CKA_CLASS, &objClass, sizeof(objClass) },
6952 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6953 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6954 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
6956 CK_ULONG keyAttribsCount = 4;
6958 // Add the additional
6959 if (ulCount > (maxAttribs - keyAttribsCount))
6960 rv = CKR_TEMPLATE_INCONSISTENT;
6961 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
6963 switch (pTemplate[i].type)
6969 case CKA_CHECK_VALUE:
6972 keyAttribs[keyAttribsCount++] = pTemplate[i];
6977 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
6979 // Store the attributes that are being supplied
6982 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
6983 if (osobject == NULL_PTR || !osobject->isValid()) {
6984 rv = CKR_FUNCTION_FAILED;
6985 } else if (osobject->startTransaction()) {
6988 // Common Attributes
6989 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
6990 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
6991 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
6993 // Common Secret Key Attributes
6994 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
6995 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
6996 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
6997 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
6999 // AES Secret Key Attributes
7004 token->encrypt(key->getKeyBits(), value);
7005 token->encrypt(key->getKeyCheckValue(), kcv);
7009 value = key->getKeyBits();
7010 kcv = key->getKeyCheckValue();
7012 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7014 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7017 bOK = osobject->commitTransaction();
7019 osobject->abortTransaction();
7022 rv = CKR_FUNCTION_FAILED;
7024 rv = CKR_FUNCTION_FAILED;
7028 aes->recycleKey(key);
7029 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7031 // Remove the key that may have been created already when the function fails.
7034 if (*phKey != CK_INVALID_HANDLE)
7036 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7037 handleManager->destroyObject(*phKey);
7038 if (oskey) oskey->destroyObject();
7039 *phKey = CK_INVALID_HANDLE;
7046 // Generate a DES secret key
7047 CK_RV SoftHSM::generateDES
7048 (CK_SESSION_HANDLE hSession,
7049 CK_ATTRIBUTE_PTR pTemplate,
7051 CK_OBJECT_HANDLE_PTR phKey,
7055 *phKey = CK_INVALID_HANDLE;
7058 Session* session = (Session*)handleManager->getSession(hSession);
7059 if (session == NULL)
7060 return CKR_SESSION_HANDLE_INVALID;
7063 Token* token = session->getToken();
7065 return CKR_GENERAL_ERROR;
7067 // Extract desired parameter information
7068 bool checkValue = true;
7069 for (CK_ULONG i = 0; i < ulCount; i++)
7071 switch (pTemplate[i].type)
7073 case CKA_CHECK_VALUE:
7074 if (pTemplate[i].ulValueLen > 0)
7076 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7077 return CKR_ATTRIBUTE_VALUE_INVALID;
7086 // Generate the secret key
7087 DESKey* key = new DESKey(56);
7088 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7091 ERROR_MSG("Could not get SymmetricAlgorithm");
7093 return CKR_GENERAL_ERROR;
7095 RNG* rng = CryptoFactory::i()->getRNG();
7098 ERROR_MSG("Could not get RNG");
7099 des->recycleKey(key);
7100 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7101 return CKR_GENERAL_ERROR;
7103 if (!des->generateKey(*key, rng))
7105 ERROR_MSG("Could not generate DES secret key");
7106 des->recycleKey(key);
7107 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7108 return CKR_GENERAL_ERROR;
7113 // Create the secret key object using C_CreateObject
7114 const CK_ULONG maxAttribs = 32;
7115 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7116 CK_KEY_TYPE keyType = CKK_DES;
7117 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7118 { CKA_CLASS, &objClass, sizeof(objClass) },
7119 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7120 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7121 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7123 CK_ULONG keyAttribsCount = 4;
7125 // Add the additional
7126 if (ulCount > (maxAttribs - keyAttribsCount))
7127 rv = CKR_TEMPLATE_INCONSISTENT;
7128 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7130 switch (pTemplate[i].type)
7136 case CKA_CHECK_VALUE:
7139 keyAttribs[keyAttribsCount++] = pTemplate[i];
7144 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7146 // Store the attributes that are being supplied
7149 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7150 if (osobject == NULL_PTR || !osobject->isValid()) {
7151 rv = CKR_FUNCTION_FAILED;
7152 } else if (osobject->startTransaction()) {
7155 // Common Attributes
7156 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7157 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7158 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7160 // Common Secret Key Attributes
7161 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7162 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7163 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7164 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7166 // DES Secret Key Attributes
7171 token->encrypt(key->getKeyBits(), value);
7172 token->encrypt(key->getKeyCheckValue(), kcv);
7176 value = key->getKeyBits();
7177 kcv = key->getKeyCheckValue();
7179 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7181 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7184 bOK = osobject->commitTransaction();
7186 osobject->abortTransaction();
7189 rv = CKR_FUNCTION_FAILED;
7191 rv = CKR_FUNCTION_FAILED;
7195 des->recycleKey(key);
7196 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7198 // Remove the key that may have been created already when the function fails.
7201 if (*phKey != CK_INVALID_HANDLE)
7203 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7204 handleManager->destroyObject(*phKey);
7205 if (oskey) oskey->destroyObject();
7206 *phKey = CK_INVALID_HANDLE;
7213 // Generate a DES2 secret key
7214 CK_RV SoftHSM::generateDES2
7215 (CK_SESSION_HANDLE hSession,
7216 CK_ATTRIBUTE_PTR pTemplate,
7218 CK_OBJECT_HANDLE_PTR phKey,
7222 *phKey = CK_INVALID_HANDLE;
7225 Session* session = (Session*)handleManager->getSession(hSession);
7226 if (session == NULL)
7227 return CKR_SESSION_HANDLE_INVALID;
7230 Token* token = session->getToken();
7232 return CKR_GENERAL_ERROR;
7234 // Extract desired parameter information
7235 bool checkValue = true;
7236 for (CK_ULONG i = 0; i < ulCount; i++)
7238 switch (pTemplate[i].type)
7240 case CKA_CHECK_VALUE:
7241 if (pTemplate[i].ulValueLen > 0)
7243 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7244 return CKR_ATTRIBUTE_VALUE_INVALID;
7253 // Generate the secret key
7254 DESKey* key = new DESKey(112);
7255 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7258 ERROR_MSG("Could not get SymmetricAlgorith");
7260 return CKR_GENERAL_ERROR;
7262 RNG* rng = CryptoFactory::i()->getRNG();
7265 ERROR_MSG("Could not get RNG");
7266 des->recycleKey(key);
7267 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7268 return CKR_GENERAL_ERROR;
7270 if (!des->generateKey(*key, rng))
7272 ERROR_MSG("Could not generate DES secret key");
7273 des->recycleKey(key);
7274 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7275 return CKR_GENERAL_ERROR;
7280 // Create the secret key object using C_CreateObject
7281 const CK_ULONG maxAttribs = 32;
7282 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7283 CK_KEY_TYPE keyType = CKK_DES2;
7284 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7285 { CKA_CLASS, &objClass, sizeof(objClass) },
7286 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7287 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7288 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7290 CK_ULONG keyAttribsCount = 4;
7292 // Add the additional
7293 if (ulCount > (maxAttribs - keyAttribsCount))
7294 rv = CKR_TEMPLATE_INCONSISTENT;
7295 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7297 switch (pTemplate[i].type)
7303 case CKA_CHECK_VALUE:
7306 keyAttribs[keyAttribsCount++] = pTemplate[i];
7311 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7313 // Store the attributes that are being supplied
7316 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7317 if (osobject == NULL_PTR || !osobject->isValid()) {
7318 rv = CKR_FUNCTION_FAILED;
7319 } else if (osobject->startTransaction()) {
7322 // Common Attributes
7323 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7324 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7325 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7327 // Common Secret Key Attributes
7328 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7329 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7330 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7331 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7333 // DES Secret Key Attributes
7338 token->encrypt(key->getKeyBits(), value);
7339 token->encrypt(key->getKeyCheckValue(), kcv);
7343 value = key->getKeyBits();
7344 kcv = key->getKeyCheckValue();
7346 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7348 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7351 bOK = osobject->commitTransaction();
7353 osobject->abortTransaction();
7356 rv = CKR_FUNCTION_FAILED;
7358 rv = CKR_FUNCTION_FAILED;
7362 des->recycleKey(key);
7363 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7365 // Remove the key that may have been created already when the function fails.
7368 if (*phKey != CK_INVALID_HANDLE)
7370 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7371 handleManager->destroyObject(*phKey);
7372 if (oskey) oskey->destroyObject();
7373 *phKey = CK_INVALID_HANDLE;
7380 // Generate a DES3 secret key
7381 CK_RV SoftHSM::generateDES3
7382 (CK_SESSION_HANDLE hSession,
7383 CK_ATTRIBUTE_PTR pTemplate,
7385 CK_OBJECT_HANDLE_PTR phKey,
7389 *phKey = CK_INVALID_HANDLE;
7392 Session* session = (Session*)handleManager->getSession(hSession);
7393 if (session == NULL)
7394 return CKR_SESSION_HANDLE_INVALID;
7397 Token* token = session->getToken();
7399 return CKR_GENERAL_ERROR;
7401 // Extract desired parameter information
7402 bool checkValue = true;
7403 for (CK_ULONG i = 0; i < ulCount; i++)
7405 switch (pTemplate[i].type)
7407 case CKA_CHECK_VALUE:
7408 if (pTemplate[i].ulValueLen > 0)
7410 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7411 return CKR_ATTRIBUTE_VALUE_INVALID;
7420 // Generate the secret key
7421 DESKey* key = new DESKey(168);
7422 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7425 ERROR_MSG("Could not get SymmetricAlgorithm");
7427 return CKR_GENERAL_ERROR;
7429 RNG* rng = CryptoFactory::i()->getRNG();
7432 ERROR_MSG("Could not get RNG");
7433 des->recycleKey(key);
7434 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7435 return CKR_GENERAL_ERROR;
7437 if (!des->generateKey(*key, rng))
7439 ERROR_MSG("Could not generate DES secret key");
7440 des->recycleKey(key);
7441 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7442 return CKR_GENERAL_ERROR;
7447 // Create the secret key object using C_CreateObject
7448 const CK_ULONG maxAttribs = 32;
7449 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7450 CK_KEY_TYPE keyType = CKK_DES3;
7451 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7452 { CKA_CLASS, &objClass, sizeof(objClass) },
7453 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7454 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7455 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7457 CK_ULONG keyAttribsCount = 4;
7459 // Add the additional
7460 if (ulCount > (maxAttribs - keyAttribsCount))
7461 rv = CKR_TEMPLATE_INCONSISTENT;
7462 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7464 switch (pTemplate[i].type)
7470 case CKA_CHECK_VALUE:
7473 keyAttribs[keyAttribsCount++] = pTemplate[i];
7478 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7480 // Store the attributes that are being supplied
7483 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7484 if (osobject == NULL_PTR || !osobject->isValid()) {
7485 rv = CKR_FUNCTION_FAILED;
7486 } else if (osobject->startTransaction()) {
7489 // Common Attributes
7490 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7491 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7492 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7494 // Common Secret Key Attributes
7495 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7496 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7497 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7498 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7500 // DES Secret Key Attributes
7505 token->encrypt(key->getKeyBits(), value);
7506 token->encrypt(key->getKeyCheckValue(), kcv);
7510 value = key->getKeyBits();
7511 kcv = key->getKeyCheckValue();
7513 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7515 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7518 bOK = osobject->commitTransaction();
7520 osobject->abortTransaction();
7523 rv = CKR_FUNCTION_FAILED;
7525 rv = CKR_FUNCTION_FAILED;
7529 des->recycleKey(key);
7530 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7532 // Remove the key that may have been created already when the function fails.
7535 if (*phKey != CK_INVALID_HANDLE)
7537 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7538 handleManager->destroyObject(*phKey);
7539 if (oskey) oskey->destroyObject();
7540 *phKey = CK_INVALID_HANDLE;
7547 // Generate an RSA key pair
7548 CK_RV SoftHSM::generateRSA
7549 (CK_SESSION_HANDLE hSession,
7550 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7551 CK_ULONG ulPublicKeyAttributeCount,
7552 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7553 CK_ULONG ulPrivateKeyAttributeCount,
7554 CK_OBJECT_HANDLE_PTR phPublicKey,
7555 CK_OBJECT_HANDLE_PTR phPrivateKey,
7556 CK_BBOOL isPublicKeyOnToken,
7557 CK_BBOOL isPublicKeyPrivate,
7558 CK_BBOOL isPrivateKeyOnToken,
7559 CK_BBOOL isPrivateKeyPrivate
7562 *phPublicKey = CK_INVALID_HANDLE;
7563 *phPrivateKey = CK_INVALID_HANDLE;
7566 Session* session = (Session*)handleManager->getSession(hSession);
7567 if (session == NULL)
7568 return CKR_SESSION_HANDLE_INVALID;
7571 Token* token = session->getToken();
7573 return CKR_GENERAL_ERROR;
7575 // Extract desired key information: bitlen and public exponent
7577 ByteString exponent("010001");
7578 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7580 switch (pPublicKeyTemplate[i].type)
7582 case CKA_MODULUS_BITS:
7583 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7585 INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7586 return CKR_ATTRIBUTE_VALUE_INVALID;
7588 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7590 case CKA_PUBLIC_EXPONENT:
7591 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7598 // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7600 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7601 return CKR_TEMPLATE_INCOMPLETE;
7604 // Set the parameters
7607 p.setBitLength(bitLen);
7609 // Generate key pair
7610 AsymmetricKeyPair* kp = NULL;
7611 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7613 return CKR_GENERAL_ERROR;
7614 if (!rsa->generateKeyPair(&kp, &p))
7616 ERROR_MSG("Could not generate key pair");
7617 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7618 return CKR_GENERAL_ERROR;
7621 RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7622 RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7626 // Create a public key using C_CreateObject
7629 const CK_ULONG maxAttribs = 32;
7630 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7631 CK_KEY_TYPE publicKeyType = CKK_RSA;
7632 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7633 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7634 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7635 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7636 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7638 CK_ULONG publicKeyAttribsCount = 4;
7640 // Add the additional
7641 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7642 rv = CKR_TEMPLATE_INCONSISTENT;
7643 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7645 switch (pPublicKeyTemplate[i].type)
7651 case CKA_PUBLIC_EXPONENT:
7654 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7659 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7661 // Store the attributes that are being supplied by the key generation to the object
7664 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7665 if (osobject == NULL_PTR || !osobject->isValid()) {
7666 rv = CKR_FUNCTION_FAILED;
7667 } else if (osobject->startTransaction()) {
7670 // Common Key Attributes
7671 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7672 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7673 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7675 // RSA Public Key Attributes
7677 ByteString publicExponent;
7678 if (isPublicKeyPrivate)
7680 token->encrypt(pub->getN(), modulus);
7681 token->encrypt(pub->getE(), publicExponent);
7685 modulus = pub->getN();
7686 publicExponent = pub->getE();
7688 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7689 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7692 bOK = osobject->commitTransaction();
7694 osobject->abortTransaction();
7697 rv = CKR_FUNCTION_FAILED;
7699 rv = CKR_FUNCTION_FAILED;
7703 // Create a private key using C_CreateObject
7706 const CK_ULONG maxAttribs = 32;
7707 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7708 CK_KEY_TYPE privateKeyType = CKK_RSA;
7709 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7710 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7711 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7712 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7713 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7715 CK_ULONG privateKeyAttribsCount = 4;
7716 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7717 rv = CKR_TEMPLATE_INCONSISTENT;
7718 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
7720 switch (pPrivateKeyTemplate[i].type)
7728 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
7733 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
7735 // Store the attributes that are being supplied by the key generation to the object
7738 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
7739 if (osobject == NULL_PTR || !osobject->isValid()) {
7740 rv = CKR_FUNCTION_FAILED;
7741 } else if (osobject->startTransaction()) {
7744 // Common Key Attributes
7745 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7746 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7747 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7749 // Common Private Key Attributes
7750 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7751 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7752 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7753 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7755 // RSA Private Key Attributes
7757 ByteString publicExponent;
7758 ByteString privateExponent;
7761 ByteString exponent1;
7762 ByteString exponent2;
7763 ByteString coefficient;
7764 if (isPrivateKeyPrivate)
7766 token->encrypt(priv->getN(), modulus);
7767 token->encrypt(priv->getE(), publicExponent);
7768 token->encrypt(priv->getD(), privateExponent);
7769 token->encrypt(priv->getP(), prime1);
7770 token->encrypt(priv->getQ(), prime2);
7771 token->encrypt(priv->getDP1(), exponent1);
7772 token->encrypt(priv->getDQ1(), exponent2);
7773 token->encrypt(priv->getPQ(), coefficient);
7777 modulus = priv->getN();
7778 publicExponent = priv->getE();
7779 privateExponent = priv->getD();
7780 prime1 = priv->getP();
7781 prime2 = priv->getQ();
7782 exponent1 = priv->getDP1();
7783 exponent2 = priv->getDQ1();
7784 coefficient = priv->getPQ();
7786 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7787 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7788 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
7789 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
7790 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
7791 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
7792 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
7793 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
7796 bOK = osobject->commitTransaction();
7798 osobject->abortTransaction();
7801 rv = CKR_FUNCTION_FAILED;
7803 rv = CKR_FUNCTION_FAILED;
7808 rsa->recycleKeyPair(kp);
7809 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7811 // Remove keys that may have been created already when the function fails.
7814 if (*phPrivateKey != CK_INVALID_HANDLE)
7816 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
7817 handleManager->destroyObject(*phPrivateKey);
7818 if (ospriv) ospriv->destroyObject();
7819 *phPrivateKey = CK_INVALID_HANDLE;
7822 if (*phPublicKey != CK_INVALID_HANDLE)
7824 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
7825 handleManager->destroyObject(*phPublicKey);
7826 if (ospub) ospub->destroyObject();
7827 *phPublicKey = CK_INVALID_HANDLE;
7834 // Generate a DSA key pair
7835 CK_RV SoftHSM::generateDSA
7836 (CK_SESSION_HANDLE hSession,
7837 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7838 CK_ULONG ulPublicKeyAttributeCount,
7839 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7840 CK_ULONG ulPrivateKeyAttributeCount,
7841 CK_OBJECT_HANDLE_PTR phPublicKey,
7842 CK_OBJECT_HANDLE_PTR phPrivateKey,
7843 CK_BBOOL isPublicKeyOnToken,
7844 CK_BBOOL isPublicKeyPrivate,
7845 CK_BBOOL isPrivateKeyOnToken,
7846 CK_BBOOL isPrivateKeyPrivate)
7848 *phPublicKey = CK_INVALID_HANDLE;
7849 *phPrivateKey = CK_INVALID_HANDLE;
7852 Session* session = (Session*)handleManager->getSession(hSession);
7853 if (session == NULL)
7854 return CKR_SESSION_HANDLE_INVALID;
7857 Token* token = session->getToken();
7859 return CKR_GENERAL_ERROR;
7861 // Extract desired key information
7863 ByteString subprime;
7864 ByteString generator;
7865 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7867 switch (pPublicKeyTemplate[i].type)
7870 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7873 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7876 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7883 // The parameters must be specified to be able to generate a key pair.
7884 if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
7885 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
7886 return CKR_TEMPLATE_INCOMPLETE;
7889 // Set the parameters
7895 // Generate key pair
7896 AsymmetricKeyPair* kp = NULL;
7897 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
7898 if (dsa == NULL) return CKR_GENERAL_ERROR;
7899 if (!dsa->generateKeyPair(&kp, &p))
7901 ERROR_MSG("Could not generate key pair");
7902 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
7903 return CKR_GENERAL_ERROR;
7906 DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
7907 DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
7911 // Create a public key using C_CreateObject
7914 const CK_ULONG maxAttribs = 32;
7915 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7916 CK_KEY_TYPE publicKeyType = CKK_DSA;
7917 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7918 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7919 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7920 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7921 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7923 CK_ULONG publicKeyAttribsCount = 4;
7925 // Add the additional
7926 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7927 rv = CKR_TEMPLATE_INCONSISTENT;
7928 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7930 switch (pPublicKeyTemplate[i].type)
7938 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7943 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7945 // Store the attributes that are being supplied by the key generation to the object
7948 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7949 if (osobject == NULL_PTR || !osobject->isValid()) {
7950 rv = CKR_FUNCTION_FAILED;
7951 } else if (osobject->startTransaction()) {
7954 // Common Key Attributes
7955 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7956 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
7957 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7959 // DSA Public Key Attributes
7961 if (isPublicKeyPrivate)
7963 token->encrypt(pub->getY(), value);
7967 value = pub->getY();
7969 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7972 bOK = osobject->commitTransaction();
7974 osobject->abortTransaction();
7977 rv = CKR_FUNCTION_FAILED;
7979 rv = CKR_FUNCTION_FAILED;
7983 // Create a private key using C_CreateObject
7986 const CK_ULONG maxAttribs = 32;
7987 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7988 CK_KEY_TYPE privateKeyType = CKK_DSA;
7989 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7990 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7991 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7992 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7993 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7995 CK_ULONG privateKeyAttribsCount = 4;
7996 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7997 rv = CKR_TEMPLATE_INCONSISTENT;
7998 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8000 switch (pPrivateKeyTemplate[i].type)
8008 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8013 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8015 // Store the attributes that are being supplied by the key generation to the object
8018 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8019 if (osobject == NULL_PTR || !osobject->isValid()) {
8020 rv = CKR_FUNCTION_FAILED;
8021 } else if (osobject->startTransaction()) {
8024 // Common Key Attributes
8025 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8026 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8027 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8029 // Common Private Key Attributes
8030 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8031 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8032 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8033 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8035 // DSA Private Key Attributes
8037 ByteString bSubprime;
8038 ByteString bGenerator;
8040 if (isPrivateKeyPrivate)
8042 token->encrypt(priv->getP(), bPrime);
8043 token->encrypt(priv->getQ(), bSubprime);
8044 token->encrypt(priv->getG(), bGenerator);
8045 token->encrypt(priv->getX(), bValue);
8049 bPrime = priv->getP();
8050 bSubprime = priv->getQ();
8051 bGenerator = priv->getG();
8052 bValue = priv->getX();
8054 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8055 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8056 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8057 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8060 bOK = osobject->commitTransaction();
8062 osobject->abortTransaction();
8065 rv = CKR_FUNCTION_FAILED;
8067 rv = CKR_FUNCTION_FAILED;
8072 dsa->recycleKeyPair(kp);
8073 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8075 // Remove keys that may have been created already when the function fails.
8078 if (*phPrivateKey != CK_INVALID_HANDLE)
8080 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8081 handleManager->destroyObject(*phPrivateKey);
8082 if (ospriv) ospriv->destroyObject();
8083 *phPrivateKey = CK_INVALID_HANDLE;
8086 if (*phPublicKey != CK_INVALID_HANDLE)
8088 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8089 handleManager->destroyObject(*phPublicKey);
8090 if (ospub) ospub->destroyObject();
8091 *phPublicKey = CK_INVALID_HANDLE;
8098 // Generate a DSA domain parameter set
8099 CK_RV SoftHSM::generateDSAParameters
8100 (CK_SESSION_HANDLE hSession,
8101 CK_ATTRIBUTE_PTR pTemplate,
8103 CK_OBJECT_HANDLE_PTR phKey,
8107 *phKey = CK_INVALID_HANDLE;
8110 Session* session = (Session*)handleManager->getSession(hSession);
8111 if (session == NULL)
8112 return CKR_SESSION_HANDLE_INVALID;
8115 Token* token = session->getToken();
8117 return CKR_GENERAL_ERROR;
8119 // Extract desired parameter information
8122 for (CK_ULONG i = 0; i < ulCount; i++)
8124 switch (pTemplate[i].type)
8126 case CKA_PRIME_BITS:
8127 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8129 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8130 return CKR_ATTRIBUTE_VALUE_INVALID;
8132 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8134 case CKA_SUBPRIME_BITS:
8135 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8137 INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8138 return CKR_ATTRIBUTE_VALUE_INVALID;
8140 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8147 // CKA_PRIME_BITS must be specified
8150 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8151 return CKR_TEMPLATE_INCOMPLETE;
8154 // No real choice for CKA_SUBPRIME_BITS
8156 (((bitLen >= 2048) && (qLen != 256)) ||
8157 ((bitLen < 2048) && (qLen != 160))))
8158 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8161 // Generate domain parameters
8162 AsymmetricParameters* p = NULL;
8163 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8164 if (dsa == NULL) return CKR_GENERAL_ERROR;
8165 if (!dsa->generateParameters(&p, (void *)bitLen))
8167 ERROR_MSG("Could not generate parameters");
8168 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8169 return CKR_GENERAL_ERROR;
8172 DSAParameters* params = (DSAParameters*) p;
8176 // Create the domain parameter object using C_CreateObject
8177 const CK_ULONG maxAttribs = 32;
8178 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8179 CK_KEY_TYPE keyType = CKK_DSA;
8180 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8181 { CKA_CLASS, &objClass, sizeof(objClass) },
8182 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8183 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8184 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8186 CK_ULONG paramsAttribsCount = 4;
8188 // Add the additional
8189 if (ulCount > (maxAttribs - paramsAttribsCount))
8190 rv = CKR_TEMPLATE_INCONSISTENT;
8191 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8193 switch (pTemplate[i].type)
8201 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8206 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8208 // Store the attributes that are being supplied
8211 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8212 if (osobject == NULL_PTR || !osobject->isValid()) {
8213 rv = CKR_FUNCTION_FAILED;
8214 } else if (osobject->startTransaction()) {
8217 // Common Attributes
8218 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8219 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8220 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8222 // DSA Domain Parameters Attributes
8224 ByteString subprime;
8225 ByteString generator;
8228 token->encrypt(params->getP(), prime);
8229 token->encrypt(params->getQ(), subprime);
8230 token->encrypt(params->getG(), generator);
8234 prime = params->getP();
8235 subprime = params->getQ();
8236 generator = params->getG();
8238 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8239 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8240 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8243 bOK = osobject->commitTransaction();
8245 osobject->abortTransaction();
8248 rv = CKR_FUNCTION_FAILED;
8250 rv = CKR_FUNCTION_FAILED;
8254 dsa->recycleParameters(p);
8255 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8257 // Remove parameters that may have been created already when the function fails.
8260 if (*phKey != CK_INVALID_HANDLE)
8262 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8263 handleManager->destroyObject(*phKey);
8264 if (osparams) osparams->destroyObject();
8265 *phKey = CK_INVALID_HANDLE;
8272 // Generate an EC key pair
8273 CK_RV SoftHSM::generateEC
8274 (CK_SESSION_HANDLE hSession,
8275 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8276 CK_ULONG ulPublicKeyAttributeCount,
8277 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8278 CK_ULONG ulPrivateKeyAttributeCount,
8279 CK_OBJECT_HANDLE_PTR phPublicKey,
8280 CK_OBJECT_HANDLE_PTR phPrivateKey,
8281 CK_BBOOL isPublicKeyOnToken,
8282 CK_BBOOL isPublicKeyPrivate,
8283 CK_BBOOL isPrivateKeyOnToken,
8284 CK_BBOOL isPrivateKeyPrivate)
8286 *phPublicKey = CK_INVALID_HANDLE;
8287 *phPrivateKey = CK_INVALID_HANDLE;
8290 Session* session = (Session*)handleManager->getSession(hSession);
8291 if (session == NULL)
8292 return CKR_SESSION_HANDLE_INVALID;
8295 Token* token = session->getToken();
8297 return CKR_GENERAL_ERROR;
8299 // Extract desired key information
8301 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8303 switch (pPublicKeyTemplate[i].type)
8306 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8313 // The parameters must be specified to be able to generate a key pair.
8314 if (params.size() == 0) {
8315 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8316 return CKR_TEMPLATE_INCOMPLETE;
8319 // Set the parameters
8323 // Generate key pair
8324 AsymmetricKeyPair* kp = NULL;
8325 AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8326 if (ec == NULL) return CKR_GENERAL_ERROR;
8327 if (!ec->generateKeyPair(&kp, &p))
8329 ERROR_MSG("Could not generate key pair");
8330 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8331 return CKR_GENERAL_ERROR;
8334 ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8335 ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8339 // Create a public key using C_CreateObject
8342 const CK_ULONG maxAttribs = 32;
8343 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8344 CK_KEY_TYPE publicKeyType = CKK_EC;
8345 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8346 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8347 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8348 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8349 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8351 CK_ULONG publicKeyAttribsCount = 4;
8353 // Add the additional
8354 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8355 rv = CKR_TEMPLATE_INCONSISTENT;
8356 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8358 switch (pPublicKeyTemplate[i].type)
8366 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8371 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8373 // Store the attributes that are being supplied by the key generation to the object
8376 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8377 if (osobject == NULL_PTR || !osobject->isValid()) {
8378 rv = CKR_FUNCTION_FAILED;
8379 } else if (osobject->startTransaction()) {
8382 // Common Key Attributes
8383 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8384 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8385 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8387 // EC Public Key Attributes
8389 if (isPublicKeyPrivate)
8391 token->encrypt(pub->getQ(), point);
8395 point = pub->getQ();
8397 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8400 bOK = osobject->commitTransaction();
8402 osobject->abortTransaction();
8405 rv = CKR_FUNCTION_FAILED;
8407 rv = CKR_FUNCTION_FAILED;
8411 // Create a private key using C_CreateObject
8414 const CK_ULONG maxAttribs = 32;
8415 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8416 CK_KEY_TYPE privateKeyType = CKK_EC;
8417 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8418 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8419 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8420 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8421 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8423 CK_ULONG privateKeyAttribsCount = 4;
8424 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8425 rv = CKR_TEMPLATE_INCONSISTENT;
8426 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8428 switch (pPrivateKeyTemplate[i].type)
8436 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8441 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8443 // Store the attributes that are being supplied by the key generation to the object
8446 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8447 if (osobject == NULL_PTR || !osobject->isValid()) {
8448 rv = CKR_FUNCTION_FAILED;
8449 } else if (osobject->startTransaction()) {
8452 // Common Key Attributes
8453 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8454 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8455 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8457 // Common Private Key Attributes
8458 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8459 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8460 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8461 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8463 // EC Private Key Attributes
8466 if (isPrivateKeyPrivate)
8468 token->encrypt(priv->getEC(), group);
8469 token->encrypt(priv->getD(), value);
8473 group = priv->getEC();
8474 value = priv->getD();
8476 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8477 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8480 bOK = osobject->commitTransaction();
8482 osobject->abortTransaction();
8485 rv = CKR_FUNCTION_FAILED;
8487 rv = CKR_FUNCTION_FAILED;
8492 ec->recycleKeyPair(kp);
8493 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8495 // Remove keys that may have been created already when the function fails.
8498 if (*phPrivateKey != CK_INVALID_HANDLE)
8500 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8501 handleManager->destroyObject(*phPrivateKey);
8502 if (ospriv) ospriv->destroyObject();
8503 *phPrivateKey = CK_INVALID_HANDLE;
8506 if (*phPublicKey != CK_INVALID_HANDLE)
8508 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8509 handleManager->destroyObject(*phPublicKey);
8510 if (ospub) ospub->destroyObject();
8511 *phPublicKey = CK_INVALID_HANDLE;
8518 // Generate a DH key pair
8519 CK_RV SoftHSM::generateDH
8520 (CK_SESSION_HANDLE hSession,
8521 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8522 CK_ULONG ulPublicKeyAttributeCount,
8523 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8524 CK_ULONG ulPrivateKeyAttributeCount,
8525 CK_OBJECT_HANDLE_PTR phPublicKey,
8526 CK_OBJECT_HANDLE_PTR phPrivateKey,
8527 CK_BBOOL isPublicKeyOnToken,
8528 CK_BBOOL isPublicKeyPrivate,
8529 CK_BBOOL isPrivateKeyOnToken,
8530 CK_BBOOL isPrivateKeyPrivate)
8532 *phPublicKey = CK_INVALID_HANDLE;
8533 *phPrivateKey = CK_INVALID_HANDLE;
8536 Session* session = (Session*)handleManager->getSession(hSession);
8537 if (session == NULL)
8538 return CKR_SESSION_HANDLE_INVALID;
8541 Token* token = session->getToken();
8543 return CKR_GENERAL_ERROR;
8545 // Extract desired key information
8547 ByteString generator;
8548 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8550 switch (pPublicKeyTemplate[i].type)
8553 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8556 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8563 // The parameters must be specified to be able to generate a key pair.
8564 if (prime.size() == 0 || generator.size() == 0) {
8565 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8566 return CKR_TEMPLATE_INCOMPLETE;
8569 // Extract optional bit length
8571 for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8573 switch (pPrivateKeyTemplate[i].type)
8575 case CKA_VALUE_BITS:
8576 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8583 // Set the parameters
8587 p.setXBitLength(bitLen);
8589 // Generate key pair
8590 AsymmetricKeyPair* kp = NULL;
8591 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8592 if (dh == NULL) return CKR_GENERAL_ERROR;
8593 if (!dh->generateKeyPair(&kp, &p))
8595 ERROR_MSG("Could not generate key pair");
8596 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8597 return CKR_GENERAL_ERROR;
8600 DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8601 DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8605 // Create a public key using C_CreateObject
8608 const CK_ULONG maxAttribs = 32;
8609 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8610 CK_KEY_TYPE publicKeyType = CKK_DH;
8611 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8612 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8613 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8614 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8615 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8617 CK_ULONG publicKeyAttribsCount = 4;
8619 // Add the additional
8620 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8621 rv = CKR_TEMPLATE_INCONSISTENT;
8622 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8624 switch (pPublicKeyTemplate[i].type)
8632 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8637 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8639 // Store the attributes that are being supplied by the key generation to the object
8642 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8643 if (osobject == NULL_PTR || !osobject->isValid()) {
8644 rv = CKR_FUNCTION_FAILED;
8645 } else if (osobject->startTransaction()) {
8648 // Common Key Attributes
8649 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8650 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8651 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8653 // DH Public Key Attributes
8655 if (isPublicKeyPrivate)
8657 token->encrypt(pub->getY(), value);
8661 value = pub->getY();
8663 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8666 bOK = osobject->commitTransaction();
8668 osobject->abortTransaction();
8671 rv = CKR_FUNCTION_FAILED;
8673 rv = CKR_FUNCTION_FAILED;
8677 // Create a private key using C_CreateObject
8680 const CK_ULONG maxAttribs = 32;
8681 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8682 CK_KEY_TYPE privateKeyType = CKK_DH;
8683 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8684 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8685 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8686 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8687 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8689 CK_ULONG privateKeyAttribsCount = 4;
8690 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8691 rv = CKR_TEMPLATE_INCONSISTENT;
8692 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8694 switch (pPrivateKeyTemplate[i].type)
8702 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8707 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8709 // Store the attributes that are being supplied by the key generation to the object
8712 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8713 if (osobject == NULL_PTR || !osobject->isValid()) {
8714 rv = CKR_FUNCTION_FAILED;
8715 } else if (osobject->startTransaction()) {
8718 // Common Key Attributes
8719 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8720 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8721 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8723 // Common Private Key Attributes
8724 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8725 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8726 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8727 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8729 // DH Private Key Attributes
8731 ByteString bGenerator;
8733 if (isPrivateKeyPrivate)
8735 token->encrypt(priv->getP(), bPrime);
8736 token->encrypt(priv->getG(), bGenerator);
8737 token->encrypt(priv->getX(), bValue);
8741 bPrime = priv->getP();
8742 bGenerator = priv->getG();
8743 bValue = priv->getX();
8745 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8746 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8747 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8751 bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
8755 bOK = osobject->commitTransaction();
8757 osobject->abortTransaction();
8760 rv = CKR_FUNCTION_FAILED;
8762 rv = CKR_FUNCTION_FAILED;
8767 dh->recycleKeyPair(kp);
8768 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8770 // Remove keys that may have been created already when the function fails.
8773 if (*phPrivateKey != CK_INVALID_HANDLE)
8775 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8776 handleManager->destroyObject(*phPrivateKey);
8777 if (ospriv) ospriv->destroyObject();
8778 *phPrivateKey = CK_INVALID_HANDLE;
8781 if (*phPublicKey != CK_INVALID_HANDLE)
8783 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8784 handleManager->destroyObject(*phPublicKey);
8785 if (ospub) ospub->destroyObject();
8786 *phPublicKey = CK_INVALID_HANDLE;
8793 // Generate a DH domain parameter set
8794 CK_RV SoftHSM::generateDHParameters
8795 (CK_SESSION_HANDLE hSession,
8796 CK_ATTRIBUTE_PTR pTemplate,
8798 CK_OBJECT_HANDLE_PTR phKey,
8802 *phKey = CK_INVALID_HANDLE;
8805 Session* session = (Session*)handleManager->getSession(hSession);
8806 if (session == NULL)
8807 return CKR_SESSION_HANDLE_INVALID;
8810 Token* token = session->getToken();
8812 return CKR_GENERAL_ERROR;
8814 // Extract desired parameter information
8816 for (CK_ULONG i = 0; i < ulCount; i++)
8818 switch (pTemplate[i].type)
8820 case CKA_PRIME_BITS:
8821 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8823 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8824 return CKR_ATTRIBUTE_VALUE_INVALID;
8826 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8833 // CKA_PRIME_BITS must be specified
8836 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8837 return CKR_TEMPLATE_INCOMPLETE;
8840 // Generate domain parameters
8841 AsymmetricParameters* p = NULL;
8842 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8843 if (dh == NULL) return CKR_GENERAL_ERROR;
8844 if (!dh->generateParameters(&p, (void *)bitLen))
8846 ERROR_MSG("Could not generate parameters");
8847 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8848 return CKR_GENERAL_ERROR;
8851 DHParameters* params = (DHParameters*) p;
8855 // Create the domain parameter object using C_CreateObject
8856 const CK_ULONG maxAttribs = 32;
8857 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8858 CK_KEY_TYPE keyType = CKK_DH;
8859 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8860 { CKA_CLASS, &objClass, sizeof(objClass) },
8861 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8862 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8863 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8865 CK_ULONG paramsAttribsCount = 4;
8867 // Add the additional
8868 if (ulCount > (maxAttribs - paramsAttribsCount))
8869 rv = CKR_TEMPLATE_INCONSISTENT;
8870 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8872 switch (pTemplate[i].type)
8880 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8885 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8887 // Store the attributes that are being supplied
8890 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8891 if (osobject == NULL_PTR || !osobject->isValid()) {
8892 rv = CKR_FUNCTION_FAILED;
8893 } else if (osobject->startTransaction()) {
8896 // Common Attributes
8897 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8898 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
8899 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8901 // DH Domain Parameters Attributes
8903 ByteString generator;
8906 token->encrypt(params->getP(), prime);
8907 token->encrypt(params->getG(), generator);
8911 prime = params->getP();
8912 generator = params->getG();
8914 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8915 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8918 bOK = osobject->commitTransaction();
8920 osobject->abortTransaction();
8923 rv = CKR_FUNCTION_FAILED;
8925 rv = CKR_FUNCTION_FAILED;
8929 dh->recycleParameters(p);
8930 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8932 // Remove parameters that may have been created already when the function fails.
8935 if (*phKey != CK_INVALID_HANDLE)
8937 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8938 handleManager->destroyObject(*phKey);
8939 if (osparams) osparams->destroyObject();
8940 *phKey = CK_INVALID_HANDLE;
8947 // Generate a GOST key pair
8948 CK_RV SoftHSM::generateGOST
8949 (CK_SESSION_HANDLE hSession,
8950 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8951 CK_ULONG ulPublicKeyAttributeCount,
8952 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8953 CK_ULONG ulPrivateKeyAttributeCount,
8954 CK_OBJECT_HANDLE_PTR phPublicKey,
8955 CK_OBJECT_HANDLE_PTR phPrivateKey,
8956 CK_BBOOL isPublicKeyOnToken,
8957 CK_BBOOL isPublicKeyPrivate,
8958 CK_BBOOL isPrivateKeyOnToken,
8959 CK_BBOOL isPrivateKeyPrivate)
8961 *phPublicKey = CK_INVALID_HANDLE;
8962 *phPrivateKey = CK_INVALID_HANDLE;
8965 Session* session = (Session*)handleManager->getSession(hSession);
8966 if (session == NULL)
8967 return CKR_SESSION_HANDLE_INVALID;
8970 Token* token = session->getToken();
8972 return CKR_GENERAL_ERROR;
8974 // Extract desired key information
8975 ByteString param_3410;
8976 ByteString param_3411;
8977 ByteString param_28147;
8978 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8980 switch (pPublicKeyTemplate[i].type)
8982 case CKA_GOSTR3410_PARAMS:
8983 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8985 case CKA_GOSTR3411_PARAMS:
8986 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8988 case CKA_GOST28147_PARAMS:
8989 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8996 // The parameters must be specified to be able to generate a key pair.
8997 if (param_3410.size() == 0 || param_3411.size() == 0) {
8998 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8999 return CKR_TEMPLATE_INCOMPLETE;
9002 // Set the parameters
9004 p.setEC(param_3410);
9006 // Generate key pair
9007 AsymmetricKeyPair* kp = NULL;
9008 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9009 if (gost == NULL) return CKR_GENERAL_ERROR;
9010 if (!gost->generateKeyPair(&kp, &p))
9012 ERROR_MSG("Could not generate key pair");
9013 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9014 return CKR_GENERAL_ERROR;
9017 GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9018 GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9022 // Create a public key using C_CreateObject
9025 const CK_ULONG maxAttribs = 32;
9026 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9027 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9028 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9029 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9030 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9031 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9032 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9034 CK_ULONG publicKeyAttribsCount = 4;
9036 // Add the additional
9037 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9038 rv = CKR_TEMPLATE_INCONSISTENT;
9039 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9041 switch (pPublicKeyTemplate[i].type)
9049 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9054 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9056 // Store the attributes that are being supplied by the key generation to the object
9059 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9060 if (osobject == NULL_PTR || !osobject->isValid()) {
9061 rv = CKR_FUNCTION_FAILED;
9062 } else if (osobject->startTransaction()) {
9065 // Common Key Attributes
9066 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9067 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9068 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9070 // EC Public Key Attributes
9072 if (isPublicKeyPrivate)
9074 token->encrypt(pub->getQ(), point);
9078 point = pub->getQ();
9080 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9083 bOK = osobject->commitTransaction();
9085 osobject->abortTransaction();
9088 rv = CKR_FUNCTION_FAILED;
9090 rv = CKR_FUNCTION_FAILED;
9094 // Create a private key using C_CreateObject
9097 const CK_ULONG maxAttribs = 32;
9098 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9099 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9100 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9101 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9102 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9103 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9104 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9106 CK_ULONG privateKeyAttribsCount = 4;
9107 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9108 rv = CKR_TEMPLATE_INCONSISTENT;
9109 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9111 switch (pPrivateKeyTemplate[i].type)
9119 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9124 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9126 // Store the attributes that are being supplied by the key generation to the object
9129 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9130 if (osobject == NULL_PTR || !osobject->isValid()) {
9131 rv = CKR_FUNCTION_FAILED;
9132 } else if (osobject->startTransaction()) {
9135 // Common Key Attributes
9136 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9137 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9138 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9140 // Common Private Key Attributes
9141 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9142 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9143 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9144 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9146 // GOST Private Key Attributes
9151 if (isPrivateKeyPrivate)
9153 token->encrypt(priv->getD(), value);
9154 token->encrypt(priv->getEC(), param_a);
9155 token->encrypt(param_3411, param_b);
9156 token->encrypt(param_28147, param_c);
9160 value = priv->getD();
9161 param_a = priv->getEC();
9162 param_b = param_3411;
9163 param_c = param_28147;
9165 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9166 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9167 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9168 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9171 bOK = osobject->commitTransaction();
9173 osobject->abortTransaction();
9176 rv = CKR_FUNCTION_FAILED;
9178 rv = CKR_FUNCTION_FAILED;
9183 gost->recycleKeyPair(kp);
9184 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9186 // Remove keys that may have been created already when the function fails.
9189 if (*phPrivateKey != CK_INVALID_HANDLE)
9191 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9192 handleManager->destroyObject(*phPrivateKey);
9193 if (ospriv) ospriv->destroyObject();
9194 *phPrivateKey = CK_INVALID_HANDLE;
9197 if (*phPublicKey != CK_INVALID_HANDLE)
9199 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9200 handleManager->destroyObject(*phPublicKey);
9201 if (ospub) ospub->destroyObject();
9202 *phPublicKey = CK_INVALID_HANDLE;
9209 // Derive a DH secret
9210 CK_RV SoftHSM::deriveDH
9211 (CK_SESSION_HANDLE hSession,
9212 CK_MECHANISM_PTR pMechanism,
9213 CK_OBJECT_HANDLE hBaseKey,
9214 CK_ATTRIBUTE_PTR pTemplate,
9216 CK_OBJECT_HANDLE_PTR phKey,
9217 CK_KEY_TYPE keyType,
9221 *phKey = CK_INVALID_HANDLE;
9223 if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9224 if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9227 Session* session = (Session*)handleManager->getSession(hSession);
9228 if (session == NULL)
9229 return CKR_SESSION_HANDLE_INVALID;
9232 Token* token = session->getToken();
9234 return CKR_GENERAL_ERROR;
9236 // Extract desired parameter information
9238 bool checkValue = true;
9239 for (CK_ULONG i = 0; i < ulCount; i++)
9241 switch (pTemplate[i].type)
9244 INFO_MSG("CKA_VALUE must not be included");
9245 return CKR_ATTRIBUTE_READ_ONLY;
9247 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9249 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9250 return CKR_ATTRIBUTE_VALUE_INVALID;
9252 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9254 case CKA_CHECK_VALUE:
9255 if (pTemplate[i].ulValueLen > 0)
9257 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9258 return CKR_ATTRIBUTE_VALUE_INVALID;
9270 case CKK_GENERIC_SECRET:
9273 INFO_MSG("CKA_VALUE_LEN must be set");
9274 return CKR_TEMPLATE_INCOMPLETE;
9281 INFO_MSG("CKA_VALUE_LEN must not be set");
9282 return CKR_ATTRIBUTE_READ_ONLY;
9290 INFO_MSG("CKA_VALUE_LEN must not be set");
9291 return CKR_ATTRIBUTE_READ_ONLY;
9298 INFO_MSG("CKA_VALUE_LEN must not be set");
9299 return CKR_ATTRIBUTE_READ_ONLY;
9304 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9306 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9307 return CKR_ATTRIBUTE_VALUE_INVALID;
9311 return CKR_ATTRIBUTE_VALUE_INVALID;
9314 // Get the base key handle
9315 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9316 if (baseKey == NULL || !baseKey->isValid())
9317 return CKR_KEY_HANDLE_INVALID;
9319 // Get the DH algorithm handler
9320 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9322 return CKR_MECHANISM_INVALID;
9325 PrivateKey* privateKey = dh->newPrivateKey();
9326 if (privateKey == NULL)
9328 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9329 return CKR_HOST_MEMORY;
9331 if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9333 dh->recyclePrivateKey(privateKey);
9334 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9335 return CKR_GENERAL_ERROR;
9338 ByteString mechParameters;
9339 mechParameters.resize(pMechanism->ulParameterLen);
9340 memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9341 PublicKey* publicKey = dh->newPublicKey();
9342 if (publicKey == NULL)
9344 dh->recyclePrivateKey(privateKey);
9345 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9346 return CKR_HOST_MEMORY;
9348 if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9350 dh->recyclePrivateKey(privateKey);
9351 dh->recyclePublicKey(publicKey);
9352 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9353 return CKR_GENERAL_ERROR;
9356 // Derive the secret
9357 SymmetricKey* secret = NULL;
9359 if (!dh->deriveKey(&secret, publicKey, privateKey))
9360 rv = CKR_GENERAL_ERROR;
9361 dh->recyclePrivateKey(privateKey);
9362 dh->recyclePublicKey(publicKey);
9364 // Create the secret object using C_CreateObject
9365 const CK_ULONG maxAttribs = 32;
9366 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9367 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9368 { CKA_CLASS, &objClass, sizeof(objClass) },
9369 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9370 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9371 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9373 CK_ULONG secretAttribsCount = 4;
9375 // Add the additional
9376 if (ulCount > (maxAttribs - secretAttribsCount))
9377 rv = CKR_TEMPLATE_INCONSISTENT;
9378 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9380 switch (pTemplate[i].type)
9386 case CKA_CHECK_VALUE:
9389 secretAttribs[secretAttribsCount++] = pTemplate[i];
9394 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9396 // Store the attributes that are being supplied
9399 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9400 if (osobject == NULL_PTR || !osobject->isValid()) {
9401 rv = CKR_FUNCTION_FAILED;
9402 } else if (osobject->startTransaction()) {
9405 // Common Attributes
9406 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9408 // Common Secret Key Attributes
9409 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9411 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9412 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9416 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9418 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9420 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9421 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9425 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9428 // Secret Attributes
9429 ByteString secretValue = secret->getKeyBits();
9431 ByteString plainKCV;
9434 if (byteLen > secretValue.size())
9436 INFO_MSG("The derived secret is too short");
9441 // Truncate value when requested, remove from the leading end
9442 if (byteLen < secretValue.size())
9443 secretValue.split(secretValue.size() - byteLen);
9445 // Fix the odd parity for DES
9446 if (keyType == CKK_DES ||
9447 keyType == CKK_DES2 ||
9448 keyType == CKK_DES3)
9450 for (size_t i = 0; i < secretValue.size(); i++)
9452 secretValue[i] = odd_parity[secretValue[i]];
9459 case CKK_GENERIC_SECRET:
9460 secret->setBitLen(byteLen * 8);
9461 plainKCV = secret->getKeyCheckValue();
9466 secret->setBitLen(byteLen * 7);
9467 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9470 secret->setBitLen(byteLen * 8);
9471 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9480 token->encrypt(secretValue, value);
9481 token->encrypt(plainKCV, kcv);
9485 value = secretValue;
9489 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9491 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9494 bOK = osobject->commitTransaction();
9496 osobject->abortTransaction();
9499 rv = CKR_FUNCTION_FAILED;
9501 rv = CKR_FUNCTION_FAILED;
9505 dh->recycleSymmetricKey(secret);
9506 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9508 // Remove secret that may have been created already when the function fails.
9511 if (*phKey != CK_INVALID_HANDLE)
9513 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9514 handleManager->destroyObject(*phKey);
9515 if (ossecret) ossecret->destroyObject();
9516 *phKey = CK_INVALID_HANDLE;
9523 // Derive an ECDH secret
9524 CK_RV SoftHSM::deriveECDH
9525 (CK_SESSION_HANDLE hSession,
9526 CK_MECHANISM_PTR pMechanism,
9527 CK_OBJECT_HANDLE hBaseKey,
9528 CK_ATTRIBUTE_PTR pTemplate,
9530 CK_OBJECT_HANDLE_PTR phKey,
9531 CK_KEY_TYPE keyType,
9536 *phKey = CK_INVALID_HANDLE;
9538 if ((pMechanism->pParameter == NULL_PTR) ||
9539 (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9541 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9542 return CKR_MECHANISM_PARAM_INVALID;
9544 if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9546 DEBUG_MSG("kdf must be CKD_NULL");
9547 return CKR_MECHANISM_PARAM_INVALID;
9549 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9550 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9552 DEBUG_MSG("there must be no shared data");
9553 return CKR_MECHANISM_PARAM_INVALID;
9555 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9556 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9558 DEBUG_MSG("there must be a public data");
9559 return CKR_MECHANISM_PARAM_INVALID;
9563 Session* session = (Session*)handleManager->getSession(hSession);
9564 if (session == NULL)
9565 return CKR_SESSION_HANDLE_INVALID;
9568 Token* token = session->getToken();
9570 return CKR_GENERAL_ERROR;
9572 // Extract desired parameter information
9574 bool checkValue = true;
9575 for (CK_ULONG i = 0; i < ulCount; i++)
9577 switch (pTemplate[i].type)
9580 INFO_MSG("CKA_VALUE must not be included");
9581 return CKR_ATTRIBUTE_READ_ONLY;
9583 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9585 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9586 return CKR_ATTRIBUTE_VALUE_INVALID;
9588 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9590 case CKA_CHECK_VALUE:
9591 if (pTemplate[i].ulValueLen > 0)
9593 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9594 return CKR_ATTRIBUTE_VALUE_INVALID;
9604 // byteLen == 0 impiles return max size the ECC can derive
9607 case CKK_GENERIC_SECRET:
9611 if (byteLen != 0 && byteLen != 8)
9613 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9614 return CKR_ATTRIBUTE_VALUE_INVALID;
9620 if (byteLen != 0 && byteLen != 16)
9622 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9623 return CKR_ATTRIBUTE_VALUE_INVALID;
9628 if (byteLen != 0 && byteLen != 24)
9630 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9631 return CKR_ATTRIBUTE_VALUE_INVALID;
9636 if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9638 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9639 return CKR_ATTRIBUTE_VALUE_INVALID;
9643 return CKR_ATTRIBUTE_VALUE_INVALID;
9646 // Get the base key handle
9647 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9648 if (baseKey == NULL || !baseKey->isValid())
9649 return CKR_KEY_HANDLE_INVALID;
9651 // Get the ECDH algorithm handler
9652 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9654 return CKR_MECHANISM_INVALID;
9657 PrivateKey* privateKey = ecdh->newPrivateKey();
9658 if (privateKey == NULL)
9660 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9661 return CKR_HOST_MEMORY;
9663 if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9665 ecdh->recyclePrivateKey(privateKey);
9666 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9667 return CKR_GENERAL_ERROR;
9670 ByteString publicData;
9671 publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9672 memcpy(&publicData[0],
9673 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9674 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9675 PublicKey* publicKey = ecdh->newPublicKey();
9676 if (publicKey == NULL)
9678 ecdh->recyclePrivateKey(privateKey);
9679 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9680 return CKR_HOST_MEMORY;
9682 if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9684 ecdh->recyclePrivateKey(privateKey);
9685 ecdh->recyclePublicKey(publicKey);
9686 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9687 return CKR_GENERAL_ERROR;
9690 // Derive the secret
9691 SymmetricKey* secret = NULL;
9693 if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9694 rv = CKR_GENERAL_ERROR;
9695 ecdh->recyclePrivateKey(privateKey);
9696 ecdh->recyclePublicKey(publicKey);
9698 // Create the secret object using C_CreateObject
9699 const CK_ULONG maxAttribs = 32;
9700 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9701 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9702 { CKA_CLASS, &objClass, sizeof(objClass) },
9703 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9704 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9705 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9707 CK_ULONG secretAttribsCount = 4;
9709 // Add the additional
9710 if (ulCount > (maxAttribs - secretAttribsCount))
9711 rv = CKR_TEMPLATE_INCONSISTENT;
9712 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9714 switch (pTemplate[i].type)
9720 case CKA_CHECK_VALUE:
9723 secretAttribs[secretAttribsCount++] = pTemplate[i];
9728 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9730 // Store the attributes that are being supplied
9733 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9734 if (osobject == NULL_PTR || !osobject->isValid()) {
9735 rv = CKR_FUNCTION_FAILED;
9736 } else if (osobject->startTransaction()) {
9739 // Common Attributes
9740 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9742 // Common Secret Key Attributes
9743 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9745 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9746 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9750 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9752 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9754 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9755 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9759 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9762 // Secret Attributes
9763 ByteString secretValue = secret->getKeyBits();
9765 ByteString plainKCV;
9768 // For generic and AES keys:
9769 // default to return max size available.
9774 case CKK_GENERIC_SECRET:
9775 byteLen = secretValue.size();
9778 if (secretValue.size() >= 32)
9780 else if (secretValue.size() >= 24)
9787 if (byteLen > secretValue.size())
9789 INFO_MSG("The derived secret is too short");
9794 // Truncate value when requested, remove from the leading end
9795 if (byteLen < secretValue.size())
9796 secretValue.split(secretValue.size() - byteLen);
9798 // Fix the odd parity for DES
9799 if (keyType == CKK_DES ||
9800 keyType == CKK_DES2 ||
9801 keyType == CKK_DES3)
9803 for (size_t i = 0; i < secretValue.size(); i++)
9805 secretValue[i] = odd_parity[secretValue[i]];
9812 case CKK_GENERIC_SECRET:
9813 secret->setBitLen(byteLen * 8);
9814 plainKCV = secret->getKeyCheckValue();
9819 secret->setBitLen(byteLen * 7);
9820 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9823 secret->setBitLen(byteLen * 8);
9824 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9833 token->encrypt(secretValue, value);
9834 token->encrypt(plainKCV, kcv);
9838 value = secretValue;
9842 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9844 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9847 bOK = osobject->commitTransaction();
9849 osobject->abortTransaction();
9852 rv = CKR_FUNCTION_FAILED;
9854 rv = CKR_FUNCTION_FAILED;
9858 ecdh->recycleSymmetricKey(secret);
9859 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9861 // Remove secret that may have been created already when the function fails.
9864 if (*phKey != CK_INVALID_HANDLE)
9866 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9867 handleManager->destroyObject(*phKey);
9868 if (ossecret) ossecret->destroyObject();
9869 *phKey = CK_INVALID_HANDLE;
9875 return CKR_MECHANISM_INVALID;
9879 // Derive an symmetric secret
9880 CK_RV SoftHSM::deriveSymmetric
9881 (CK_SESSION_HANDLE hSession,
9882 CK_MECHANISM_PTR pMechanism,
9883 CK_OBJECT_HANDLE hBaseKey,
9884 CK_ATTRIBUTE_PTR pTemplate,
9886 CK_OBJECT_HANDLE_PTR phKey,
9887 CK_KEY_TYPE keyType,
9891 *phKey = CK_INVALID_HANDLE;
9893 if (pMechanism->pParameter == NULL_PTR)
9895 DEBUG_MSG("pParameter must be supplied");
9896 return CKR_MECHANISM_PARAM_INVALID;
9901 if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
9902 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
9903 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9905 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9906 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9907 if (ulLen == 0 || pData == NULL_PTR)
9909 DEBUG_MSG("There must be data in the parameter");
9910 return CKR_MECHANISM_PARAM_INVALID;
9914 DEBUG_MSG("The data must be a multiple of 8 bytes long");
9915 return CKR_MECHANISM_PARAM_INVALID;
9922 else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
9923 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
9924 pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
9926 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9927 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9928 if (length == 0 || pData == NULL_PTR)
9930 DEBUG_MSG("There must be data in the parameter");
9931 return CKR_MECHANISM_PARAM_INVALID;
9933 if (length % 8 != 0)
9935 DEBUG_MSG("The data must be a multiple of 8 bytes long");
9936 return CKR_MECHANISM_PARAM_INVALID;
9938 data.resize(length);
9943 else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
9944 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9946 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9947 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9948 if (ulLen == 0 || pData == NULL_PTR)
9950 DEBUG_MSG("There must be data in the parameter");
9951 return CKR_MECHANISM_PARAM_INVALID;
9953 if (ulLen % 16 != 0)
9955 DEBUG_MSG("The data must be a multiple of 16 bytes long");
9956 return CKR_MECHANISM_PARAM_INVALID;
9963 else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
9964 pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
9966 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9967 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9968 if (length == 0 || pData == NULL_PTR)
9970 DEBUG_MSG("There must be data in the parameter");
9971 return CKR_MECHANISM_PARAM_INVALID;
9973 if (length % 16 != 0)
9975 DEBUG_MSG("The data must be a multiple of 16 bytes long");
9976 return CKR_MECHANISM_PARAM_INVALID;
9978 data.resize(length);
9985 DEBUG_MSG("pParameter is invalid");
9986 return CKR_MECHANISM_PARAM_INVALID;
9990 Session* session = (Session*)handleManager->getSession(hSession);
9991 if (session == NULL)
9992 return CKR_SESSION_HANDLE_INVALID;
9995 Token* token = session->getToken();
9997 return CKR_GENERAL_ERROR;
9999 // Extract desired parameter information
10000 size_t byteLen = 0;
10001 bool checkValue = true;
10002 for (CK_ULONG i = 0; i < ulCount; i++)
10004 switch (pTemplate[i].type)
10007 INFO_MSG("CKA_VALUE must not be included");
10008 return CKR_ATTRIBUTE_READ_ONLY;
10009 case CKA_VALUE_LEN:
10010 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10012 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10013 return CKR_ATTRIBUTE_VALUE_INVALID;
10015 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10017 case CKA_CHECK_VALUE:
10018 if (pTemplate[i].ulValueLen > 0)
10020 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10021 return CKR_ATTRIBUTE_VALUE_INVALID;
10023 checkValue = false;
10030 // Check the length
10033 case CKK_GENERIC_SECRET:
10036 INFO_MSG("CKA_VALUE_LEN must be set");
10037 return CKR_TEMPLATE_INCOMPLETE;
10044 INFO_MSG("CKA_VALUE_LEN must not be set");
10045 return CKR_ATTRIBUTE_READ_ONLY;
10053 INFO_MSG("CKA_VALUE_LEN must not be set");
10054 return CKR_ATTRIBUTE_READ_ONLY;
10061 INFO_MSG("CKA_VALUE_LEN must not be set");
10062 return CKR_ATTRIBUTE_READ_ONLY;
10067 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10069 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10070 return CKR_ATTRIBUTE_VALUE_INVALID;
10074 return CKR_ATTRIBUTE_VALUE_INVALID;
10077 // Get the symmetric algorithm matching the mechanism
10078 SymAlgo::Type algo = SymAlgo::Unknown;
10079 SymMode::Type mode = SymMode::Unknown;
10080 bool padding = false;
10083 switch(pMechanism->mechanism) {
10085 case CKM_DES_ECB_ENCRYPT_DATA:
10086 algo = SymAlgo::DES;
10087 mode = SymMode::ECB;
10090 case CKM_DES_CBC_ENCRYPT_DATA:
10091 algo = SymAlgo::DES;
10092 mode = SymMode::CBC;
10096 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10100 case CKM_DES3_ECB_ENCRYPT_DATA:
10101 algo = SymAlgo::DES3;
10102 mode = SymMode::ECB;
10105 case CKM_DES3_CBC_ENCRYPT_DATA:
10106 algo = SymAlgo::DES3;
10107 mode = SymMode::CBC;
10111 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10114 case CKM_AES_ECB_ENCRYPT_DATA:
10115 algo = SymAlgo::AES;
10116 mode = SymMode::ECB;
10118 case CKM_AES_CBC_ENCRYPT_DATA:
10119 algo = SymAlgo::AES;
10120 mode = SymMode::CBC;
10123 &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10127 return CKR_MECHANISM_INVALID;
10130 // Check the key handle
10131 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10132 if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10134 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10135 if (cipher == NULL) return CKR_MECHANISM_INVALID;
10137 SymmetricKey* secretkey = new SymmetricKey();
10139 if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10141 cipher->recycleKey(secretkey);
10142 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10143 return CKR_GENERAL_ERROR;
10146 // adjust key bit length
10147 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10149 // Initialize encryption
10150 if (!cipher->encryptInit(secretkey, mode, iv, padding))
10152 cipher->recycleKey(secretkey);
10153 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10154 return CKR_MECHANISM_INVALID;
10158 ByteString secretValue;
10160 // Encrypt the data
10161 if (!cipher->encryptUpdate(data, secretValue))
10163 cipher->recycleKey(secretkey);
10164 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10165 return CKR_GENERAL_ERROR;
10168 // Finalize encryption
10169 ByteString encryptedFinal;
10170 if (!cipher->encryptFinal(encryptedFinal))
10172 cipher->recycleKey(secretkey);
10173 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10174 return CKR_GENERAL_ERROR;
10176 cipher->recycleKey(secretkey);
10177 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10178 secretValue += encryptedFinal;
10180 // Create the secret object using C_CreateObject
10181 const CK_ULONG maxAttribs = 32;
10182 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10183 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10184 { CKA_CLASS, &objClass, sizeof(objClass) },
10185 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10186 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10187 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10189 CK_ULONG secretAttribsCount = 4;
10191 // Add the additional
10193 if (ulCount > (maxAttribs - secretAttribsCount))
10194 rv = CKR_TEMPLATE_INCONSISTENT;
10195 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10197 switch (pTemplate[i].type)
10203 case CKA_CHECK_VALUE:
10206 secretAttribs[secretAttribsCount++] = pTemplate[i];
10211 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10213 // Store the attributes that are being supplied
10216 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10217 if (osobject == NULL_PTR || !osobject->isValid()) {
10218 rv = CKR_FUNCTION_FAILED;
10219 } else if (osobject->startTransaction()) {
10222 // Common Attributes
10223 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10225 // Common Secret Key Attributes
10226 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10228 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10229 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10233 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10235 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10237 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10238 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10242 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10246 ByteString plainKCV;
10249 if (byteLen > secretValue.size())
10251 INFO_MSG("The derived secret is too short");
10256 // Truncate value when requested, remove from the trailing end
10257 if (byteLen < secretValue.size())
10258 secretValue.resize(byteLen);
10260 // Fix the odd parity for DES
10261 if (keyType == CKK_DES ||
10262 keyType == CKK_DES2 ||
10263 keyType == CKK_DES3)
10265 for (size_t i = 0; i < secretValue.size(); i++)
10267 secretValue[i] = odd_parity[secretValue[i]];
10272 SymmetricKey* secret = new SymmetricKey();
10273 secret->setKeyBits(secretValue);
10276 case CKK_GENERIC_SECRET:
10277 secret->setBitLen(byteLen * 8);
10278 plainKCV = secret->getKeyCheckValue();
10283 secret->setBitLen(byteLen * 7);
10284 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10287 secret->setBitLen(byteLen * 8);
10288 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10298 token->encrypt(secretValue, value);
10299 token->encrypt(plainKCV, kcv);
10303 value = secretValue;
10307 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10309 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10312 bOK = osobject->commitTransaction();
10314 osobject->abortTransaction();
10317 rv = CKR_FUNCTION_FAILED;
10319 rv = CKR_FUNCTION_FAILED;
10322 // Remove secret that may have been created already when the function fails.
10325 if (*phKey != CK_INVALID_HANDLE)
10327 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10328 handleManager->destroyObject(*phKey);
10329 if (ossecret) ossecret->destroyObject();
10330 *phKey = CK_INVALID_HANDLE;
10337 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10339 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10341 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10342 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10345 Session* session = (Session*)handleManager->getSession(hSession);
10346 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10349 Slot* slot = session->getSlot();
10350 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10353 Token* token = session->getToken();
10354 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10356 // Extract information from the template that is needed to create the object.
10357 CK_OBJECT_CLASS objClass = CKO_DATA;
10358 CK_KEY_TYPE keyType = CKK_RSA;
10359 CK_CERTIFICATE_TYPE certType = CKC_X_509;
10360 CK_BBOOL isOnToken = CK_FALSE;
10361 CK_BBOOL isPrivate = CK_TRUE;
10362 bool isImplicit = false;
10363 CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10366 ERROR_MSG("Mandatory attribute not present in template");
10370 // Check user credentials
10371 rv = haveWrite(session->getState(), isOnToken, isPrivate);
10374 if (rv == CKR_USER_NOT_LOGGED_IN)
10375 INFO_MSG("User is not authorized");
10376 if (rv == CKR_SESSION_READ_ONLY)
10377 INFO_MSG("Session is read-only");
10382 // Change order of attributes
10383 const CK_ULONG maxAttribs = 32;
10384 CK_ATTRIBUTE attribs[maxAttribs];
10385 CK_ATTRIBUTE saveAttribs[maxAttribs];
10386 CK_ULONG attribsCount = 0;
10387 CK_ULONG saveAttribsCount = 0;
10388 if (ulCount > maxAttribs)
10390 return CKR_TEMPLATE_INCONSISTENT;
10392 for (CK_ULONG i=0; i < ulCount; i++)
10394 switch (pTemplate[i].type)
10396 case CKA_CHECK_VALUE:
10397 saveAttribs[saveAttribsCount++] = pTemplate[i];
10400 attribs[attribsCount++] = pTemplate[i];
10403 for (CK_ULONG i=0; i < saveAttribsCount; i++)
10405 attribs[attribsCount++] = saveAttribs[i];
10408 P11Object* p11object = NULL;
10409 rv = newP11Object(objClass,keyType,certType,&p11object);
10413 // Create the object in session or on the token
10414 OSObject *object = NULL_PTR;
10417 object = (OSObject*) token->createObject();
10421 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10424 if (object == NULL || !p11object->init(object))
10427 return CKR_GENERAL_ERROR;
10430 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10435 if (op == OBJECT_OP_CREATE)
10437 if (objClass == CKO_PUBLIC_KEY &&
10438 (!object->startTransaction() ||
10439 !object->setAttribute(CKA_LOCAL, false) ||
10440 !object->commitTransaction()))
10442 return CKR_GENERAL_ERROR;
10445 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10446 (!object->startTransaction() ||
10447 !object->setAttribute(CKA_LOCAL, false) ||
10448 !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10449 !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10450 !object->commitTransaction()))
10452 return CKR_GENERAL_ERROR;
10458 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10460 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10466 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10468 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10469 if (token == NULL) return CKR_ARGUMENTS_BAD;
10470 if (key == NULL) return CKR_ARGUMENTS_BAD;
10472 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10473 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10475 // RSA Private Key Attributes
10476 ByteString modulus;
10477 ByteString publicExponent;
10478 ByteString privateExponent;
10481 ByteString exponent1;
10482 ByteString exponent2;
10483 ByteString coefficient;
10487 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10488 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10489 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10490 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10491 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10492 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10493 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10494 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10496 return CKR_GENERAL_ERROR;
10500 modulus = key->getByteStringValue(CKA_MODULUS);
10501 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10502 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10503 prime1 = key->getByteStringValue(CKA_PRIME_1);
10504 prime2 = key->getByteStringValue(CKA_PRIME_2);
10505 exponent1 = key->getByteStringValue(CKA_EXPONENT_1);
10506 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10507 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10510 privateKey->setN(modulus);
10511 privateKey->setE(publicExponent);
10512 privateKey->setD(privateExponent);
10513 privateKey->setP(prime1);
10514 privateKey->setQ(prime2);
10515 privateKey->setDP1(exponent1);
10516 privateKey->setDQ1(exponent2);
10517 privateKey->setPQ(coefficient);
10522 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10524 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10525 if (token == NULL) return CKR_ARGUMENTS_BAD;
10526 if (key == NULL) return CKR_ARGUMENTS_BAD;
10528 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10529 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10531 // RSA Public Key Attributes
10532 ByteString modulus;
10533 ByteString publicExponent;
10537 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10538 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10540 return CKR_GENERAL_ERROR;
10544 modulus = key->getByteStringValue(CKA_MODULUS);
10545 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10548 publicKey->setN(modulus);
10549 publicKey->setE(publicExponent);
10554 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10556 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10557 if (token == NULL) return CKR_ARGUMENTS_BAD;
10558 if (key == NULL) return CKR_ARGUMENTS_BAD;
10560 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10561 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10563 // DSA Private Key Attributes
10565 ByteString subprime;
10566 ByteString generator;
10571 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10572 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10573 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10574 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10576 return CKR_GENERAL_ERROR;
10580 prime = key->getByteStringValue(CKA_PRIME);
10581 subprime = key->getByteStringValue(CKA_SUBPRIME);
10582 generator = key->getByteStringValue(CKA_BASE);
10583 value = key->getByteStringValue(CKA_VALUE);
10586 privateKey->setP(prime);
10587 privateKey->setQ(subprime);
10588 privateKey->setG(generator);
10589 privateKey->setX(value);
10594 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10596 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10597 if (token == NULL) return CKR_ARGUMENTS_BAD;
10598 if (key == NULL) return CKR_ARGUMENTS_BAD;
10600 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10601 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10603 // DSA Public Key Attributes
10605 ByteString subprime;
10606 ByteString generator;
10611 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10612 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10613 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10614 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10616 return CKR_GENERAL_ERROR;
10620 prime = key->getByteStringValue(CKA_PRIME);
10621 subprime = key->getByteStringValue(CKA_SUBPRIME);
10622 generator = key->getByteStringValue(CKA_BASE);
10623 value = key->getByteStringValue(CKA_VALUE);
10626 publicKey->setP(prime);
10627 publicKey->setQ(subprime);
10628 publicKey->setG(generator);
10629 publicKey->setY(value);
10634 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10636 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10637 if (token == NULL) return CKR_ARGUMENTS_BAD;
10638 if (key == NULL) return CKR_ARGUMENTS_BAD;
10640 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10641 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10643 // EC Private Key Attributes
10649 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10650 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10652 return CKR_GENERAL_ERROR;
10656 group = key->getByteStringValue(CKA_EC_PARAMS);
10657 value = key->getByteStringValue(CKA_VALUE);
10660 privateKey->setEC(group);
10661 privateKey->setD(value);
10666 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10668 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10669 if (token == NULL) return CKR_ARGUMENTS_BAD;
10670 if (key == NULL) return CKR_ARGUMENTS_BAD;
10672 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10673 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10675 // EC Public Key Attributes
10681 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10682 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10684 return CKR_GENERAL_ERROR;
10688 group = key->getByteStringValue(CKA_EC_PARAMS);
10689 point = key->getByteStringValue(CKA_EC_POINT);
10692 publicKey->setEC(group);
10693 publicKey->setQ(point);
10698 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10700 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10701 if (token == NULL) return CKR_ARGUMENTS_BAD;
10702 if (key == NULL) return CKR_ARGUMENTS_BAD;
10704 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10705 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10707 // DH Private Key Attributes
10709 ByteString generator;
10714 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10715 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10716 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10718 return CKR_GENERAL_ERROR;
10722 prime = key->getByteStringValue(CKA_PRIME);
10723 generator = key->getByteStringValue(CKA_BASE);
10724 value = key->getByteStringValue(CKA_VALUE);
10727 privateKey->setP(prime);
10728 privateKey->setG(generator);
10729 privateKey->setX(value);
10734 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
10736 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10737 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10739 // Copy Domain Parameters from Private Key
10740 publicKey->setP(privateKey->getP());
10741 publicKey->setG(privateKey->getG());
10744 publicKey->setY(pubParams);
10749 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
10751 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10752 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10754 // Copy Domain Parameters from Private Key
10755 publicKey->setEC(privateKey->getEC());
10758 ByteString data = getECDHPubData(pubData);
10759 publicKey->setQ(data);
10764 // ECDH pubData can be in RAW or DER format.
10765 // Need to convert RAW as SoftHSM uses DER.
10766 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
10768 size_t len = pubData.size();
10769 size_t controlOctets = 2;
10770 if (len == 65 || len == 97 || len == 133)
10772 // Raw: Length matches the public key size of P-256, P-384, or P-521
10775 else if (len < controlOctets || pubData[0] != 0x04)
10777 // Raw: Too short or does not start with 0x04
10780 else if (pubData[1] < 0x80)
10782 // Raw: Length octet does not match remaining data length
10783 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
10787 size_t lengthOctets = pubData[1] & 0x7F;
10788 controlOctets += lengthOctets;
10790 if (controlOctets >= len)
10797 ByteString length(&pubData[2], lengthOctets);
10799 if (length.long_val() != (len - controlOctets))
10801 // Raw: Length octets does not match remaining data length
10808 if (controlOctets != 0) return pubData;
10815 header[0] = (unsigned char)0x04;
10816 header[1] = (unsigned char)(len & 0x7F);
10820 // Count significate bytes
10821 size_t bytes = sizeof(size_t);
10822 for(; bytes > 0; bytes--)
10824 size_t value = len >> ((bytes - 1) * 8);
10825 if (value & 0xFF) break;
10829 header.resize(2 + bytes);
10830 header[0] = (unsigned char)0x04;
10831 header[1] = (unsigned char)(0x80 | bytes);
10832 for (size_t i = 1; i <= bytes; i++)
10834 header[2+bytes-i] = (unsigned char) (len & 0xFF);
10839 return header + pubData;
10842 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
10844 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10845 if (token == NULL) return CKR_ARGUMENTS_BAD;
10846 if (key == NULL) return CKR_ARGUMENTS_BAD;
10848 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10849 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10851 // GOST Private Key Attributes
10857 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10858 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10860 return CKR_GENERAL_ERROR;
10864 value = key->getByteStringValue(CKA_VALUE);
10865 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10868 privateKey->setD(value);
10869 privateKey->setEC(param);
10874 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
10876 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10877 if (token == NULL) return CKR_ARGUMENTS_BAD;
10878 if (key == NULL) return CKR_ARGUMENTS_BAD;
10880 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10881 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10883 // GOST Public Key Attributes
10889 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
10890 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10892 return CKR_GENERAL_ERROR;
10896 point = key->getByteStringValue(CKA_VALUE);
10897 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10900 publicKey->setQ(point);
10901 publicKey->setEC(param);
10906 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
10908 if (skey == NULL) return CKR_ARGUMENTS_BAD;
10909 if (token == NULL) return CKR_ARGUMENTS_BAD;
10910 if (key == NULL) return CKR_ARGUMENTS_BAD;
10912 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10913 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10915 ByteString keybits;
10918 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
10919 return CKR_GENERAL_ERROR;
10923 keybits = key->getByteStringValue(CKA_VALUE);
10926 skey->setKeyBits(keybits);
10931 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
10933 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
10936 PrivateKey* priv = rsa->newPrivateKey();
10939 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10942 if (!priv->PKCS8Decode(ber))
10944 rsa->recyclePrivateKey(priv);
10945 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10948 // RSA Private Key Attributes
10949 ByteString modulus;
10950 ByteString publicExponent;
10951 ByteString privateExponent;
10954 ByteString exponent1;
10955 ByteString exponent2;
10956 ByteString coefficient;
10959 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
10960 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
10961 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
10962 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
10963 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
10964 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
10965 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
10966 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
10970 modulus = ((RSAPrivateKey*)priv)->getN();
10971 publicExponent = ((RSAPrivateKey*)priv)->getE();
10972 privateExponent = ((RSAPrivateKey*)priv)->getD();
10973 prime1 = ((RSAPrivateKey*)priv)->getP();
10974 prime2 = ((RSAPrivateKey*)priv)->getQ();
10975 exponent1 = ((RSAPrivateKey*)priv)->getDP1();
10976 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
10977 coefficient = ((RSAPrivateKey*)priv)->getPQ();
10980 bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
10981 bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
10982 bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
10983 bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
10984 bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
10985 bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
10986 bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
10987 bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
10989 rsa->recyclePrivateKey(priv);
10990 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10995 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
10997 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
11000 PrivateKey* priv = dsa->newPrivateKey();
11003 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11006 if (!priv->PKCS8Decode(ber))
11008 dsa->recyclePrivateKey(priv);
11009 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11012 // DSA Private Key Attributes
11014 ByteString subprime;
11015 ByteString generator;
11019 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11020 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11021 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11022 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11026 prime = ((DSAPrivateKey*)priv)->getP();
11027 subprime = ((DSAPrivateKey*)priv)->getQ();
11028 generator = ((DSAPrivateKey*)priv)->getG();
11029 value = ((DSAPrivateKey*)priv)->getX();
11032 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11033 bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11034 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11035 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11037 dsa->recyclePrivateKey(priv);
11038 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11043 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11045 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11048 PrivateKey* priv = dh->newPrivateKey();
11051 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11054 if (!priv->PKCS8Decode(ber))
11056 dh->recyclePrivateKey(priv);
11057 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11060 // DH Private Key Attributes
11062 ByteString generator;
11066 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11067 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11068 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11072 prime = ((DHPrivateKey*)priv)->getP();
11073 generator = ((DHPrivateKey*)priv)->getG();
11074 value = ((DHPrivateKey*)priv)->getX();
11077 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11078 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11079 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11081 dh->recyclePrivateKey(priv);
11082 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11086 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11088 AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11091 PrivateKey* priv = ecc->newPrivateKey();
11094 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11097 if (!priv->PKCS8Decode(ber))
11099 ecc->recyclePrivateKey(priv);
11100 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11103 // EC Private Key Attributes
11108 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11109 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11113 group = ((ECPrivateKey*)priv)->getEC();
11114 value = ((ECPrivateKey*)priv)->getD();
11117 bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11118 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11120 ecc->recyclePrivateKey(priv);
11121 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11126 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11128 // This is a programming error
11129 if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11130 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11131 return CKR_GENERAL_ERROR;
11134 if (pMechanism->pParameter == NULL_PTR ||
11135 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11137 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11138 return CKR_ARGUMENTS_BAD;
11141 CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11142 if (params->hashAlg != CKM_SHA_1)
11144 ERROR_MSG("hashAlg must be CKM_SHA_1");
11145 return CKR_ARGUMENTS_BAD;
11147 if (params->mgf != CKG_MGF1_SHA1)
11149 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11150 return CKR_ARGUMENTS_BAD;
11152 if (params->source != CKZ_DATA_SPECIFIED)
11154 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11155 return CKR_ARGUMENTS_BAD;
11157 if (params->pSourceData != NULL)
11159 ERROR_MSG("pSourceData must be NULL");
11160 return CKR_ARGUMENTS_BAD;
11162 if (params->ulSourceDataLen != 0)
11164 ERROR_MSG("ulSourceDataLen must be 0");
11165 return CKR_ARGUMENTS_BAD;
11170 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11171 OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11172 std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11173 if (allowed.empty()) {
11177 return allowed.find(pMechanism->mechanism) != allowed.end();