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;
6136 alg = AsymAlgo::GOST;
6140 return CKR_KEY_NOT_WRAPPABLE;
6142 AsymmetricAlgorithm* asymCrypto = NULL;
6143 PrivateKey* privateKey = NULL;
6144 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6145 if (asymCrypto == NULL)
6146 return CKR_GENERAL_ERROR;
6147 privateKey = asymCrypto->newPrivateKey();
6148 if (privateKey == NULL)
6150 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6151 return CKR_HOST_MEMORY;
6155 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6158 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6161 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6165 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6170 rv = getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key);
6176 asymCrypto->recyclePrivateKey(privateKey);
6177 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6178 return CKR_GENERAL_ERROR;
6180 keydata = privateKey->PKCS8Encode();
6181 asymCrypto->recyclePrivateKey(privateKey);
6182 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6184 if (keydata.size() == 0)
6185 return CKR_KEY_NOT_WRAPPABLE;
6187 keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6189 if (keyClass == CKO_SECRET_KEY)
6190 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6192 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6196 if (pWrappedKey != NULL) {
6197 if (*pulWrappedKeyLen >= wrapped.size())
6198 memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6200 rv = CKR_BUFFER_TOO_SMALL;
6203 *pulWrappedKeyLen = wrapped.size();
6207 // Internal: Unwrap blob using symmetric key
6208 CK_RV SoftHSM::UnwrapKeySym
6210 CK_MECHANISM_PTR pMechanism,
6211 ByteString& wrapped,
6213 OSObject* unwrapKey,
6217 // Get the symmetric algorithm matching the mechanism
6218 SymAlgo::Type algo = SymAlgo::Unknown;
6219 SymWrap::Type mode = SymWrap::Unknown;
6221 switch(pMechanism->mechanism) {
6222 #ifdef HAVE_AES_KEY_WRAP
6223 case CKM_AES_KEY_WRAP:
6224 algo = SymAlgo::AES;
6225 mode = SymWrap::AES_KEYWRAP;
6228 #ifdef HAVE_AES_KEY_WRAP_PAD
6229 case CKM_AES_KEY_WRAP_PAD:
6230 algo = SymAlgo::AES;
6231 mode = SymWrap::AES_KEYWRAP_PAD;
6235 return CKR_MECHANISM_INVALID;
6237 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6238 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6240 SymmetricKey* unwrappingkey = new SymmetricKey();
6242 if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6244 cipher->recycleKey(unwrappingkey);
6245 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6246 return CKR_GENERAL_ERROR;
6249 // adjust key bit length
6250 unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6254 if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6255 rv = CKR_GENERAL_ERROR;
6256 cipher->recycleKey(unwrappingkey);
6257 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6261 // Internal: Unwrap blob using asymmetric key
6262 CK_RV SoftHSM::UnwrapKeyAsym
6264 CK_MECHANISM_PTR pMechanism,
6265 ByteString& wrapped,
6267 OSObject* unwrapKey,
6271 // Get the symmetric algorithm matching the mechanism
6272 AsymAlgo::Type algo = AsymAlgo::Unknown;
6273 AsymMech::Type mode = AsymMech::Unknown;
6274 switch(pMechanism->mechanism) {
6276 algo = AsymAlgo::RSA;
6277 mode = AsymMech::RSA_PKCS;
6280 case CKM_RSA_PKCS_OAEP:
6281 algo = AsymAlgo::RSA;
6282 mode = AsymMech::RSA_PKCS_OAEP;
6286 return CKR_MECHANISM_INVALID;
6288 AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6289 if (cipher == NULL) return CKR_MECHANISM_INVALID;
6291 PrivateKey* unwrappingkey = cipher->newPrivateKey();
6292 if (unwrappingkey == NULL)
6294 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6295 return CKR_HOST_MEMORY;
6298 switch(pMechanism->mechanism) {
6300 case CKM_RSA_PKCS_OAEP:
6301 if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6303 cipher->recyclePrivateKey(unwrappingkey);
6304 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6305 return CKR_GENERAL_ERROR;
6310 return CKR_MECHANISM_INVALID;
6315 if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6316 rv = CKR_GENERAL_ERROR;
6317 cipher->recyclePrivateKey(unwrappingkey);
6318 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6322 // Unwrap the specified key using the specified unwrapping key
6323 CK_RV SoftHSM::C_UnwrapKey
6325 CK_SESSION_HANDLE hSession,
6326 CK_MECHANISM_PTR pMechanism,
6327 CK_OBJECT_HANDLE hUnwrappingKey,
6328 CK_BYTE_PTR pWrappedKey,
6329 CK_ULONG ulWrappedKeyLen,
6330 CK_ATTRIBUTE_PTR pTemplate,
6332 CK_OBJECT_HANDLE_PTR hKey
6335 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6337 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6338 if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6339 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6340 if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6343 Session* session = (Session*)handleManager->getSession(hSession);
6344 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6347 // Check the mechanism
6348 switch(pMechanism->mechanism)
6350 #ifdef HAVE_AES_KEY_WRAP
6351 case CKM_AES_KEY_WRAP:
6352 if ((ulWrappedKeyLen < 24) || ((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;
6360 #ifdef HAVE_AES_KEY_WRAP_PAD
6361 case CKM_AES_KEY_WRAP_PAD:
6362 if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6363 return CKR_WRAPPED_KEY_LEN_RANGE;
6364 // Does not handle optional init vector
6365 if (pMechanism->pParameter != NULL_PTR ||
6366 pMechanism->ulParameterLen != 0)
6367 return CKR_ARGUMENTS_BAD;
6371 // Input length checks needs to be done later when unwrapping key is known
6373 case CKM_RSA_PKCS_OAEP:
6374 rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6380 return CKR_MECHANISM_INVALID;
6384 Token* token = session->getToken();
6385 if (token == NULL) return CKR_GENERAL_ERROR;
6387 // Check the unwrapping key handle.
6388 OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6389 if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6391 CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6392 CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6394 // Check user credentials
6395 rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6398 if (rv == CKR_USER_NOT_LOGGED_IN)
6399 INFO_MSG("User is not authorized");
6404 // Check unwrapping key class and type
6405 if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6406 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6407 if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6408 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6409 if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6410 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6411 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6412 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6413 if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6414 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6416 // Check if the unwrapping key can be used for unwrapping
6417 if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6418 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6420 // Check if the specified mechanism is allowed for the unwrap key
6421 if (!isMechanismPermitted(unwrapKey, pMechanism))
6422 return CKR_MECHANISM_INVALID;
6424 // Extract information from the template that is needed to create the object.
6425 CK_OBJECT_CLASS objClass;
6426 CK_KEY_TYPE keyType;
6427 CK_BBOOL isOnToken = CK_FALSE;
6428 CK_BBOOL isPrivate = CK_TRUE;
6429 CK_CERTIFICATE_TYPE dummy;
6430 bool isImplicit = false;
6431 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6434 ERROR_MSG("Mandatory attribute not present in template");
6438 // Report errors and/or unexpected usage.
6439 if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6440 return CKR_ATTRIBUTE_VALUE_INVALID;
6441 // Key type will be handled at object creation
6443 // Check authorization
6444 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6447 if (rv == CKR_USER_NOT_LOGGED_IN)
6448 INFO_MSG("User is not authorized");
6449 if (rv == CKR_SESSION_READ_ONLY)
6450 INFO_MSG("Session is read-only");
6455 // Build unwrapped key template
6456 const CK_ULONG maxAttribs = 32;
6457 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6458 { CKA_CLASS, &objClass, sizeof(objClass) },
6459 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6460 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6461 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6463 CK_ULONG secretAttribsCount = 4;
6465 // Add the additional
6466 if (ulCount > (maxAttribs - secretAttribsCount))
6467 return CKR_TEMPLATE_INCONSISTENT;
6468 for (CK_ULONG i = 0; i < ulCount; ++i)
6470 switch (pTemplate[i].type)
6478 secretAttribs[secretAttribsCount++] = pTemplate[i];
6482 // Apply the unwrap template
6483 if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6485 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6487 if (unwrapAttr.isAttributeMapAttribute())
6489 typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6491 const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6493 for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6495 CK_ATTRIBUTE* attr = NULL;
6496 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6498 if (it->first == secretAttribs[i].type)
6502 return CKR_TEMPLATE_INCONSISTENT;
6504 attr = &secretAttribs[i];
6506 it->second.peekValue(value);
6507 if (attr->ulValueLen != value.size())
6509 return CKR_TEMPLATE_INCONSISTENT;
6511 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6513 return CKR_TEMPLATE_INCONSISTENT;
6519 return CKR_TEMPLATE_INCONSISTENT;
6525 *hKey = CK_INVALID_HANDLE;
6528 ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6530 if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6531 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6532 else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6533 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6535 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6539 // Create the secret object using C_CreateObject
6540 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6542 // Store the attributes that are being supplied
6545 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6546 if (osobject == NULL_PTR || !osobject->isValid())
6547 rv = CKR_FUNCTION_FAILED;
6548 if (osobject->startTransaction())
6552 // Common Attributes
6553 bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6555 // Common Secret Key Attributes
6556 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6557 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6559 // Secret Attributes
6560 if (objClass == CKO_SECRET_KEY)
6564 token->encrypt(keydata, value);
6567 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6569 else if (keyType == CKK_RSA)
6571 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6573 else if (keyType == CKK_DSA)
6575 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6577 else if (keyType == CKK_DH)
6579 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6582 else if (keyType == CKK_EC)
6584 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6588 else if (keyType == CKK_GOSTR3410)
6590 bOK = bOK && setGOSTPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6597 bOK = osobject->commitTransaction();
6599 osobject->abortTransaction();
6602 rv = CKR_FUNCTION_FAILED;
6605 rv = CKR_FUNCTION_FAILED;
6608 // Remove secret that may have been created already when the function fails.
6611 if (*hKey != CK_INVALID_HANDLE)
6613 OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6614 handleManager->destroyObject(*hKey);
6615 if (obj) obj->destroyObject();
6616 *hKey = CK_INVALID_HANDLE;
6624 // Derive a key from the specified base key
6625 CK_RV SoftHSM::C_DeriveKey
6627 CK_SESSION_HANDLE hSession,
6628 CK_MECHANISM_PTR pMechanism,
6629 CK_OBJECT_HANDLE hBaseKey,
6630 CK_ATTRIBUTE_PTR pTemplate,
6632 CK_OBJECT_HANDLE_PTR phKey
6635 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6637 if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6638 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6639 if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6642 Session* session = (Session*)handleManager->getSession(hSession);
6643 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6645 // Check the mechanism, only accept DH and ECDH derive
6646 switch (pMechanism->mechanism)
6648 case CKM_DH_PKCS_DERIVE:
6650 case CKM_ECDH1_DERIVE:
6653 case CKM_DES_ECB_ENCRYPT_DATA:
6654 case CKM_DES_CBC_ENCRYPT_DATA:
6656 case CKM_DES3_ECB_ENCRYPT_DATA:
6657 case CKM_DES3_CBC_ENCRYPT_DATA:
6658 case CKM_AES_ECB_ENCRYPT_DATA:
6659 case CKM_AES_CBC_ENCRYPT_DATA:
6662 ERROR_MSG("Invalid mechanism");
6663 return CKR_MECHANISM_INVALID;
6667 Token* token = session->getToken();
6668 if (token == NULL) return CKR_GENERAL_ERROR;
6670 // Check the key handle.
6671 OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6672 if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6674 CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6675 CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6677 // Check user credentials
6678 CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6681 if (rv == CKR_USER_NOT_LOGGED_IN)
6682 INFO_MSG("User is not authorized");
6687 // Check if key can be used for derive
6688 if (!key->getBooleanValue(CKA_DERIVE, false))
6689 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6691 // Check if the specified mechanism is allowed for the key
6692 if (!isMechanismPermitted(key, pMechanism))
6693 return CKR_MECHANISM_INVALID;
6695 // Extract information from the template that is needed to create the object.
6696 CK_OBJECT_CLASS objClass;
6697 CK_KEY_TYPE keyType;
6698 CK_BBOOL isOnToken = CK_FALSE;
6699 CK_BBOOL isPrivate = CK_TRUE;
6700 CK_CERTIFICATE_TYPE dummy;
6701 bool isImplicit = false;
6702 rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6705 ERROR_MSG("Mandatory attribute not present in template");
6709 // Report errors and/or unexpected usage.
6710 if (objClass != CKO_SECRET_KEY)
6711 return CKR_ATTRIBUTE_VALUE_INVALID;
6712 if (keyType != CKK_GENERIC_SECRET &&
6713 keyType != CKK_DES &&
6714 keyType != CKK_DES2 &&
6715 keyType != CKK_DES3 &&
6717 return CKR_TEMPLATE_INCONSISTENT;
6719 // Check authorization
6720 rv = haveWrite(session->getState(), isOnToken, isPrivate);
6723 if (rv == CKR_USER_NOT_LOGGED_IN)
6724 INFO_MSG("User is not authorized");
6725 if (rv == CKR_SESSION_READ_ONLY)
6726 INFO_MSG("Session is read-only");
6732 if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
6734 // Check key class and type
6735 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6736 return CKR_KEY_TYPE_INCONSISTENT;
6737 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
6738 return CKR_KEY_TYPE_INCONSISTENT;
6740 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6744 // Derive ECDH secret
6745 if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
6747 // Check key class and type
6748 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6749 return CKR_KEY_TYPE_INCONSISTENT;
6750 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
6751 return CKR_KEY_TYPE_INCONSISTENT;
6753 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6757 // Derive symmetric secret
6758 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
6759 pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
6760 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
6761 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
6762 pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
6763 pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
6765 // Check key class and type
6766 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6767 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6768 return CKR_KEY_TYPE_INCONSISTENT;
6769 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
6770 baseKeyType != CKK_DES)
6771 return CKR_KEY_TYPE_INCONSISTENT;
6772 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
6773 baseKeyType != CKK_DES)
6774 return CKR_KEY_TYPE_INCONSISTENT;
6775 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
6776 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6777 return CKR_KEY_TYPE_INCONSISTENT;
6778 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
6779 baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6780 return CKR_KEY_TYPE_INCONSISTENT;
6781 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
6782 baseKeyType != CKK_AES)
6783 return CKR_KEY_TYPE_INCONSISTENT;
6784 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
6785 baseKeyType != CKK_AES)
6786 return CKR_KEY_TYPE_INCONSISTENT;
6788 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6791 return CKR_MECHANISM_INVALID;
6794 // Seed the random number generator with new data
6795 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
6797 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6799 if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
6802 Session* session = (Session*)handleManager->getSession(hSession);
6803 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6806 RNG* rng = CryptoFactory::i()->getRNG();
6807 if (rng == NULL) return CKR_GENERAL_ERROR;
6810 ByteString seed(pSeed, ulSeedLen);
6816 // Generate the specified amount of random data
6817 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
6819 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6821 if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
6824 Session* session = (Session*)handleManager->getSession(hSession);
6825 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6828 RNG* rng = CryptoFactory::i()->getRNG();
6829 if (rng == NULL) return CKR_GENERAL_ERROR;
6831 // Generate random data
6832 ByteString randomData;
6833 if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
6835 // Return random data
6836 if (ulRandomLen != 0)
6838 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
6845 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
6847 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6850 Session* session = (Session*)handleManager->getSession(hSession);
6851 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6853 return CKR_FUNCTION_NOT_PARALLEL;
6857 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
6859 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6862 Session* session = (Session*)handleManager->getSession(hSession);
6863 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6865 return CKR_FUNCTION_NOT_PARALLEL;
6868 // Wait or poll for a slot event on the specified slot
6869 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
6871 return CKR_FUNCTION_NOT_SUPPORTED;
6874 // Generate an AES secret key
6875 CK_RV SoftHSM::generateAES
6876 (CK_SESSION_HANDLE hSession,
6877 CK_ATTRIBUTE_PTR pTemplate,
6879 CK_OBJECT_HANDLE_PTR phKey,
6883 *phKey = CK_INVALID_HANDLE;
6886 Session* session = (Session*)handleManager->getSession(hSession);
6887 if (session == NULL)
6888 return CKR_SESSION_HANDLE_INVALID;
6891 Token* token = session->getToken();
6893 return CKR_GENERAL_ERROR;
6895 // Extract desired parameter information
6897 bool checkValue = true;
6898 for (CK_ULONG i = 0; i < ulCount; i++)
6900 switch (pTemplate[i].type)
6903 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
6905 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
6906 return CKR_ATTRIBUTE_VALUE_INVALID;
6908 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
6910 case CKA_CHECK_VALUE:
6911 if (pTemplate[i].ulValueLen > 0)
6913 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
6914 return CKR_ATTRIBUTE_VALUE_INVALID;
6923 // CKA_VALUE_LEN must be specified
6926 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
6927 return CKR_TEMPLATE_INCOMPLETE;
6930 // keyLen must be 16, 24, or 32
6931 if (keyLen != 16 && keyLen != 24 && keyLen != 32)
6933 INFO_MSG("bad AES key length");
6934 return CKR_ATTRIBUTE_VALUE_INVALID;
6937 // Generate the secret key
6938 AESKey* key = new AESKey(keyLen * 8);
6939 SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
6942 ERROR_MSG("Could not get SymmetricAlgorithm");
6944 return CKR_GENERAL_ERROR;
6946 RNG* rng = CryptoFactory::i()->getRNG();
6949 ERROR_MSG("Could not get RNG");
6950 aes->recycleKey(key);
6951 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6952 return CKR_GENERAL_ERROR;
6954 if (!aes->generateKey(*key, rng))
6956 ERROR_MSG("Could not generate AES secret key");
6957 aes->recycleKey(key);
6958 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6959 return CKR_GENERAL_ERROR;
6964 // Create the secret key object using C_CreateObject
6965 const CK_ULONG maxAttribs = 32;
6966 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
6967 CK_KEY_TYPE keyType = CKK_AES;
6968 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
6969 { CKA_CLASS, &objClass, sizeof(objClass) },
6970 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6971 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6972 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
6974 CK_ULONG keyAttribsCount = 4;
6976 // Add the additional
6977 if (ulCount > (maxAttribs - keyAttribsCount))
6978 rv = CKR_TEMPLATE_INCONSISTENT;
6979 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
6981 switch (pTemplate[i].type)
6987 case CKA_CHECK_VALUE:
6990 keyAttribs[keyAttribsCount++] = pTemplate[i];
6995 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
6997 // Store the attributes that are being supplied
7000 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7001 if (osobject == NULL_PTR || !osobject->isValid()) {
7002 rv = CKR_FUNCTION_FAILED;
7003 } else if (osobject->startTransaction()) {
7006 // Common Attributes
7007 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7008 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
7009 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7011 // Common Secret Key Attributes
7012 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7013 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7014 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7015 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7017 // AES Secret Key Attributes
7022 token->encrypt(key->getKeyBits(), value);
7023 token->encrypt(key->getKeyCheckValue(), kcv);
7027 value = key->getKeyBits();
7028 kcv = key->getKeyCheckValue();
7030 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7032 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7035 bOK = osobject->commitTransaction();
7037 osobject->abortTransaction();
7040 rv = CKR_FUNCTION_FAILED;
7042 rv = CKR_FUNCTION_FAILED;
7046 aes->recycleKey(key);
7047 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7049 // Remove the key that may have been created already when the function fails.
7052 if (*phKey != CK_INVALID_HANDLE)
7054 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7055 handleManager->destroyObject(*phKey);
7056 if (oskey) oskey->destroyObject();
7057 *phKey = CK_INVALID_HANDLE;
7064 // Generate a DES secret key
7065 CK_RV SoftHSM::generateDES
7066 (CK_SESSION_HANDLE hSession,
7067 CK_ATTRIBUTE_PTR pTemplate,
7069 CK_OBJECT_HANDLE_PTR phKey,
7073 *phKey = CK_INVALID_HANDLE;
7076 Session* session = (Session*)handleManager->getSession(hSession);
7077 if (session == NULL)
7078 return CKR_SESSION_HANDLE_INVALID;
7081 Token* token = session->getToken();
7083 return CKR_GENERAL_ERROR;
7085 // Extract desired parameter information
7086 bool checkValue = true;
7087 for (CK_ULONG i = 0; i < ulCount; i++)
7089 switch (pTemplate[i].type)
7091 case CKA_CHECK_VALUE:
7092 if (pTemplate[i].ulValueLen > 0)
7094 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7095 return CKR_ATTRIBUTE_VALUE_INVALID;
7104 // Generate the secret key
7105 DESKey* key = new DESKey(56);
7106 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7109 ERROR_MSG("Could not get SymmetricAlgorithm");
7111 return CKR_GENERAL_ERROR;
7113 RNG* rng = CryptoFactory::i()->getRNG();
7116 ERROR_MSG("Could not get RNG");
7117 des->recycleKey(key);
7118 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7119 return CKR_GENERAL_ERROR;
7121 if (!des->generateKey(*key, rng))
7123 ERROR_MSG("Could not generate DES secret key");
7124 des->recycleKey(key);
7125 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7126 return CKR_GENERAL_ERROR;
7131 // Create the secret key object using C_CreateObject
7132 const CK_ULONG maxAttribs = 32;
7133 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7134 CK_KEY_TYPE keyType = CKK_DES;
7135 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7136 { CKA_CLASS, &objClass, sizeof(objClass) },
7137 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7138 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7139 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7141 CK_ULONG keyAttribsCount = 4;
7143 // Add the additional
7144 if (ulCount > (maxAttribs - keyAttribsCount))
7145 rv = CKR_TEMPLATE_INCONSISTENT;
7146 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7148 switch (pTemplate[i].type)
7154 case CKA_CHECK_VALUE:
7157 keyAttribs[keyAttribsCount++] = pTemplate[i];
7162 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7164 // Store the attributes that are being supplied
7167 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7168 if (osobject == NULL_PTR || !osobject->isValid()) {
7169 rv = CKR_FUNCTION_FAILED;
7170 } else if (osobject->startTransaction()) {
7173 // Common Attributes
7174 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7175 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7176 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7178 // Common Secret Key Attributes
7179 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7180 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7181 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7182 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7184 // DES Secret Key Attributes
7189 token->encrypt(key->getKeyBits(), value);
7190 token->encrypt(key->getKeyCheckValue(), kcv);
7194 value = key->getKeyBits();
7195 kcv = key->getKeyCheckValue();
7197 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7199 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7202 bOK = osobject->commitTransaction();
7204 osobject->abortTransaction();
7207 rv = CKR_FUNCTION_FAILED;
7209 rv = CKR_FUNCTION_FAILED;
7213 des->recycleKey(key);
7214 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7216 // Remove the key that may have been created already when the function fails.
7219 if (*phKey != CK_INVALID_HANDLE)
7221 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7222 handleManager->destroyObject(*phKey);
7223 if (oskey) oskey->destroyObject();
7224 *phKey = CK_INVALID_HANDLE;
7231 // Generate a DES2 secret key
7232 CK_RV SoftHSM::generateDES2
7233 (CK_SESSION_HANDLE hSession,
7234 CK_ATTRIBUTE_PTR pTemplate,
7236 CK_OBJECT_HANDLE_PTR phKey,
7240 *phKey = CK_INVALID_HANDLE;
7243 Session* session = (Session*)handleManager->getSession(hSession);
7244 if (session == NULL)
7245 return CKR_SESSION_HANDLE_INVALID;
7248 Token* token = session->getToken();
7250 return CKR_GENERAL_ERROR;
7252 // Extract desired parameter information
7253 bool checkValue = true;
7254 for (CK_ULONG i = 0; i < ulCount; i++)
7256 switch (pTemplate[i].type)
7258 case CKA_CHECK_VALUE:
7259 if (pTemplate[i].ulValueLen > 0)
7261 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7262 return CKR_ATTRIBUTE_VALUE_INVALID;
7271 // Generate the secret key
7272 DESKey* key = new DESKey(112);
7273 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7276 ERROR_MSG("Could not get SymmetricAlgorith");
7278 return CKR_GENERAL_ERROR;
7280 RNG* rng = CryptoFactory::i()->getRNG();
7283 ERROR_MSG("Could not get RNG");
7284 des->recycleKey(key);
7285 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7286 return CKR_GENERAL_ERROR;
7288 if (!des->generateKey(*key, rng))
7290 ERROR_MSG("Could not generate DES secret key");
7291 des->recycleKey(key);
7292 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7293 return CKR_GENERAL_ERROR;
7298 // Create the secret key object using C_CreateObject
7299 const CK_ULONG maxAttribs = 32;
7300 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7301 CK_KEY_TYPE keyType = CKK_DES2;
7302 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7303 { CKA_CLASS, &objClass, sizeof(objClass) },
7304 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7305 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7306 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7308 CK_ULONG keyAttribsCount = 4;
7310 // Add the additional
7311 if (ulCount > (maxAttribs - keyAttribsCount))
7312 rv = CKR_TEMPLATE_INCONSISTENT;
7313 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7315 switch (pTemplate[i].type)
7321 case CKA_CHECK_VALUE:
7324 keyAttribs[keyAttribsCount++] = pTemplate[i];
7329 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7331 // Store the attributes that are being supplied
7334 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7335 if (osobject == NULL_PTR || !osobject->isValid()) {
7336 rv = CKR_FUNCTION_FAILED;
7337 } else if (osobject->startTransaction()) {
7340 // Common Attributes
7341 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7342 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7343 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7345 // Common Secret Key Attributes
7346 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7347 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7348 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7349 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7351 // DES Secret Key Attributes
7356 token->encrypt(key->getKeyBits(), value);
7357 token->encrypt(key->getKeyCheckValue(), kcv);
7361 value = key->getKeyBits();
7362 kcv = key->getKeyCheckValue();
7364 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7366 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7369 bOK = osobject->commitTransaction();
7371 osobject->abortTransaction();
7374 rv = CKR_FUNCTION_FAILED;
7376 rv = CKR_FUNCTION_FAILED;
7380 des->recycleKey(key);
7381 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7383 // Remove the key that may have been created already when the function fails.
7386 if (*phKey != CK_INVALID_HANDLE)
7388 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7389 handleManager->destroyObject(*phKey);
7390 if (oskey) oskey->destroyObject();
7391 *phKey = CK_INVALID_HANDLE;
7398 // Generate a DES3 secret key
7399 CK_RV SoftHSM::generateDES3
7400 (CK_SESSION_HANDLE hSession,
7401 CK_ATTRIBUTE_PTR pTemplate,
7403 CK_OBJECT_HANDLE_PTR phKey,
7407 *phKey = CK_INVALID_HANDLE;
7410 Session* session = (Session*)handleManager->getSession(hSession);
7411 if (session == NULL)
7412 return CKR_SESSION_HANDLE_INVALID;
7415 Token* token = session->getToken();
7417 return CKR_GENERAL_ERROR;
7419 // Extract desired parameter information
7420 bool checkValue = true;
7421 for (CK_ULONG i = 0; i < ulCount; i++)
7423 switch (pTemplate[i].type)
7425 case CKA_CHECK_VALUE:
7426 if (pTemplate[i].ulValueLen > 0)
7428 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7429 return CKR_ATTRIBUTE_VALUE_INVALID;
7438 // Generate the secret key
7439 DESKey* key = new DESKey(168);
7440 SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7443 ERROR_MSG("Could not get SymmetricAlgorithm");
7445 return CKR_GENERAL_ERROR;
7447 RNG* rng = CryptoFactory::i()->getRNG();
7450 ERROR_MSG("Could not get RNG");
7451 des->recycleKey(key);
7452 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7453 return CKR_GENERAL_ERROR;
7455 if (!des->generateKey(*key, rng))
7457 ERROR_MSG("Could not generate DES secret key");
7458 des->recycleKey(key);
7459 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7460 return CKR_GENERAL_ERROR;
7465 // Create the secret key object using C_CreateObject
7466 const CK_ULONG maxAttribs = 32;
7467 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7468 CK_KEY_TYPE keyType = CKK_DES3;
7469 CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7470 { CKA_CLASS, &objClass, sizeof(objClass) },
7471 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7472 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7473 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7475 CK_ULONG keyAttribsCount = 4;
7477 // Add the additional
7478 if (ulCount > (maxAttribs - keyAttribsCount))
7479 rv = CKR_TEMPLATE_INCONSISTENT;
7480 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7482 switch (pTemplate[i].type)
7488 case CKA_CHECK_VALUE:
7491 keyAttribs[keyAttribsCount++] = pTemplate[i];
7496 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7498 // Store the attributes that are being supplied
7501 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7502 if (osobject == NULL_PTR || !osobject->isValid()) {
7503 rv = CKR_FUNCTION_FAILED;
7504 } else if (osobject->startTransaction()) {
7507 // Common Attributes
7508 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7509 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7510 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7512 // Common Secret Key Attributes
7513 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7514 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7515 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7516 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7518 // DES Secret Key Attributes
7523 token->encrypt(key->getKeyBits(), value);
7524 token->encrypt(key->getKeyCheckValue(), kcv);
7528 value = key->getKeyBits();
7529 kcv = key->getKeyCheckValue();
7531 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7533 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7536 bOK = osobject->commitTransaction();
7538 osobject->abortTransaction();
7541 rv = CKR_FUNCTION_FAILED;
7543 rv = CKR_FUNCTION_FAILED;
7547 des->recycleKey(key);
7548 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7550 // Remove the key that may have been created already when the function fails.
7553 if (*phKey != CK_INVALID_HANDLE)
7555 OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7556 handleManager->destroyObject(*phKey);
7557 if (oskey) oskey->destroyObject();
7558 *phKey = CK_INVALID_HANDLE;
7565 // Generate an RSA key pair
7566 CK_RV SoftHSM::generateRSA
7567 (CK_SESSION_HANDLE hSession,
7568 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7569 CK_ULONG ulPublicKeyAttributeCount,
7570 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7571 CK_ULONG ulPrivateKeyAttributeCount,
7572 CK_OBJECT_HANDLE_PTR phPublicKey,
7573 CK_OBJECT_HANDLE_PTR phPrivateKey,
7574 CK_BBOOL isPublicKeyOnToken,
7575 CK_BBOOL isPublicKeyPrivate,
7576 CK_BBOOL isPrivateKeyOnToken,
7577 CK_BBOOL isPrivateKeyPrivate
7580 *phPublicKey = CK_INVALID_HANDLE;
7581 *phPrivateKey = CK_INVALID_HANDLE;
7584 Session* session = (Session*)handleManager->getSession(hSession);
7585 if (session == NULL)
7586 return CKR_SESSION_HANDLE_INVALID;
7589 Token* token = session->getToken();
7591 return CKR_GENERAL_ERROR;
7593 // Extract desired key information: bitlen and public exponent
7595 ByteString exponent("010001");
7596 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7598 switch (pPublicKeyTemplate[i].type)
7600 case CKA_MODULUS_BITS:
7601 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7603 INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7604 return CKR_ATTRIBUTE_VALUE_INVALID;
7606 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7608 case CKA_PUBLIC_EXPONENT:
7609 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7616 // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7618 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7619 return CKR_TEMPLATE_INCOMPLETE;
7622 // Set the parameters
7625 p.setBitLength(bitLen);
7627 // Generate key pair
7628 AsymmetricKeyPair* kp = NULL;
7629 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7631 return CKR_GENERAL_ERROR;
7632 if (!rsa->generateKeyPair(&kp, &p))
7634 ERROR_MSG("Could not generate key pair");
7635 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7636 return CKR_GENERAL_ERROR;
7639 RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7640 RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7644 // Create a public key using C_CreateObject
7647 const CK_ULONG maxAttribs = 32;
7648 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7649 CK_KEY_TYPE publicKeyType = CKK_RSA;
7650 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7651 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7652 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7653 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7654 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7656 CK_ULONG publicKeyAttribsCount = 4;
7658 // Add the additional
7659 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7660 rv = CKR_TEMPLATE_INCONSISTENT;
7661 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7663 switch (pPublicKeyTemplate[i].type)
7669 case CKA_PUBLIC_EXPONENT:
7672 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7677 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7679 // Store the attributes that are being supplied by the key generation to the object
7682 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7683 if (osobject == NULL_PTR || !osobject->isValid()) {
7684 rv = CKR_FUNCTION_FAILED;
7685 } else if (osobject->startTransaction()) {
7688 // Common Key Attributes
7689 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7690 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7691 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7693 // RSA Public Key Attributes
7695 ByteString publicExponent;
7696 if (isPublicKeyPrivate)
7698 token->encrypt(pub->getN(), modulus);
7699 token->encrypt(pub->getE(), publicExponent);
7703 modulus = pub->getN();
7704 publicExponent = pub->getE();
7706 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7707 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7710 bOK = osobject->commitTransaction();
7712 osobject->abortTransaction();
7715 rv = CKR_FUNCTION_FAILED;
7717 rv = CKR_FUNCTION_FAILED;
7721 // Create a private key using C_CreateObject
7724 const CK_ULONG maxAttribs = 32;
7725 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7726 CK_KEY_TYPE privateKeyType = CKK_RSA;
7727 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7728 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7729 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7730 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7731 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7733 CK_ULONG privateKeyAttribsCount = 4;
7734 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7735 rv = CKR_TEMPLATE_INCONSISTENT;
7736 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
7738 switch (pPrivateKeyTemplate[i].type)
7746 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
7751 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
7753 // Store the attributes that are being supplied by the key generation to the object
7756 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
7757 if (osobject == NULL_PTR || !osobject->isValid()) {
7758 rv = CKR_FUNCTION_FAILED;
7759 } else if (osobject->startTransaction()) {
7762 // Common Key Attributes
7763 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7764 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7765 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7767 // Common Private Key Attributes
7768 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7769 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7770 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7771 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7773 // RSA Private Key Attributes
7775 ByteString publicExponent;
7776 ByteString privateExponent;
7779 ByteString exponent1;
7780 ByteString exponent2;
7781 ByteString coefficient;
7782 if (isPrivateKeyPrivate)
7784 token->encrypt(priv->getN(), modulus);
7785 token->encrypt(priv->getE(), publicExponent);
7786 token->encrypt(priv->getD(), privateExponent);
7787 token->encrypt(priv->getP(), prime1);
7788 token->encrypt(priv->getQ(), prime2);
7789 token->encrypt(priv->getDP1(), exponent1);
7790 token->encrypt(priv->getDQ1(), exponent2);
7791 token->encrypt(priv->getPQ(), coefficient);
7795 modulus = priv->getN();
7796 publicExponent = priv->getE();
7797 privateExponent = priv->getD();
7798 prime1 = priv->getP();
7799 prime2 = priv->getQ();
7800 exponent1 = priv->getDP1();
7801 exponent2 = priv->getDQ1();
7802 coefficient = priv->getPQ();
7804 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7805 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7806 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
7807 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
7808 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
7809 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
7810 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
7811 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
7814 bOK = osobject->commitTransaction();
7816 osobject->abortTransaction();
7819 rv = CKR_FUNCTION_FAILED;
7821 rv = CKR_FUNCTION_FAILED;
7826 rsa->recycleKeyPair(kp);
7827 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7829 // Remove keys that may have been created already when the function fails.
7832 if (*phPrivateKey != CK_INVALID_HANDLE)
7834 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
7835 handleManager->destroyObject(*phPrivateKey);
7836 if (ospriv) ospriv->destroyObject();
7837 *phPrivateKey = CK_INVALID_HANDLE;
7840 if (*phPublicKey != CK_INVALID_HANDLE)
7842 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
7843 handleManager->destroyObject(*phPublicKey);
7844 if (ospub) ospub->destroyObject();
7845 *phPublicKey = CK_INVALID_HANDLE;
7852 // Generate a DSA key pair
7853 CK_RV SoftHSM::generateDSA
7854 (CK_SESSION_HANDLE hSession,
7855 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7856 CK_ULONG ulPublicKeyAttributeCount,
7857 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7858 CK_ULONG ulPrivateKeyAttributeCount,
7859 CK_OBJECT_HANDLE_PTR phPublicKey,
7860 CK_OBJECT_HANDLE_PTR phPrivateKey,
7861 CK_BBOOL isPublicKeyOnToken,
7862 CK_BBOOL isPublicKeyPrivate,
7863 CK_BBOOL isPrivateKeyOnToken,
7864 CK_BBOOL isPrivateKeyPrivate)
7866 *phPublicKey = CK_INVALID_HANDLE;
7867 *phPrivateKey = CK_INVALID_HANDLE;
7870 Session* session = (Session*)handleManager->getSession(hSession);
7871 if (session == NULL)
7872 return CKR_SESSION_HANDLE_INVALID;
7875 Token* token = session->getToken();
7877 return CKR_GENERAL_ERROR;
7879 // Extract desired key information
7881 ByteString subprime;
7882 ByteString generator;
7883 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7885 switch (pPublicKeyTemplate[i].type)
7888 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7891 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7894 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7901 // The parameters must be specified to be able to generate a key pair.
7902 if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
7903 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
7904 return CKR_TEMPLATE_INCOMPLETE;
7907 // Set the parameters
7913 // Generate key pair
7914 AsymmetricKeyPair* kp = NULL;
7915 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
7916 if (dsa == NULL) return CKR_GENERAL_ERROR;
7917 if (!dsa->generateKeyPair(&kp, &p))
7919 ERROR_MSG("Could not generate key pair");
7920 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
7921 return CKR_GENERAL_ERROR;
7924 DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
7925 DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
7929 // Create a public key using C_CreateObject
7932 const CK_ULONG maxAttribs = 32;
7933 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7934 CK_KEY_TYPE publicKeyType = CKK_DSA;
7935 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7936 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7937 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7938 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7939 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7941 CK_ULONG publicKeyAttribsCount = 4;
7943 // Add the additional
7944 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7945 rv = CKR_TEMPLATE_INCONSISTENT;
7946 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7948 switch (pPublicKeyTemplate[i].type)
7956 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7961 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7963 // Store the attributes that are being supplied by the key generation to the object
7966 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7967 if (osobject == NULL_PTR || !osobject->isValid()) {
7968 rv = CKR_FUNCTION_FAILED;
7969 } else if (osobject->startTransaction()) {
7972 // Common Key Attributes
7973 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7974 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
7975 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7977 // DSA Public Key Attributes
7979 if (isPublicKeyPrivate)
7981 token->encrypt(pub->getY(), value);
7985 value = pub->getY();
7987 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7990 bOK = osobject->commitTransaction();
7992 osobject->abortTransaction();
7995 rv = CKR_FUNCTION_FAILED;
7997 rv = CKR_FUNCTION_FAILED;
8001 // Create a private key using C_CreateObject
8004 const CK_ULONG maxAttribs = 32;
8005 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8006 CK_KEY_TYPE privateKeyType = CKK_DSA;
8007 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8008 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8009 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8010 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8011 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8013 CK_ULONG privateKeyAttribsCount = 4;
8014 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8015 rv = CKR_TEMPLATE_INCONSISTENT;
8016 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8018 switch (pPrivateKeyTemplate[i].type)
8026 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8031 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8033 // Store the attributes that are being supplied by the key generation to the object
8036 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8037 if (osobject == NULL_PTR || !osobject->isValid()) {
8038 rv = CKR_FUNCTION_FAILED;
8039 } else if (osobject->startTransaction()) {
8042 // Common Key Attributes
8043 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8044 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8045 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8047 // Common Private Key Attributes
8048 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8049 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8050 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8051 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8053 // DSA Private Key Attributes
8055 ByteString bSubprime;
8056 ByteString bGenerator;
8058 if (isPrivateKeyPrivate)
8060 token->encrypt(priv->getP(), bPrime);
8061 token->encrypt(priv->getQ(), bSubprime);
8062 token->encrypt(priv->getG(), bGenerator);
8063 token->encrypt(priv->getX(), bValue);
8067 bPrime = priv->getP();
8068 bSubprime = priv->getQ();
8069 bGenerator = priv->getG();
8070 bValue = priv->getX();
8072 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8073 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8074 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8075 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8078 bOK = osobject->commitTransaction();
8080 osobject->abortTransaction();
8083 rv = CKR_FUNCTION_FAILED;
8085 rv = CKR_FUNCTION_FAILED;
8090 dsa->recycleKeyPair(kp);
8091 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8093 // Remove keys that may have been created already when the function fails.
8096 if (*phPrivateKey != CK_INVALID_HANDLE)
8098 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8099 handleManager->destroyObject(*phPrivateKey);
8100 if (ospriv) ospriv->destroyObject();
8101 *phPrivateKey = CK_INVALID_HANDLE;
8104 if (*phPublicKey != CK_INVALID_HANDLE)
8106 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8107 handleManager->destroyObject(*phPublicKey);
8108 if (ospub) ospub->destroyObject();
8109 *phPublicKey = CK_INVALID_HANDLE;
8116 // Generate a DSA domain parameter set
8117 CK_RV SoftHSM::generateDSAParameters
8118 (CK_SESSION_HANDLE hSession,
8119 CK_ATTRIBUTE_PTR pTemplate,
8121 CK_OBJECT_HANDLE_PTR phKey,
8125 *phKey = CK_INVALID_HANDLE;
8128 Session* session = (Session*)handleManager->getSession(hSession);
8129 if (session == NULL)
8130 return CKR_SESSION_HANDLE_INVALID;
8133 Token* token = session->getToken();
8135 return CKR_GENERAL_ERROR;
8137 // Extract desired parameter information
8140 for (CK_ULONG i = 0; i < ulCount; i++)
8142 switch (pTemplate[i].type)
8144 case CKA_PRIME_BITS:
8145 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8147 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8148 return CKR_ATTRIBUTE_VALUE_INVALID;
8150 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8152 case CKA_SUBPRIME_BITS:
8153 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8155 INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8156 return CKR_ATTRIBUTE_VALUE_INVALID;
8158 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8165 // CKA_PRIME_BITS must be specified
8168 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8169 return CKR_TEMPLATE_INCOMPLETE;
8172 // No real choice for CKA_SUBPRIME_BITS
8174 (((bitLen >= 2048) && (qLen != 256)) ||
8175 ((bitLen < 2048) && (qLen != 160))))
8176 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8179 // Generate domain parameters
8180 AsymmetricParameters* p = NULL;
8181 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8182 if (dsa == NULL) return CKR_GENERAL_ERROR;
8183 if (!dsa->generateParameters(&p, (void *)bitLen))
8185 ERROR_MSG("Could not generate parameters");
8186 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8187 return CKR_GENERAL_ERROR;
8190 DSAParameters* params = (DSAParameters*) p;
8194 // Create the domain parameter object using C_CreateObject
8195 const CK_ULONG maxAttribs = 32;
8196 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8197 CK_KEY_TYPE keyType = CKK_DSA;
8198 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8199 { CKA_CLASS, &objClass, sizeof(objClass) },
8200 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8201 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8202 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8204 CK_ULONG paramsAttribsCount = 4;
8206 // Add the additional
8207 if (ulCount > (maxAttribs - paramsAttribsCount))
8208 rv = CKR_TEMPLATE_INCONSISTENT;
8209 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8211 switch (pTemplate[i].type)
8219 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8224 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8226 // Store the attributes that are being supplied
8229 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8230 if (osobject == NULL_PTR || !osobject->isValid()) {
8231 rv = CKR_FUNCTION_FAILED;
8232 } else if (osobject->startTransaction()) {
8235 // Common Attributes
8236 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8237 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8238 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8240 // DSA Domain Parameters Attributes
8242 ByteString subprime;
8243 ByteString generator;
8246 token->encrypt(params->getP(), prime);
8247 token->encrypt(params->getQ(), subprime);
8248 token->encrypt(params->getG(), generator);
8252 prime = params->getP();
8253 subprime = params->getQ();
8254 generator = params->getG();
8256 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8257 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8258 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8261 bOK = osobject->commitTransaction();
8263 osobject->abortTransaction();
8266 rv = CKR_FUNCTION_FAILED;
8268 rv = CKR_FUNCTION_FAILED;
8272 dsa->recycleParameters(p);
8273 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8275 // Remove parameters that may have been created already when the function fails.
8278 if (*phKey != CK_INVALID_HANDLE)
8280 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8281 handleManager->destroyObject(*phKey);
8282 if (osparams) osparams->destroyObject();
8283 *phKey = CK_INVALID_HANDLE;
8290 // Generate an EC key pair
8291 CK_RV SoftHSM::generateEC
8292 (CK_SESSION_HANDLE hSession,
8293 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8294 CK_ULONG ulPublicKeyAttributeCount,
8295 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8296 CK_ULONG ulPrivateKeyAttributeCount,
8297 CK_OBJECT_HANDLE_PTR phPublicKey,
8298 CK_OBJECT_HANDLE_PTR phPrivateKey,
8299 CK_BBOOL isPublicKeyOnToken,
8300 CK_BBOOL isPublicKeyPrivate,
8301 CK_BBOOL isPrivateKeyOnToken,
8302 CK_BBOOL isPrivateKeyPrivate)
8304 *phPublicKey = CK_INVALID_HANDLE;
8305 *phPrivateKey = CK_INVALID_HANDLE;
8308 Session* session = (Session*)handleManager->getSession(hSession);
8309 if (session == NULL)
8310 return CKR_SESSION_HANDLE_INVALID;
8313 Token* token = session->getToken();
8315 return CKR_GENERAL_ERROR;
8317 // Extract desired key information
8319 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8321 switch (pPublicKeyTemplate[i].type)
8324 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8331 // The parameters must be specified to be able to generate a key pair.
8332 if (params.size() == 0) {
8333 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8334 return CKR_TEMPLATE_INCOMPLETE;
8337 // Set the parameters
8341 // Generate key pair
8342 AsymmetricKeyPair* kp = NULL;
8343 AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8344 if (ec == NULL) return CKR_GENERAL_ERROR;
8345 if (!ec->generateKeyPair(&kp, &p))
8347 ERROR_MSG("Could not generate key pair");
8348 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8349 return CKR_GENERAL_ERROR;
8352 ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8353 ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8357 // Create a public key using C_CreateObject
8360 const CK_ULONG maxAttribs = 32;
8361 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8362 CK_KEY_TYPE publicKeyType = CKK_EC;
8363 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8364 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8365 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8366 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8367 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8369 CK_ULONG publicKeyAttribsCount = 4;
8371 // Add the additional
8372 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8373 rv = CKR_TEMPLATE_INCONSISTENT;
8374 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8376 switch (pPublicKeyTemplate[i].type)
8384 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8389 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8391 // Store the attributes that are being supplied by the key generation to the object
8394 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8395 if (osobject == NULL_PTR || !osobject->isValid()) {
8396 rv = CKR_FUNCTION_FAILED;
8397 } else if (osobject->startTransaction()) {
8400 // Common Key Attributes
8401 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8402 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8403 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8405 // EC Public Key Attributes
8407 if (isPublicKeyPrivate)
8409 token->encrypt(pub->getQ(), point);
8413 point = pub->getQ();
8415 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8418 bOK = osobject->commitTransaction();
8420 osobject->abortTransaction();
8423 rv = CKR_FUNCTION_FAILED;
8425 rv = CKR_FUNCTION_FAILED;
8429 // Create a private key using C_CreateObject
8432 const CK_ULONG maxAttribs = 32;
8433 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8434 CK_KEY_TYPE privateKeyType = CKK_EC;
8435 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8436 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8437 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8438 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8439 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8441 CK_ULONG privateKeyAttribsCount = 4;
8442 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8443 rv = CKR_TEMPLATE_INCONSISTENT;
8444 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8446 switch (pPrivateKeyTemplate[i].type)
8454 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8459 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8461 // Store the attributes that are being supplied by the key generation to the object
8464 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8465 if (osobject == NULL_PTR || !osobject->isValid()) {
8466 rv = CKR_FUNCTION_FAILED;
8467 } else if (osobject->startTransaction()) {
8470 // Common Key Attributes
8471 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8472 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8473 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8475 // Common Private Key Attributes
8476 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8477 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8478 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8479 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8481 // EC Private Key Attributes
8484 if (isPrivateKeyPrivate)
8486 token->encrypt(priv->getEC(), group);
8487 token->encrypt(priv->getD(), value);
8491 group = priv->getEC();
8492 value = priv->getD();
8494 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8495 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8498 bOK = osobject->commitTransaction();
8500 osobject->abortTransaction();
8503 rv = CKR_FUNCTION_FAILED;
8505 rv = CKR_FUNCTION_FAILED;
8510 ec->recycleKeyPair(kp);
8511 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8513 // Remove keys that may have been created already when the function fails.
8516 if (*phPrivateKey != CK_INVALID_HANDLE)
8518 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8519 handleManager->destroyObject(*phPrivateKey);
8520 if (ospriv) ospriv->destroyObject();
8521 *phPrivateKey = CK_INVALID_HANDLE;
8524 if (*phPublicKey != CK_INVALID_HANDLE)
8526 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8527 handleManager->destroyObject(*phPublicKey);
8528 if (ospub) ospub->destroyObject();
8529 *phPublicKey = CK_INVALID_HANDLE;
8536 // Generate a DH key pair
8537 CK_RV SoftHSM::generateDH
8538 (CK_SESSION_HANDLE hSession,
8539 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8540 CK_ULONG ulPublicKeyAttributeCount,
8541 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8542 CK_ULONG ulPrivateKeyAttributeCount,
8543 CK_OBJECT_HANDLE_PTR phPublicKey,
8544 CK_OBJECT_HANDLE_PTR phPrivateKey,
8545 CK_BBOOL isPublicKeyOnToken,
8546 CK_BBOOL isPublicKeyPrivate,
8547 CK_BBOOL isPrivateKeyOnToken,
8548 CK_BBOOL isPrivateKeyPrivate)
8550 *phPublicKey = CK_INVALID_HANDLE;
8551 *phPrivateKey = CK_INVALID_HANDLE;
8554 Session* session = (Session*)handleManager->getSession(hSession);
8555 if (session == NULL)
8556 return CKR_SESSION_HANDLE_INVALID;
8559 Token* token = session->getToken();
8561 return CKR_GENERAL_ERROR;
8563 // Extract desired key information
8565 ByteString generator;
8566 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8568 switch (pPublicKeyTemplate[i].type)
8571 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8574 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8581 // The parameters must be specified to be able to generate a key pair.
8582 if (prime.size() == 0 || generator.size() == 0) {
8583 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8584 return CKR_TEMPLATE_INCOMPLETE;
8587 // Extract optional bit length
8589 for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8591 switch (pPrivateKeyTemplate[i].type)
8593 case CKA_VALUE_BITS:
8594 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8601 // Set the parameters
8605 p.setXBitLength(bitLen);
8607 // Generate key pair
8608 AsymmetricKeyPair* kp = NULL;
8609 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8610 if (dh == NULL) return CKR_GENERAL_ERROR;
8611 if (!dh->generateKeyPair(&kp, &p))
8613 ERROR_MSG("Could not generate key pair");
8614 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8615 return CKR_GENERAL_ERROR;
8618 DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8619 DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8623 // Create a public key using C_CreateObject
8626 const CK_ULONG maxAttribs = 32;
8627 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8628 CK_KEY_TYPE publicKeyType = CKK_DH;
8629 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8630 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8631 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8632 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8633 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8635 CK_ULONG publicKeyAttribsCount = 4;
8637 // Add the additional
8638 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8639 rv = CKR_TEMPLATE_INCONSISTENT;
8640 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8642 switch (pPublicKeyTemplate[i].type)
8650 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8655 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8657 // Store the attributes that are being supplied by the key generation to the object
8660 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8661 if (osobject == NULL_PTR || !osobject->isValid()) {
8662 rv = CKR_FUNCTION_FAILED;
8663 } else if (osobject->startTransaction()) {
8666 // Common Key Attributes
8667 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8668 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8669 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8671 // DH Public Key Attributes
8673 if (isPublicKeyPrivate)
8675 token->encrypt(pub->getY(), value);
8679 value = pub->getY();
8681 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8684 bOK = osobject->commitTransaction();
8686 osobject->abortTransaction();
8689 rv = CKR_FUNCTION_FAILED;
8691 rv = CKR_FUNCTION_FAILED;
8695 // Create a private key using C_CreateObject
8698 const CK_ULONG maxAttribs = 32;
8699 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8700 CK_KEY_TYPE privateKeyType = CKK_DH;
8701 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8702 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8703 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8704 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8705 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8707 CK_ULONG privateKeyAttribsCount = 4;
8708 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8709 rv = CKR_TEMPLATE_INCONSISTENT;
8710 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8712 switch (pPrivateKeyTemplate[i].type)
8720 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8725 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8727 // Store the attributes that are being supplied by the key generation to the object
8730 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8731 if (osobject == NULL_PTR || !osobject->isValid()) {
8732 rv = CKR_FUNCTION_FAILED;
8733 } else if (osobject->startTransaction()) {
8736 // Common Key Attributes
8737 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8738 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8739 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8741 // Common Private Key Attributes
8742 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8743 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8744 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8745 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8747 // DH Private Key Attributes
8749 ByteString bGenerator;
8751 if (isPrivateKeyPrivate)
8753 token->encrypt(priv->getP(), bPrime);
8754 token->encrypt(priv->getG(), bGenerator);
8755 token->encrypt(priv->getX(), bValue);
8759 bPrime = priv->getP();
8760 bGenerator = priv->getG();
8761 bValue = priv->getX();
8763 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8764 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8765 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8769 bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
8773 bOK = osobject->commitTransaction();
8775 osobject->abortTransaction();
8778 rv = CKR_FUNCTION_FAILED;
8780 rv = CKR_FUNCTION_FAILED;
8785 dh->recycleKeyPair(kp);
8786 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8788 // Remove keys that may have been created already when the function fails.
8791 if (*phPrivateKey != CK_INVALID_HANDLE)
8793 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8794 handleManager->destroyObject(*phPrivateKey);
8795 if (ospriv) ospriv->destroyObject();
8796 *phPrivateKey = CK_INVALID_HANDLE;
8799 if (*phPublicKey != CK_INVALID_HANDLE)
8801 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8802 handleManager->destroyObject(*phPublicKey);
8803 if (ospub) ospub->destroyObject();
8804 *phPublicKey = CK_INVALID_HANDLE;
8811 // Generate a DH domain parameter set
8812 CK_RV SoftHSM::generateDHParameters
8813 (CK_SESSION_HANDLE hSession,
8814 CK_ATTRIBUTE_PTR pTemplate,
8816 CK_OBJECT_HANDLE_PTR phKey,
8820 *phKey = CK_INVALID_HANDLE;
8823 Session* session = (Session*)handleManager->getSession(hSession);
8824 if (session == NULL)
8825 return CKR_SESSION_HANDLE_INVALID;
8828 Token* token = session->getToken();
8830 return CKR_GENERAL_ERROR;
8832 // Extract desired parameter information
8834 for (CK_ULONG i = 0; i < ulCount; i++)
8836 switch (pTemplate[i].type)
8838 case CKA_PRIME_BITS:
8839 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8841 INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8842 return CKR_ATTRIBUTE_VALUE_INVALID;
8844 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8851 // CKA_PRIME_BITS must be specified
8854 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8855 return CKR_TEMPLATE_INCOMPLETE;
8858 // Generate domain parameters
8859 AsymmetricParameters* p = NULL;
8860 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8861 if (dh == NULL) return CKR_GENERAL_ERROR;
8862 if (!dh->generateParameters(&p, (void *)bitLen))
8864 ERROR_MSG("Could not generate parameters");
8865 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8866 return CKR_GENERAL_ERROR;
8869 DHParameters* params = (DHParameters*) p;
8873 // Create the domain parameter object using C_CreateObject
8874 const CK_ULONG maxAttribs = 32;
8875 CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8876 CK_KEY_TYPE keyType = CKK_DH;
8877 CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8878 { CKA_CLASS, &objClass, sizeof(objClass) },
8879 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8880 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8881 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8883 CK_ULONG paramsAttribsCount = 4;
8885 // Add the additional
8886 if (ulCount > (maxAttribs - paramsAttribsCount))
8887 rv = CKR_TEMPLATE_INCONSISTENT;
8888 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8890 switch (pTemplate[i].type)
8898 paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8903 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8905 // Store the attributes that are being supplied
8908 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8909 if (osobject == NULL_PTR || !osobject->isValid()) {
8910 rv = CKR_FUNCTION_FAILED;
8911 } else if (osobject->startTransaction()) {
8914 // Common Attributes
8915 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8916 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
8917 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8919 // DH Domain Parameters Attributes
8921 ByteString generator;
8924 token->encrypt(params->getP(), prime);
8925 token->encrypt(params->getG(), generator);
8929 prime = params->getP();
8930 generator = params->getG();
8932 bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8933 bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8936 bOK = osobject->commitTransaction();
8938 osobject->abortTransaction();
8941 rv = CKR_FUNCTION_FAILED;
8943 rv = CKR_FUNCTION_FAILED;
8947 dh->recycleParameters(p);
8948 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8950 // Remove parameters that may have been created already when the function fails.
8953 if (*phKey != CK_INVALID_HANDLE)
8955 OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8956 handleManager->destroyObject(*phKey);
8957 if (osparams) osparams->destroyObject();
8958 *phKey = CK_INVALID_HANDLE;
8965 // Generate a GOST key pair
8966 CK_RV SoftHSM::generateGOST
8967 (CK_SESSION_HANDLE hSession,
8968 CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8969 CK_ULONG ulPublicKeyAttributeCount,
8970 CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8971 CK_ULONG ulPrivateKeyAttributeCount,
8972 CK_OBJECT_HANDLE_PTR phPublicKey,
8973 CK_OBJECT_HANDLE_PTR phPrivateKey,
8974 CK_BBOOL isPublicKeyOnToken,
8975 CK_BBOOL isPublicKeyPrivate,
8976 CK_BBOOL isPrivateKeyOnToken,
8977 CK_BBOOL isPrivateKeyPrivate)
8979 *phPublicKey = CK_INVALID_HANDLE;
8980 *phPrivateKey = CK_INVALID_HANDLE;
8983 Session* session = (Session*)handleManager->getSession(hSession);
8984 if (session == NULL)
8985 return CKR_SESSION_HANDLE_INVALID;
8988 Token* token = session->getToken();
8990 return CKR_GENERAL_ERROR;
8992 // Extract desired key information
8993 ByteString param_3410;
8994 ByteString param_3411;
8995 ByteString param_28147;
8996 for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8998 switch (pPublicKeyTemplate[i].type)
9000 case CKA_GOSTR3410_PARAMS:
9001 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9003 case CKA_GOSTR3411_PARAMS:
9004 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9006 case CKA_GOST28147_PARAMS:
9007 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9014 // The parameters must be specified to be able to generate a key pair.
9015 if (param_3410.size() == 0 || param_3411.size() == 0) {
9016 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
9017 return CKR_TEMPLATE_INCOMPLETE;
9020 // Set the parameters
9022 p.setEC(param_3410);
9024 // Generate key pair
9025 AsymmetricKeyPair* kp = NULL;
9026 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9027 if (gost == NULL) return CKR_GENERAL_ERROR;
9028 if (!gost->generateKeyPair(&kp, &p))
9030 ERROR_MSG("Could not generate key pair");
9031 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9032 return CKR_GENERAL_ERROR;
9035 GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9036 GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9040 // Create a public key using C_CreateObject
9043 const CK_ULONG maxAttribs = 32;
9044 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9045 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9046 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9047 { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9048 { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9049 { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9050 { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9052 CK_ULONG publicKeyAttribsCount = 4;
9054 // Add the additional
9055 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9056 rv = CKR_TEMPLATE_INCONSISTENT;
9057 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9059 switch (pPublicKeyTemplate[i].type)
9067 publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9072 rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9074 // Store the attributes that are being supplied by the key generation to the object
9077 OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9078 if (osobject == NULL_PTR || !osobject->isValid()) {
9079 rv = CKR_FUNCTION_FAILED;
9080 } else if (osobject->startTransaction()) {
9083 // Common Key Attributes
9084 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9085 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9086 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9088 // EC Public Key Attributes
9090 if (isPublicKeyPrivate)
9092 token->encrypt(pub->getQ(), point);
9096 point = pub->getQ();
9098 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9101 bOK = osobject->commitTransaction();
9103 osobject->abortTransaction();
9106 rv = CKR_FUNCTION_FAILED;
9108 rv = CKR_FUNCTION_FAILED;
9112 // Create a private key using C_CreateObject
9115 const CK_ULONG maxAttribs = 32;
9116 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9117 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9118 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9119 { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9120 { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9121 { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9122 { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9124 CK_ULONG privateKeyAttribsCount = 4;
9125 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9126 rv = CKR_TEMPLATE_INCONSISTENT;
9127 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9129 switch (pPrivateKeyTemplate[i].type)
9137 privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9142 rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9144 // Store the attributes that are being supplied by the key generation to the object
9147 OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9148 if (osobject == NULL_PTR || !osobject->isValid()) {
9149 rv = CKR_FUNCTION_FAILED;
9150 } else if (osobject->startTransaction()) {
9153 // Common Key Attributes
9154 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9155 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9156 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9158 // Common Private Key Attributes
9159 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9160 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9161 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9162 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9164 // GOST Private Key Attributes
9169 if (isPrivateKeyPrivate)
9171 token->encrypt(priv->getD(), value);
9172 token->encrypt(priv->getEC(), param_a);
9173 token->encrypt(param_3411, param_b);
9174 token->encrypt(param_28147, param_c);
9178 value = priv->getD();
9179 param_a = priv->getEC();
9180 param_b = param_3411;
9181 param_c = param_28147;
9183 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9184 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9185 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9186 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9189 bOK = osobject->commitTransaction();
9191 osobject->abortTransaction();
9194 rv = CKR_FUNCTION_FAILED;
9196 rv = CKR_FUNCTION_FAILED;
9201 gost->recycleKeyPair(kp);
9202 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9204 // Remove keys that may have been created already when the function fails.
9207 if (*phPrivateKey != CK_INVALID_HANDLE)
9209 OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9210 handleManager->destroyObject(*phPrivateKey);
9211 if (ospriv) ospriv->destroyObject();
9212 *phPrivateKey = CK_INVALID_HANDLE;
9215 if (*phPublicKey != CK_INVALID_HANDLE)
9217 OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9218 handleManager->destroyObject(*phPublicKey);
9219 if (ospub) ospub->destroyObject();
9220 *phPublicKey = CK_INVALID_HANDLE;
9227 // Derive a DH secret
9228 CK_RV SoftHSM::deriveDH
9229 (CK_SESSION_HANDLE hSession,
9230 CK_MECHANISM_PTR pMechanism,
9231 CK_OBJECT_HANDLE hBaseKey,
9232 CK_ATTRIBUTE_PTR pTemplate,
9234 CK_OBJECT_HANDLE_PTR phKey,
9235 CK_KEY_TYPE keyType,
9239 *phKey = CK_INVALID_HANDLE;
9241 if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9242 if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9245 Session* session = (Session*)handleManager->getSession(hSession);
9246 if (session == NULL)
9247 return CKR_SESSION_HANDLE_INVALID;
9250 Token* token = session->getToken();
9252 return CKR_GENERAL_ERROR;
9254 // Extract desired parameter information
9256 bool checkValue = true;
9257 for (CK_ULONG i = 0; i < ulCount; i++)
9259 switch (pTemplate[i].type)
9262 INFO_MSG("CKA_VALUE must not be included");
9263 return CKR_ATTRIBUTE_READ_ONLY;
9265 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9267 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9268 return CKR_ATTRIBUTE_VALUE_INVALID;
9270 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9272 case CKA_CHECK_VALUE:
9273 if (pTemplate[i].ulValueLen > 0)
9275 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9276 return CKR_ATTRIBUTE_VALUE_INVALID;
9288 case CKK_GENERIC_SECRET:
9291 INFO_MSG("CKA_VALUE_LEN must be set");
9292 return CKR_TEMPLATE_INCOMPLETE;
9299 INFO_MSG("CKA_VALUE_LEN must not be set");
9300 return CKR_ATTRIBUTE_READ_ONLY;
9308 INFO_MSG("CKA_VALUE_LEN must not be set");
9309 return CKR_ATTRIBUTE_READ_ONLY;
9316 INFO_MSG("CKA_VALUE_LEN must not be set");
9317 return CKR_ATTRIBUTE_READ_ONLY;
9322 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9324 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9325 return CKR_ATTRIBUTE_VALUE_INVALID;
9329 return CKR_ATTRIBUTE_VALUE_INVALID;
9332 // Get the base key handle
9333 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9334 if (baseKey == NULL || !baseKey->isValid())
9335 return CKR_KEY_HANDLE_INVALID;
9337 // Get the DH algorithm handler
9338 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9340 return CKR_MECHANISM_INVALID;
9343 PrivateKey* privateKey = dh->newPrivateKey();
9344 if (privateKey == NULL)
9346 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9347 return CKR_HOST_MEMORY;
9349 if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9351 dh->recyclePrivateKey(privateKey);
9352 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9353 return CKR_GENERAL_ERROR;
9356 ByteString mechParameters;
9357 mechParameters.resize(pMechanism->ulParameterLen);
9358 memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9359 PublicKey* publicKey = dh->newPublicKey();
9360 if (publicKey == NULL)
9362 dh->recyclePrivateKey(privateKey);
9363 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9364 return CKR_HOST_MEMORY;
9366 if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9368 dh->recyclePrivateKey(privateKey);
9369 dh->recyclePublicKey(publicKey);
9370 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9371 return CKR_GENERAL_ERROR;
9374 // Derive the secret
9375 SymmetricKey* secret = NULL;
9377 if (!dh->deriveKey(&secret, publicKey, privateKey))
9378 rv = CKR_GENERAL_ERROR;
9379 dh->recyclePrivateKey(privateKey);
9380 dh->recyclePublicKey(publicKey);
9382 // Create the secret object using C_CreateObject
9383 const CK_ULONG maxAttribs = 32;
9384 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9385 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9386 { CKA_CLASS, &objClass, sizeof(objClass) },
9387 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9388 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9389 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9391 CK_ULONG secretAttribsCount = 4;
9393 // Add the additional
9394 if (ulCount > (maxAttribs - secretAttribsCount))
9395 rv = CKR_TEMPLATE_INCONSISTENT;
9396 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9398 switch (pTemplate[i].type)
9404 case CKA_CHECK_VALUE:
9407 secretAttribs[secretAttribsCount++] = pTemplate[i];
9412 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9414 // Store the attributes that are being supplied
9417 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9418 if (osobject == NULL_PTR || !osobject->isValid()) {
9419 rv = CKR_FUNCTION_FAILED;
9420 } else if (osobject->startTransaction()) {
9423 // Common Attributes
9424 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9426 // Common Secret Key Attributes
9427 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9429 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9430 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9434 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9436 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9438 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9439 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9443 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9446 // Secret Attributes
9447 ByteString secretValue = secret->getKeyBits();
9449 ByteString plainKCV;
9452 if (byteLen > secretValue.size())
9454 INFO_MSG("The derived secret is too short");
9459 // Truncate value when requested, remove from the leading end
9460 if (byteLen < secretValue.size())
9461 secretValue.split(secretValue.size() - byteLen);
9463 // Fix the odd parity for DES
9464 if (keyType == CKK_DES ||
9465 keyType == CKK_DES2 ||
9466 keyType == CKK_DES3)
9468 for (size_t i = 0; i < secretValue.size(); i++)
9470 secretValue[i] = odd_parity[secretValue[i]];
9477 case CKK_GENERIC_SECRET:
9478 secret->setBitLen(byteLen * 8);
9479 plainKCV = secret->getKeyCheckValue();
9484 secret->setBitLen(byteLen * 7);
9485 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9488 secret->setBitLen(byteLen * 8);
9489 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9498 token->encrypt(secretValue, value);
9499 token->encrypt(plainKCV, kcv);
9503 value = secretValue;
9507 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9509 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9512 bOK = osobject->commitTransaction();
9514 osobject->abortTransaction();
9517 rv = CKR_FUNCTION_FAILED;
9519 rv = CKR_FUNCTION_FAILED;
9523 dh->recycleSymmetricKey(secret);
9524 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9526 // Remove secret that may have been created already when the function fails.
9529 if (*phKey != CK_INVALID_HANDLE)
9531 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9532 handleManager->destroyObject(*phKey);
9533 if (ossecret) ossecret->destroyObject();
9534 *phKey = CK_INVALID_HANDLE;
9541 // Derive an ECDH secret
9542 CK_RV SoftHSM::deriveECDH
9543 (CK_SESSION_HANDLE hSession,
9544 CK_MECHANISM_PTR pMechanism,
9545 CK_OBJECT_HANDLE hBaseKey,
9546 CK_ATTRIBUTE_PTR pTemplate,
9548 CK_OBJECT_HANDLE_PTR phKey,
9549 CK_KEY_TYPE keyType,
9554 *phKey = CK_INVALID_HANDLE;
9556 if ((pMechanism->pParameter == NULL_PTR) ||
9557 (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9559 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9560 return CKR_MECHANISM_PARAM_INVALID;
9562 if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9564 DEBUG_MSG("kdf must be CKD_NULL");
9565 return CKR_MECHANISM_PARAM_INVALID;
9567 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9568 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9570 DEBUG_MSG("there must be no shared data");
9571 return CKR_MECHANISM_PARAM_INVALID;
9573 if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9574 (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9576 DEBUG_MSG("there must be a public data");
9577 return CKR_MECHANISM_PARAM_INVALID;
9581 Session* session = (Session*)handleManager->getSession(hSession);
9582 if (session == NULL)
9583 return CKR_SESSION_HANDLE_INVALID;
9586 Token* token = session->getToken();
9588 return CKR_GENERAL_ERROR;
9590 // Extract desired parameter information
9592 bool checkValue = true;
9593 for (CK_ULONG i = 0; i < ulCount; i++)
9595 switch (pTemplate[i].type)
9598 INFO_MSG("CKA_VALUE must not be included");
9599 return CKR_ATTRIBUTE_READ_ONLY;
9601 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9603 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9604 return CKR_ATTRIBUTE_VALUE_INVALID;
9606 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9608 case CKA_CHECK_VALUE:
9609 if (pTemplate[i].ulValueLen > 0)
9611 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9612 return CKR_ATTRIBUTE_VALUE_INVALID;
9622 // byteLen == 0 impiles return max size the ECC can derive
9625 case CKK_GENERIC_SECRET:
9629 if (byteLen != 0 && byteLen != 8)
9631 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9632 return CKR_ATTRIBUTE_VALUE_INVALID;
9638 if (byteLen != 0 && byteLen != 16)
9640 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9641 return CKR_ATTRIBUTE_VALUE_INVALID;
9646 if (byteLen != 0 && byteLen != 24)
9648 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9649 return CKR_ATTRIBUTE_VALUE_INVALID;
9654 if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9656 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9657 return CKR_ATTRIBUTE_VALUE_INVALID;
9661 return CKR_ATTRIBUTE_VALUE_INVALID;
9664 // Get the base key handle
9665 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9666 if (baseKey == NULL || !baseKey->isValid())
9667 return CKR_KEY_HANDLE_INVALID;
9669 // Get the ECDH algorithm handler
9670 AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9672 return CKR_MECHANISM_INVALID;
9675 PrivateKey* privateKey = ecdh->newPrivateKey();
9676 if (privateKey == NULL)
9678 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9679 return CKR_HOST_MEMORY;
9681 if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9683 ecdh->recyclePrivateKey(privateKey);
9684 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9685 return CKR_GENERAL_ERROR;
9688 ByteString publicData;
9689 publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9690 memcpy(&publicData[0],
9691 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9692 CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9693 PublicKey* publicKey = ecdh->newPublicKey();
9694 if (publicKey == NULL)
9696 ecdh->recyclePrivateKey(privateKey);
9697 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9698 return CKR_HOST_MEMORY;
9700 if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9702 ecdh->recyclePrivateKey(privateKey);
9703 ecdh->recyclePublicKey(publicKey);
9704 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9705 return CKR_GENERAL_ERROR;
9708 // Derive the secret
9709 SymmetricKey* secret = NULL;
9711 if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9712 rv = CKR_GENERAL_ERROR;
9713 ecdh->recyclePrivateKey(privateKey);
9714 ecdh->recyclePublicKey(publicKey);
9716 // Create the secret object using C_CreateObject
9717 const CK_ULONG maxAttribs = 32;
9718 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9719 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9720 { CKA_CLASS, &objClass, sizeof(objClass) },
9721 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9722 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9723 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9725 CK_ULONG secretAttribsCount = 4;
9727 // Add the additional
9728 if (ulCount > (maxAttribs - secretAttribsCount))
9729 rv = CKR_TEMPLATE_INCONSISTENT;
9730 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9732 switch (pTemplate[i].type)
9738 case CKA_CHECK_VALUE:
9741 secretAttribs[secretAttribsCount++] = pTemplate[i];
9746 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9748 // Store the attributes that are being supplied
9751 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9752 if (osobject == NULL_PTR || !osobject->isValid()) {
9753 rv = CKR_FUNCTION_FAILED;
9754 } else if (osobject->startTransaction()) {
9757 // Common Attributes
9758 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9760 // Common Secret Key Attributes
9761 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9763 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9764 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9768 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9770 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9772 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9773 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9777 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9780 // Secret Attributes
9781 ByteString secretValue = secret->getKeyBits();
9783 ByteString plainKCV;
9786 // For generic and AES keys:
9787 // default to return max size available.
9792 case CKK_GENERIC_SECRET:
9793 byteLen = secretValue.size();
9796 if (secretValue.size() >= 32)
9798 else if (secretValue.size() >= 24)
9805 if (byteLen > secretValue.size())
9807 INFO_MSG("The derived secret is too short");
9812 // Truncate value when requested, remove from the leading end
9813 if (byteLen < secretValue.size())
9814 secretValue.split(secretValue.size() - byteLen);
9816 // Fix the odd parity for DES
9817 if (keyType == CKK_DES ||
9818 keyType == CKK_DES2 ||
9819 keyType == CKK_DES3)
9821 for (size_t i = 0; i < secretValue.size(); i++)
9823 secretValue[i] = odd_parity[secretValue[i]];
9830 case CKK_GENERIC_SECRET:
9831 secret->setBitLen(byteLen * 8);
9832 plainKCV = secret->getKeyCheckValue();
9837 secret->setBitLen(byteLen * 7);
9838 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9841 secret->setBitLen(byteLen * 8);
9842 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9851 token->encrypt(secretValue, value);
9852 token->encrypt(plainKCV, kcv);
9856 value = secretValue;
9860 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9862 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9865 bOK = osobject->commitTransaction();
9867 osobject->abortTransaction();
9870 rv = CKR_FUNCTION_FAILED;
9872 rv = CKR_FUNCTION_FAILED;
9876 ecdh->recycleSymmetricKey(secret);
9877 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9879 // Remove secret that may have been created already when the function fails.
9882 if (*phKey != CK_INVALID_HANDLE)
9884 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9885 handleManager->destroyObject(*phKey);
9886 if (ossecret) ossecret->destroyObject();
9887 *phKey = CK_INVALID_HANDLE;
9893 return CKR_MECHANISM_INVALID;
9897 // Derive an symmetric secret
9898 CK_RV SoftHSM::deriveSymmetric
9899 (CK_SESSION_HANDLE hSession,
9900 CK_MECHANISM_PTR pMechanism,
9901 CK_OBJECT_HANDLE hBaseKey,
9902 CK_ATTRIBUTE_PTR pTemplate,
9904 CK_OBJECT_HANDLE_PTR phKey,
9905 CK_KEY_TYPE keyType,
9909 *phKey = CK_INVALID_HANDLE;
9911 if (pMechanism->pParameter == NULL_PTR)
9913 DEBUG_MSG("pParameter must be supplied");
9914 return CKR_MECHANISM_PARAM_INVALID;
9919 if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
9920 pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
9921 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9923 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9924 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9925 if (ulLen == 0 || pData == NULL_PTR)
9927 DEBUG_MSG("There must be data in the parameter");
9928 return CKR_MECHANISM_PARAM_INVALID;
9932 DEBUG_MSG("The data must be a multiple of 8 bytes long");
9933 return CKR_MECHANISM_PARAM_INVALID;
9940 else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
9941 pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
9942 pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
9944 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9945 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9946 if (length == 0 || pData == NULL_PTR)
9948 DEBUG_MSG("There must be data in the parameter");
9949 return CKR_MECHANISM_PARAM_INVALID;
9951 if (length % 8 != 0)
9953 DEBUG_MSG("The data must be a multiple of 8 bytes long");
9954 return CKR_MECHANISM_PARAM_INVALID;
9956 data.resize(length);
9961 else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
9962 pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9964 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9965 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9966 if (ulLen == 0 || pData == NULL_PTR)
9968 DEBUG_MSG("There must be data in the parameter");
9969 return CKR_MECHANISM_PARAM_INVALID;
9971 if (ulLen % 16 != 0)
9973 DEBUG_MSG("The data must be a multiple of 16 bytes long");
9974 return CKR_MECHANISM_PARAM_INVALID;
9981 else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
9982 pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
9984 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9985 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9986 if (length == 0 || pData == NULL_PTR)
9988 DEBUG_MSG("There must be data in the parameter");
9989 return CKR_MECHANISM_PARAM_INVALID;
9991 if (length % 16 != 0)
9993 DEBUG_MSG("The data must be a multiple of 16 bytes long");
9994 return CKR_MECHANISM_PARAM_INVALID;
9996 data.resize(length);
10003 DEBUG_MSG("pParameter is invalid");
10004 return CKR_MECHANISM_PARAM_INVALID;
10008 Session* session = (Session*)handleManager->getSession(hSession);
10009 if (session == NULL)
10010 return CKR_SESSION_HANDLE_INVALID;
10013 Token* token = session->getToken();
10015 return CKR_GENERAL_ERROR;
10017 // Extract desired parameter information
10018 size_t byteLen = 0;
10019 bool checkValue = true;
10020 for (CK_ULONG i = 0; i < ulCount; i++)
10022 switch (pTemplate[i].type)
10025 INFO_MSG("CKA_VALUE must not be included");
10026 return CKR_ATTRIBUTE_READ_ONLY;
10027 case CKA_VALUE_LEN:
10028 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10030 INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10031 return CKR_ATTRIBUTE_VALUE_INVALID;
10033 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10035 case CKA_CHECK_VALUE:
10036 if (pTemplate[i].ulValueLen > 0)
10038 INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10039 return CKR_ATTRIBUTE_VALUE_INVALID;
10041 checkValue = false;
10048 // Check the length
10051 case CKK_GENERIC_SECRET:
10054 INFO_MSG("CKA_VALUE_LEN must be set");
10055 return CKR_TEMPLATE_INCOMPLETE;
10062 INFO_MSG("CKA_VALUE_LEN must not be set");
10063 return CKR_ATTRIBUTE_READ_ONLY;
10071 INFO_MSG("CKA_VALUE_LEN must not be set");
10072 return CKR_ATTRIBUTE_READ_ONLY;
10079 INFO_MSG("CKA_VALUE_LEN must not be set");
10080 return CKR_ATTRIBUTE_READ_ONLY;
10085 if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10087 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10088 return CKR_ATTRIBUTE_VALUE_INVALID;
10092 return CKR_ATTRIBUTE_VALUE_INVALID;
10095 // Get the symmetric algorithm matching the mechanism
10096 SymAlgo::Type algo = SymAlgo::Unknown;
10097 SymMode::Type mode = SymMode::Unknown;
10098 bool padding = false;
10101 switch(pMechanism->mechanism) {
10103 case CKM_DES_ECB_ENCRYPT_DATA:
10104 algo = SymAlgo::DES;
10105 mode = SymMode::ECB;
10108 case CKM_DES_CBC_ENCRYPT_DATA:
10109 algo = SymAlgo::DES;
10110 mode = SymMode::CBC;
10114 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10118 case CKM_DES3_ECB_ENCRYPT_DATA:
10119 algo = SymAlgo::DES3;
10120 mode = SymMode::ECB;
10123 case CKM_DES3_CBC_ENCRYPT_DATA:
10124 algo = SymAlgo::DES3;
10125 mode = SymMode::CBC;
10129 &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10132 case CKM_AES_ECB_ENCRYPT_DATA:
10133 algo = SymAlgo::AES;
10134 mode = SymMode::ECB;
10136 case CKM_AES_CBC_ENCRYPT_DATA:
10137 algo = SymAlgo::AES;
10138 mode = SymMode::CBC;
10141 &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10145 return CKR_MECHANISM_INVALID;
10148 // Check the key handle
10149 OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10150 if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10152 SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10153 if (cipher == NULL) return CKR_MECHANISM_INVALID;
10155 SymmetricKey* secretkey = new SymmetricKey();
10157 if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10159 cipher->recycleKey(secretkey);
10160 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10161 return CKR_GENERAL_ERROR;
10164 // adjust key bit length
10165 secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10167 // Initialize encryption
10168 if (!cipher->encryptInit(secretkey, mode, iv, padding))
10170 cipher->recycleKey(secretkey);
10171 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10172 return CKR_MECHANISM_INVALID;
10176 ByteString secretValue;
10178 // Encrypt the data
10179 if (!cipher->encryptUpdate(data, secretValue))
10181 cipher->recycleKey(secretkey);
10182 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10183 return CKR_GENERAL_ERROR;
10186 // Finalize encryption
10187 ByteString encryptedFinal;
10188 if (!cipher->encryptFinal(encryptedFinal))
10190 cipher->recycleKey(secretkey);
10191 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10192 return CKR_GENERAL_ERROR;
10194 cipher->recycleKey(secretkey);
10195 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10196 secretValue += encryptedFinal;
10198 // Create the secret object using C_CreateObject
10199 const CK_ULONG maxAttribs = 32;
10200 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10201 CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10202 { CKA_CLASS, &objClass, sizeof(objClass) },
10203 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10204 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10205 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10207 CK_ULONG secretAttribsCount = 4;
10209 // Add the additional
10211 if (ulCount > (maxAttribs - secretAttribsCount))
10212 rv = CKR_TEMPLATE_INCONSISTENT;
10213 for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10215 switch (pTemplate[i].type)
10221 case CKA_CHECK_VALUE:
10224 secretAttribs[secretAttribsCount++] = pTemplate[i];
10229 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10231 // Store the attributes that are being supplied
10234 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10235 if (osobject == NULL_PTR || !osobject->isValid()) {
10236 rv = CKR_FUNCTION_FAILED;
10237 } else if (osobject->startTransaction()) {
10240 // Common Attributes
10241 bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10243 // Common Secret Key Attributes
10244 if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10246 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10247 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10251 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10253 if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10255 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10256 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10260 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10264 ByteString plainKCV;
10267 if (byteLen > secretValue.size())
10269 INFO_MSG("The derived secret is too short");
10274 // Truncate value when requested, remove from the trailing end
10275 if (byteLen < secretValue.size())
10276 secretValue.resize(byteLen);
10278 // Fix the odd parity for DES
10279 if (keyType == CKK_DES ||
10280 keyType == CKK_DES2 ||
10281 keyType == CKK_DES3)
10283 for (size_t i = 0; i < secretValue.size(); i++)
10285 secretValue[i] = odd_parity[secretValue[i]];
10290 SymmetricKey* secret = new SymmetricKey();
10291 secret->setKeyBits(secretValue);
10294 case CKK_GENERIC_SECRET:
10295 secret->setBitLen(byteLen * 8);
10296 plainKCV = secret->getKeyCheckValue();
10301 secret->setBitLen(byteLen * 7);
10302 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10305 secret->setBitLen(byteLen * 8);
10306 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10316 token->encrypt(secretValue, value);
10317 token->encrypt(plainKCV, kcv);
10321 value = secretValue;
10325 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10327 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10330 bOK = osobject->commitTransaction();
10332 osobject->abortTransaction();
10335 rv = CKR_FUNCTION_FAILED;
10337 rv = CKR_FUNCTION_FAILED;
10340 // Remove secret that may have been created already when the function fails.
10343 if (*phKey != CK_INVALID_HANDLE)
10345 OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10346 handleManager->destroyObject(*phKey);
10347 if (ossecret) ossecret->destroyObject();
10348 *phKey = CK_INVALID_HANDLE;
10355 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10357 if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10359 if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10360 if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10363 Session* session = (Session*)handleManager->getSession(hSession);
10364 if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10367 Slot* slot = session->getSlot();
10368 if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10371 Token* token = session->getToken();
10372 if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10374 // Extract information from the template that is needed to create the object.
10375 CK_OBJECT_CLASS objClass = CKO_DATA;
10376 CK_KEY_TYPE keyType = CKK_RSA;
10377 CK_CERTIFICATE_TYPE certType = CKC_X_509;
10378 CK_BBOOL isOnToken = CK_FALSE;
10379 CK_BBOOL isPrivate = CK_TRUE;
10380 bool isImplicit = false;
10381 CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10384 ERROR_MSG("Mandatory attribute not present in template");
10388 // Check user credentials
10389 rv = haveWrite(session->getState(), isOnToken, isPrivate);
10392 if (rv == CKR_USER_NOT_LOGGED_IN)
10393 INFO_MSG("User is not authorized");
10394 if (rv == CKR_SESSION_READ_ONLY)
10395 INFO_MSG("Session is read-only");
10400 // Change order of attributes
10401 const CK_ULONG maxAttribs = 32;
10402 CK_ATTRIBUTE attribs[maxAttribs];
10403 CK_ATTRIBUTE saveAttribs[maxAttribs];
10404 CK_ULONG attribsCount = 0;
10405 CK_ULONG saveAttribsCount = 0;
10406 if (ulCount > maxAttribs)
10408 return CKR_TEMPLATE_INCONSISTENT;
10410 for (CK_ULONG i=0; i < ulCount; i++)
10412 switch (pTemplate[i].type)
10414 case CKA_CHECK_VALUE:
10415 saveAttribs[saveAttribsCount++] = pTemplate[i];
10418 attribs[attribsCount++] = pTemplate[i];
10421 for (CK_ULONG i=0; i < saveAttribsCount; i++)
10423 attribs[attribsCount++] = saveAttribs[i];
10426 P11Object* p11object = NULL;
10427 rv = newP11Object(objClass,keyType,certType,&p11object);
10431 // Create the object in session or on the token
10432 OSObject *object = NULL_PTR;
10435 object = (OSObject*) token->createObject();
10439 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10442 if (object == NULL || !p11object->init(object))
10445 return CKR_GENERAL_ERROR;
10448 rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10453 if (op == OBJECT_OP_CREATE)
10455 if (objClass == CKO_PUBLIC_KEY &&
10456 (!object->startTransaction() ||
10457 !object->setAttribute(CKA_LOCAL, false) ||
10458 !object->commitTransaction()))
10460 return CKR_GENERAL_ERROR;
10463 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10464 (!object->startTransaction() ||
10465 !object->setAttribute(CKA_LOCAL, false) ||
10466 !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10467 !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10468 !object->commitTransaction()))
10470 return CKR_GENERAL_ERROR;
10476 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10478 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10484 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10486 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10487 if (token == NULL) return CKR_ARGUMENTS_BAD;
10488 if (key == NULL) return CKR_ARGUMENTS_BAD;
10490 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10491 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10493 // RSA Private Key Attributes
10494 ByteString modulus;
10495 ByteString publicExponent;
10496 ByteString privateExponent;
10499 ByteString exponent1;
10500 ByteString exponent2;
10501 ByteString coefficient;
10505 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10506 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10507 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10508 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10509 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10510 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10511 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10512 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10514 return CKR_GENERAL_ERROR;
10518 modulus = key->getByteStringValue(CKA_MODULUS);
10519 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10520 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10521 prime1 = key->getByteStringValue(CKA_PRIME_1);
10522 prime2 = key->getByteStringValue(CKA_PRIME_2);
10523 exponent1 = key->getByteStringValue(CKA_EXPONENT_1);
10524 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10525 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10528 privateKey->setN(modulus);
10529 privateKey->setE(publicExponent);
10530 privateKey->setD(privateExponent);
10531 privateKey->setP(prime1);
10532 privateKey->setQ(prime2);
10533 privateKey->setDP1(exponent1);
10534 privateKey->setDQ1(exponent2);
10535 privateKey->setPQ(coefficient);
10540 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10542 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10543 if (token == NULL) return CKR_ARGUMENTS_BAD;
10544 if (key == NULL) return CKR_ARGUMENTS_BAD;
10546 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10547 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10549 // RSA Public Key Attributes
10550 ByteString modulus;
10551 ByteString publicExponent;
10555 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10556 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10558 return CKR_GENERAL_ERROR;
10562 modulus = key->getByteStringValue(CKA_MODULUS);
10563 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10566 publicKey->setN(modulus);
10567 publicKey->setE(publicExponent);
10572 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10574 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10575 if (token == NULL) return CKR_ARGUMENTS_BAD;
10576 if (key == NULL) return CKR_ARGUMENTS_BAD;
10578 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10579 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10581 // DSA Private Key Attributes
10583 ByteString subprime;
10584 ByteString generator;
10589 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10590 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10591 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10592 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10594 return CKR_GENERAL_ERROR;
10598 prime = key->getByteStringValue(CKA_PRIME);
10599 subprime = key->getByteStringValue(CKA_SUBPRIME);
10600 generator = key->getByteStringValue(CKA_BASE);
10601 value = key->getByteStringValue(CKA_VALUE);
10604 privateKey->setP(prime);
10605 privateKey->setQ(subprime);
10606 privateKey->setG(generator);
10607 privateKey->setX(value);
10612 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10614 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10615 if (token == NULL) return CKR_ARGUMENTS_BAD;
10616 if (key == NULL) return CKR_ARGUMENTS_BAD;
10618 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10619 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10621 // DSA Public Key Attributes
10623 ByteString subprime;
10624 ByteString generator;
10629 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10630 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10631 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10632 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10634 return CKR_GENERAL_ERROR;
10638 prime = key->getByteStringValue(CKA_PRIME);
10639 subprime = key->getByteStringValue(CKA_SUBPRIME);
10640 generator = key->getByteStringValue(CKA_BASE);
10641 value = key->getByteStringValue(CKA_VALUE);
10644 publicKey->setP(prime);
10645 publicKey->setQ(subprime);
10646 publicKey->setG(generator);
10647 publicKey->setY(value);
10652 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10654 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10655 if (token == NULL) return CKR_ARGUMENTS_BAD;
10656 if (key == NULL) return CKR_ARGUMENTS_BAD;
10658 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10659 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10661 // EC Private Key Attributes
10667 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10668 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10670 return CKR_GENERAL_ERROR;
10674 group = key->getByteStringValue(CKA_EC_PARAMS);
10675 value = key->getByteStringValue(CKA_VALUE);
10678 privateKey->setEC(group);
10679 privateKey->setD(value);
10684 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10686 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10687 if (token == NULL) return CKR_ARGUMENTS_BAD;
10688 if (key == NULL) return CKR_ARGUMENTS_BAD;
10690 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10691 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10693 // EC Public Key Attributes
10699 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10700 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10702 return CKR_GENERAL_ERROR;
10706 group = key->getByteStringValue(CKA_EC_PARAMS);
10707 point = key->getByteStringValue(CKA_EC_POINT);
10710 publicKey->setEC(group);
10711 publicKey->setQ(point);
10716 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10718 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10719 if (token == NULL) return CKR_ARGUMENTS_BAD;
10720 if (key == NULL) return CKR_ARGUMENTS_BAD;
10722 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10723 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10725 // DH Private Key Attributes
10727 ByteString generator;
10732 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10733 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10734 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10736 return CKR_GENERAL_ERROR;
10740 prime = key->getByteStringValue(CKA_PRIME);
10741 generator = key->getByteStringValue(CKA_BASE);
10742 value = key->getByteStringValue(CKA_VALUE);
10745 privateKey->setP(prime);
10746 privateKey->setG(generator);
10747 privateKey->setX(value);
10752 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
10754 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10755 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10757 // Copy Domain Parameters from Private Key
10758 publicKey->setP(privateKey->getP());
10759 publicKey->setG(privateKey->getG());
10762 publicKey->setY(pubParams);
10767 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
10769 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10770 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10772 // Copy Domain Parameters from Private Key
10773 publicKey->setEC(privateKey->getEC());
10776 ByteString data = getECDHPubData(pubData);
10777 publicKey->setQ(data);
10782 // ECDH pubData can be in RAW or DER format.
10783 // Need to convert RAW as SoftHSM uses DER.
10784 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
10786 size_t len = pubData.size();
10787 size_t controlOctets = 2;
10788 if (len == 65 || len == 97 || len == 133)
10790 // Raw: Length matches the public key size of P-256, P-384, or P-521
10793 else if (len < controlOctets || pubData[0] != 0x04)
10795 // Raw: Too short or does not start with 0x04
10798 else if (pubData[1] < 0x80)
10800 // Raw: Length octet does not match remaining data length
10801 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
10805 size_t lengthOctets = pubData[1] & 0x7F;
10806 controlOctets += lengthOctets;
10808 if (controlOctets >= len)
10815 ByteString length(&pubData[2], lengthOctets);
10817 if (length.long_val() != (len - controlOctets))
10819 // Raw: Length octets does not match remaining data length
10826 if (controlOctets != 0) return pubData;
10833 header[0] = (unsigned char)0x04;
10834 header[1] = (unsigned char)(len & 0x7F);
10838 // Count significate bytes
10839 size_t bytes = sizeof(size_t);
10840 for(; bytes > 0; bytes--)
10842 size_t value = len >> ((bytes - 1) * 8);
10843 if (value & 0xFF) break;
10847 header.resize(2 + bytes);
10848 header[0] = (unsigned char)0x04;
10849 header[1] = (unsigned char)(0x80 | bytes);
10850 for (size_t i = 1; i <= bytes; i++)
10852 header[2+bytes-i] = (unsigned char) (len & 0xFF);
10857 return header + pubData;
10860 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
10862 if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10863 if (token == NULL) return CKR_ARGUMENTS_BAD;
10864 if (key == NULL) return CKR_ARGUMENTS_BAD;
10866 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10867 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10869 // GOST Private Key Attributes
10875 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10876 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10878 return CKR_GENERAL_ERROR;
10882 value = key->getByteStringValue(CKA_VALUE);
10883 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10886 privateKey->setD(value);
10887 privateKey->setEC(param);
10892 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
10894 if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10895 if (token == NULL) return CKR_ARGUMENTS_BAD;
10896 if (key == NULL) return CKR_ARGUMENTS_BAD;
10898 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10899 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10901 // GOST Public Key Attributes
10907 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
10908 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10910 return CKR_GENERAL_ERROR;
10914 point = key->getByteStringValue(CKA_VALUE);
10915 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10918 publicKey->setQ(point);
10919 publicKey->setEC(param);
10924 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
10926 if (skey == NULL) return CKR_ARGUMENTS_BAD;
10927 if (token == NULL) return CKR_ARGUMENTS_BAD;
10928 if (key == NULL) return CKR_ARGUMENTS_BAD;
10930 // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10931 bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10933 ByteString keybits;
10936 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
10937 return CKR_GENERAL_ERROR;
10941 keybits = key->getByteStringValue(CKA_VALUE);
10944 skey->setKeyBits(keybits);
10949 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
10951 AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
10954 PrivateKey* priv = rsa->newPrivateKey();
10957 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10960 if (!priv->PKCS8Decode(ber))
10962 rsa->recyclePrivateKey(priv);
10963 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10966 // RSA Private Key Attributes
10967 ByteString modulus;
10968 ByteString publicExponent;
10969 ByteString privateExponent;
10972 ByteString exponent1;
10973 ByteString exponent2;
10974 ByteString coefficient;
10977 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
10978 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
10979 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
10980 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
10981 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
10982 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
10983 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
10984 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
10988 modulus = ((RSAPrivateKey*)priv)->getN();
10989 publicExponent = ((RSAPrivateKey*)priv)->getE();
10990 privateExponent = ((RSAPrivateKey*)priv)->getD();
10991 prime1 = ((RSAPrivateKey*)priv)->getP();
10992 prime2 = ((RSAPrivateKey*)priv)->getQ();
10993 exponent1 = ((RSAPrivateKey*)priv)->getDP1();
10994 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
10995 coefficient = ((RSAPrivateKey*)priv)->getPQ();
10998 bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
10999 bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
11000 bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
11001 bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
11002 bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
11003 bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
11004 bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
11005 bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
11007 rsa->recyclePrivateKey(priv);
11008 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11013 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11015 AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
11018 PrivateKey* priv = dsa->newPrivateKey();
11021 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11024 if (!priv->PKCS8Decode(ber))
11026 dsa->recyclePrivateKey(priv);
11027 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11030 // DSA Private Key Attributes
11032 ByteString subprime;
11033 ByteString generator;
11037 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11038 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11039 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11040 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11044 prime = ((DSAPrivateKey*)priv)->getP();
11045 subprime = ((DSAPrivateKey*)priv)->getQ();
11046 generator = ((DSAPrivateKey*)priv)->getG();
11047 value = ((DSAPrivateKey*)priv)->getX();
11050 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11051 bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11052 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11053 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11055 dsa->recyclePrivateKey(priv);
11056 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11061 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11063 AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11066 PrivateKey* priv = dh->newPrivateKey();
11069 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11072 if (!priv->PKCS8Decode(ber))
11074 dh->recyclePrivateKey(priv);
11075 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11078 // DH Private Key Attributes
11080 ByteString generator;
11084 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11085 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11086 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11090 prime = ((DHPrivateKey*)priv)->getP();
11091 generator = ((DHPrivateKey*)priv)->getG();
11092 value = ((DHPrivateKey*)priv)->getX();
11095 bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11096 bOK = bOK && key->setAttribute(CKA_BASE, generator);
11097 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11099 dh->recyclePrivateKey(priv);
11100 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11105 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11107 AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11110 PrivateKey* priv = ecc->newPrivateKey();
11113 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11116 if (!priv->PKCS8Decode(ber))
11118 ecc->recyclePrivateKey(priv);
11119 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11122 // EC Private Key Attributes
11127 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11128 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11132 group = ((ECPrivateKey*)priv)->getEC();
11133 value = ((ECPrivateKey*)priv)->getD();
11136 bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11137 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11139 ecc->recyclePrivateKey(priv);
11140 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11145 bool SoftHSM::setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11147 AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
11150 PrivateKey* priv = gost->newPrivateKey();
11153 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11156 if (!priv->PKCS8Decode(ber))
11158 gost->recyclePrivateKey(priv);
11159 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11162 // GOST Private Key Attributes
11164 ByteString param_a;
11167 token->encrypt(((GOSTPrivateKey*)priv)->getD(), value);
11168 token->encrypt(((GOSTPrivateKey*)priv)->getEC(), param_a);
11172 value = ((GOSTPrivateKey*)priv)->getD();
11173 param_a = ((GOSTPrivateKey*)priv)->getEC();
11176 bOK = bOK && key->setAttribute(CKA_VALUE, value);
11177 bOK = bOK && key->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
11179 gost->recyclePrivateKey(priv);
11180 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11185 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11187 // This is a programming error
11188 if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11189 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11190 return CKR_GENERAL_ERROR;
11193 if (pMechanism->pParameter == NULL_PTR ||
11194 pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11196 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11197 return CKR_ARGUMENTS_BAD;
11200 CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11201 if (params->hashAlg != CKM_SHA_1)
11203 ERROR_MSG("hashAlg must be CKM_SHA_1");
11204 return CKR_ARGUMENTS_BAD;
11206 if (params->mgf != CKG_MGF1_SHA1)
11208 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11209 return CKR_ARGUMENTS_BAD;
11211 if (params->source != CKZ_DATA_SPECIFIED)
11213 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11214 return CKR_ARGUMENTS_BAD;
11216 if (params->pSourceData != NULL)
11218 ERROR_MSG("pSourceData must be NULL");
11219 return CKR_ARGUMENTS_BAD;
11221 if (params->ulSourceDataLen != 0)
11223 ERROR_MSG("ulSourceDataLen must be 0");
11224 return CKR_ARGUMENTS_BAD;
11229 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11230 OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11231 std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11232 if (allowed.empty()) {
11236 return allowed.find(pMechanism->mechanism) != allowed.end();