Added a new Attribute to store TPM key handle
[aaf/sshsm.git] / SoftHSMv2 / src / lib / SoftHSM.cpp
1 /*
2  * Copyright (c) 2010 SURFnet bv
3  * Copyright (c) 2010 .SE (The Internet Infrastructure Foundation)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
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.
14  *
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.
26  */
27
28 /*****************************************************************************
29  SoftHSM.cpp
30
31  The implementation of the SoftHSM's main class
32  *****************************************************************************/
33
34 #include "config.h"
35 #include "log.h"
36 #include "access.h"
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"
44 #include "AESKey.h"
45 #include "DESKey.h"
46 #include "RNG.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"
61 #include "cryptoki.h"
62 #include "SoftHSM.h"
63 #include "osmutex.h"
64 #include "SessionManager.h"
65 #include "SessionObjectStore.h"
66 #include "HandleManager.h"
67 #include "P11Objects.h"
68 #include "odd.h"
69
70 #include "HwInfra.h"
71
72 #if defined(WITH_OPENSSL)
73 #include "OSSLCryptoFactory.h"
74 #else
75 #include "BotanCryptoFactory.h"
76 #endif
77
78 #include <stdlib.h>
79
80 // Initialise the one-and-only instance
81
82 #ifdef HAVE_CXX11
83
84 std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
85 std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
86 #if defined(WITH_OPENSSL)
87 std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
88 #else
89 std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
90 #endif
91 std::unique_ptr<SoftHSM> SoftHSM::instance(nullptr);
92
93 #else
94
95 std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
96 std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
97 #if defined(WITH_OPENSSL)
98 std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
99 #else
100 std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
101 #endif
102 std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
103
104 #endif
105
106
107 static CK_RV Extract_key_handle(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, void *private_handle)
108 {
109     CK_RV rv=CK_TRUE;
110
111     // get value of the wrapped data (ck)
112     CK_ATTRIBUTE valAttrib[] = {
113       {CKA_OS_PRIVATE_HANDLE,  NULL_PTR,   sizeof(CK_ULONG)}
114     };
115
116     *(CK_ULONG*)private_handle = 0;
117     valAttrib[0].pValue = private_handle;
118
119     rv = C_GetAttributeValue(hSession, hObject, valAttrib, sizeof(valAttrib)/sizeof(CK_ATTRIBUTE));
120     if (rv != CKR_OK)
121     {
122        LOG("C_GetAttributeValue() API failed ! %lx\n", rv);
123     }
124
125     return rv;
126 }
127
128 static CK_RV newP11Object(CK_OBJECT_CLASS objClass, CK_KEY_TYPE keyType, CK_CERTIFICATE_TYPE certType, P11Object **p11object)
129 {
130         switch(objClass) {
131                 case CKO_DATA:
132                         *p11object = new P11DataObj();
133                         break;
134                 case CKO_CERTIFICATE:
135                         if (certType == CKC_X_509)
136                                 *p11object = new P11X509CertificateObj();
137                         else if (certType == CKC_OPENPGP)
138                                 *p11object = new P11OpenPGPPublicKeyObj();
139                         else
140                                 return CKR_ATTRIBUTE_VALUE_INVALID;
141                         break;
142                 case CKO_PUBLIC_KEY:
143                         if (keyType == CKK_RSA)
144                                 *p11object = new P11RSAPublicKeyObj();
145                         else if (keyType == CKK_DSA)
146                                 *p11object = new P11DSAPublicKeyObj();
147                         else if (keyType == CKK_EC)
148                                 *p11object = new P11ECPublicKeyObj();
149                         else if (keyType == CKK_DH)
150                                 *p11object = new P11DHPublicKeyObj();
151                         else if (keyType == CKK_GOSTR3410)
152                                 *p11object = new P11GOSTPublicKeyObj();
153                         else
154                                 return CKR_ATTRIBUTE_VALUE_INVALID;
155                         break;
156                 case CKO_PRIVATE_KEY:
157                         // we need to know the type too
158                         if (keyType == CKK_RSA)
159                                 *p11object = new P11RSAPrivateKeyObj();
160                         else if (keyType == CKK_DSA)
161                                 *p11object = new P11DSAPrivateKeyObj();
162                         else if (keyType == CKK_EC)
163                                 *p11object = new P11ECPrivateKeyObj();
164                         else if (keyType == CKK_DH)
165                                 *p11object = new P11DHPrivateKeyObj();
166                         else if (keyType == CKK_GOSTR3410)
167                                 *p11object = new P11GOSTPrivateKeyObj();
168                         else
169                                 return CKR_ATTRIBUTE_VALUE_INVALID;
170                         break;
171                 case CKO_SECRET_KEY:
172                         if ((keyType == CKK_GENERIC_SECRET) ||
173                             (keyType == CKK_MD5_HMAC) ||
174                             (keyType == CKK_SHA_1_HMAC) ||
175                             (keyType == CKK_SHA224_HMAC) ||
176                             (keyType == CKK_SHA256_HMAC) ||
177                             (keyType == CKK_SHA384_HMAC) ||
178                             (keyType == CKK_SHA512_HMAC))
179                         {
180                                 P11GenericSecretKeyObj* key = new P11GenericSecretKeyObj();
181                                 *p11object = key;
182                                 key->setKeyType(keyType);
183                         }
184                         else if (keyType == CKK_AES)
185                         {
186                                 *p11object = new P11AESSecretKeyObj();
187                         }
188                         else if ((keyType == CKK_DES) ||
189                                  (keyType == CKK_DES2) ||
190                                  (keyType == CKK_DES3))
191                         {
192                                 P11DESSecretKeyObj* key = new P11DESSecretKeyObj();
193                                 *p11object = key;
194                                 key->setKeyType(keyType);
195                         }
196                         else if (keyType == CKK_GOST28147)
197                         {
198                                 *p11object = new P11GOSTSecretKeyObj();
199                         }
200                         else
201                                 return CKR_ATTRIBUTE_VALUE_INVALID;
202                         break;
203                 case CKO_DOMAIN_PARAMETERS:
204                         if (keyType == CKK_DSA)
205                                 *p11object = new P11DSADomainObj();
206                         else if (keyType == CKK_DH)
207                                 *p11object = new P11DHDomainObj();
208                         else
209                                 return CKR_ATTRIBUTE_VALUE_INVALID;
210                         break;
211                 default:
212                         return CKR_ATTRIBUTE_VALUE_INVALID; // invalid value for a valid argument
213         }
214         return CKR_OK;
215 }
216
217 static CK_RV extractObjectInformation(CK_ATTRIBUTE_PTR pTemplate,
218                                       CK_ULONG ulCount,
219                                       CK_OBJECT_CLASS &objClass,
220                                       CK_KEY_TYPE &keyType,
221                                       CK_CERTIFICATE_TYPE &certType,
222                                       CK_BBOOL &isOnToken,
223                                       CK_BBOOL &isPrivate,
224                                       bool bImplicit)
225 {
226         bool bHasClass = false;
227         bool bHasKeyType = false;
228         bool bHasCertType = false;
229         bool bHasPrivate = false;
230
231         // Extract object information
232         for (CK_ULONG i = 0; i < ulCount; ++i)
233         {
234                 switch (pTemplate[i].type)
235                 {
236                         case CKA_CLASS:
237                                 if (pTemplate[i].ulValueLen == sizeof(CK_OBJECT_CLASS))
238                                 {
239                                         objClass = *(CK_OBJECT_CLASS_PTR)pTemplate[i].pValue;
240                                         bHasClass = true;
241                                 }
242                                 break;
243                         case CKA_KEY_TYPE:
244                                 if (pTemplate[i].ulValueLen == sizeof(CK_KEY_TYPE))
245                                 {
246                                         keyType = *(CK_KEY_TYPE*)pTemplate[i].pValue;
247                                         bHasKeyType = true;
248                                 }
249                                 break;
250                         case CKA_CERTIFICATE_TYPE:
251                                 if (pTemplate[i].ulValueLen == sizeof(CK_CERTIFICATE_TYPE))
252                                 {
253                                         certType = *(CK_CERTIFICATE_TYPE*)pTemplate[i].pValue;
254                                         bHasCertType = true;
255                                 }
256                                 break;
257                         case CKA_TOKEN:
258                                 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
259                                 {
260                                         isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
261                                 }
262                                 break;
263                         case CKA_PRIVATE:
264                                 if (pTemplate[i].ulValueLen == sizeof(CK_BBOOL))
265                                 {
266                                         isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
267                                         bHasPrivate = true;
268                                 }
269                                 break;
270                         default:
271                                 break;
272                 }
273         }
274
275         if (bImplicit)
276         {
277                 return CKR_OK;
278         }
279
280         if (!bHasClass)
281         {
282                 return CKR_TEMPLATE_INCOMPLETE;
283         }
284
285         bool bKeyTypeRequired = (objClass == CKO_PUBLIC_KEY || objClass == CKO_PRIVATE_KEY || objClass == CKO_SECRET_KEY);
286         if (bKeyTypeRequired && !bHasKeyType)
287         {
288                  return CKR_TEMPLATE_INCOMPLETE;
289         }
290
291         if (objClass == CKO_CERTIFICATE)
292         {
293                 if (!bHasCertType)
294                 {
295                         return CKR_TEMPLATE_INCOMPLETE;
296                 }
297                 if (!bHasPrivate)
298                 {
299                         // Change default value for certificates
300                         isPrivate = CK_FALSE;
301                 }
302         }
303
304         if (objClass == CKO_PUBLIC_KEY && !bHasPrivate)
305         {
306                 // Change default value for public keys
307                 isPrivate = CK_FALSE;
308         }
309
310         return CKR_OK;
311 }
312
313 static CK_RV newP11Object(OSObject *object, P11Object **p11object)
314 {
315         CK_OBJECT_CLASS objClass = object->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
316         CK_KEY_TYPE keyType = CKK_RSA;
317         CK_CERTIFICATE_TYPE certType = CKC_X_509;
318         if (object->attributeExists(CKA_KEY_TYPE))
319                 keyType = object->getUnsignedLongValue(CKA_KEY_TYPE, CKK_RSA);
320         if (object->attributeExists(CKA_CERTIFICATE_TYPE))
321                 certType = object->getUnsignedLongValue(CKA_CERTIFICATE_TYPE, CKC_X_509);
322         CK_RV rv = newP11Object(objClass,keyType,certType,p11object);
323         if (rv != CKR_OK)
324                 return rv;
325         if (!(*p11object)->init(object))
326                 return CKR_GENERAL_ERROR; // something went wrong that shouldn't have.
327         return CKR_OK;
328 }
329
330 #ifdef notyet
331 static CK_ATTRIBUTE bsAttribute(CK_ATTRIBUTE_TYPE type, const ByteString &value)
332 {
333         CK_ATTRIBUTE attr = {type, (CK_VOID_PTR)value.const_byte_str(), value.size() };
334         return attr;
335 }
336 #endif
337
338 /*****************************************************************************
339  Implementation of SoftHSM class specific functions
340  *****************************************************************************/
341
342 // Return the one-and-only instance
343 SoftHSM* SoftHSM::i()
344 {
345         if (!instance.get())
346         {
347                 instance.reset(new SoftHSM());
348         }
349
350         return instance.get();
351 }
352
353 void SoftHSM::reset()
354 {
355         if (instance.get())
356                 instance.reset();
357 }
358
359 // Constructor
360 SoftHSM::SoftHSM()
361 {
362         isInitialised = false;
363         isRemovable = false;
364         sessionObjectStore = NULL;
365         objectStore = NULL;
366         slotManager = NULL;
367         sessionManager = NULL;
368         handleManager = NULL;
369         isHWavailable = false;
370 }
371
372 // Destructor
373 SoftHSM::~SoftHSM()
374 {
375         if (handleManager != NULL) delete handleManager;
376         if (sessionManager != NULL) delete sessionManager;
377         if (slotManager != NULL) delete slotManager;
378         if (objectStore != NULL) delete objectStore;
379         if (sessionObjectStore != NULL) delete sessionObjectStore;
380 }
381
382 /*****************************************************************************
383  Implementation of PKCS #11 functions
384  *****************************************************************************/
385
386 // PKCS #11 initialisation function
387 CK_RV SoftHSM::C_Initialize(CK_VOID_PTR pInitArgs)
388 {
389         CK_C_INITIALIZE_ARGS_PTR args;
390
391         // Check if PKCS#11 is already initialized
392         if (isInitialised)
393         {
394                 ERROR_MSG("SoftHSM is already initialized");
395                 return CKR_CRYPTOKI_ALREADY_INITIALIZED;
396         }
397
398         // Do we have any arguments?
399         if (pInitArgs != NULL_PTR)
400         {
401                 args = (CK_C_INITIALIZE_ARGS_PTR)pInitArgs;
402
403                 // Must be set to NULL_PTR in this version of PKCS#11
404                 if (args->pReserved != NULL_PTR)
405                 {
406                         ERROR_MSG("pReserved must be set to NULL_PTR");
407                         return CKR_ARGUMENTS_BAD;
408                 }
409
410                 // Can we spawn our own threads?
411                 // if (args->flags & CKF_LIBRARY_CANT_CREATE_OS_THREADS)
412                 // {
413                 //      DEBUG_MSG("Cannot create threads if CKF_LIBRARY_CANT_CREATE_OS_THREADS is set");
414                 //      return CKR_NEED_TO_CREATE_THREADS;
415                 // }
416
417                 // Are we not supplied with mutex functions?
418                 if
419                 (
420                         args->CreateMutex == NULL_PTR &&
421                         args->DestroyMutex == NULL_PTR &&
422                         args->LockMutex == NULL_PTR &&
423                         args->UnlockMutex == NULL_PTR
424                 )
425                 {
426                         // Can we use our own mutex functions?
427                         if (args->flags & CKF_OS_LOCKING_OK)
428                         {
429                                 // Use our own mutex functions.
430                                 MutexFactory::i()->setCreateMutex(OSCreateMutex);
431                                 MutexFactory::i()->setDestroyMutex(OSDestroyMutex);
432                                 MutexFactory::i()->setLockMutex(OSLockMutex);
433                                 MutexFactory::i()->setUnlockMutex(OSUnlockMutex);
434                                 MutexFactory::i()->enable();
435                         }
436                         else
437                         {
438                                 // The external application is not using threading
439                                 MutexFactory::i()->disable();
440                         }
441                 }
442                 else
443                 {
444                         // We must have all mutex functions
445                         if
446                         (
447                                 args->CreateMutex == NULL_PTR ||
448                                 args->DestroyMutex == NULL_PTR ||
449                                 args->LockMutex == NULL_PTR ||
450                                 args->UnlockMutex == NULL_PTR
451                         )
452                         {
453                                 ERROR_MSG("Not all mutex functions are supplied");
454                                 return CKR_ARGUMENTS_BAD;
455                         }
456
457                         // We could use our own mutex functions if the flag is set,
458                         // but we use the external functions in both cases.
459
460                         // Load the external mutex functions
461                         MutexFactory::i()->setCreateMutex(args->CreateMutex);
462                         MutexFactory::i()->setDestroyMutex(args->DestroyMutex);
463                         MutexFactory::i()->setLockMutex(args->LockMutex);
464                         MutexFactory::i()->setUnlockMutex(args->UnlockMutex);
465                         MutexFactory::i()->enable();
466                 }
467         }
468         else
469         {
470                 // No concurrent access by multiple threads
471                 MutexFactory::i()->disable();
472         }
473
474         // Initiate SecureMemoryRegistry
475         if (SecureMemoryRegistry::i() == NULL)
476         {
477                 ERROR_MSG("Could not load the SecureMemoryRegistry");
478                 return CKR_GENERAL_ERROR;
479         }
480
481         // Build the CryptoFactory
482         if (CryptoFactory::i() == NULL)
483         {
484                 ERROR_MSG("Could not load the CryptoFactory");
485                 return CKR_GENERAL_ERROR;
486         }
487
488 #ifdef WITH_FIPS
489         // Check the FIPS status
490         if (!CryptoFactory::i()->getFipsSelfTestStatus())
491         {
492                 ERROR_MSG("The FIPS self test failed");
493                 return CKR_FIPS_SELF_TEST_FAILED;
494         }
495 #endif
496
497         // (Re)load the configuration
498         if (!Configuration::i()->reload(SimpleConfigLoader::i()))
499         {
500                 ERROR_MSG("Could not load the configuration");
501                 return CKR_GENERAL_ERROR;
502         }
503
504         // Configure the log level
505         if (!setLogLevel(Configuration::i()->getString("log.level", DEFAULT_LOG_LEVEL)))
506         {
507                 ERROR_MSG("Could not set the log level");
508                 return CKR_GENERAL_ERROR;
509         }
510
511         // Configure object store storage backend used by all tokens.
512         if (!ObjectStoreToken::selectBackend(Configuration::i()->getString("objectstore.backend", DEFAULT_OBJECTSTORE_BACKEND)))
513         {
514                 ERROR_MSG("Could not set the storage backend");
515                 return CKR_GENERAL_ERROR;
516         }
517
518         sessionObjectStore = new SessionObjectStore();
519
520         // Load the object store
521         objectStore = new ObjectStore(Configuration::i()->getString("directories.tokendir", DEFAULT_TOKENDIR));
522         if (!objectStore->isValid())
523         {
524                 WARNING_MSG("Could not load the object store");
525                 delete objectStore;
526                 objectStore = NULL;
527                 delete sessionObjectStore;
528                 sessionObjectStore = NULL;
529                 return CKR_GENERAL_ERROR;
530         }
531
532         isRemovable = Configuration::i()->getBool("slots.removable", false);
533
534         // Load the slot manager
535         slotManager = new SlotManager(objectStore);
536
537         // Load the session manager
538         sessionManager = new SessionManager();
539
540         // Load the handle manager
541         handleManager = new HandleManager();
542
543         // Set the state to initialised
544         isInitialised = true;
545
546     if(prepareHWPlugin())
547     {
548        printf("HW plugin NOT available to use ! \n");
549        isHWavailable = false;
550     }
551     else
552     {
553        printf("HW plugin available and initialized ! \n");
554        isHWavailable = true;
555    }
556
557         return CKR_OK;
558 }
559
560 // PKCS #11 finalisation function
561 CK_RV SoftHSM::C_Finalize(CK_VOID_PTR pReserved)
562 {
563         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
564
565         // Must be set to NULL_PTR in this version of PKCS#11
566         if (pReserved != NULL_PTR) return CKR_ARGUMENTS_BAD;
567
568         if (handleManager != NULL) delete handleManager;
569         handleManager = NULL;
570         if (sessionManager != NULL) delete sessionManager;
571         sessionManager = NULL;
572         if (slotManager != NULL) delete slotManager;
573         slotManager = NULL;
574         if (objectStore != NULL) delete objectStore;
575         objectStore = NULL;
576         if (sessionObjectStore != NULL) delete sessionObjectStore;
577         sessionObjectStore = NULL;
578         CryptoFactory::reset();
579         SecureMemoryRegistry::reset();
580
581         isInitialised = false;
582
583         SoftHSM::reset();
584         return CKR_OK;
585 }
586
587 // Return information about the PKCS #11 module
588 CK_RV SoftHSM::C_GetInfo(CK_INFO_PTR pInfo)
589 {
590         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
591         if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
592
593         pInfo->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
594         pInfo->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
595         memset(pInfo->manufacturerID, ' ', 32);
596         memcpy(pInfo->manufacturerID, "SoftHSM", 7);
597         pInfo->flags = 0;
598         memset(pInfo->libraryDescription, ' ', 32);
599 #ifdef WITH_FIPS
600         memcpy(pInfo->libraryDescription, "Implementation of PKCS11+FIPS", 29);
601 #else
602         memcpy(pInfo->libraryDescription, "Implementation of PKCS11", 24);
603 #endif
604         pInfo->libraryVersion.major = VERSION_MAJOR;
605         pInfo->libraryVersion.minor = VERSION_MINOR;
606
607         return CKR_OK;
608 }
609
610 // Return a list of available slots
611 CK_RV SoftHSM::C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount)
612 {
613         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
614
615         return slotManager->getSlotList(objectStore, tokenPresent, pSlotList, pulCount);
616 }
617
618 // Return information about a slot
619 CK_RV SoftHSM::C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
620 {
621         CK_RV rv;
622         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
623
624         Slot* slot = slotManager->getSlot(slotID);
625         if (slot == NULL)
626         {
627                 return CKR_SLOT_ID_INVALID;
628         }
629
630         rv = slot->getSlotInfo(pInfo);
631         if (rv != CKR_OK) {
632                 return rv;
633         }
634
635         if (isRemovable) {
636                 pInfo->flags |= CKF_REMOVABLE_DEVICE;
637         }
638
639         return CKR_OK;
640 }
641
642 // Return information about a token in a slot
643 CK_RV SoftHSM::C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
644 {
645         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
646
647         Slot* slot = slotManager->getSlot(slotID);
648         if (slot == NULL)
649         {
650                 return CKR_SLOT_ID_INVALID;
651         }
652
653         Token* token = slot->getToken();
654         if (token == NULL)
655         {
656                 return CKR_TOKEN_NOT_PRESENT;
657         }
658
659         return token->getTokenInfo(pInfo);
660 }
661
662 // Return the list of supported mechanisms for a given slot
663 CK_RV SoftHSM::C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount)
664 {
665         // A list with the supported mechanisms
666         CK_ULONG nrSupportedMechanisms = 61;
667 #ifdef WITH_ECC
668         nrSupportedMechanisms += 3;
669 #endif
670 #ifdef WITH_FIPS
671         nrSupportedMechanisms -= 9;
672 #endif
673 #ifdef WITH_GOST
674         nrSupportedMechanisms += 5;
675 #endif
676 #ifdef HAVE_AES_KEY_WRAP_PAD
677         nrSupportedMechanisms += 1;
678 #endif
679 #ifdef WITH_RAW_PSS
680         nrSupportedMechanisms += 1; // CKM_RSA_PKCS_PSS
681 #endif
682 #ifdef WITH_AES_GCM
683         nrSupportedMechanisms += 1;
684 #endif
685
686         CK_MECHANISM_TYPE supportedMechanisms[] =
687         {
688 #ifndef WITH_FIPS
689                 CKM_MD5,
690 #endif
691                 CKM_SHA_1,
692                 CKM_SHA224,
693                 CKM_SHA256,
694                 CKM_SHA384,
695                 CKM_SHA512,
696 #ifndef WITH_FIPS
697                 CKM_MD5_HMAC,
698 #endif
699                 CKM_SHA_1_HMAC,
700                 CKM_SHA224_HMAC,
701                 CKM_SHA256_HMAC,
702                 CKM_SHA384_HMAC,
703                 CKM_SHA512_HMAC,
704                 CKM_RSA_PKCS_KEY_PAIR_GEN,
705                 CKM_RSA_PKCS,
706                 CKM_RSA_X_509,
707 #ifndef WITH_FIPS
708                 CKM_MD5_RSA_PKCS,
709 #endif
710                 CKM_SHA1_RSA_PKCS,
711                 CKM_RSA_PKCS_OAEP,
712                 CKM_SHA224_RSA_PKCS,
713                 CKM_SHA256_RSA_PKCS,
714                 CKM_SHA384_RSA_PKCS,
715                 CKM_SHA512_RSA_PKCS,
716 #ifdef WITH_RAW_PSS
717                 CKM_RSA_PKCS_PSS,
718 #endif
719                 CKM_SHA1_RSA_PKCS_PSS,
720                 CKM_SHA224_RSA_PKCS_PSS,
721                 CKM_SHA256_RSA_PKCS_PSS,
722                 CKM_SHA384_RSA_PKCS_PSS,
723                 CKM_SHA512_RSA_PKCS_PSS,
724 #ifndef WITH_FIPS
725                 CKM_DES_KEY_GEN,
726 #endif
727                 CKM_DES2_KEY_GEN,
728                 CKM_DES3_KEY_GEN,
729 #ifndef WITH_FIPS
730                 CKM_DES_ECB,
731                 CKM_DES_CBC,
732                 CKM_DES_CBC_PAD,
733                 CKM_DES_ECB_ENCRYPT_DATA,
734                 CKM_DES_CBC_ENCRYPT_DATA,
735 #endif
736                 CKM_DES3_ECB,
737                 CKM_DES3_CBC,
738                 CKM_DES3_CBC_PAD,
739                 CKM_DES3_ECB_ENCRYPT_DATA,
740                 CKM_DES3_CBC_ENCRYPT_DATA,
741                 CKM_DES3_CMAC,
742                 CKM_AES_KEY_GEN,
743                 CKM_AES_ECB,
744                 CKM_AES_CBC,
745                 CKM_AES_CBC_PAD,
746                 CKM_AES_CTR,
747 #ifdef WITH_AES_GCM
748                 CKM_AES_GCM,
749 #endif
750                 CKM_AES_KEY_WRAP,
751 #ifdef HAVE_AES_KEY_WRAP_PAD
752                 CKM_AES_KEY_WRAP_PAD,
753 #endif
754                 CKM_AES_ECB_ENCRYPT_DATA,
755                 CKM_AES_CBC_ENCRYPT_DATA,
756                 CKM_AES_CMAC,
757                 CKM_DSA_PARAMETER_GEN,
758                 CKM_DSA_KEY_PAIR_GEN,
759                 CKM_DSA,
760                 CKM_DSA_SHA1,
761                 CKM_DSA_SHA224,
762                 CKM_DSA_SHA256,
763                 CKM_DSA_SHA384,
764                 CKM_DSA_SHA512,
765                 CKM_DH_PKCS_KEY_PAIR_GEN,
766                 CKM_DH_PKCS_PARAMETER_GEN,
767                 CKM_DH_PKCS_DERIVE,
768 #ifdef WITH_ECC
769                 CKM_EC_KEY_PAIR_GEN,
770                 CKM_ECDSA,
771                 CKM_ECDH1_DERIVE,
772 #endif
773 #ifdef WITH_GOST
774                 CKM_GOSTR3411,
775                 CKM_GOSTR3411_HMAC,
776                 CKM_GOSTR3410_KEY_PAIR_GEN,
777                 CKM_GOSTR3410,
778                 CKM_GOSTR3410_WITH_GOSTR3411
779 #endif
780         };
781
782         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
783         if (pulCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
784
785         Slot* slot = slotManager->getSlot(slotID);
786         if (slot == NULL)
787         {
788                 return CKR_SLOT_ID_INVALID;
789         }
790
791         if (pMechanismList == NULL_PTR)
792         {
793                 *pulCount = nrSupportedMechanisms;
794
795                 return CKR_OK;
796         }
797
798         if (*pulCount < nrSupportedMechanisms)
799         {
800                 *pulCount = nrSupportedMechanisms;
801
802                 return CKR_BUFFER_TOO_SMALL;
803         }
804
805         *pulCount = nrSupportedMechanisms;
806
807         for (CK_ULONG i = 0; i < nrSupportedMechanisms; i ++)
808         {
809                 pMechanismList[i] = supportedMechanisms[i];
810         }
811
812         return CKR_OK;
813 }
814
815 // Return more information about a mechanism for a given slot
816 CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo)
817 {
818         unsigned long rsaMinSize, rsaMaxSize;
819         unsigned long dsaMinSize, dsaMaxSize;
820         unsigned long dhMinSize, dhMaxSize;
821 #ifdef WITH_ECC
822         unsigned long ecdsaMinSize, ecdsaMaxSize;
823         unsigned long ecdhMinSize, ecdhMaxSize;
824 #endif
825
826         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
827         if (pInfo == NULL_PTR) return CKR_ARGUMENTS_BAD;
828
829         Slot* slot = slotManager->getSlot(slotID);
830         if (slot == NULL)
831         {
832                 return CKR_SLOT_ID_INVALID;
833         }
834
835         AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
836         if (rsa != NULL)
837         {
838                 rsaMinSize = rsa->getMinKeySize();
839                 rsaMaxSize = rsa->getMaxKeySize();
840         }
841         else
842         {
843                 return CKR_GENERAL_ERROR;
844         }
845         CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
846
847         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
848         if (dsa != NULL)
849         {
850                 dsaMinSize = dsa->getMinKeySize();
851                 // Limitation in PKCS#11
852                 if (dsaMinSize < 512)
853                 {
854                         dsaMinSize = 512;
855                 }
856
857                 dsaMaxSize = dsa->getMaxKeySize();
858                 // Limitation in PKCS#11
859                 if (dsaMaxSize > 1024)
860                 {
861                         dsaMaxSize = 1024;
862                 }
863         }
864         else
865         {
866                 return CKR_GENERAL_ERROR;
867         }
868         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
869
870         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
871         if (dh != NULL)
872         {
873                 dhMinSize = dh->getMinKeySize();
874                 dhMaxSize = dh->getMaxKeySize();
875         }
876         else
877         {
878                 return CKR_GENERAL_ERROR;
879         }
880         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
881
882 #ifdef WITH_ECC
883         AsymmetricAlgorithm* ecdsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
884         if (ecdsa != NULL)
885         {
886                 ecdsaMinSize = ecdsa->getMinKeySize();
887                 ecdsaMaxSize = ecdsa->getMaxKeySize();
888         }
889         else
890         {
891                 return CKR_GENERAL_ERROR;
892         }
893         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdsa);
894
895         AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
896         if (ecdh != NULL)
897         {
898                 ecdhMinSize = ecdh->getMinKeySize();
899                 ecdhMaxSize = ecdh->getMaxKeySize();
900         }
901         else
902         {
903                 return CKR_GENERAL_ERROR;
904         }
905         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
906 #endif
907
908         switch (type)
909         {
910 #ifndef WITH_FIPS
911                 case CKM_MD5:
912 #endif
913                 case CKM_SHA_1:
914                 case CKM_SHA224:
915                 case CKM_SHA256:
916                 case CKM_SHA384:
917                 case CKM_SHA512:
918                         // Key size is not in use
919                         pInfo->ulMinKeySize = 0;
920                         pInfo->ulMaxKeySize = 0;
921                         pInfo->flags = CKF_DIGEST;
922                         break;
923 #ifndef WITH_FIPS
924                 case CKM_MD5_HMAC:
925                         pInfo->ulMinKeySize = 16;
926                         pInfo->ulMaxKeySize = 512;
927                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
928                         break;
929 #endif
930                 case CKM_SHA_1_HMAC:
931                         pInfo->ulMinKeySize = 20;
932                         pInfo->ulMaxKeySize = 512;
933                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
934                         break;
935                 case CKM_SHA224_HMAC:
936                         pInfo->ulMinKeySize = 28;
937                         pInfo->ulMaxKeySize = 512;
938                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
939                         break;
940                 case CKM_SHA256_HMAC:
941                         pInfo->ulMinKeySize = 32;
942                         pInfo->ulMaxKeySize = 512;
943                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
944                         break;
945                 case CKM_SHA384_HMAC:
946                         pInfo->ulMinKeySize = 48;
947                         pInfo->ulMaxKeySize = 512;
948                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
949                         break;
950                 case CKM_SHA512_HMAC:
951                         pInfo->ulMinKeySize = 64;
952                         pInfo->ulMaxKeySize = 512;
953                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
954                         break;
955                 case CKM_RSA_PKCS_KEY_PAIR_GEN:
956                         pInfo->ulMinKeySize = rsaMinSize;
957                         pInfo->ulMaxKeySize = rsaMaxSize;
958                         pInfo->flags = CKF_GENERATE_KEY_PAIR;
959                         break;
960                 case CKM_RSA_PKCS:
961                         pInfo->ulMinKeySize = rsaMinSize;
962                         pInfo->ulMaxKeySize = rsaMaxSize;
963                         pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
964                         break;
965                 case CKM_RSA_X_509:
966                         pInfo->ulMinKeySize = rsaMinSize;
967                         pInfo->ulMaxKeySize = rsaMaxSize;
968                         pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_ENCRYPT | CKF_DECRYPT;
969                         break;
970 #ifndef WITH_FIPS
971                 case CKM_MD5_RSA_PKCS:
972 #endif
973                 case CKM_SHA1_RSA_PKCS:
974                 case CKM_SHA224_RSA_PKCS:
975                 case CKM_SHA256_RSA_PKCS:
976                 case CKM_SHA384_RSA_PKCS:
977                 case CKM_SHA512_RSA_PKCS:
978 #ifdef WITH_RAW_PSS
979                 case CKM_RSA_PKCS_PSS:
980 #endif
981                 case CKM_SHA1_RSA_PKCS_PSS:
982                 case CKM_SHA224_RSA_PKCS_PSS:
983                 case CKM_SHA256_RSA_PKCS_PSS:
984                 case CKM_SHA384_RSA_PKCS_PSS:
985                 case CKM_SHA512_RSA_PKCS_PSS:
986                         pInfo->ulMinKeySize = rsaMinSize;
987                         pInfo->ulMaxKeySize = rsaMaxSize;
988                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
989                         break;
990                 case CKM_RSA_PKCS_OAEP:
991                         pInfo->ulMinKeySize = rsaMinSize;
992                         pInfo->ulMaxKeySize = rsaMaxSize;
993                         pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP;
994                         break;
995 #ifndef WITH_FIPS
996                 case CKM_DES_KEY_GEN:
997 #endif
998                 case CKM_DES2_KEY_GEN:
999                 case CKM_DES3_KEY_GEN:
1000                         // Key size is not in use
1001                         pInfo->ulMinKeySize = 0;
1002                         pInfo->ulMaxKeySize = 0;
1003                         pInfo->flags = CKF_GENERATE;
1004                         break;
1005 #ifndef WITH_FIPS
1006                 case CKM_DES_ECB:
1007                 case CKM_DES_CBC:
1008                 case CKM_DES_CBC_PAD:
1009 #endif
1010                 case CKM_DES3_ECB:
1011                 case CKM_DES3_CBC:
1012                 case CKM_DES3_CBC_PAD:
1013                         // Key size is not in use
1014                         pInfo->ulMinKeySize = 0;
1015                         pInfo->ulMaxKeySize = 0;
1016                         pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1017                         break;
1018                 case CKM_DES3_CMAC:
1019                         // Key size is not in use
1020                         pInfo->ulMinKeySize = 0;
1021                         pInfo->ulMaxKeySize = 0;
1022                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1023                         break;
1024                 case CKM_AES_KEY_GEN:
1025                         pInfo->ulMinKeySize = 16;
1026                         pInfo->ulMaxKeySize = 32;
1027                         pInfo->flags = CKF_GENERATE;
1028                         break;
1029                 case CKM_AES_ECB:
1030                 case CKM_AES_CBC:
1031                 case CKM_AES_CBC_PAD:
1032                 case CKM_AES_CTR:
1033 #ifdef WITH_AES_GCM
1034                 case CKM_AES_GCM:
1035 #endif
1036                         pInfo->ulMinKeySize = 16;
1037                         pInfo->ulMaxKeySize = 32;
1038                         pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT;
1039                         break;
1040                 case CKM_AES_KEY_WRAP:
1041                         pInfo->ulMinKeySize = 16;
1042                         pInfo->ulMaxKeySize = 0x80000000;
1043                         pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1044                         break;
1045 #ifdef HAVE_AES_KEY_WRAP_PAD
1046                 case CKM_AES_KEY_WRAP_PAD:
1047                         pInfo->ulMinKeySize = 1;
1048                         pInfo->ulMaxKeySize = 0x80000000;
1049                         pInfo->flags = CKF_WRAP | CKF_UNWRAP;
1050                         break;
1051 #endif
1052 #ifndef WITH_FIPS
1053                 case CKM_DES_ECB_ENCRYPT_DATA:
1054                 case CKM_DES_CBC_ENCRYPT_DATA:
1055 #endif
1056                 case CKM_DES3_ECB_ENCRYPT_DATA:
1057                 case CKM_DES3_CBC_ENCRYPT_DATA:
1058                 case CKM_AES_ECB_ENCRYPT_DATA:
1059                 case CKM_AES_CBC_ENCRYPT_DATA:
1060                         // Key size is not in use
1061                         pInfo->ulMinKeySize = 0;
1062                         pInfo->ulMaxKeySize = 0;
1063                         pInfo->flags = CKF_DERIVE;
1064                         break;
1065                 case CKM_AES_CMAC:
1066                         pInfo->ulMinKeySize = 16;
1067                         pInfo->ulMaxKeySize = 32;
1068                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1069                         break;
1070                 case CKM_DSA_PARAMETER_GEN:
1071                         pInfo->ulMinKeySize = dsaMinSize;
1072                         pInfo->ulMaxKeySize = dsaMaxSize;
1073                         pInfo->flags = CKF_GENERATE;
1074                         break;
1075                 case CKM_DSA_KEY_PAIR_GEN:
1076                         pInfo->ulMinKeySize = dsaMinSize;
1077                         pInfo->ulMaxKeySize = dsaMaxSize;
1078                         pInfo->flags = CKF_GENERATE_KEY_PAIR;
1079                         break;
1080                 case CKM_DSA:
1081                 case CKM_DSA_SHA1:
1082                 case CKM_DSA_SHA224:
1083                 case CKM_DSA_SHA256:
1084                 case CKM_DSA_SHA384:
1085                 case CKM_DSA_SHA512:
1086                         pInfo->ulMinKeySize = dsaMinSize;
1087                         pInfo->ulMaxKeySize = dsaMaxSize;
1088                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1089                         break;
1090                 case CKM_DH_PKCS_KEY_PAIR_GEN:
1091                         pInfo->ulMinKeySize = dhMinSize;
1092                         pInfo->ulMaxKeySize = dhMaxSize;
1093                         pInfo->flags = CKF_GENERATE_KEY_PAIR;
1094                         break;
1095                 case CKM_DH_PKCS_PARAMETER_GEN:
1096                         pInfo->ulMinKeySize = dhMinSize;
1097                         pInfo->ulMaxKeySize = dhMaxSize;
1098                         pInfo->flags = CKF_GENERATE;
1099                         break;
1100                 case CKM_DH_PKCS_DERIVE:
1101                         pInfo->ulMinKeySize = dhMinSize;
1102                         pInfo->ulMaxKeySize = dhMaxSize;
1103                         pInfo->flags = CKF_DERIVE;
1104                         break;
1105 #ifdef WITH_ECC
1106                 case CKM_EC_KEY_PAIR_GEN:
1107                         pInfo->ulMinKeySize = ecdsaMinSize;
1108                         pInfo->ulMaxKeySize = ecdsaMaxSize;
1109 #define CKF_EC_COMMOM   (CKF_EC_F_P | CKF_EC_NAMEDCURVE | CKF_EC_UNCOMPRESS)
1110                         pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
1111                         break;
1112                 case CKM_ECDSA:
1113                         pInfo->ulMinKeySize = ecdsaMinSize;
1114                         pInfo->ulMaxKeySize = ecdsaMaxSize;
1115                         pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
1116                         break;
1117                 case CKM_ECDH1_DERIVE:
1118                         pInfo->ulMinKeySize = ecdhMinSize;
1119                         pInfo->ulMaxKeySize = ecdhMaxSize;
1120                         pInfo->flags = CKF_DERIVE;
1121                         break;
1122 #endif
1123 #ifdef WITH_GOST
1124                 case CKM_GOSTR3411:
1125                         // Key size is not in use
1126                         pInfo->ulMinKeySize = 0;
1127                         pInfo->ulMaxKeySize = 0;
1128                         pInfo->flags = CKF_DIGEST;
1129                         break;
1130                 case CKM_GOSTR3411_HMAC:
1131                         // Key size is not in use
1132                         pInfo->ulMinKeySize = 32;
1133                         pInfo->ulMaxKeySize = 512;
1134                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1135                         break;
1136                 case CKM_GOSTR3410_KEY_PAIR_GEN:
1137                         // Key size is not in use
1138                         pInfo->ulMinKeySize = 0;
1139                         pInfo->ulMaxKeySize = 0;
1140                         pInfo->flags = CKF_GENERATE_KEY_PAIR;
1141                         break;
1142                 case CKM_GOSTR3410:
1143                         // Key size is not in use
1144                         pInfo->ulMinKeySize = 0;
1145                         pInfo->ulMaxKeySize = 0;
1146                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1147                         break;
1148                 case CKM_GOSTR3410_WITH_GOSTR3411:
1149                         // Key size is not in use
1150                         pInfo->ulMinKeySize = 0;
1151                         pInfo->ulMaxKeySize = 0;
1152                         pInfo->flags = CKF_SIGN | CKF_VERIFY;
1153                         break;
1154 #endif
1155                 default:
1156                         DEBUG_MSG("The selected mechanism is not supported");
1157                         return CKR_MECHANISM_INVALID;
1158                         break;
1159         }
1160
1161         return CKR_OK;
1162 }
1163
1164 // Initialise the token in the specified slot
1165 CK_RV SoftHSM::C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel)
1166 {
1167         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1168
1169         Slot* slot = slotManager->getSlot(slotID);
1170         if (slot == NULL)
1171         {
1172                 return CKR_SLOT_ID_INVALID;
1173         }
1174
1175         // Check if any session is open with this token.
1176         if (sessionManager->haveSession(slotID))
1177         {
1178                 return CKR_SESSION_EXISTS;
1179         }
1180
1181         // Check the PIN
1182         if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1183         if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_INCORRECT;
1184
1185         ByteString soPIN(pPin, ulPinLen);
1186
1187         return slot->initToken(soPIN, pLabel);
1188 }
1189
1190 // Initialise the user PIN
1191 CK_RV SoftHSM::C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1192 {
1193         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1194
1195         // Get the session
1196         Session* session = (Session*)handleManager->getSession(hSession);
1197         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1198
1199         // The SO must be logged in
1200         if (session->getState() != CKS_RW_SO_FUNCTIONS) return CKR_USER_NOT_LOGGED_IN;
1201
1202         // Get the token
1203         Token* token = session->getToken();
1204         if (token == NULL) return CKR_GENERAL_ERROR;
1205
1206         // Check the PIN
1207         if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1208         if (ulPinLen < MIN_PIN_LEN || ulPinLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1209
1210         ByteString userPIN(pPin, ulPinLen);
1211
1212         return token->initUserPIN(userPIN);
1213 }
1214
1215 // Change the PIN
1216 CK_RV SoftHSM::C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
1217 {
1218         CK_RV rv = CKR_OK;
1219
1220         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1221
1222         // Get the session
1223         Session* session = (Session*)handleManager->getSession(hSession);
1224         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1225
1226         // Check the new PINs
1227         if (pOldPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1228         if (pNewPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1229         if (ulNewLen < MIN_PIN_LEN || ulNewLen > MAX_PIN_LEN) return CKR_PIN_LEN_RANGE;
1230
1231         ByteString oldPIN(pOldPin, ulOldLen);
1232         ByteString newPIN(pNewPin, ulNewLen);
1233
1234         // Get the token
1235         Token* token = session->getToken();
1236         if (token == NULL) return CKR_GENERAL_ERROR;
1237
1238         switch (session->getState())
1239         {
1240                 case CKS_RW_PUBLIC_SESSION:
1241                 case CKS_RW_USER_FUNCTIONS:
1242                         rv = token->setUserPIN(oldPIN, newPIN);
1243                         break;
1244                 case CKS_RW_SO_FUNCTIONS:
1245                         rv = token->setSOPIN(oldPIN, newPIN);
1246                         break;
1247                 default:
1248                         return CKR_SESSION_READ_ONLY;
1249         }
1250
1251         return rv;
1252 }
1253
1254 // Open a new session to the specified slot
1255 CK_RV SoftHSM::C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY notify, CK_SESSION_HANDLE_PTR phSession)
1256 {
1257         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1258
1259         Slot* slot = slotManager->getSlot(slotID);
1260
1261         CK_RV rv = sessionManager->openSession(slot, flags, pApplication, notify, phSession);
1262         if (rv != CKR_OK)
1263                 return rv;
1264
1265         // Get a pointer to the session object and store it in the handle manager.
1266         Session* session = sessionManager->getSession(*phSession);
1267         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1268         *phSession = handleManager->addSession(slotID,session);
1269
1270         return CKR_OK;
1271 }
1272
1273 // Close the given session
1274 CK_RV SoftHSM::C_CloseSession(CK_SESSION_HANDLE hSession)
1275 {
1276         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1277
1278         // Get the session
1279         Session* session = (Session*)handleManager->getSession(hSession);
1280         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1281
1282         // Tell the handle manager the session has been closed.
1283         handleManager->sessionClosed(hSession);
1284
1285
1286         // Tell the session object store that the session has closed.
1287         sessionObjectStore->sessionClosed(hSession);
1288
1289         // Tell the session manager the session has been closed.
1290         return sessionManager->closeSession(session->getHandle());
1291 }
1292
1293 // Close all open sessions
1294 CK_RV SoftHSM::C_CloseAllSessions(CK_SLOT_ID slotID)
1295 {
1296         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1297
1298         // Get the slot
1299         Slot* slot = slotManager->getSlot(slotID);
1300         if (slot == NULL) return CKR_SLOT_ID_INVALID;
1301
1302         // Get the token
1303         Token* token = slot->getToken();
1304         if (token == NULL) return CKR_TOKEN_NOT_PRESENT;
1305
1306         // Tell the handle manager all sessions were closed for the given slotID.
1307         // The handle manager should then remove all session and object handles for this slot.
1308         handleManager->allSessionsClosed(slotID);
1309
1310         // Tell the session object store that all sessions were closed for the given slotID.
1311         // The session object store should then remove all session objects for this slot.
1312         sessionObjectStore->allSessionsClosed(slotID);
1313
1314         // Finally tell the session manager tho close all sessions for the given slot.
1315         // This will also trigger a logout on the associated token to occur.
1316         return sessionManager->closeAllSessions(slot);
1317 }
1318
1319 // Retrieve information about the specified session
1320 CK_RV SoftHSM::C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
1321 {
1322         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1323
1324         // Get the session
1325         Session* session = (Session*)handleManager->getSession(hSession);
1326         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1327
1328         return session->getInfo(pInfo);
1329 }
1330
1331 // Determine the state of a running operation in a session
1332 CK_RV SoftHSM::C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG_PTR /*pulOperationStateLen*/)
1333 {
1334         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1335
1336         // Get the session
1337         Session* session = (Session*)handleManager->getSession(hSession);
1338         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1339
1340         return CKR_FUNCTION_NOT_SUPPORTED;
1341 }
1342
1343 // Set the operation sate in a session
1344 CK_RV SoftHSM::C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pOperationState*/, CK_ULONG /*ulOperationStateLen*/, CK_OBJECT_HANDLE /*hEncryptionKey*/, CK_OBJECT_HANDLE /*hAuthenticationKey*/)
1345 {
1346         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1347
1348         // Get the session
1349         Session* session = (Session*)handleManager->getSession(hSession);
1350         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1351
1352         return CKR_FUNCTION_NOT_SUPPORTED;
1353 }
1354
1355 // Login on the token in the specified session
1356 CK_RV SoftHSM::C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
1357 {
1358         CK_RV rv = CKR_OK;
1359
1360         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1361
1362         // Get the session
1363         Session* session = (Session*)handleManager->getSession(hSession);
1364         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1365
1366         // Get the PIN
1367         if (pPin == NULL_PTR) return CKR_ARGUMENTS_BAD;
1368         ByteString pin(pPin, ulPinLen);
1369
1370         // Get the token
1371         Token* token = session->getToken();
1372         if (token == NULL) return CKR_GENERAL_ERROR;
1373
1374         switch (userType)
1375         {
1376                 case CKU_SO:
1377                         // There cannot exist a R/O session on this slot
1378                         if (sessionManager->haveROSession(session->getSlot()->getSlotID())) return CKR_SESSION_READ_ONLY_EXISTS;
1379
1380                         // Login
1381                         rv = token->loginSO(pin);
1382                         break;
1383                 case CKU_USER:
1384                         // Login
1385                         rv = token->loginUser(pin);
1386                         break;
1387                 case CKU_CONTEXT_SPECIFIC:
1388                         // Check if re-authentication is required
1389                         if (!session->getReAuthentication()) return CKR_OPERATION_NOT_INITIALIZED;
1390
1391                         // Re-authenticate
1392                         rv = token->reAuthenticate(pin);
1393                         if (rv == CKR_OK) session->setReAuthentication(false);
1394                         break;
1395                 default:
1396                         return CKR_USER_TYPE_INVALID;
1397         }
1398
1399         return rv;
1400 }
1401
1402 // Log out of the token in the specified session
1403 CK_RV SoftHSM::C_Logout(CK_SESSION_HANDLE hSession)
1404 {
1405         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1406
1407         // Get the session
1408         Session* session = (Session*)handleManager->getSession(hSession);
1409         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1410
1411         // Get the token
1412         Token* token = session->getToken();
1413         if (token == NULL) return CKR_GENERAL_ERROR;
1414
1415         // Logout
1416         token->logout();
1417
1418         // [PKCS#11 v2.40, C_Logout] When logout is successful...
1419         // a. Any of the application's handles to private objects become invalid.
1420         // b. Even if a user is later logged back into the token those handles remain invalid.
1421         // c. All private session objects from sessions belonging to the application are destroyed.
1422
1423         // Have the handle manager remove all handles pointing to private objects for this slot.
1424         CK_SLOT_ID slotID = session->getSlot()->getSlotID();
1425         handleManager->tokenLoggedOut(slotID);
1426         sessionObjectStore->tokenLoggedOut(slotID);
1427
1428         return CKR_OK;
1429 }
1430
1431 // Create a new object on the token in the specified session using the given attribute template
1432 CK_RV SoftHSM::C_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
1433 {
1434         return this->CreateObject(hSession,pTemplate,ulCount,phObject,OBJECT_OP_CREATE);
1435 }
1436
1437 // Create a copy of the object with the specified handle
1438 CK_RV SoftHSM::C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject)
1439 {
1440         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1441
1442         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
1443         if (phNewObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1444         *phNewObject = CK_INVALID_HANDLE;
1445
1446         // Get the session
1447         Session* session = (Session*)handleManager->getSession(hSession);
1448         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1449
1450         // Get the slot
1451         Slot* slot = session->getSlot();
1452         if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1453
1454         // Get the token
1455         Token* token = session->getToken();
1456         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1457
1458         // Check the object handle.
1459         OSObject *object = (OSObject *)handleManager->getObject(hObject);
1460         if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1461
1462         CK_BBOOL wasOnToken = object->getBooleanValue(CKA_TOKEN, false);
1463         CK_BBOOL wasPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1464
1465         // Check read user credentials
1466         CK_RV rv = haveRead(session->getState(), wasOnToken, wasPrivate);
1467         if (rv != CKR_OK)
1468         {
1469                 if (rv == CKR_USER_NOT_LOGGED_IN)
1470                         INFO_MSG("User is not authorized");
1471
1472                 return rv;
1473         }
1474
1475         // Check if the object is copyable
1476         CK_BBOOL isCopyable = object->getBooleanValue(CKA_COPYABLE, true);
1477         if (!isCopyable) return CKR_ACTION_PROHIBITED;
1478
1479         // Extract critical information from the template
1480         CK_BBOOL isOnToken = wasOnToken;
1481         CK_BBOOL isPrivate = wasPrivate;
1482
1483         for (CK_ULONG i = 0; i < ulCount; i++)
1484         {
1485                 if ((pTemplate[i].type == CKA_TOKEN) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1486                 {
1487                         isOnToken = *(CK_BBOOL*)pTemplate[i].pValue;
1488                         continue;
1489                 }
1490                 if ((pTemplate[i].type == CKA_PRIVATE) && (pTemplate[i].ulValueLen == sizeof(CK_BBOOL)))
1491                 {
1492                         isPrivate = *(CK_BBOOL*)pTemplate[i].pValue;
1493                         continue;
1494                 }
1495         }
1496
1497         // Check privacy does not downgrade
1498         if (wasPrivate && !isPrivate) return CKR_TEMPLATE_INCONSISTENT;
1499
1500         // Check write user credentials
1501         rv = haveWrite(session->getState(), isOnToken, isPrivate);
1502         if (rv != CKR_OK)
1503         {
1504                 if (rv == CKR_USER_NOT_LOGGED_IN)
1505                         INFO_MSG("User is not authorized");
1506                 if (rv == CKR_SESSION_READ_ONLY)
1507                         INFO_MSG("Session is read-only");
1508
1509                 return rv;
1510         }
1511
1512         // Create the object in session or on the token
1513         OSObject *newobject = NULL_PTR;
1514         if (isOnToken)
1515         {
1516                 newobject = (OSObject*) token->createObject();
1517         }
1518         else
1519         {
1520                 newobject = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
1521         }
1522         if (newobject == NULL) return CKR_GENERAL_ERROR;
1523
1524         // Copy attributes from object class (CKA_CLASS=0 so the first)
1525         if (!newobject->startTransaction())
1526         {
1527                 newobject->destroyObject();
1528                 return CKR_FUNCTION_FAILED;
1529         }
1530
1531         CK_ATTRIBUTE_TYPE attrType = CKA_CLASS;
1532         do
1533         {
1534                 if (!object->attributeExists(attrType))
1535                 {
1536                         rv = CKR_FUNCTION_FAILED;
1537                         break;
1538                 }
1539
1540                 OSAttribute attr = object->getAttribute(attrType);
1541
1542                 // Upgrade privacy has to encrypt byte strings
1543                 if (!wasPrivate && isPrivate &&
1544                     attr.isByteStringAttribute() &&
1545                     attr.getByteStringValue().size() != 0)
1546                 {
1547                         ByteString value;
1548                         if (!token->encrypt(attr.getByteStringValue(), value) ||
1549                             !newobject->setAttribute(attrType, value))
1550                         {
1551                                 rv = CKR_FUNCTION_FAILED;
1552                                 break;
1553                         }
1554                 }
1555                 else
1556                 {
1557                         if (!newobject->setAttribute(attrType, attr))
1558                         {
1559                                 rv = CKR_FUNCTION_FAILED;
1560                                 break;
1561                         }
1562                 }
1563                 attrType = object->nextAttributeType(attrType);
1564         }
1565         while (attrType != CKA_CLASS);
1566
1567         if (rv != CKR_OK)
1568         {
1569                 newobject->abortTransaction();
1570         }
1571         else if (!newobject->commitTransaction())
1572         {
1573                 rv = CKR_FUNCTION_FAILED;
1574         }
1575
1576         if (rv != CKR_OK)
1577         {
1578                 newobject->destroyObject();
1579                 return rv;
1580         }
1581
1582         // Get the new P11 object
1583         P11Object* newp11object = NULL;
1584         rv = newP11Object(newobject,&newp11object);
1585         if (rv != CKR_OK)
1586         {
1587                 newobject->destroyObject();
1588                 return rv;
1589         }
1590
1591         // Apply the template
1592         rv = newp11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate, ulCount, OBJECT_OP_COPY);
1593         delete newp11object;
1594
1595         if (rv != CKR_OK)
1596         {
1597                 newobject->destroyObject();
1598                 return rv;
1599         }
1600
1601         // Set handle
1602         if (isOnToken)
1603         {
1604                 *phNewObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, newobject);
1605         }
1606         else
1607         {
1608                 *phNewObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, newobject);
1609         }
1610
1611         return CKR_OK;
1612 }
1613
1614 // Destroy the specified object
1615 CK_RV SoftHSM::C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
1616 {
1617         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1618
1619         // Get the session
1620         Session* session = (Session*)handleManager->getSession(hSession);
1621         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1622
1623         // Get the token
1624         Token* token = session->getToken();
1625         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1626
1627         // Check the object handle.
1628         OSObject *object = (OSObject *)handleManager->getObject(hObject);
1629         if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1630
1631         CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1632         CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1633
1634         // Check user credentials
1635         CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1636         if (rv != CKR_OK)
1637         {
1638                 if (rv == CKR_USER_NOT_LOGGED_IN)
1639                         INFO_MSG("User is not authorized");
1640                 if (rv == CKR_SESSION_READ_ONLY)
1641                         INFO_MSG("Session is read-only");
1642
1643                 return rv;
1644         }
1645
1646         // Check if the object is destroyable
1647         CK_BBOOL isDestroyable = object->getBooleanValue(CKA_DESTROYABLE, true);
1648         if (!isDestroyable) return CKR_ACTION_PROHIBITED;
1649
1650         // Tell the handleManager to forget about the object.
1651         handleManager->destroyObject(hObject);
1652
1653         // Destroy the object
1654         if (!object->destroyObject())
1655                 return CKR_FUNCTION_FAILED;
1656
1657         return CKR_OK;
1658 }
1659
1660 // Determine the size of the specified object
1661 CK_RV SoftHSM::C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize)
1662 {
1663         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1664
1665         if (pulSize == NULL) return CKR_ARGUMENTS_BAD;
1666
1667         // Get the session
1668         Session* session = (Session*)handleManager->getSession(hSession);
1669         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1670
1671         // Get the token
1672         Token* token = session->getToken();
1673         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1674
1675         // Check the object handle.
1676         OSObject *object = (OSObject *)handleManager->getObject(hObject);
1677         if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1678
1679         *pulSize = CK_UNAVAILABLE_INFORMATION;
1680
1681         return CKR_OK;
1682 }
1683
1684 // Retrieve the specified attributes for the given object
1685 CK_RV SoftHSM::C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1686 {
1687         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1688
1689         if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1690
1691         // Get the session
1692         Session* session = (Session*)handleManager->getSession(hSession);
1693         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1694
1695         // Get the token
1696         Token* token = session->getToken();
1697         if (token == NULL) return CKR_GENERAL_ERROR;
1698
1699         // Check the object handle.
1700         OSObject *object = (OSObject *)handleManager->getObject(hObject);
1701         if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1702
1703         CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1704         CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1705
1706         // Check read user credentials
1707         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
1708         if (rv != CKR_OK)
1709         {
1710                 if (rv == CKR_USER_NOT_LOGGED_IN)
1711                         INFO_MSG("User is not authorized");
1712
1713                 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
1714                 // so we use CKR_GENERAL_ERROR.
1715                 return CKR_GENERAL_ERROR;
1716         }
1717
1718         // Wrap a P11Object around the OSObject so we can access the attributes in the
1719         // context of the object in which it is defined.
1720         P11Object* p11object = NULL;
1721         rv = newP11Object(object,&p11object);
1722         if (rv != CKR_OK)
1723                 return rv;
1724
1725         // Ask the P11Object to fill the template with attribute values.
1726         rv = p11object->loadTemplate(token, pTemplate,ulCount);
1727         delete p11object;
1728         return rv;
1729 }
1730
1731 // Change or set the value of the specified attributes on the specified object
1732 CK_RV SoftHSM::C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1733 {
1734         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1735
1736         if (pTemplate == NULL) return CKR_ARGUMENTS_BAD;
1737
1738         // Get the session
1739         Session* session = (Session*)handleManager->getSession(hSession);
1740         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1741
1742         // Get the token
1743         Token* token = session->getToken();
1744         if (token == NULL) return CKR_GENERAL_ERROR;
1745
1746         // Check the object handle.
1747         OSObject *object = (OSObject *)handleManager->getObject(hObject);
1748         if (object == NULL_PTR || !object->isValid()) return CKR_OBJECT_HANDLE_INVALID;
1749
1750         CK_BBOOL isOnToken = object->getBooleanValue(CKA_TOKEN, false);
1751         CK_BBOOL isPrivate = object->getBooleanValue(CKA_PRIVATE, true);
1752
1753         // Check user credentials
1754         CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
1755         if (rv != CKR_OK)
1756         {
1757                 if (rv == CKR_USER_NOT_LOGGED_IN)
1758                         INFO_MSG("User is not authorized");
1759                 if (rv == CKR_SESSION_READ_ONLY)
1760                         INFO_MSG("Session is read-only");
1761
1762                 return rv;
1763         }
1764
1765         // Check if the object is modifiable
1766         CK_BBOOL isModifiable = object->getBooleanValue(CKA_MODIFIABLE, true);
1767         if (!isModifiable) return CKR_ACTION_PROHIBITED;
1768
1769         // Wrap a P11Object around the OSObject so we can access the attributes in the
1770         // context of the object in which it is defined.
1771         P11Object* p11object = NULL;
1772         rv = newP11Object(object,&p11object);
1773         if (rv != CKR_OK)
1774                 return rv;
1775
1776         // Ask the P11Object to save the template with attribute values.
1777         rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, pTemplate,ulCount,OBJECT_OP_SET);
1778         delete p11object;
1779         return rv;
1780 }
1781
1782 // Initialise object search in the specified session using the specified attribute template as search parameters
1783 CK_RV SoftHSM::C_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
1784 {
1785         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1786
1787         // Get the session
1788         Session* session = (Session*)handleManager->getSession(hSession);
1789         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1790
1791         // Get the slot
1792         Slot* slot = session->getSlot();
1793         if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
1794
1795         // Determine whether we have a public session or not.
1796         bool isPublicSession;
1797         switch (session->getState()) {
1798                 case CKS_RO_USER_FUNCTIONS:
1799                 case CKS_RW_USER_FUNCTIONS:
1800                         isPublicSession = false;
1801                         break;
1802                 default:
1803                         isPublicSession = true;
1804         }
1805
1806         // Get the token
1807         Token* token = session->getToken();
1808         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
1809
1810         // Check if we have another operation
1811         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
1812
1813         session->setOpType(SESSION_OP_FIND);
1814         FindOperation *findOp = FindOperation::create();
1815
1816         // Check if we are out of memory
1817         if (findOp == NULL_PTR) return CKR_HOST_MEMORY;
1818
1819         std::set<OSObject*> allObjects;
1820         token->getObjects(allObjects);
1821         sessionObjectStore->getObjects(slot->getSlotID(),allObjects);
1822
1823         std::set<CK_OBJECT_HANDLE> handles;
1824         std::set<OSObject*>::iterator it;
1825         for (it=allObjects.begin(); it != allObjects.end(); ++it)
1826         {
1827                 // Refresh object and check if it is valid
1828                 if (!(*it)->isValid()) {
1829                         DEBUG_MSG("Object is not valid, skipping");
1830                         continue;
1831                 }
1832
1833                 // Determine if the object has CKA_PRIVATE set to CK_TRUE
1834                 bool isPrivateObject = (*it)->getBooleanValue(CKA_PRIVATE, true);
1835
1836                 // If the object is private, and we are in a public session then skip it !
1837                 if (isPublicSession && isPrivateObject)
1838                         continue; // skip object
1839
1840                 // Perform the actual attribute matching.
1841                 bool bAttrMatch = true; // We let an empty template match everything.
1842                 for (CK_ULONG i=0; i<ulCount; ++i)
1843                 {
1844                         bAttrMatch = false;
1845
1846                         if (!(*it)->attributeExists(pTemplate[i].type))
1847                                 break;
1848
1849                         OSAttribute attr = (*it)->getAttribute(pTemplate[i].type);
1850
1851                         if (attr.isBooleanAttribute())
1852                         {
1853                                 if (sizeof(CK_BBOOL) != pTemplate[i].ulValueLen)
1854                                         break;
1855                                 bool bTemplateValue = (*(CK_BBOOL*)pTemplate[i].pValue == CK_TRUE);
1856                                 if (attr.getBooleanValue() != bTemplateValue)
1857                                         break;
1858                         }
1859                         else
1860                         {
1861                                 if (attr.isUnsignedLongAttribute())
1862                                 {
1863                                         if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen)
1864                                                 break;
1865                                         CK_ULONG ulTemplateValue = *(CK_ULONG_PTR)pTemplate[i].pValue;
1866                                         if (attr.getUnsignedLongValue() != ulTemplateValue)
1867                                                 break;
1868                                 }
1869                                 else
1870                                 {
1871                                         if (attr.isByteStringAttribute())
1872                                         {
1873                                                 ByteString bsAttrValue;
1874                                                 if (isPrivateObject && attr.getByteStringValue().size() != 0)
1875                                                 {
1876                                                         if (!token->decrypt(attr.getByteStringValue(), bsAttrValue))
1877                                                         {
1878                                                                 delete findOp;
1879                                                                 return CKR_GENERAL_ERROR;
1880                                                         }
1881                                                 }
1882                                                 else
1883                                                         bsAttrValue = attr.getByteStringValue();
1884
1885                                                 if (bsAttrValue.size() != pTemplate[i].ulValueLen)
1886                                                         break;
1887                                                 if (pTemplate[i].ulValueLen != 0)
1888                                                 {
1889                                                         ByteString bsTemplateValue((const unsigned char*)pTemplate[i].pValue, pTemplate[i].ulValueLen);
1890                                                         if (bsAttrValue != bsTemplateValue)
1891                                                                 break;
1892                                                 }
1893                                         }
1894                                         else
1895                                                 break;
1896                                 }
1897                         }
1898                         // The attribute matched !
1899                         bAttrMatch = true;
1900                 }
1901
1902                 if (bAttrMatch)
1903                 {
1904                         CK_SLOT_ID slotID = slot->getSlotID();
1905                         bool isOnToken = (*it)->getBooleanValue(CKA_TOKEN, false);
1906                         bool isPrivate = (*it)->getBooleanValue(CKA_PRIVATE, true);
1907                         // Create an object handle for every returned object.
1908                         CK_OBJECT_HANDLE hObject;
1909                         if (isOnToken)
1910                                 hObject = handleManager->addTokenObject(slotID,isPrivate,*it);
1911                         else
1912                                 hObject = handleManager->addSessionObject(slotID,hSession,isPrivate,*it);
1913                         if (hObject == CK_INVALID_HANDLE)
1914                         {
1915                                 delete findOp;
1916                                 return CKR_GENERAL_ERROR;
1917                         }
1918                         handles.insert(hObject);
1919                 }
1920         }
1921
1922         // Storing the object handles for the find will protect the library
1923         // whenever a stale object handle is used to access the library.
1924         findOp->setHandles(handles);
1925
1926         session->setFindOp(findOp);
1927
1928         return CKR_OK;
1929 }
1930
1931 // Continue the search for objects in the specified session
1932 CK_RV SoftHSM::C_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
1933 {
1934         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1935         if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
1936         if (pulObjectCount == NULL_PTR) return CKR_ARGUMENTS_BAD;
1937
1938         // Get the session
1939         Session* session = (Session*)handleManager->getSession(hSession);
1940         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1941
1942         // Check if we are doing the correct operation
1943         if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1944
1945         // return the object handles that have been added to the find operation.
1946         FindOperation *findOp = session->getFindOp();
1947         if (findOp == NULL) return CKR_GENERAL_ERROR;
1948
1949         // Ask the find operation to retrieve the object handles
1950         *pulObjectCount = findOp->retrieveHandles(phObject,ulMaxObjectCount);
1951
1952         // Erase the object handles from the find operation.
1953         findOp->eraseHandles(0,*pulObjectCount);
1954
1955         return CKR_OK;
1956 }
1957
1958 // Finish searching for objects
1959 CK_RV SoftHSM::C_FindObjectsFinal(CK_SESSION_HANDLE hSession)
1960 {
1961         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
1962
1963         // Get the session
1964         Session* session = (Session*)handleManager->getSession(hSession);
1965         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
1966
1967         // Check if we are doing the correct operation
1968         if (session->getOpType() != SESSION_OP_FIND) return CKR_OPERATION_NOT_INITIALIZED;
1969
1970         session->resetOp();
1971         return CKR_OK;
1972 }
1973
1974 // Encrypt*/Decrypt*() is for Symmetrical ciphers too
1975 static bool isSymMechanism(CK_MECHANISM_PTR pMechanism)
1976 {
1977         if (pMechanism == NULL_PTR) return false;
1978
1979         switch(pMechanism->mechanism) {
1980                 case CKM_DES_ECB:
1981                 case CKM_DES_CBC:
1982                 case CKM_DES_CBC_PAD:
1983                 case CKM_DES3_ECB:
1984                 case CKM_DES3_CBC:
1985                 case CKM_DES3_CBC_PAD:
1986                 case CKM_AES_ECB:
1987                 case CKM_AES_CBC:
1988                 case CKM_AES_CBC_PAD:
1989                 case CKM_AES_CTR:
1990                 case CKM_AES_GCM:
1991                         return true;
1992                 default:
1993                         return false;
1994         }
1995 }
1996
1997 // SymAlgorithm version of C_EncryptInit
1998 CK_RV SoftHSM::SymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
1999 {
2000         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2001
2002         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2003
2004         // Get the session
2005         Session* session = (Session*)handleManager->getSession(hSession);
2006         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2007
2008         // Check if we have another operation
2009         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2010
2011         // Get the token
2012         Token* token = session->getToken();
2013         if (token == NULL) return CKR_GENERAL_ERROR;
2014
2015         // Check the key handle.
2016         OSObject *key = (OSObject *)handleManager->getObject(hKey);
2017         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2018
2019         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2020         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2021
2022         // Check read user credentials
2023         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2024         if (rv != CKR_OK)
2025         {
2026                 if (rv == CKR_USER_NOT_LOGGED_IN)
2027                         INFO_MSG("User is not authorized");
2028
2029                 return rv;
2030         }
2031
2032         // Check if key can be used for encryption
2033         if (!key->getBooleanValue(CKA_ENCRYPT, false))
2034                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2035
2036         // Check if the specified mechanism is allowed for the key
2037         if (!isMechanismPermitted(key, pMechanism))
2038                 return CKR_MECHANISM_INVALID;
2039
2040         // Get the symmetric algorithm matching the mechanism
2041         SymAlgo::Type algo = SymAlgo::Unknown;
2042         SymMode::Type mode = SymMode::Unknown;
2043         bool padding = false;
2044         ByteString iv;
2045         size_t bb = 8;
2046         size_t counterBits = 0;
2047         ByteString aad;
2048         size_t tagBytes = 0;
2049         switch(pMechanism->mechanism) {
2050 #ifndef WITH_FIPS
2051                 case CKM_DES_ECB:
2052                         algo = SymAlgo::DES;
2053                         mode = SymMode::ECB;
2054                         bb = 7;
2055                         break;
2056                 case CKM_DES_CBC:
2057                         algo = SymAlgo::DES;
2058                         mode = SymMode::CBC;
2059                         if (pMechanism->pParameter == NULL_PTR ||
2060                             pMechanism->ulParameterLen == 0)
2061                         {
2062                                 DEBUG_MSG("CBC mode requires an init vector");
2063                                 return CKR_ARGUMENTS_BAD;
2064                         }
2065                         iv.resize(pMechanism->ulParameterLen);
2066                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2067                         bb = 7;
2068                         break;
2069                 case CKM_DES_CBC_PAD:
2070                         algo = SymAlgo::DES;
2071                         mode = SymMode::CBC;
2072                         padding = true;
2073                         if (pMechanism->pParameter == NULL_PTR ||
2074                             pMechanism->ulParameterLen == 0)
2075                         {
2076                                 DEBUG_MSG("CBC mode requires an init vector");
2077                                 return CKR_ARGUMENTS_BAD;
2078                         }
2079                         iv.resize(pMechanism->ulParameterLen);
2080                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2081                         bb = 7;
2082                         break;
2083 #endif
2084                 case CKM_DES3_ECB:
2085                         algo = SymAlgo::DES3;
2086                         mode = SymMode::ECB;
2087                         bb = 7;
2088                         break;
2089                 case CKM_DES3_CBC:
2090                         algo = SymAlgo::DES3;
2091                         mode = SymMode::CBC;
2092                         if (pMechanism->pParameter == NULL_PTR ||
2093                             pMechanism->ulParameterLen == 0)
2094                         {
2095                                 DEBUG_MSG("CBC mode requires an init vector");
2096                                 return CKR_ARGUMENTS_BAD;
2097                         }
2098                         iv.resize(pMechanism->ulParameterLen);
2099                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2100                         bb = 7;
2101                         break;
2102                 case CKM_DES3_CBC_PAD:
2103                         algo = SymAlgo::DES3;
2104                         mode = SymMode::CBC;
2105                         padding = true;
2106                         if (pMechanism->pParameter == NULL_PTR ||
2107                             pMechanism->ulParameterLen == 0)
2108                         {
2109                                 DEBUG_MSG("CBC mode requires an init vector");
2110                                 return CKR_ARGUMENTS_BAD;
2111                         }
2112                         iv.resize(pMechanism->ulParameterLen);
2113                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2114                         bb = 7;
2115                         break;
2116                 case CKM_AES_ECB:
2117                         algo = SymAlgo::AES;
2118                         mode = SymMode::ECB;
2119                         break;
2120                 case CKM_AES_CBC:
2121                         algo = SymAlgo::AES;
2122                         mode = SymMode::CBC;
2123                         if (pMechanism->pParameter == NULL_PTR ||
2124                             pMechanism->ulParameterLen == 0)
2125                         {
2126                                 DEBUG_MSG("CBC mode requires an init vector");
2127                                 return CKR_ARGUMENTS_BAD;
2128                         }
2129                         iv.resize(pMechanism->ulParameterLen);
2130                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2131                         break;
2132                 case CKM_AES_CBC_PAD:
2133                         algo = SymAlgo::AES;
2134                         mode = SymMode::CBC;
2135                         padding = true;
2136                         if (pMechanism->pParameter == NULL_PTR ||
2137                             pMechanism->ulParameterLen == 0)
2138                         {
2139                                 DEBUG_MSG("CBC mode requires an init vector");
2140                                 return CKR_ARGUMENTS_BAD;
2141                         }
2142                         iv.resize(pMechanism->ulParameterLen);
2143                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2144                         break;
2145                 case CKM_AES_CTR:
2146                         algo = SymAlgo::AES;
2147                         mode = SymMode::CTR;
2148                         if (pMechanism->pParameter == NULL_PTR ||
2149                             pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2150                         {
2151                                 DEBUG_MSG("CTR mode requires a counter block");
2152                                 return CKR_ARGUMENTS_BAD;
2153                         }
2154                         counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2155                         if (counterBits == 0 || counterBits > 128)
2156                         {
2157                                 DEBUG_MSG("Invalid ulCounterBits");
2158                                 return CKR_MECHANISM_PARAM_INVALID;
2159                         }
2160                         iv.resize(16);
2161                         memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2162                         break;
2163 #ifdef WITH_AES_GCM
2164                 case CKM_AES_GCM:
2165                         algo = SymAlgo::AES;
2166                         mode = SymMode::GCM;
2167                         if (pMechanism->pParameter == NULL_PTR ||
2168                             pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2169                         {
2170                                 DEBUG_MSG("GCM mode requires parameters");
2171                                 return CKR_ARGUMENTS_BAD;
2172                         }
2173                         iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2174                         memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2175                         aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2176                         memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2177                         tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2178                         if (tagBytes > 128 || tagBytes % 8 != 0)
2179                         {
2180                                 DEBUG_MSG("Invalid ulTagBits value");
2181                                 return CKR_ARGUMENTS_BAD;
2182                         }
2183                         tagBytes = tagBytes / 8;
2184                         break;
2185 #endif
2186                 default:
2187                         return CKR_MECHANISM_INVALID;
2188         }
2189         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2190         if (cipher == NULL) return CKR_MECHANISM_INVALID;
2191
2192         SymmetricKey* secretkey = new SymmetricKey();
2193
2194         if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2195         {
2196                 cipher->recycleKey(secretkey);
2197                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2198                 return CKR_GENERAL_ERROR;
2199         }
2200
2201         // adjust key bit length
2202         secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2203
2204         // Initialize encryption
2205         if (!cipher->encryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2206         {
2207                 cipher->recycleKey(secretkey);
2208                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2209                 return CKR_MECHANISM_INVALID;
2210         }
2211
2212         session->setOpType(SESSION_OP_ENCRYPT);
2213         session->setSymmetricCryptoOp(cipher);
2214         session->setAllowMultiPartOp(true);
2215         session->setAllowSinglePartOp(true);
2216         session->setSymmetricKey(secretkey);
2217
2218         return CKR_OK;
2219 }
2220
2221 // AsymAlgorithm version of C_EncryptInit
2222 CK_RV SoftHSM::AsymEncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2223 {
2224         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2225
2226         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2227
2228         // Get the session
2229         Session* session = (Session*)handleManager->getSession(hSession);
2230         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2231
2232         // Check if we have another operation
2233         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2234
2235         // Get the token
2236         Token* token = session->getToken();
2237         if (token == NULL) return CKR_GENERAL_ERROR;
2238
2239         // Check the key handle.
2240         OSObject *key = (OSObject *)handleManager->getObject(hKey);
2241         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2242
2243         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2244         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2245
2246         // Check read user credentials
2247         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2248         if (rv != CKR_OK)
2249         {
2250                 if (rv == CKR_USER_NOT_LOGGED_IN)
2251                         INFO_MSG("User is not authorized");
2252
2253                 return rv;
2254         }
2255
2256         // Check if key can be used for encryption
2257         if (!key->getBooleanValue(CKA_ENCRYPT, false))
2258                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2259
2260         // Get the asymmetric algorithm matching the mechanism
2261         AsymMech::Type mechanism;
2262         bool isRSA = false;
2263         switch(pMechanism->mechanism) {
2264                 case CKM_RSA_PKCS:
2265                         mechanism = AsymMech::RSA_PKCS;
2266                         isRSA = true;
2267                         break;
2268                 case CKM_RSA_X_509:
2269                         mechanism = AsymMech::RSA;
2270                         isRSA = true;
2271                         break;
2272                 case CKM_RSA_PKCS_OAEP:
2273                         rv = MechParamCheckRSAPKCSOAEP(pMechanism);
2274                         if (rv != CKR_OK)
2275                                 return rv;
2276
2277                         mechanism = AsymMech::RSA_PKCS_OAEP;
2278                         isRSA = true;
2279                         break;
2280                 default:
2281                         return CKR_MECHANISM_INVALID;
2282         }
2283
2284         AsymmetricAlgorithm* asymCrypto = NULL;
2285         PublicKey* publicKey = NULL;
2286         if (isRSA)
2287         {
2288                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2289                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2290
2291                 publicKey = asymCrypto->newPublicKey();
2292                 if (publicKey == NULL)
2293                 {
2294                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2295                         return CKR_HOST_MEMORY;
2296                 }
2297
2298                 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
2299                 {
2300                         asymCrypto->recyclePublicKey(publicKey);
2301                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2302                         return CKR_GENERAL_ERROR;
2303                 }
2304         }
2305         else
2306         {
2307                 return CKR_MECHANISM_INVALID;
2308         }
2309
2310         session->setOpType(SESSION_OP_ENCRYPT);
2311         session->setAsymmetricCryptoOp(asymCrypto);
2312         session->setMechanism(mechanism);
2313         session->setAllowMultiPartOp(false);
2314         session->setAllowSinglePartOp(true);
2315         session->setPublicKey(publicKey);
2316
2317         return CKR_OK;
2318 }
2319
2320 // Initialise encryption using the specified object and mechanism
2321 CK_RV SoftHSM::C_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2322 {
2323         if (isSymMechanism(pMechanism))
2324                 return SymEncryptInit(hSession, pMechanism, hKey);
2325         else
2326                 return AsymEncryptInit(hSession, pMechanism, hKey);
2327 }
2328
2329 // SymAlgorithm version of C_Encrypt
2330 static CK_RV SymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2331 {
2332         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2333         if (cipher == NULL || !session->getAllowSinglePartOp())
2334         {
2335                 session->resetOp();
2336                 return CKR_OPERATION_NOT_INITIALIZED;
2337         }
2338
2339         // Check data size
2340         CK_ULONG maxSize = ulDataLen + cipher->getTagBytes();
2341         if (cipher->isBlockCipher())
2342         {
2343                 CK_ULONG remainder = ulDataLen % cipher->getBlockSize();
2344                 if (cipher->getPaddingMode() == false && remainder != 0)
2345                 {
2346                         session->resetOp();
2347                         return CKR_DATA_LEN_RANGE;
2348                 }
2349
2350                 // Round up to block size
2351                 if (remainder != 0)
2352                 {
2353                         maxSize = ulDataLen + cipher->getBlockSize() - remainder;
2354                 }
2355                 else if (cipher->getPaddingMode() == true)
2356                 {
2357                         maxSize = ulDataLen + cipher->getBlockSize();
2358                 }
2359         }
2360         if (!cipher->checkMaximumBytes(ulDataLen))
2361         {
2362                 session->resetOp();
2363                 return CKR_DATA_LEN_RANGE;
2364         }
2365
2366         if (pEncryptedData == NULL_PTR)
2367         {
2368                 *pulEncryptedDataLen = maxSize;
2369                 return CKR_OK;
2370         }
2371
2372         // Check buffer size
2373         if (*pulEncryptedDataLen < maxSize)
2374         {
2375                 *pulEncryptedDataLen = maxSize;
2376                 return CKR_BUFFER_TOO_SMALL;
2377         }
2378
2379         // Get the data
2380         ByteString data(pData, ulDataLen);
2381         ByteString encryptedData;
2382
2383         // Encrypt the data
2384         if (!cipher->encryptUpdate(data, encryptedData))
2385         {
2386                 session->resetOp();
2387                 return CKR_GENERAL_ERROR;
2388         }
2389
2390         // Finalize encryption
2391         ByteString encryptedFinal;
2392         if (!cipher->encryptFinal(encryptedFinal))
2393         {
2394                 session->resetOp();
2395                 return CKR_GENERAL_ERROR;
2396         }
2397         encryptedData += encryptedFinal;
2398         encryptedData.resize(maxSize);
2399
2400         memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2401         *pulEncryptedDataLen = encryptedData.size();
2402
2403         session->resetOp();
2404         return CKR_OK;
2405 }
2406
2407 // AsymAlgorithm version of C_Encrypt
2408 static CK_RV AsymEncrypt(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2409 {
2410         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
2411         AsymMech::Type mechanism = session->getMechanism();
2412         PublicKey* publicKey = session->getPublicKey();
2413         if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
2414         {
2415                 session->resetOp();
2416                 return CKR_OPERATION_NOT_INITIALIZED;
2417         }
2418
2419         // Size of the encrypted data
2420         CK_ULONG size = publicKey->getOutputLength();
2421
2422         if (pEncryptedData == NULL_PTR)
2423         {
2424                 *pulEncryptedDataLen = size;
2425                 return CKR_OK;
2426         }
2427
2428         // Check buffer size
2429         if (*pulEncryptedDataLen < size)
2430         {
2431                 *pulEncryptedDataLen = size;
2432                 return CKR_BUFFER_TOO_SMALL;
2433         }
2434
2435         // Get the data
2436         ByteString data;
2437         ByteString encryptedData;
2438
2439         // We must allow input length <= k and therfore need to prepend the data with zeroes.
2440         if (mechanism == AsymMech::RSA) {
2441                 data.wipe(size-ulDataLen);
2442         }
2443
2444         data += ByteString(pData, ulDataLen);
2445
2446         // Encrypt the data
2447         if (!asymCrypto->encrypt(publicKey,data,encryptedData,mechanism))
2448         {
2449                 session->resetOp();
2450                 return CKR_GENERAL_ERROR;
2451         }
2452
2453         // Check size
2454         if (encryptedData.size() != size)
2455         {
2456                 ERROR_MSG("The size of the encrypted data differs from the size of the mechanism");
2457                 session->resetOp();
2458                 return CKR_GENERAL_ERROR;
2459         }
2460         memcpy(pEncryptedData, encryptedData.byte_str(), size);
2461         *pulEncryptedDataLen = size;
2462
2463         session->resetOp();
2464         return CKR_OK;
2465 }
2466
2467 // Perform a single operation encryption operation in the specified session
2468 CK_RV SoftHSM::C_Encrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2469 {
2470         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2471
2472         if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2473         if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2474
2475         // Get the session
2476         Session* session = (Session*)handleManager->getSession(hSession);
2477         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2478
2479         // Check if we are doing the correct operation
2480         if (session->getOpType() != SESSION_OP_ENCRYPT)
2481                 return CKR_OPERATION_NOT_INITIALIZED;
2482
2483         if (session->getSymmetricCryptoOp() != NULL)
2484                 return SymEncrypt(session, pData, ulDataLen,
2485                                   pEncryptedData, pulEncryptedDataLen);
2486         else
2487                 return AsymEncrypt(session, pData, ulDataLen,
2488                                    pEncryptedData, pulEncryptedDataLen);
2489 }
2490
2491 // SymAlgorithm version of C_EncryptUpdate
2492 static CK_RV SymEncryptUpdate(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2493 {
2494         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2495         if (cipher == NULL || !session->getAllowMultiPartOp())
2496         {
2497                 session->resetOp();
2498                 return CKR_OPERATION_NOT_INITIALIZED;
2499         }
2500
2501         // Check data size
2502         size_t blockSize = cipher->getBlockSize();
2503         size_t remainingSize = cipher->getBufferSize();
2504         CK_ULONG maxSize = ulDataLen + remainingSize;
2505         if (cipher->isBlockCipher())
2506         {
2507                 int nrOfBlocks = (ulDataLen + remainingSize) / blockSize;
2508                 maxSize = nrOfBlocks * blockSize;
2509         }
2510         if (!cipher->checkMaximumBytes(ulDataLen))
2511         {
2512                 session->resetOp();
2513                 return CKR_DATA_LEN_RANGE;
2514         }
2515
2516         // Check data size
2517         if (pEncryptedData == NULL_PTR)
2518         {
2519                 *pulEncryptedDataLen = maxSize;
2520                 return CKR_OK;
2521         }
2522
2523         // Check output buffer size
2524         if (*pulEncryptedDataLen < maxSize)
2525         {
2526                 DEBUG_MSG("ulDataLen: %#5x  output buffer size: %#5x  blockSize: %#3x  remainingSize: %#4x  maxSize: %#5x",
2527                           ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize);
2528                 *pulEncryptedDataLen = maxSize;
2529                 return CKR_BUFFER_TOO_SMALL;
2530         }
2531
2532         // Get the data
2533         ByteString data(pData, ulDataLen);
2534         ByteString encryptedData;
2535
2536         // Encrypt the data
2537         if (!cipher->encryptUpdate(data, encryptedData))
2538         {
2539                 session->resetOp();
2540                 return CKR_GENERAL_ERROR;
2541         }
2542         DEBUG_MSG("ulDataLen: %#5x  output buffer size: %#5x  blockSize: %#3x  remainingSize: %#4x  maxSize: %#5x  encryptedData.size(): %#5x",
2543                   ulDataLen, *pulEncryptedDataLen, blockSize, remainingSize, maxSize, encryptedData.size());
2544
2545         // Check output size from crypto. Unrecoverable error if to large.
2546         if (*pulEncryptedDataLen < encryptedData.size())
2547         {
2548                 session->resetOp();
2549                 ERROR_MSG("EncryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2550                           *pulEncryptedDataLen, encryptedData.size());
2551                 return CKR_GENERAL_ERROR;
2552         }
2553
2554         if (encryptedData.size() > 0)
2555         {
2556                 memcpy(pEncryptedData, encryptedData.byte_str(), encryptedData.size());
2557         }
2558         *pulEncryptedDataLen = encryptedData.size();
2559
2560         return CKR_OK;
2561 }
2562
2563 // Feed data to the running encryption operation in a session
2564 CK_RV SoftHSM::C_EncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2565 {
2566         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2567
2568         if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
2569         if (pulEncryptedDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
2570
2571         // Get the session
2572         Session* session = (Session*)handleManager->getSession(hSession);
2573         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2574
2575         // Check if we are doing the correct operation
2576         if (session->getOpType() != SESSION_OP_ENCRYPT)
2577                 return CKR_OPERATION_NOT_INITIALIZED;
2578
2579         if (session->getSymmetricCryptoOp() != NULL)
2580                 return SymEncryptUpdate(session, pData, ulDataLen,
2581                                   pEncryptedData, pulEncryptedDataLen);
2582         else
2583                 return CKR_FUNCTION_NOT_SUPPORTED;
2584 }
2585
2586 // SymAlgorithm version of C_EncryptFinal
2587 static CK_RV SymEncryptFinal(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2588 {
2589         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
2590         if (cipher == NULL || !session->getAllowMultiPartOp())
2591         {
2592                 session->resetOp();
2593                 return CKR_OPERATION_NOT_INITIALIZED;
2594         }
2595
2596         // Check data size
2597         size_t remainingSize = cipher->getBufferSize() + cipher->getTagBytes();
2598         CK_ULONG size = remainingSize;
2599         if (cipher->isBlockCipher())
2600         {
2601                 size_t blockSize = cipher->getBlockSize();
2602                 bool isPadding = cipher->getPaddingMode();
2603                 if ((remainingSize % blockSize) != 0 && !isPadding)
2604                 {
2605                         session->resetOp();
2606                         DEBUG_MSG("Remaining buffer size is not an integral of the block size. Block size: %#2x  Remaining size: %#2x",
2607                                   blockSize, remainingSize);
2608                         return CKR_DATA_LEN_RANGE;
2609                 }
2610                 // when padding: an integral of the block size that is longer than the remaining data.
2611                 size = isPadding ? ((remainingSize + blockSize) / blockSize) * blockSize : remainingSize;
2612         }
2613
2614         // Give required output buffer size.
2615         if (pEncryptedData == NULL_PTR)
2616         {
2617                 *pulEncryptedDataLen = size;
2618                 return CKR_OK;
2619         }
2620
2621         // Check output buffer size
2622         if (*pulEncryptedDataLen < size)
2623         {
2624                 DEBUG_MSG("output buffer size: %#5x  size: %#5x",
2625                           *pulEncryptedDataLen, size);
2626                 *pulEncryptedDataLen = size;
2627                 return CKR_BUFFER_TOO_SMALL;
2628         }
2629
2630         // Finalize encryption
2631         ByteString encryptedFinal;
2632         if (!cipher->encryptFinal(encryptedFinal))
2633         {
2634                 session->resetOp();
2635                 return CKR_GENERAL_ERROR;
2636         }
2637         DEBUG_MSG("output buffer size: %#2x  size: %#2x  encryptedFinal.size(): %#2x",
2638                   *pulEncryptedDataLen, size, encryptedFinal.size());
2639
2640         // Check output size from crypto. Unrecoverable error if to large.
2641         if (*pulEncryptedDataLen < encryptedFinal.size())
2642         {
2643                 session->resetOp();
2644                 ERROR_MSG("EncryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
2645                           *pulEncryptedDataLen, encryptedFinal.size());
2646                 return CKR_GENERAL_ERROR;
2647         }
2648
2649         if (encryptedFinal.size() > 0)
2650         {
2651                 memcpy(pEncryptedData, encryptedFinal.byte_str(), encryptedFinal.size());
2652         }
2653         *pulEncryptedDataLen = encryptedFinal.size();
2654
2655         session->resetOp();
2656         return CKR_OK;
2657 }
2658
2659 // Finalise the encryption operation
2660 CK_RV SoftHSM::C_EncryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen)
2661 {
2662         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2663
2664         // Get the session
2665         Session* session = (Session*)handleManager->getSession(hSession);
2666         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2667
2668         // Check if we are doing the correct operation
2669         if (session->getOpType() != SESSION_OP_ENCRYPT) return CKR_OPERATION_NOT_INITIALIZED;
2670
2671         if (session->getSymmetricCryptoOp() != NULL)
2672                 return SymEncryptFinal(session, pEncryptedData, pulEncryptedDataLen);
2673         else
2674                 return CKR_FUNCTION_NOT_SUPPORTED;
2675 }
2676
2677 // SymAlgorithm version of C_DecryptInit
2678 CK_RV SoftHSM::SymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2679 {
2680         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2681
2682         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2683
2684         // Get the session
2685         Session* session = (Session*)handleManager->getSession(hSession);
2686         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2687
2688         // Get the token
2689         Token* token = session->getToken();
2690         if (token == NULL) return CKR_GENERAL_ERROR;
2691
2692         // Check if we have another operation
2693         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2694
2695         // Check the key handle.
2696         OSObject *key = (OSObject *)handleManager->getObject(hKey);
2697         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2698
2699         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2700         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2701
2702         // Check read user credentials
2703         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2704         if (rv != CKR_OK)
2705         {
2706                 if (rv == CKR_USER_NOT_LOGGED_IN)
2707                         INFO_MSG("User is not authorized");
2708
2709                 return rv;
2710         }
2711
2712         // Check if key can be used for decryption
2713         if (!key->getBooleanValue(CKA_DECRYPT, false))
2714                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2715
2716
2717         // Check if the specified mechanism is allowed for the key
2718         if (!isMechanismPermitted(key, pMechanism))
2719                 return CKR_MECHANISM_INVALID;
2720
2721         // Get the symmetric algorithm matching the mechanism
2722         SymAlgo::Type algo = SymAlgo::Unknown;
2723         SymMode::Type mode = SymMode::Unknown;
2724         bool padding = false;
2725         ByteString iv;
2726         size_t bb = 8;
2727         size_t counterBits = 0;
2728         ByteString aad;
2729         size_t tagBytes = 0;
2730         switch(pMechanism->mechanism) {
2731 #ifndef WITH_FIPS
2732                 case CKM_DES_ECB:
2733                         algo = SymAlgo::DES;
2734                         mode = SymMode::ECB;
2735                         bb = 7;
2736                         break;
2737                 case CKM_DES_CBC:
2738                         algo = SymAlgo::DES;
2739                         mode = SymMode::CBC;
2740                         if (pMechanism->pParameter == NULL_PTR ||
2741                             pMechanism->ulParameterLen == 0)
2742                         {
2743                                 DEBUG_MSG("CBC mode requires an init vector");
2744                                 return CKR_ARGUMENTS_BAD;
2745                         }
2746                         iv.resize(pMechanism->ulParameterLen);
2747                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2748                         bb = 7;
2749                         break;
2750                 case CKM_DES_CBC_PAD:
2751                         algo = SymAlgo::DES;
2752                         mode = SymMode::CBC;
2753                         padding = true;
2754                         if (pMechanism->pParameter == NULL_PTR ||
2755                             pMechanism->ulParameterLen == 0)
2756                         {
2757                                 DEBUG_MSG("CBC mode requires an init vector");
2758                                 return CKR_ARGUMENTS_BAD;
2759                         }
2760                         iv.resize(pMechanism->ulParameterLen);
2761                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2762                         bb = 7;
2763                         break;
2764 #endif
2765                 case CKM_DES3_ECB:
2766                         algo = SymAlgo::DES3;
2767                         mode = SymMode::ECB;
2768                         bb = 7;
2769                         break;
2770                 case CKM_DES3_CBC:
2771                         algo = SymAlgo::DES3;
2772                         mode = SymMode::CBC;
2773                         if (pMechanism->pParameter == NULL_PTR ||
2774                             pMechanism->ulParameterLen == 0)
2775                         {
2776                                 DEBUG_MSG("CBC mode requires an init vector");
2777                                 return CKR_ARGUMENTS_BAD;
2778                         }
2779                         iv.resize(pMechanism->ulParameterLen);
2780                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2781                         bb = 7;
2782                         break;
2783                 case CKM_DES3_CBC_PAD:
2784                         algo = SymAlgo::DES3;
2785                         mode = SymMode::CBC;
2786                         padding = true;
2787                         if (pMechanism->pParameter == NULL_PTR ||
2788                             pMechanism->ulParameterLen == 0)
2789                         {
2790                                 DEBUG_MSG("CBC mode requires an init vector");
2791                                 return CKR_ARGUMENTS_BAD;
2792                         }
2793                         iv.resize(pMechanism->ulParameterLen);
2794                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2795                         bb = 7;
2796                         break;
2797                 case CKM_AES_ECB:
2798                         algo = SymAlgo::AES;
2799                         mode = SymMode::ECB;
2800                         break;
2801                 case CKM_AES_CBC:
2802                         algo = SymAlgo::AES;
2803                         mode = SymMode::CBC;
2804                         if (pMechanism->pParameter == NULL_PTR ||
2805                             pMechanism->ulParameterLen == 0)
2806                         {
2807                                 DEBUG_MSG("CBC mode requires an init vector");
2808                                 return CKR_ARGUMENTS_BAD;
2809                         }
2810                         iv.resize(pMechanism->ulParameterLen);
2811                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2812                         break;
2813                 case CKM_AES_CBC_PAD:
2814                         algo = SymAlgo::AES;
2815                         mode = SymMode::CBC;
2816                         padding = true;
2817                         if (pMechanism->pParameter == NULL_PTR ||
2818                             pMechanism->ulParameterLen == 0)
2819                         {
2820                                 DEBUG_MSG("CBC mode requires an init vector");
2821                                 return CKR_ARGUMENTS_BAD;
2822                         }
2823                         iv.resize(pMechanism->ulParameterLen);
2824                         memcpy(&iv[0], pMechanism->pParameter, pMechanism->ulParameterLen);
2825                         break;
2826                 case CKM_AES_CTR:
2827                         algo = SymAlgo::AES;
2828                         mode = SymMode::CTR;
2829                         if (pMechanism->pParameter == NULL_PTR ||
2830                             pMechanism->ulParameterLen != sizeof(CK_AES_CTR_PARAMS))
2831                         {
2832                                 DEBUG_MSG("CTR mode requires a counter block");
2833                                 return CKR_ARGUMENTS_BAD;
2834                         }
2835                         counterBits = CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->ulCounterBits;
2836                         if (counterBits == 0 || counterBits > 128)
2837                         {
2838                                 DEBUG_MSG("Invalid ulCounterBits");
2839                                 return CKR_MECHANISM_PARAM_INVALID;
2840                         }
2841                         iv.resize(16);
2842                         memcpy(&iv[0], CK_AES_CTR_PARAMS_PTR(pMechanism->pParameter)->cb, 16);
2843                         break;
2844 #ifdef WITH_AES_GCM
2845                 case CKM_AES_GCM:
2846                         algo = SymAlgo::AES;
2847                         mode = SymMode::GCM;
2848                         if (pMechanism->pParameter == NULL_PTR ||
2849                             pMechanism->ulParameterLen != sizeof(CK_GCM_PARAMS))
2850                         {
2851                                 DEBUG_MSG("GCM mode requires parameters");
2852                                 return CKR_ARGUMENTS_BAD;
2853                         }
2854                         iv.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2855                         memcpy(&iv[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pIv, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulIvLen);
2856                         aad.resize(CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2857                         memcpy(&aad[0], CK_GCM_PARAMS_PTR(pMechanism->pParameter)->pAAD, CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulAADLen);
2858                         tagBytes = CK_GCM_PARAMS_PTR(pMechanism->pParameter)->ulTagBits;
2859                         if (tagBytes > 128 || tagBytes % 8 != 0)
2860                         {
2861                                 DEBUG_MSG("Invalid ulTagBits value");
2862                                 return CKR_ARGUMENTS_BAD;
2863                         }
2864                         tagBytes = tagBytes / 8;
2865                         break;
2866 #endif
2867                 default:
2868                         return CKR_MECHANISM_INVALID;
2869         }
2870         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
2871         if (cipher == NULL) return CKR_MECHANISM_INVALID;
2872
2873         SymmetricKey* secretkey = new SymmetricKey();
2874
2875         if (getSymmetricKey(secretkey, token, key) != CKR_OK)
2876         {
2877                 cipher->recycleKey(secretkey);
2878                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2879                 return CKR_GENERAL_ERROR;
2880         }
2881
2882         // adjust key bit length
2883         secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
2884
2885         // Initialize decryption
2886         if (!cipher->decryptInit(secretkey, mode, iv, padding, counterBits, aad, tagBytes))
2887         {
2888                 cipher->recycleKey(secretkey);
2889                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
2890                 return CKR_MECHANISM_INVALID;
2891         }
2892
2893         session->setOpType(SESSION_OP_DECRYPT);
2894         session->setSymmetricCryptoOp(cipher);
2895         session->setAllowMultiPartOp(true);
2896         session->setAllowSinglePartOp(true);
2897         session->setSymmetricKey(secretkey);
2898
2899         return CKR_OK;
2900 }
2901
2902 // AsymAlgorithm version of C_DecryptInit
2903 CK_RV SoftHSM::AsymDecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
2904 {
2905         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
2906
2907         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
2908
2909         // Get the session
2910         Session* session = (Session*)handleManager->getSession(hSession);
2911         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
2912
2913         // Get the token
2914         Token* token = session->getToken();
2915         if (token == NULL) return CKR_GENERAL_ERROR;
2916
2917         // Check if we have another operation
2918         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
2919
2920         // Check the key handle.
2921         OSObject *key = (OSObject *)handleManager->getObject(hKey);
2922         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
2923
2924         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
2925         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
2926
2927         // Check read user credentials
2928         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
2929         if (rv != CKR_OK)
2930         {
2931                 if (rv == CKR_USER_NOT_LOGGED_IN)
2932                         INFO_MSG("User is not authorized");
2933
2934                 return rv;
2935         }
2936
2937         // Check if key can be used for decryption
2938         if (!key->getBooleanValue(CKA_DECRYPT, false))
2939                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
2940
2941         // Check if the specified mechanism is allowed for the key
2942         if (!isMechanismPermitted(key, pMechanism))
2943                 return CKR_MECHANISM_INVALID;
2944
2945         // Get the asymmetric algorithm matching the mechanism
2946         AsymMech::Type mechanism = AsymMech::Unknown;
2947         bool isRSA = false;
2948         switch(pMechanism->mechanism) {
2949                 case CKM_RSA_PKCS:
2950                         mechanism = AsymMech::RSA_PKCS;
2951                         isRSA = true;
2952                         break;
2953                 case CKM_RSA_X_509:
2954                         mechanism = AsymMech::RSA;
2955                         isRSA = true;
2956                         break;
2957                 case CKM_RSA_PKCS_OAEP:
2958                         if (pMechanism->pParameter == NULL_PTR ||
2959                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
2960                         {
2961                                 DEBUG_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
2962                                 return CKR_ARGUMENTS_BAD;
2963                         }
2964                         if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1)
2965                         {
2966                                 DEBUG_MSG("hashAlg must be CKM_SHA_1");
2967                                 return CKR_ARGUMENTS_BAD;
2968                         }
2969                         if (CK_RSA_PKCS_OAEP_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
2970                         {
2971                                 DEBUG_MSG("mgf must be CKG_MGF1_SHA1");
2972                                 return CKR_ARGUMENTS_BAD;
2973                         }
2974
2975                         mechanism = AsymMech::RSA_PKCS_OAEP;
2976                         isRSA = true;
2977                         break;
2978                 default:
2979                         return CKR_MECHANISM_INVALID;
2980         }
2981
2982         AsymmetricAlgorithm* asymCrypto = NULL;
2983         PrivateKey* privateKey = NULL;
2984         if (isRSA)
2985         {
2986                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
2987                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
2988
2989                 privateKey = asymCrypto->newPrivateKey();
2990                 if (privateKey == NULL)
2991                 {
2992                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
2993                         return CKR_HOST_MEMORY;
2994                 }
2995
2996                 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
2997                 {
2998                         asymCrypto->recyclePrivateKey(privateKey);
2999                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
3000                         return CKR_GENERAL_ERROR;
3001                 }
3002         }
3003         else
3004         {
3005                 return CKR_MECHANISM_INVALID;
3006         }
3007
3008         // Check if re-authentication is required
3009         if (key->getBooleanValue(CKA_ALWAYS_AUTHENTICATE, false))
3010         {
3011                 session->setReAuthentication(true);
3012         }
3013
3014         session->setOpType(SESSION_OP_DECRYPT);
3015         session->setAsymmetricCryptoOp(asymCrypto);
3016         session->setMechanism(mechanism);
3017         session->setAllowMultiPartOp(false);
3018         session->setAllowSinglePartOp(true);
3019         session->setPrivateKey(privateKey);
3020
3021         return CKR_OK;
3022 }
3023
3024 // Initialise decryption using the specified object
3025 CK_RV SoftHSM::C_DecryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3026 {
3027         if (isSymMechanism(pMechanism))
3028                 return SymDecryptInit(hSession, pMechanism, hKey);
3029         else
3030                 return AsymDecryptInit(hSession, pMechanism, hKey);
3031 }
3032
3033 // SymAlgorithm version of C_Decrypt
3034 static CK_RV SymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3035 {
3036         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3037         if (cipher == NULL || !session->getAllowSinglePartOp())
3038         {
3039                 session->resetOp();
3040                 return CKR_OPERATION_NOT_INITIALIZED;
3041         }
3042
3043         // Check encrypted data size
3044         if (cipher->isBlockCipher() && ulEncryptedDataLen % cipher->getBlockSize() != 0)
3045         {
3046                 session->resetOp();
3047                 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3048         }
3049         if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3050         {
3051                 session->resetOp();
3052                 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3053         }
3054
3055         if (pData == NULL_PTR)
3056         {
3057                 *pulDataLen = ulEncryptedDataLen;
3058                 return CKR_OK;
3059         }
3060
3061         // Check buffer size
3062         if (*pulDataLen < ulEncryptedDataLen)
3063         {
3064                 *pulDataLen = ulEncryptedDataLen;
3065                 return CKR_BUFFER_TOO_SMALL;
3066         }
3067
3068         // Get the data
3069         ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3070         ByteString data;
3071
3072         // Decrypt the data
3073         if (!cipher->decryptUpdate(encryptedData,data))
3074         {
3075                 session->resetOp();
3076                 return CKR_GENERAL_ERROR;
3077         }
3078
3079         // Finalize decryption
3080         ByteString dataFinal;
3081         if (!cipher->decryptFinal(dataFinal))
3082         {
3083                 session->resetOp();
3084                 return CKR_GENERAL_ERROR;
3085         }
3086         data += dataFinal;
3087         if (data.size() > ulEncryptedDataLen)
3088         {
3089                 data.resize(ulEncryptedDataLen);
3090         }
3091
3092         if (data.size() != 0)
3093         {
3094                 memcpy(pData, data.byte_str(), data.size());
3095         }
3096         *pulDataLen = data.size();
3097
3098         session->resetOp();
3099         return CKR_OK;
3100
3101 }
3102
3103 // AsymAlgorithm version of C_Decrypt
3104 static CK_RV AsymDecrypt(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3105 {
3106         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
3107         AsymMech::Type mechanism = session->getMechanism();
3108         PrivateKey* privateKey = session->getPrivateKey();
3109         if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
3110         {
3111                 session->resetOp();
3112                 return CKR_OPERATION_NOT_INITIALIZED;
3113         }
3114
3115         // Check if re-authentication is required
3116         if (session->getReAuthentication())
3117         {
3118                 session->resetOp();
3119                 return CKR_USER_NOT_LOGGED_IN;
3120         }
3121
3122         // Size of the data
3123         CK_ULONG size = privateKey->getOutputLength();
3124         if (pData == NULL_PTR)
3125         {
3126                 *pulDataLen = size;
3127                 return CKR_OK;
3128         }
3129
3130         // Check buffer size
3131         if (*pulDataLen < size)
3132         {
3133                 *pulDataLen = size;
3134                 return CKR_BUFFER_TOO_SMALL;
3135         }
3136
3137         // Get the data
3138         ByteString encryptedData(pEncryptedData, ulEncryptedDataLen);
3139         ByteString data;
3140
3141         // Decrypt the data
3142         if (!asymCrypto->decrypt(privateKey,encryptedData,data,mechanism))
3143         {
3144                 session->resetOp();
3145                 return CKR_GENERAL_ERROR;
3146         }
3147
3148         // Check size
3149         if (data.size() > size)
3150         {
3151                 ERROR_MSG("The size of the decrypted data exceeds the size of the mechanism");
3152                 session->resetOp();
3153                 return CKR_GENERAL_ERROR;
3154         }
3155         if (data.size() != 0)
3156         {
3157                 memcpy(pData, data.byte_str(), data.size());
3158         }
3159         *pulDataLen = data.size();
3160
3161         session->resetOp();
3162         return CKR_OK;
3163
3164 }
3165
3166 // Perform a single operation decryption in the given session
3167 CK_RV SoftHSM::C_Decrypt(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
3168 {
3169         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3170
3171         if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3172         if (pulDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3173
3174         // Get the session
3175         Session* session = (Session*)handleManager->getSession(hSession);
3176         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3177
3178         // Check if we are doing the correct operation
3179         if (session->getOpType() != SESSION_OP_DECRYPT)
3180                 return CKR_OPERATION_NOT_INITIALIZED;
3181
3182         if (session->getSymmetricCryptoOp() != NULL)
3183                 return SymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3184                                   pData, pulDataLen);
3185         else
3186                 return AsymDecrypt(session, pEncryptedData, ulEncryptedDataLen,
3187                                    pData, pulDataLen);
3188 }
3189
3190 // SymAlgorithm version of C_DecryptUpdate
3191 static CK_RV SymDecryptUpdate(Session* session, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3192 {
3193         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3194         if (cipher == NULL || !session->getAllowMultiPartOp())
3195         {
3196                 session->resetOp();
3197                 return CKR_OPERATION_NOT_INITIALIZED;
3198         }
3199
3200         // Check encrypted data size
3201         size_t blockSize = cipher->getBlockSize();
3202         size_t remainingSize = cipher->getBufferSize();
3203         CK_ULONG maxSize = ulEncryptedDataLen + remainingSize;
3204         if (cipher->isBlockCipher())
3205         {
3206                 // There must always be one block left in padding mode if next operation is DecryptFinal.
3207                 // To guarantee that one byte is removed in padding mode when the number of blocks is calculated.
3208                 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3209                 int nrOfBlocks = (ulEncryptedDataLen + remainingSize - paddingAdjustByte) / blockSize;
3210                 maxSize = nrOfBlocks * blockSize;
3211         }
3212         if (!cipher->checkMaximumBytes(ulEncryptedDataLen))
3213         {
3214                 session->resetOp();
3215                 return CKR_ENCRYPTED_DATA_LEN_RANGE;
3216         }
3217
3218         // Give required output buffer size.
3219         if (pData == NULL_PTR)
3220         {
3221                 *pDataLen = maxSize;
3222                 return CKR_OK;
3223         }
3224
3225         // Check output buffer size
3226         if (*pDataLen < maxSize)
3227         {
3228                 DEBUG_MSG("Output buffer too short   ulEncryptedDataLen: %#5x  output buffer size: %#5x  blockSize: %#3x  remainingSize: %#4x  maxSize: %#5x",
3229                           ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize);
3230                 *pDataLen = maxSize;
3231                 return CKR_BUFFER_TOO_SMALL;
3232         }
3233
3234         // Get the data
3235         ByteString data(pEncryptedData, ulEncryptedDataLen);
3236         ByteString decryptedData;
3237
3238         // Encrypt the data
3239         if (!cipher->decryptUpdate(data, decryptedData))
3240         {
3241                 session->resetOp();
3242                 return CKR_GENERAL_ERROR;
3243         }
3244         DEBUG_MSG("ulEncryptedDataLen: %#5x  output buffer size: %#5x  blockSize: %#3x  remainingSize: %#4x  maxSize: %#5x  decryptedData.size(): %#5x",
3245                   ulEncryptedDataLen, *pDataLen, blockSize, remainingSize, maxSize, decryptedData.size());
3246
3247         // Check output size from crypto. Unrecoverable error if to large.
3248         if (*pDataLen < decryptedData.size())
3249         {
3250                 session->resetOp();
3251                 ERROR_MSG("DecryptUpdate returning too much data. Length of output data buffer is %i but %i bytes was returned by the decrypt.",
3252                                 *pDataLen, decryptedData.size());
3253                 return CKR_GENERAL_ERROR;
3254         }
3255
3256         if (decryptedData.size() > 0)
3257         {
3258                 memcpy(pData, decryptedData.byte_str(), decryptedData.size());
3259         }
3260         *pDataLen = decryptedData.size();
3261
3262         return CKR_OK;
3263 }
3264
3265
3266 // Feed data to the running decryption operation in a session
3267 CK_RV SoftHSM::C_DecryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3268 {
3269         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3270
3271         if (pEncryptedData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3272         if (pDataLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3273
3274         // Get the session
3275         Session* session = (Session*)handleManager->getSession(hSession);
3276         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3277
3278         // Check if we are doing the correct operation
3279         if (session->getOpType() != SESSION_OP_DECRYPT)
3280                 return CKR_OPERATION_NOT_INITIALIZED;
3281
3282         if (session->getSymmetricCryptoOp() != NULL)
3283                 return SymDecryptUpdate(session, pEncryptedData, ulEncryptedDataLen,
3284                                   pData, pDataLen);
3285         else
3286                 return CKR_FUNCTION_NOT_SUPPORTED;
3287 }
3288
3289 static CK_RV SymDecryptFinal(Session* session, CK_BYTE_PTR pDecryptedData, CK_ULONG_PTR pulDecryptedDataLen)
3290 {
3291         SymmetricAlgorithm* cipher = session->getSymmetricCryptoOp();
3292         if (cipher == NULL || !session->getAllowMultiPartOp())
3293         {
3294                 session->resetOp();
3295                 return CKR_OPERATION_NOT_INITIALIZED;
3296         }
3297
3298         // Check encrypted data size
3299         size_t remainingSize = cipher->getBufferSize();
3300         CK_ULONG size = remainingSize;
3301         if (cipher->isBlockCipher())
3302         {
3303                 size_t blockSize = cipher->getBlockSize();
3304                 if (remainingSize % blockSize != 0)
3305                 {
3306                         session->resetOp();
3307                         DEBUG_MSG("Remaining data length is not an integral of the block size. Block size: %#2x  Remaining size: %#2x",
3308                                    blockSize, remainingSize);
3309                         return CKR_ENCRYPTED_DATA_LEN_RANGE;
3310                 }
3311                 // It is at least one padding byte. If no padding the all remains will be returned.
3312                 size_t paddingAdjustByte = cipher->getPaddingMode() ? 1 : 0;
3313                 size = remainingSize - paddingAdjustByte;
3314         }
3315
3316         // Give required output buffer size.
3317         if (pDecryptedData == NULL_PTR)
3318         {
3319                 *pulDecryptedDataLen = size;
3320                 return CKR_OK;
3321         }
3322
3323         // Check output buffer size
3324         if (*pulDecryptedDataLen < size)
3325         {
3326                 DEBUG_MSG("output buffer size: %#5x  size: %#5x",
3327                           *pulDecryptedDataLen, size);
3328                 *pulDecryptedDataLen = size;
3329                 return CKR_BUFFER_TOO_SMALL;
3330         }
3331
3332         // Finalize decryption
3333         ByteString decryptedFinal;
3334         if (!cipher->decryptFinal(decryptedFinal))
3335         {
3336                 session->resetOp();
3337                 return CKR_GENERAL_ERROR;
3338         }
3339         DEBUG_MSG("output buffer size: %#2x  size: %#2x  decryptedFinal.size(): %#2x",
3340                   *pulDecryptedDataLen, size, decryptedFinal.size());
3341
3342         // Check output size from crypto. Unrecoverable error if to large.
3343         if (*pulDecryptedDataLen < decryptedFinal.size())
3344         {
3345                 session->resetOp();
3346                 ERROR_MSG("DecryptFinal returning too much data. Length of output data buffer is %i but %i bytes was returned by the encrypt.",
3347                           *pulDecryptedDataLen, decryptedFinal.size());
3348                 return CKR_GENERAL_ERROR;
3349         }
3350
3351         if (decryptedFinal.size() > 0)
3352         {
3353                 memcpy(pDecryptedData, decryptedFinal.byte_str(), decryptedFinal.size());
3354         }
3355         *pulDecryptedDataLen = decryptedFinal.size();
3356
3357         session->resetOp();
3358         return CKR_OK;
3359 }
3360
3361 // Finalise the decryption operation
3362 CK_RV SoftHSM::C_DecryptFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG_PTR pDataLen)
3363 {
3364         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3365
3366         // Get the session
3367         Session* session = (Session*)handleManager->getSession(hSession);
3368         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3369
3370         // Check if we are doing the correct operation
3371         if (session->getOpType() != SESSION_OP_DECRYPT) return CKR_OPERATION_NOT_INITIALIZED;
3372
3373         if (session->getSymmetricCryptoOp() != NULL)
3374                 return SymDecryptFinal(session, pData, pDataLen);
3375         else
3376                 return CKR_FUNCTION_NOT_SUPPORTED;
3377 }
3378
3379 // Initialise digesting using the specified mechanism in the specified session
3380 CK_RV SoftHSM::C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
3381 {
3382         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3383
3384         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3385
3386         // Get the session
3387         Session* session = (Session*)handleManager->getSession(hSession);
3388         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3389
3390         // Check if we have another operation
3391         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3392
3393         // Get the mechanism
3394         HashAlgo::Type algo = HashAlgo::Unknown;
3395         switch(pMechanism->mechanism) {
3396 #ifndef WITH_FIPS
3397                 case CKM_MD5:
3398                         algo = HashAlgo::MD5;
3399                         break;
3400 #endif
3401                 case CKM_SHA_1:
3402                         algo = HashAlgo::SHA1;
3403                         break;
3404                 case CKM_SHA224:
3405                         algo = HashAlgo::SHA224;
3406                         break;
3407                 case CKM_SHA256:
3408                         algo = HashAlgo::SHA256;
3409                         break;
3410                 case CKM_SHA384:
3411                         algo = HashAlgo::SHA384;
3412                         break;
3413                 case CKM_SHA512:
3414                         algo = HashAlgo::SHA512;
3415                         break;
3416 #ifdef WITH_GOST
3417                 case CKM_GOSTR3411:
3418                         algo = HashAlgo::GOST;
3419                         break;
3420 #endif
3421                 default:
3422                         return CKR_MECHANISM_INVALID;
3423         }
3424         HashAlgorithm* hash = CryptoFactory::i()->getHashAlgorithm(algo);
3425         if (hash == NULL) return CKR_MECHANISM_INVALID;
3426
3427         // Initialize hashing
3428         if (hash->hashInit() == false)
3429         {
3430                 CryptoFactory::i()->recycleHashAlgorithm(hash);
3431                 return CKR_GENERAL_ERROR;
3432         }
3433
3434         session->setOpType(SESSION_OP_DIGEST);
3435         session->setDigestOp(hash);
3436         session->setHashAlgo(algo);
3437
3438         return CKR_OK;
3439 }
3440
3441 // Digest the specified data in a one-pass operation and return the resulting digest
3442 CK_RV SoftHSM::C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3443 {
3444         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3445
3446         if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3447         if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
3448
3449         // Get the session
3450         Session* session = (Session*)handleManager->getSession(hSession);
3451         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3452
3453         // Check if we are doing the correct operation
3454         if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3455
3456         // Return size
3457         CK_ULONG size = session->getDigestOp()->getHashSize();
3458         if (pDigest == NULL_PTR)
3459         {
3460                 *pulDigestLen = size;
3461                 return CKR_OK;
3462         }
3463
3464         // Check buffer size
3465         if (*pulDigestLen < size)
3466         {
3467                 *pulDigestLen = size;
3468                 return CKR_BUFFER_TOO_SMALL;
3469         }
3470
3471         // Get the data
3472         ByteString data(pData, ulDataLen);
3473
3474         // Digest the data
3475         if (session->getDigestOp()->hashUpdate(data) == false)
3476         {
3477                 session->resetOp();
3478                 return CKR_GENERAL_ERROR;
3479         }
3480
3481         // Get the digest
3482         ByteString digest;
3483         if (session->getDigestOp()->hashFinal(digest) == false)
3484         {
3485                 session->resetOp();
3486                 return CKR_GENERAL_ERROR;
3487         }
3488
3489         // Check size
3490         if (digest.size() != size)
3491         {
3492                 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3493                 session->resetOp();
3494                 return CKR_GENERAL_ERROR;
3495         }
3496         memcpy(pDigest, digest.byte_str(), size);
3497         *pulDigestLen = size;
3498
3499         session->resetOp();
3500
3501         return CKR_OK;
3502 }
3503
3504 // Update a running digest operation
3505 CK_RV SoftHSM::C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
3506 {
3507         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3508
3509         if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
3510
3511         // Get the session
3512         Session* session = (Session*)handleManager->getSession(hSession);
3513         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3514
3515         // Check if we are doing the correct operation
3516         if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3517
3518         // Get the data
3519         ByteString data(pPart, ulPartLen);
3520
3521         // Digest the data
3522         if (session->getDigestOp()->hashUpdate(data) == false)
3523         {
3524                 session->resetOp();
3525                 return CKR_GENERAL_ERROR;
3526         }
3527
3528         return CKR_OK;
3529 }
3530
3531 // Update a running digest operation by digesting a secret key with the specified handle
3532 CK_RV SoftHSM::C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3533 {
3534         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3535
3536         // Get the session
3537         Session* session = (Session*)handleManager->getSession(hSession);
3538         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3539
3540         // Check if we are doing the correct operation
3541         if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3542
3543         // Get the token
3544         Token* token = session->getToken();
3545         if (token == NULL) return CKR_GENERAL_ERROR;
3546
3547         // Check the key handle.
3548         OSObject *key = (OSObject *)handleManager->getObject(hObject);
3549         if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
3550
3551         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3552         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3553
3554         // Check read user credentials
3555         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3556         if (rv != CKR_OK)
3557         {
3558                 if (rv == CKR_USER_NOT_LOGGED_IN)
3559                         INFO_MSG("User is not authorized");
3560
3561                 // CKR_USER_NOT_LOGGED_IN is not a valid return code for this function,
3562                 // so we use CKR_GENERAL_ERROR.
3563                 return CKR_GENERAL_ERROR;
3564         }
3565
3566         // Whitelist
3567         HashAlgo::Type algo = session->getHashAlgo();
3568         if (algo != HashAlgo::SHA1 &&
3569             algo != HashAlgo::SHA224 &&
3570             algo != HashAlgo::SHA256 &&
3571             algo != HashAlgo::SHA384 &&
3572             algo != HashAlgo::SHA512)
3573         {
3574                 // Parano...
3575                 if (!key->getBooleanValue(CKA_EXTRACTABLE, false))
3576                         return CKR_KEY_INDIGESTIBLE;
3577                 if (key->getBooleanValue(CKA_SENSITIVE, false))
3578                         return CKR_KEY_INDIGESTIBLE;
3579         }
3580
3581         // Get value
3582         if (!key->attributeExists(CKA_VALUE))
3583                 return CKR_KEY_INDIGESTIBLE;
3584         ByteString keybits;
3585         if (isPrivate)
3586         {
3587                 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
3588                         return CKR_GENERAL_ERROR;
3589         }
3590         else
3591         {
3592                 keybits = key->getByteStringValue(CKA_VALUE);
3593         }
3594
3595         // Digest the value
3596         if (session->getDigestOp()->hashUpdate(keybits) == false)
3597         {
3598                 session->resetOp();
3599                 return CKR_GENERAL_ERROR;
3600         }
3601
3602         return CKR_OK;
3603 }
3604
3605 // Finalise the digest operation in the specified session and return the digest
3606 CK_RV SoftHSM::C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3607 {
3608         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3609
3610         if (pulDigestLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
3611
3612         // Get the session
3613         Session* session = (Session*)handleManager->getSession(hSession);
3614         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3615
3616         // Check if we are doing the correct operation
3617         if (session->getOpType() != SESSION_OP_DIGEST) return CKR_OPERATION_NOT_INITIALIZED;
3618
3619         // Return size
3620         CK_ULONG size = session->getDigestOp()->getHashSize();
3621         if (pDigest == NULL_PTR)
3622         {
3623                 *pulDigestLen = size;
3624                 return CKR_OK;
3625         }
3626
3627         // Check buffer size
3628         if (*pulDigestLen < size)
3629         {
3630                 *pulDigestLen = size;
3631                 return CKR_BUFFER_TOO_SMALL;
3632         }
3633
3634         // Get the digest
3635         ByteString digest;
3636         if (session->getDigestOp()->hashFinal(digest) == false)
3637         {
3638                 session->resetOp();
3639                 return CKR_GENERAL_ERROR;
3640         }
3641
3642         // Check size
3643         if (digest.size() != size)
3644         {
3645                 ERROR_MSG("The size of the digest differ from the size of the mechanism");
3646                 session->resetOp();
3647                 return CKR_GENERAL_ERROR;
3648         }
3649         memcpy(pDigest, digest.byte_str(), size);
3650         *pulDigestLen = size;
3651
3652         session->resetOp();
3653
3654         return CKR_OK;
3655 }
3656
3657 // Sign*/Verify*() is for MACs too
3658 static bool isMacMechanism(CK_MECHANISM_PTR pMechanism)
3659 {
3660         if (pMechanism == NULL_PTR) return false;
3661
3662         switch(pMechanism->mechanism) {
3663                 case CKM_MD5_HMAC:
3664                 case CKM_SHA_1_HMAC:
3665                 case CKM_SHA224_HMAC:
3666                 case CKM_SHA256_HMAC:
3667                 case CKM_SHA384_HMAC:
3668                 case CKM_SHA512_HMAC:
3669 #ifdef WITH_GOST
3670                 case CKM_GOSTR3411_HMAC:
3671 #endif
3672                 case CKM_DES3_CMAC:
3673                 case CKM_AES_CMAC:
3674                         return true;
3675                 default:
3676                         return false;
3677         }
3678 }
3679
3680 // MacAlgorithm version of C_SignInit
3681 CK_RV SoftHSM::MacSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3682 {
3683         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3684
3685         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3686
3687         // Get the session
3688         Session* session = (Session*)handleManager->getSession(hSession);
3689         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3690
3691         // Check if we have another operation
3692         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3693
3694         // Get the token
3695         Token* token = session->getToken();
3696         if (token == NULL) return CKR_GENERAL_ERROR;
3697
3698         // Check the key handle.
3699         OSObject *key = (OSObject *)handleManager->getObject(hKey);
3700         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3701
3702         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3703         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3704
3705         // Check read user credentials
3706         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3707         if (rv != CKR_OK)
3708         {
3709                 if (rv == CKR_USER_NOT_LOGGED_IN)
3710                         INFO_MSG("User is not authorized");
3711
3712                 return rv;
3713         }
3714
3715         // Check if key can be used for signing
3716         if (!key->getBooleanValue(CKA_SIGN, false))
3717                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3718
3719         // Check if the specified mechanism is allowed for the key
3720         if (!isMechanismPermitted(key, pMechanism))
3721                 return CKR_MECHANISM_INVALID;
3722
3723         // Get key info
3724         CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
3725
3726         // Get the MAC algorithm matching the mechanism
3727         // Also check mechanism constraints
3728         MacAlgo::Type algo = MacAlgo::Unknown;
3729         size_t bb = 8;
3730         size_t minSize = 0;
3731         switch(pMechanism->mechanism) {
3732 #ifndef WITH_FIPS
3733                 case CKM_MD5_HMAC:
3734                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
3735                                 return CKR_KEY_TYPE_INCONSISTENT;
3736                         minSize = 16;
3737                         algo = MacAlgo::HMAC_MD5;
3738                         break;
3739 #endif
3740                 case CKM_SHA_1_HMAC:
3741                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
3742                                 return CKR_KEY_TYPE_INCONSISTENT;
3743                         minSize = 20;
3744                         algo = MacAlgo::HMAC_SHA1;
3745                         break;
3746                 case CKM_SHA224_HMAC:
3747                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
3748                                 return CKR_KEY_TYPE_INCONSISTENT;
3749                         minSize = 28;
3750                         algo = MacAlgo::HMAC_SHA224;
3751                         break;
3752                 case CKM_SHA256_HMAC:
3753                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
3754                                 return CKR_KEY_TYPE_INCONSISTENT;
3755                         minSize = 32;
3756                         algo = MacAlgo::HMAC_SHA256;
3757                         break;
3758                 case CKM_SHA384_HMAC:
3759                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
3760                                 return CKR_KEY_TYPE_INCONSISTENT;
3761                         minSize = 48;
3762                         algo = MacAlgo::HMAC_SHA384;
3763                         break;
3764                 case CKM_SHA512_HMAC:
3765                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
3766                                 return CKR_KEY_TYPE_INCONSISTENT;
3767                         minSize = 64;
3768                         algo = MacAlgo::HMAC_SHA512;
3769                         break;
3770 #ifdef WITH_GOST
3771                 case CKM_GOSTR3411_HMAC:
3772                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
3773                                 return CKR_KEY_TYPE_INCONSISTENT;
3774                         minSize = 32;
3775                         algo = MacAlgo::HMAC_GOST;
3776                         break;
3777 #endif
3778                 case CKM_DES3_CMAC:
3779                         if (keyType != CKK_DES2 && keyType != CKK_DES3)
3780                                 return CKR_KEY_TYPE_INCONSISTENT;
3781                         algo = MacAlgo::CMAC_DES;
3782                         bb = 7;
3783                         break;
3784                 case CKM_AES_CMAC:
3785                         if (keyType != CKK_AES)
3786                                 return CKR_KEY_TYPE_INCONSISTENT;
3787                         algo = MacAlgo::CMAC_AES;
3788                         break;
3789                 default:
3790                         return CKR_MECHANISM_INVALID;
3791         }
3792         MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
3793         if (mac == NULL) return CKR_MECHANISM_INVALID;
3794
3795         SymmetricKey* privkey = new SymmetricKey();
3796
3797         if (getSymmetricKey(privkey, token, key) != CKR_OK)
3798         {
3799                 mac->recycleKey(privkey);
3800                 CryptoFactory::i()->recycleMacAlgorithm(mac);
3801                 return CKR_GENERAL_ERROR;
3802         }
3803
3804         // Adjust key bit length
3805         privkey->setBitLen(privkey->getKeyBits().size() * bb);
3806
3807         // Check key size
3808         if (privkey->getBitLen() < (minSize*8))
3809         {
3810                 mac->recycleKey(privkey);
3811                 CryptoFactory::i()->recycleMacAlgorithm(mac);
3812                 return CKR_KEY_SIZE_RANGE;
3813         }
3814
3815         // Initialize signing
3816         if (!mac->signInit(privkey))
3817         {
3818                 mac->recycleKey(privkey);
3819                 CryptoFactory::i()->recycleMacAlgorithm(mac);
3820                 return CKR_MECHANISM_INVALID;
3821         }
3822
3823         session->setOpType(SESSION_OP_SIGN);
3824         session->setMacOp(mac);
3825         session->setAllowMultiPartOp(true);
3826         session->setAllowSinglePartOp(true);
3827         session->setSymmetricKey(privkey);
3828
3829         return CKR_OK;
3830 }
3831
3832 // AsymmetricAlgorithm version of C_SignInit
3833 CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
3834 {
3835         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
3836
3837         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
3838
3839         // Get the session
3840         Session* session = (Session*)handleManager->getSession(hSession);
3841         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
3842
3843         // Check if we have another operation
3844         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
3845
3846         // Get the token
3847         Token* token = session->getToken();
3848         if (token == NULL) return CKR_GENERAL_ERROR;
3849
3850         // Check the key handle.
3851         OSObject *key = (OSObject *)handleManager->getObject(hKey);
3852         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
3853
3854         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
3855         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
3856
3857         // Check read user credentials
3858         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
3859         if (rv != CKR_OK)
3860         {
3861                 if (rv == CKR_USER_NOT_LOGGED_IN)
3862                         INFO_MSG("User is not authorized");
3863
3864                 return rv;
3865         }
3866
3867         // Check if key can be used for signing
3868         if (!key->getBooleanValue(CKA_SIGN, false))
3869                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
3870
3871         // Check if the specified mechanism is allowed for the key
3872         if (!isMechanismPermitted(key, pMechanism))
3873                 return CKR_MECHANISM_INVALID;
3874
3875         // Get the asymmetric algorithm matching the mechanism
3876         AsymMech::Type mechanism = AsymMech::Unknown;
3877         void* param = NULL;
3878         size_t paramLen = 0;
3879         RSA_PKCS_PSS_PARAMS pssParam;
3880         bool bAllowMultiPartOp;
3881         bool isRSA = false;
3882         bool isDSA = false;
3883         bool isECDSA = false;
3884         switch(pMechanism->mechanism) {
3885                 case CKM_RSA_PKCS:
3886                         mechanism = AsymMech::RSA_PKCS;
3887                         bAllowMultiPartOp = false;
3888                         isRSA = true;
3889                         break;
3890                 case CKM_RSA_X_509:
3891                         mechanism = AsymMech::RSA;
3892                         bAllowMultiPartOp = false;
3893                         isRSA = true;
3894                         break;
3895 #ifndef WITH_FIPS
3896                 case CKM_MD5_RSA_PKCS:
3897                         mechanism = AsymMech::RSA_MD5_PKCS;
3898                         bAllowMultiPartOp = true;
3899                         isRSA = true;
3900                         break;
3901 #endif
3902                 case CKM_SHA1_RSA_PKCS:
3903                         mechanism = AsymMech::RSA_SHA1_PKCS;
3904                         bAllowMultiPartOp = true;
3905                         isRSA = true;
3906                         break;
3907                 case CKM_SHA224_RSA_PKCS:
3908                         mechanism = AsymMech::RSA_SHA224_PKCS;
3909                         bAllowMultiPartOp = true;
3910                         isRSA = true;
3911                         break;
3912                 case CKM_SHA256_RSA_PKCS:
3913                         mechanism = AsymMech::RSA_SHA256_PKCS;
3914                         bAllowMultiPartOp = true;
3915                         isRSA = true;
3916                         break;
3917                 case CKM_SHA384_RSA_PKCS:
3918                         mechanism = AsymMech::RSA_SHA384_PKCS;
3919                         bAllowMultiPartOp = true;
3920                         isRSA = true;
3921                         break;
3922                 case CKM_SHA512_RSA_PKCS:
3923                         mechanism = AsymMech::RSA_SHA512_PKCS;
3924                         bAllowMultiPartOp = true;
3925                         isRSA = true;
3926                         break;
3927 #ifdef WITH_RAW_PSS
3928                 case CKM_RSA_PKCS_PSS:
3929                         if (pMechanism->pParameter == NULL_PTR ||
3930                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
3931                         {
3932                                 ERROR_MSG("Invalid RSA-PSS parameters");
3933                                 return CKR_ARGUMENTS_BAD;
3934                         }
3935                         mechanism = AsymMech::RSA_PKCS_PSS;
3936                         unsigned long allowedMgf;
3937
3938                         switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
3939                                 case CKM_SHA_1:
3940                                         pssParam.hashAlg = HashAlgo::SHA1;
3941                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3942                                         allowedMgf = CKG_MGF1_SHA1;
3943                                         break;
3944                                 case CKM_SHA224:
3945                                         pssParam.hashAlg = HashAlgo::SHA224;
3946                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
3947                                         allowedMgf = CKG_MGF1_SHA224;
3948                                         break;
3949                                 case CKM_SHA256:
3950                                         pssParam.hashAlg = HashAlgo::SHA256;
3951                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
3952                                         allowedMgf = CKG_MGF1_SHA256;
3953                                         break;
3954                                 case CKM_SHA384:
3955                                         pssParam.hashAlg = HashAlgo::SHA384;
3956                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
3957                                         allowedMgf = CKG_MGF1_SHA384;
3958                                         break;
3959                                 case CKM_SHA512:
3960                                         pssParam.hashAlg = HashAlgo::SHA512;
3961                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
3962                                         allowedMgf = CKG_MGF1_SHA512;
3963                                         break;
3964                                 default:
3965                                         ERROR_MSG("Invalid RSA-PSS hash");
3966                                         return CKR_ARGUMENTS_BAD;
3967                         }
3968
3969                         if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != allowedMgf) {
3970                                 ERROR_MSG("Hash and MGF don't match");
3971                                 return CKR_ARGUMENTS_BAD;
3972                         }
3973
3974                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3975                         param = &pssParam;
3976                         paramLen = sizeof(pssParam);
3977                         bAllowMultiPartOp = false;
3978                         isRSA = true;
3979                         break;
3980 #endif
3981                 case CKM_SHA1_RSA_PKCS_PSS:
3982                         if (pMechanism->pParameter == NULL_PTR ||
3983                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
3984                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
3985                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
3986                         {
3987                                 ERROR_MSG("Invalid parameters");
3988                                 return CKR_ARGUMENTS_BAD;
3989                         }
3990                         mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
3991                         pssParam.hashAlg = HashAlgo::SHA1;
3992                         pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
3993                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
3994                         param = &pssParam;
3995                         paramLen = sizeof(pssParam);
3996                         bAllowMultiPartOp = true;
3997                         isRSA = true;
3998                         break;
3999                 case CKM_SHA224_RSA_PKCS_PSS:
4000                         if (pMechanism->pParameter == NULL_PTR ||
4001                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4002                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
4003                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
4004                         {
4005                                 ERROR_MSG("Invalid parameters");
4006                                 return CKR_ARGUMENTS_BAD;
4007                         }
4008                         mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
4009                         pssParam.hashAlg = HashAlgo::SHA224;
4010                         pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
4011                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4012                         param = &pssParam;
4013                         paramLen = sizeof(pssParam);
4014                         bAllowMultiPartOp = true;
4015                         isRSA = true;
4016                         break;
4017                 case CKM_SHA256_RSA_PKCS_PSS:
4018                         if (pMechanism->pParameter == NULL_PTR ||
4019                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4020                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
4021                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
4022                         {
4023                                 ERROR_MSG("Invalid parameters");
4024                                 return CKR_ARGUMENTS_BAD;
4025                         }
4026                         mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
4027                         pssParam.hashAlg = HashAlgo::SHA256;
4028                         pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
4029                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4030                         param = &pssParam;
4031                         paramLen = sizeof(pssParam);
4032                         bAllowMultiPartOp = true;
4033                         isRSA = true;
4034                         break;
4035                 case CKM_SHA384_RSA_PKCS_PSS:
4036                         if (pMechanism->pParameter == NULL_PTR ||
4037                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4038                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
4039                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
4040                         {
4041                                 ERROR_MSG("Invalid parameters");
4042                                 return CKR_ARGUMENTS_BAD;
4043                         }
4044                         mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
4045                         pssParam.hashAlg = HashAlgo::SHA384;
4046                         pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
4047                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4048                         param = &pssParam;
4049                         paramLen = sizeof(pssParam);
4050                         bAllowMultiPartOp = true;
4051                         isRSA = true;
4052                         break;
4053                 case CKM_SHA512_RSA_PKCS_PSS:
4054                         if (pMechanism->pParameter == NULL_PTR ||
4055                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
4056                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
4057                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
4058                         {
4059                                 ERROR_MSG("Invalid parameters");
4060                                 return CKR_ARGUMENTS_BAD;
4061                         }
4062                         mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
4063                         pssParam.hashAlg = HashAlgo::SHA512;
4064                         pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
4065                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
4066                         param = &pssParam;
4067                         paramLen = sizeof(pssParam);
4068                         bAllowMultiPartOp = true;
4069                         isRSA = true;
4070                         break;
4071                 case CKM_DSA:
4072                         mechanism = AsymMech::DSA;
4073                         bAllowMultiPartOp = false;
4074                         isDSA = true;
4075                         break;
4076                 case CKM_DSA_SHA1:
4077                         mechanism = AsymMech::DSA_SHA1;
4078                         bAllowMultiPartOp = true;
4079                         isDSA = true;
4080                         break;
4081                 case CKM_DSA_SHA224:
4082                         mechanism = AsymMech::DSA_SHA224;
4083                         bAllowMultiPartOp = true;
4084                         isDSA = true;
4085                         break;
4086                 case CKM_DSA_SHA256:
4087                         mechanism = AsymMech::DSA_SHA256;
4088                         bAllowMultiPartOp = true;
4089                         isDSA = true;
4090                         break;
4091                 case CKM_DSA_SHA384:
4092                         mechanism = AsymMech::DSA_SHA384;
4093                         bAllowMultiPartOp = true;
4094                         isDSA = true;
4095                         break;
4096                 case CKM_DSA_SHA512:
4097                         mechanism = AsymMech::DSA_SHA512;
4098                         bAllowMultiPartOp = true;
4099                         isDSA = true;
4100                         break;
4101 #ifdef WITH_ECC
4102                 case CKM_ECDSA:
4103                         mechanism = AsymMech::ECDSA;
4104                         bAllowMultiPartOp = false;
4105                         isECDSA = true;
4106                         break;
4107 #endif
4108 #ifdef WITH_GOST
4109                 case CKM_GOSTR3410:
4110                         mechanism = AsymMech::GOST;
4111                         bAllowMultiPartOp = false;
4112                         break;
4113                 case CKM_GOSTR3410_WITH_GOSTR3411:
4114                         mechanism = AsymMech::GOST_GOST;
4115                         bAllowMultiPartOp = true;
4116                         break;
4117 #endif
4118                 default:
4119                         return CKR_MECHANISM_INVALID;
4120         }
4121
4122         AsymmetricAlgorithm* asymCrypto = NULL;
4123         PrivateKey* privateKey = NULL;
4124         if (isRSA)
4125         {
4126                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
4127                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4128
4129                 privateKey = asymCrypto->newPrivateKey();
4130                 if (privateKey == NULL)
4131                 {
4132                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4133                         return CKR_HOST_MEMORY;
4134                 }
4135
4136                 if (getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key) != CKR_OK)
4137                 {
4138                         asymCrypto->recyclePrivateKey(privateKey);
4139                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4140                         return CKR_GENERAL_ERROR;
4141                 }
4142         }
4143         else if (isDSA)
4144         {
4145                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
4146                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4147
4148                 privateKey = asymCrypto->newPrivateKey();
4149                 if (privateKey == NULL)
4150                 {
4151                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4152                         return CKR_HOST_MEMORY;
4153                 }
4154
4155                 if (getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key) != CKR_OK)
4156                 {
4157                         asymCrypto->recyclePrivateKey(privateKey);
4158                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4159                         return CKR_GENERAL_ERROR;
4160                 }
4161         }
4162 #ifdef WITH_ECC
4163         else if (isECDSA)
4164         {
4165                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
4166                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4167
4168                 privateKey = asymCrypto->newPrivateKey();
4169                 if (privateKey == NULL)
4170                 {
4171                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4172                         return CKR_HOST_MEMORY;
4173                 }
4174
4175                 if (getECPrivateKey((ECPrivateKey*)privateKey, token, key) != CKR_OK)
4176                 {
4177                         asymCrypto->recyclePrivateKey(privateKey);
4178                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4179                         return CKR_GENERAL_ERROR;
4180                 }
4181         }
4182 #endif
4183         else
4184         {
4185 #ifdef WITH_GOST
4186                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
4187                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
4188
4189                 privateKey = asymCrypto->newPrivateKey();
4190                 if (privateKey == NULL)
4191                 {
4192                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4193                         return CKR_HOST_MEMORY;
4194                 }
4195
4196                 if (getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key) != CKR_OK)
4197                 {
4198                         asymCrypto->recyclePrivateKey(privateKey);
4199                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4200                         return CKR_GENERAL_ERROR;
4201                 }
4202 #else
4203                 return CKR_MECHANISM_INVALID;
4204 #endif
4205         }
4206     // Initialize signing
4207     if(isHWavailable)
4208     {
4209         // Extract HW key handle
4210         CK_ULONG hwKeyHandle = 0;
4211         if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4212         {
4213             LOG("ERROR in extracting key handle \n");
4214             session->resetOp();
4215             return CKR_GENERAL_ERROR;
4216         }
4217         LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4218         void *hwCryptoOpaque;
4219
4220         if(HwInfraSignInit(&hwKeyHandle, mechanism, param, paramLen, &hwCryptoOpaque) != 0)
4221         {
4222             return CKR_MECHANISM_INVALID;
4223         }
4224         session->setHwCryptoOpaque(hwCryptoOpaque);
4225     }
4226     else
4227     {
4228         if (bAllowMultiPartOp && !asymCrypto->signInit(privateKey,mechanism,param,paramLen))
4229         {
4230             asymCrypto->recyclePrivateKey(privateKey);
4231             CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
4232             return CKR_MECHANISM_INVALID;
4233         }
4234     }
4235         session->setOpType(SESSION_OP_SIGN);
4236         session->setAsymmetricCryptoOp(asymCrypto);
4237         session->setMechanism(mechanism);
4238         session->setParameters(param, paramLen);
4239         session->setAllowMultiPartOp(bAllowMultiPartOp);
4240         session->setAllowSinglePartOp(true);
4241         session->setPrivateKey(privateKey);
4242         session->setKeyHandle(hKey);
4243         return CKR_OK;
4244 }
4245
4246 // Initialise a signing operation using the specified key and mechanism
4247 CK_RV SoftHSM::C_SignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4248 {
4249         if (isMacMechanism(pMechanism))
4250                 return MacSignInit(hSession, pMechanism, hKey);
4251         else
4252                 return AsymSignInit(hSession, pMechanism, hKey);
4253 }
4254
4255 // MacAlgorithm version of C_Sign
4256 static CK_RV MacSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4257 {
4258         MacAlgorithm* mac = session->getMacOp();
4259         if (mac == NULL || !session->getAllowSinglePartOp())
4260         {
4261                 session->resetOp();
4262                 return CKR_OPERATION_NOT_INITIALIZED;
4263         }
4264
4265         // Size of the signature
4266         CK_ULONG size = mac->getMacSize();
4267         if (pSignature == NULL_PTR)
4268         {
4269                 *pulSignatureLen = size;
4270                 return CKR_OK;
4271         }
4272
4273         // Check buffer size
4274         if (*pulSignatureLen < size)
4275         {
4276                 *pulSignatureLen = size;
4277                 return CKR_BUFFER_TOO_SMALL;
4278         }
4279
4280         // Get the data
4281         ByteString data(pData, ulDataLen);
4282
4283         // Sign the data
4284         if (!mac->signUpdate(data))
4285         {
4286                 session->resetOp();
4287                 return CKR_GENERAL_ERROR;
4288         }
4289
4290         // Get the signature
4291         ByteString signature;
4292         if (!mac->signFinal(signature))
4293         {
4294                 session->resetOp();
4295                 return CKR_GENERAL_ERROR;
4296         }
4297
4298         // Check size
4299         if (signature.size() != size)
4300         {
4301                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4302                 session->resetOp();
4303                 return CKR_GENERAL_ERROR;
4304         }
4305         memcpy(pSignature, signature.byte_str(), size);
4306         *pulSignatureLen = size;
4307
4308         session->resetOp();
4309         return CKR_OK;
4310 }
4311
4312 // AsymmetricAlgorithm version of C_Sign
4313 static CK_RV AsymSign(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4314 {
4315         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4316         AsymMech::Type mechanism = session->getMechanism();
4317         PrivateKey* privateKey = session->getPrivateKey();
4318         size_t paramLen;
4319         void* param = session->getParameters(paramLen);
4320         if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4321         {
4322                 session->resetOp();
4323                 return CKR_OPERATION_NOT_INITIALIZED;
4324         }
4325
4326         // Check if re-authentication is required
4327         if (session->getReAuthentication())
4328         {
4329                 session->resetOp();
4330                 return CKR_USER_NOT_LOGGED_IN;
4331         }
4332
4333         // Size of the signature
4334         CK_ULONG size = privateKey->getOutputLength();
4335         if (pSignature == NULL_PTR)
4336         {
4337                 *pulSignatureLen = size;
4338                 return CKR_OK;
4339         }
4340
4341         // Check buffer size
4342         if (*pulSignatureLen < size)
4343         {
4344                 *pulSignatureLen = size;
4345                 return CKR_BUFFER_TOO_SMALL;
4346         }
4347
4348         // Get the data
4349         ByteString data;
4350
4351         // We must allow input length <= k and therfore need to prepend the data with zeroes.
4352         if (mechanism == AsymMech::RSA) {
4353                 data.wipe(size-ulDataLen);
4354         }
4355
4356         data += ByteString(pData, ulDataLen);
4357         ByteString signature;
4358
4359         // Sign the data
4360         if (session->getAllowMultiPartOp())
4361         {
4362                 if (!asymCrypto->signUpdate(data) ||
4363                     !asymCrypto->signFinal(signature))
4364                 {
4365                         session->resetOp();
4366                         return CKR_GENERAL_ERROR;
4367                 }
4368         }
4369         else if (!asymCrypto->sign(privateKey,data,signature,mechanism,param,paramLen))
4370         {
4371                 session->resetOp();
4372                 return CKR_GENERAL_ERROR;
4373         }
4374
4375         // Check size
4376         if (signature.size() != size)
4377         {
4378                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4379                 session->resetOp();
4380                 return CKR_GENERAL_ERROR;
4381         }
4382         memcpy(pSignature, signature.byte_str(), size);
4383         *pulSignatureLen = size;
4384
4385         session->resetOp();
4386         return CKR_OK;
4387 }
4388
4389 // AsymmetricAlgorithm version of C_Sign
4390 static CK_RV AsymSignHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4391 {
4392         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4393         AsymMech::Type mechanism = session->getMechanism();
4394         PrivateKey* privateKey = session->getPrivateKey();
4395         CK_ULONG hwKeyHandle = 0;
4396         if (asymCrypto == NULL || !session->getAllowSinglePartOp() || privateKey == NULL)
4397         {
4398                 session->resetOp();
4399                 return CKR_OPERATION_NOT_INITIALIZED;
4400         }
4401
4402         // Size of the signature
4403         CK_ULONG size = privateKey->getOutputLength();
4404         if (pSignature == NULL_PTR)
4405         {
4406                 *pulSignatureLen = size;
4407                 return CKR_OK;
4408         }
4409
4410         // Check buffer sizeq
4411         if (*pulSignatureLen < size)
4412         {
4413                 *pulSignatureLen = size;
4414                 return CKR_BUFFER_TOO_SMALL;
4415         }
4416
4417         // Get the data
4418         ByteString data;
4419
4420         // We must allow input length <= k and therfore need to prepend the data with zeroes.
4421         if (mechanism == AsymMech::RSA) {
4422                 data.wipe(size-ulDataLen);
4423         }
4424
4425         data += ByteString(pData, ulDataLen);
4426         ByteString signature;
4427
4428         // Extract HW key handle
4429     CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4430     if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4431     {
4432         LOG("ERROR in extracting key handle \n");
4433                 session->resetOp();
4434                 return CKR_GENERAL_ERROR;
4435     }
4436     LOG("Extracted key handle value: %lu \n", hwKeyHandle);
4437
4438     void *hwCryptoOpaque = session->getHwCryptoOpaque();
4439         // Sign the data
4440     if(HwInfraSign((void *)&hwKeyHandle, mechanism,
4441                  pData, ulDataLen, hwCryptoOpaque,
4442                  pSignature, (int *) pulSignatureLen) != 0)
4443     {
4444                 session->resetOp();
4445                 return CKR_GENERAL_ERROR;
4446     }
4447
4448         // Check size
4449         if (*pulSignatureLen != size)
4450         {
4451                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4452                 session->resetOp();
4453                 return CKR_GENERAL_ERROR;
4454         }
4455
4456
4457         session->resetOp();
4458         return CKR_OK;
4459 }
4460
4461
4462
4463 // Sign the data in a single pass operation
4464 CK_RV SoftHSM::C_Sign(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4465 {
4466         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4467
4468         if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
4469         if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4470
4471         // Get the session
4472         Session* session = (Session*)handleManager->getSession(hSession);
4473         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4474
4475         // Check if we are doing the correct operation
4476         if (session->getOpType() != SESSION_OP_SIGN)
4477                 return CKR_OPERATION_NOT_INITIALIZED;
4478
4479         if (session->getMacOp() != NULL)
4480                 return MacSign(session, pData, ulDataLen,
4481                                pSignature, pulSignatureLen);
4482         else
4483     {
4484         if(isHWavailable)
4485         {
4486                     return AsymSignHW(hSession, session, pData, ulDataLen,
4487                                 pSignature, pulSignatureLen);
4488         }
4489         else
4490         {
4491                     return AsymSign(session, pData, ulDataLen,
4492                                 pSignature, pulSignatureLen);
4493         }
4494     }
4495 }
4496
4497 // MacAlgorithm version of C_SignUpdate
4498 static CK_RV MacSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4499 {
4500         MacAlgorithm* mac = session->getMacOp();
4501         if (mac == NULL || !session->getAllowMultiPartOp())
4502         {
4503                 session->resetOp();
4504                 return CKR_OPERATION_NOT_INITIALIZED;
4505         }
4506
4507         // Get the part
4508         ByteString part(pPart, ulPartLen);
4509
4510         // Sign the data
4511         if (!mac->signUpdate(part))
4512         {
4513                 session->resetOp();
4514                 return CKR_GENERAL_ERROR;
4515         }
4516
4517         session->setAllowSinglePartOp(false);
4518         return CKR_OK;
4519 }
4520
4521 // AsymmetricAlgorithm version of C_SignUpdate
4522 static CK_RV AsymSignUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4523 {
4524         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4525         if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4526         {
4527                 session->resetOp();
4528                 return CKR_OPERATION_NOT_INITIALIZED;
4529         }
4530
4531         // Check if re-authentication is required
4532         if (session->getReAuthentication())
4533         {
4534                 session->resetOp();
4535                 return CKR_USER_NOT_LOGGED_IN;
4536         }
4537
4538         // Get the part
4539         ByteString part(pPart, ulPartLen);
4540
4541         // Sign the data
4542         if (!asymCrypto->signUpdate(part))
4543         {
4544                 session->resetOp();
4545                 return CKR_GENERAL_ERROR;
4546         }
4547
4548         session->setAllowSinglePartOp(false);
4549         return CKR_OK;
4550 }
4551
4552 // AsymmetricAlgorithm version of C_SignUpdate
4553 static CK_RV AsymSignUpdateHW( CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4554 {
4555         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4556         if (asymCrypto == NULL || !session->getAllowMultiPartOp())
4557         {
4558                 session->resetOp();
4559                 return CKR_OPERATION_NOT_INITIALIZED;
4560         }
4561
4562         // Check if re-authentication is required
4563         if (session->getReAuthentication())
4564         {
4565                 session->resetOp();
4566                 return CKR_USER_NOT_LOGGED_IN;
4567         }
4568
4569         // Get the part
4570         ByteString part(pPart, ulPartLen);
4571
4572 #if 0
4573         // Sign the data
4574         if (!asymCrypto->signUpdate(part))
4575         {
4576                 session->resetOp();
4577                 return CKR_GENERAL_ERROR;
4578         }
4579 #endif
4580     AsymMech::Type mechanism = session->getMechanism();
4581     // Extract HW key handle
4582     CK_ULONG hwKeyHandle = 0;
4583     CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4584     if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4585     {
4586         LOG("ERROR in extracting key handle \n");
4587                 session->resetOp();
4588                 return CKR_GENERAL_ERROR;
4589     }
4590
4591     void *hwCryptoOpaque = session->getHwCryptoOpaque();
4592         // Sign the data
4593     if(HwInfraSignUpdate((void *)&hwKeyHandle, mechanism,
4594                  pPart, ulPartLen, hwCryptoOpaque ) != 0)
4595     {
4596                 session->resetOp();
4597                 return CKR_GENERAL_ERROR;
4598     }
4599
4600         session->setAllowSinglePartOp(false);
4601         return CKR_OK;
4602 }
4603
4604
4605
4606 // Update a running signing operation with additional data
4607 CK_RV SoftHSM::C_SignUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
4608 {
4609         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4610
4611         if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
4612
4613         // Get the session
4614         Session* session = (Session*)handleManager->getSession(hSession);
4615         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4616
4617         // Check if we are doing the correct operation
4618         if (session->getOpType() != SESSION_OP_SIGN)
4619                 return CKR_OPERATION_NOT_INITIALIZED;
4620
4621         if (session->getMacOp() != NULL)
4622                 return MacSignUpdate(session, pPart, ulPartLen);
4623         else
4624         {
4625                 if(isHWavailable)
4626                 {
4627                   return AsymSignUpdateHW(hSession, session, pPart, ulPartLen);
4628                 }
4629                 else
4630                 {
4631
4632                   return AsymSignUpdate(session, pPart, ulPartLen);
4633                 }
4634         }
4635 }
4636
4637 // MacAlgorithm version of C_SignFinal
4638 static CK_RV MacSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4639 {
4640         MacAlgorithm* mac = session->getMacOp();
4641         if (mac == NULL)
4642         {
4643                 session->resetOp();
4644                 return CKR_OPERATION_NOT_INITIALIZED;
4645         }
4646
4647         // Size of the signature
4648         CK_ULONG size = mac->getMacSize();
4649         if (pSignature == NULL_PTR)
4650         {
4651                 *pulSignatureLen = size;
4652                 return CKR_OK;
4653         }
4654
4655         // Check buffer size
4656         if (*pulSignatureLen < size)
4657         {
4658                 *pulSignatureLen = size;
4659                 return CKR_BUFFER_TOO_SMALL;
4660         }
4661
4662         // Get the signature
4663         ByteString signature;
4664         if (!mac->signFinal(signature))
4665         {
4666                 session->resetOp();
4667                 return CKR_GENERAL_ERROR;
4668         }
4669
4670         // Check size
4671         if (signature.size() != size)
4672         {
4673                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4674                 session->resetOp();
4675                 return CKR_GENERAL_ERROR;
4676         }
4677         memcpy(pSignature, signature.byte_str(), size);
4678         *pulSignatureLen = size;
4679
4680         session->resetOp();
4681         return CKR_OK;
4682 }
4683
4684 // AsymmetricAlgorithm version of C_SignFinal
4685 static CK_RV AsymSignFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4686 {
4687         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4688         PrivateKey* privateKey = session->getPrivateKey();
4689         if (asymCrypto == NULL || privateKey == NULL)
4690         {
4691                 session->resetOp();
4692                 return CKR_OPERATION_NOT_INITIALIZED;
4693         }
4694
4695         // Check if re-authentication is required
4696         if (session->getReAuthentication())
4697         {
4698                 session->resetOp();
4699                 return CKR_USER_NOT_LOGGED_IN;
4700         }
4701
4702         // Size of the signature
4703         CK_ULONG size = privateKey->getOutputLength();
4704         if (pSignature == NULL_PTR)
4705         {
4706                 *pulSignatureLen = size;
4707                 return CKR_OK;
4708         }
4709
4710         // Check buffer size
4711         if (*pulSignatureLen < size)
4712         {
4713                 *pulSignatureLen = size;
4714                 return CKR_BUFFER_TOO_SMALL;
4715         }
4716
4717         // Get the signature
4718         ByteString signature;
4719         if (!asymCrypto->signFinal(signature))
4720         {
4721                 session->resetOp();
4722                 return CKR_GENERAL_ERROR;
4723         }
4724
4725         // Check size
4726         if (signature.size() != size)
4727         {
4728                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
4729                 session->resetOp();
4730                 return CKR_GENERAL_ERROR;
4731         }
4732         memcpy(pSignature, signature.byte_str(), size);
4733         *pulSignatureLen = size;
4734
4735         session->resetOp();
4736         return CKR_OK;
4737 }
4738
4739 // AsymmetricAlgorithm version of C_SignFinal
4740 static CK_RV AsymSignFinalHW(CK_SESSION_HANDLE hSession, Session* session, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4741 {
4742         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
4743         PrivateKey* privateKey = session->getPrivateKey();
4744         if (asymCrypto == NULL || privateKey == NULL)
4745         {
4746                 session->resetOp();
4747                 return CKR_OPERATION_NOT_INITIALIZED;
4748         }
4749
4750         // Check if re-authentication is required
4751         if (session->getReAuthentication())
4752         {
4753                 session->resetOp();
4754                 return CKR_USER_NOT_LOGGED_IN;
4755         }
4756
4757         // Size of the signature
4758         CK_ULONG size = privateKey->getOutputLength();
4759         if (pSignature == NULL_PTR)
4760         {
4761                 *pulSignatureLen = size;
4762                 return CKR_OK;
4763         }
4764
4765         // Check buffer size
4766         if (*pulSignatureLen < size)
4767         {
4768                 *pulSignatureLen = size;
4769                 return CKR_BUFFER_TOO_SMALL;
4770         }
4771 #if 0
4772         // Get the signature
4773         ByteString signature;
4774         if (!asymCrypto->signFinal(signature))
4775         {
4776                 session->resetOp();
4777                 return CKR_GENERAL_ERROR;
4778         }
4779 #endif
4780     AsymMech::Type mechanism = session->getMechanism();
4781     // Extract HW key handle
4782     CK_ULONG hwKeyHandle = 0;
4783     CK_OBJECT_HANDLE hKey = session->getKeyHandle();
4784     if(Extract_key_handle (hSession, hKey, &hwKeyHandle) != CKR_OK)
4785     {
4786         LOG("ERROR in extracting key handle \n");
4787                 session->resetOp();
4788                 return CKR_GENERAL_ERROR;
4789     }
4790     LOG("Extracted key handle value   : 0x%lx \n", hwKeyHandle);
4791
4792     void *hwCryptoOpaque = session->getHwCryptoOpaque();
4793         // Sign the data
4794     if(HwInfraSignFinal((void *)&hwKeyHandle, mechanism,
4795                  hwCryptoOpaque, pSignature, (int *) pulSignatureLen) != 0 )
4796     {
4797                 session->resetOp();
4798                 return CKR_GENERAL_ERROR;
4799     }
4800     // Check size
4801     if (*pulSignatureLen != size)
4802     {
4803             ERROR_MSG("The size of the signature differs from the size of the mechanism");
4804             session->resetOp();
4805             return CKR_GENERAL_ERROR;
4806     }
4807     *pulSignatureLen = size;
4808
4809      session->resetOp();
4810      return CKR_OK;
4811 }
4812
4813
4814 // Finalise a running signing operation and return the signature
4815 CK_RV SoftHSM::C_SignFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen)
4816 {
4817         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4818
4819         if (pulSignatureLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
4820
4821         // Get the session
4822         Session* session = (Session*)handleManager->getSession(hSession);
4823         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4824
4825         // Check if we are doing the correct operation
4826         if (session->getOpType() != SESSION_OP_SIGN || !session->getAllowMultiPartOp())
4827                 return CKR_OPERATION_NOT_INITIALIZED;
4828
4829         if (session->getMacOp() != NULL)
4830                 return MacSignFinal(session, pSignature, pulSignatureLen);
4831         else
4832                 if(isHWavailable)
4833                 {
4834                   return AsymSignFinalHW(hSession, session, pSignature, pulSignatureLen);
4835                 }
4836                 else
4837                 {
4838
4839                   return AsymSignFinal(session, pSignature, pulSignatureLen);
4840                 }
4841 }
4842
4843 // Initialise a signing operation that allows recovery of the signed data
4844 CK_RV SoftHSM::C_SignRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
4845 {
4846         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4847
4848         // Get the session
4849         Session* session = (Session*)handleManager->getSession(hSession);
4850         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4851
4852         // Check if we have another operation
4853         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4854
4855         return CKR_FUNCTION_NOT_SUPPORTED;
4856 }
4857
4858 // Perform a single part signing operation that allows recovery of the signed data
4859 CK_RV SoftHSM::C_SignRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pData*/, CK_ULONG /*ulDataLen*/, CK_BYTE_PTR /*pSignature*/, CK_ULONG_PTR /*pulSignatureLen*/)
4860 {
4861         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4862
4863         // Get the session
4864         Session* session = (Session*)handleManager->getSession(hSession);
4865         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4866
4867         return CKR_FUNCTION_NOT_SUPPORTED;
4868 }
4869
4870 // MacAlgorithm version of C_VerifyInit
4871 CK_RV SoftHSM::MacVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
4872 {
4873         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
4874
4875         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
4876
4877         // Get the session
4878         Session* session = (Session*)handleManager->getSession(hSession);
4879         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
4880
4881         // Check if we have another operation
4882         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
4883
4884         // Get the token
4885         Token* token = session->getToken();
4886         if (token == NULL) return CKR_GENERAL_ERROR;
4887
4888         // Check the key handle.
4889         OSObject *key = (OSObject *)handleManager->getObject(hKey);
4890         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
4891
4892         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
4893         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
4894
4895         // Check read user credentials
4896         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
4897         if (rv != CKR_OK)
4898         {
4899                 if (rv == CKR_USER_NOT_LOGGED_IN)
4900                         INFO_MSG("User is not authorized");
4901
4902                 return rv;
4903         }
4904
4905         // Check if key can be used for verifying
4906         if (!key->getBooleanValue(CKA_VERIFY, false))
4907                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
4908
4909         // Check if the specified mechanism is allowed for the key
4910         if (!isMechanismPermitted(key, pMechanism))
4911                 return CKR_MECHANISM_INVALID;
4912
4913         // Get key info
4914         CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
4915
4916         // Get the MAC algorithm matching the mechanism
4917         // Also check mechanism constraints
4918         MacAlgo::Type algo = MacAlgo::Unknown;
4919         size_t bb = 8;
4920         size_t minSize = 0;
4921         switch(pMechanism->mechanism) {
4922 #ifndef WITH_FIPS
4923                 case CKM_MD5_HMAC:
4924                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_MD5_HMAC)
4925                                 return CKR_KEY_TYPE_INCONSISTENT;
4926                         minSize = 16;
4927                         algo = MacAlgo::HMAC_MD5;
4928                         break;
4929 #endif
4930                 case CKM_SHA_1_HMAC:
4931                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA_1_HMAC)
4932                                 return CKR_KEY_TYPE_INCONSISTENT;
4933                         minSize = 20;
4934                         algo = MacAlgo::HMAC_SHA1;
4935                         break;
4936                 case CKM_SHA224_HMAC:
4937                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA224_HMAC)
4938                                 return CKR_KEY_TYPE_INCONSISTENT;
4939                         minSize = 28;
4940                         algo = MacAlgo::HMAC_SHA224;
4941                         break;
4942                 case CKM_SHA256_HMAC:
4943                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA256_HMAC)
4944                                 return CKR_KEY_TYPE_INCONSISTENT;
4945                         minSize = 32;
4946                         algo = MacAlgo::HMAC_SHA256;
4947                         break;
4948                 case CKM_SHA384_HMAC:
4949                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA384_HMAC)
4950                                 return CKR_KEY_TYPE_INCONSISTENT;
4951                         minSize = 48;
4952                         algo = MacAlgo::HMAC_SHA384;
4953                         break;
4954                 case CKM_SHA512_HMAC:
4955                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_SHA512_HMAC)
4956                                 return CKR_KEY_TYPE_INCONSISTENT;
4957                         minSize = 64;
4958                         algo = MacAlgo::HMAC_SHA512;
4959                         break;
4960 #ifdef WITH_GOST
4961                 case CKM_GOSTR3411_HMAC:
4962                         if (keyType != CKK_GENERIC_SECRET && keyType != CKK_GOST28147)
4963                                 return CKR_KEY_TYPE_INCONSISTENT;
4964                         minSize = 32;
4965                         algo = MacAlgo::HMAC_GOST;
4966                         break;
4967 #endif
4968                 case CKM_DES3_CMAC:
4969                         if (keyType != CKK_DES2 && keyType != CKK_DES3)
4970                                 return CKR_KEY_TYPE_INCONSISTENT;
4971                         algo = MacAlgo::CMAC_DES;
4972                         bb = 7;
4973                         break;
4974                 case CKM_AES_CMAC:
4975                         if (keyType != CKK_AES)
4976                                 return CKR_KEY_TYPE_INCONSISTENT;
4977                         algo = MacAlgo::CMAC_AES;
4978                         break;
4979                 default:
4980                         return CKR_MECHANISM_INVALID;
4981         }
4982         MacAlgorithm* mac = CryptoFactory::i()->getMacAlgorithm(algo);
4983         if (mac == NULL) return CKR_MECHANISM_INVALID;
4984
4985         SymmetricKey* pubkey = new SymmetricKey();
4986
4987         if (getSymmetricKey(pubkey, token, key) != CKR_OK)
4988         {
4989                 mac->recycleKey(pubkey);
4990                 CryptoFactory::i()->recycleMacAlgorithm(mac);
4991                 return CKR_GENERAL_ERROR;
4992         }
4993
4994         // Adjust key bit length
4995         pubkey->setBitLen(pubkey->getKeyBits().size() * bb);
4996
4997         // Check key size
4998         if (pubkey->getBitLen() < (minSize*8))
4999         {
5000                 mac->recycleKey(pubkey);
5001                 CryptoFactory::i()->recycleMacAlgorithm(mac);
5002                 return CKR_KEY_SIZE_RANGE;
5003         }
5004
5005         // Initialize verifying
5006         if (!mac->verifyInit(pubkey))
5007         {
5008                 mac->recycleKey(pubkey);
5009                 CryptoFactory::i()->recycleMacAlgorithm(mac);
5010                 return CKR_MECHANISM_INVALID;
5011         }
5012
5013         session->setOpType(SESSION_OP_VERIFY);
5014         session->setMacOp(mac);
5015         session->setAllowMultiPartOp(true);
5016         session->setAllowSinglePartOp(true);
5017         session->setSymmetricKey(pubkey);
5018
5019         return CKR_OK;
5020 }
5021
5022 // AsymmetricAlgorithm version of C_VerifyInit
5023 CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5024 {
5025         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5026
5027         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5028
5029         // Get the session
5030         Session* session = (Session*)handleManager->getSession(hSession);
5031         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5032
5033         // Check if we have another operation
5034         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5035
5036         // Get the token
5037         Token* token = session->getToken();
5038         if (token == NULL) return CKR_GENERAL_ERROR;
5039
5040         // Check the key handle.
5041         OSObject *key = (OSObject *)handleManager->getObject(hKey);
5042         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
5043
5044         CK_BBOOL isOnToken = key->getBooleanValue(CKA_TOKEN, false);
5045         CK_BBOOL isPrivate = key->getBooleanValue(CKA_PRIVATE, true);
5046
5047         // Check read user credentials
5048         CK_RV rv = haveRead(session->getState(), isOnToken, isPrivate);
5049         if (rv != CKR_OK)
5050         {
5051                 if (rv == CKR_USER_NOT_LOGGED_IN)
5052                         INFO_MSG("User is not authorized");
5053
5054                 return rv;
5055         }
5056
5057         // Check if key can be used for verifying
5058         if (!key->getBooleanValue(CKA_VERIFY, false))
5059                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
5060
5061         // Check if the specified mechanism is allowed for the key
5062         if (!isMechanismPermitted(key, pMechanism))
5063                 return CKR_MECHANISM_INVALID;
5064
5065         // Get the asymmetric algorithm matching the mechanism
5066         AsymMech::Type mechanism = AsymMech::Unknown;
5067         void* param = NULL;
5068         size_t paramLen = 0;
5069         RSA_PKCS_PSS_PARAMS pssParam;
5070         bool bAllowMultiPartOp;
5071         bool isRSA = false;
5072         bool isDSA = false;
5073         bool isECDSA = false;
5074         switch(pMechanism->mechanism) {
5075                 case CKM_RSA_PKCS:
5076                         mechanism = AsymMech::RSA_PKCS;
5077                         bAllowMultiPartOp = false;
5078                         isRSA = true;
5079                         break;
5080                 case CKM_RSA_X_509:
5081                         mechanism = AsymMech::RSA;
5082                         bAllowMultiPartOp = false;
5083                         isRSA = true;
5084                         break;
5085 #ifndef WITH_FIPS
5086                 case CKM_MD5_RSA_PKCS:
5087                         mechanism = AsymMech::RSA_MD5_PKCS;
5088                         bAllowMultiPartOp = true;
5089                         isRSA = true;
5090                         break;
5091 #endif
5092                 case CKM_SHA1_RSA_PKCS:
5093                         mechanism = AsymMech::RSA_SHA1_PKCS;
5094                         bAllowMultiPartOp = true;
5095                         isRSA = true;
5096                         break;
5097                 case CKM_SHA224_RSA_PKCS:
5098                         mechanism = AsymMech::RSA_SHA224_PKCS;
5099                         bAllowMultiPartOp = true;
5100                         isRSA = true;
5101                         break;
5102                 case CKM_SHA256_RSA_PKCS:
5103                         mechanism = AsymMech::RSA_SHA256_PKCS;
5104                         bAllowMultiPartOp = true;
5105                         isRSA = true;
5106                         break;
5107                 case CKM_SHA384_RSA_PKCS:
5108                         mechanism = AsymMech::RSA_SHA384_PKCS;
5109                         bAllowMultiPartOp = true;
5110                         isRSA = true;
5111                         break;
5112                 case CKM_SHA512_RSA_PKCS:
5113                         mechanism = AsymMech::RSA_SHA512_PKCS;
5114                         bAllowMultiPartOp = true;
5115                         isRSA = true;
5116                         break;
5117 #ifdef WITH_RAW_PSS
5118                 case CKM_RSA_PKCS_PSS:
5119                         if (pMechanism->pParameter == NULL_PTR ||
5120                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS))
5121                         {
5122                                 ERROR_MSG("Invalid parameters");
5123                                 return CKR_ARGUMENTS_BAD;
5124                         }
5125                         mechanism = AsymMech::RSA_PKCS_PSS;
5126
5127                         unsigned long expectedMgf;
5128                         switch(CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg) {
5129                                 case CKM_SHA_1:
5130                                         pssParam.hashAlg = HashAlgo::SHA1;
5131                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
5132                                         expectedMgf = CKG_MGF1_SHA1;
5133                                         break;
5134                                 case CKM_SHA224:
5135                                         pssParam.hashAlg = HashAlgo::SHA224;
5136                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5137                                         expectedMgf = CKG_MGF1_SHA224;
5138                                         break;
5139                                 case CKM_SHA256:
5140                                         pssParam.hashAlg = HashAlgo::SHA256;
5141                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5142                                         expectedMgf = CKG_MGF1_SHA256;
5143                                         break;
5144                                 case CKM_SHA384:
5145                                         pssParam.hashAlg = HashAlgo::SHA384;
5146                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5147                                         expectedMgf = CKG_MGF1_SHA384;
5148                                         break;
5149                                 case CKM_SHA512:
5150                                         pssParam.hashAlg = HashAlgo::SHA512;
5151                                         pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5152                                         expectedMgf = CKG_MGF1_SHA512;
5153                                         break;
5154                                 default:
5155                                         return CKR_ARGUMENTS_BAD;
5156                         }
5157
5158                         if (CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != expectedMgf) {
5159                                 return CKR_ARGUMENTS_BAD;
5160                         }
5161
5162                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5163                         param = &pssParam;
5164                         paramLen = sizeof(pssParam);
5165                         bAllowMultiPartOp = false;
5166                         isRSA = true;
5167                         break;
5168 #endif
5169                 case CKM_SHA1_RSA_PKCS_PSS:
5170                         if (pMechanism->pParameter == NULL_PTR ||
5171                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5172                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA_1 ||
5173                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA1)
5174                         {
5175                                 ERROR_MSG("Invalid parameters");
5176                                 return CKR_ARGUMENTS_BAD;
5177                         }
5178                         mechanism = AsymMech::RSA_SHA1_PKCS_PSS;
5179                         pssParam.hashAlg = HashAlgo::SHA1;
5180                         pssParam.mgf = AsymRSAMGF::MGF1_SHA1;
5181                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5182                         param = &pssParam;
5183                         paramLen = sizeof(pssParam);
5184                         bAllowMultiPartOp = true;
5185                         isRSA = true;
5186                         break;
5187                 case CKM_SHA224_RSA_PKCS_PSS:
5188                         if (pMechanism->pParameter == NULL_PTR ||
5189                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5190                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA224 ||
5191                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA224)
5192                         {
5193                                 ERROR_MSG("Invalid parameters");
5194                                 return CKR_ARGUMENTS_BAD;
5195                         }
5196                         mechanism = AsymMech::RSA_SHA224_PKCS_PSS;
5197                         pssParam.hashAlg = HashAlgo::SHA224;
5198                         pssParam.mgf = AsymRSAMGF::MGF1_SHA224;
5199                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5200                         param = &pssParam;
5201                         paramLen = sizeof(pssParam);
5202                         bAllowMultiPartOp = true;
5203                         isRSA = true;
5204                         break;
5205                 case CKM_SHA256_RSA_PKCS_PSS:
5206                         if (pMechanism->pParameter == NULL_PTR ||
5207                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5208                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA256 ||
5209                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA256)
5210                         {
5211                                 ERROR_MSG("Invalid parameters");
5212                                 return CKR_ARGUMENTS_BAD;
5213                         }
5214                         mechanism = AsymMech::RSA_SHA256_PKCS_PSS;
5215                         pssParam.hashAlg = HashAlgo::SHA256;
5216                         pssParam.mgf = AsymRSAMGF::MGF1_SHA256;
5217                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5218                         param = &pssParam;
5219                         paramLen = sizeof(pssParam);
5220                         bAllowMultiPartOp = true;
5221                         isRSA = true;
5222                         break;
5223                 case CKM_SHA384_RSA_PKCS_PSS:
5224                         if (pMechanism->pParameter == NULL_PTR ||
5225                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5226                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA384 ||
5227                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA384)
5228                         {
5229                                 ERROR_MSG("Invalid parameters");
5230                                 return CKR_ARGUMENTS_BAD;
5231                         }
5232                         mechanism = AsymMech::RSA_SHA384_PKCS_PSS;
5233                         pssParam.hashAlg = HashAlgo::SHA384;
5234                         pssParam.mgf = AsymRSAMGF::MGF1_SHA384;
5235                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5236                         param = &pssParam;
5237                         paramLen = sizeof(pssParam);
5238                         bAllowMultiPartOp = true;
5239                         isRSA = true;
5240                         break;
5241                 case CKM_SHA512_RSA_PKCS_PSS:
5242                         if (pMechanism->pParameter == NULL_PTR ||
5243                             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_PSS_PARAMS) ||
5244                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->hashAlg != CKM_SHA512 ||
5245                             CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->mgf != CKG_MGF1_SHA512)
5246                         {
5247                                 ERROR_MSG("Invalid parameters");
5248                                 return CKR_ARGUMENTS_BAD;
5249                         }
5250                         mechanism = AsymMech::RSA_SHA512_PKCS_PSS;
5251                         pssParam.hashAlg = HashAlgo::SHA512;
5252                         pssParam.mgf = AsymRSAMGF::MGF1_SHA512;
5253                         pssParam.sLen = CK_RSA_PKCS_PSS_PARAMS_PTR(pMechanism->pParameter)->sLen;
5254                         param = &pssParam;
5255                         paramLen = sizeof(pssParam);
5256                         bAllowMultiPartOp = true;
5257                         isRSA = true;
5258                         break;
5259                 case CKM_DSA:
5260                         mechanism = AsymMech::DSA;
5261                         bAllowMultiPartOp = false;
5262                         isDSA = true;
5263                         break;
5264                 case CKM_DSA_SHA1:
5265                         mechanism = AsymMech::DSA_SHA1;
5266                         bAllowMultiPartOp = true;
5267                         isDSA = true;
5268                         break;
5269                 case CKM_DSA_SHA224:
5270                         mechanism = AsymMech::DSA_SHA224;
5271                         bAllowMultiPartOp = true;
5272                         isDSA = true;
5273                         break;
5274                 case CKM_DSA_SHA256:
5275                         mechanism = AsymMech::DSA_SHA256;
5276                         bAllowMultiPartOp = true;
5277                         isDSA = true;
5278                         break;
5279                 case CKM_DSA_SHA384:
5280                         mechanism = AsymMech::DSA_SHA384;
5281                         bAllowMultiPartOp = true;
5282                         isDSA = true;
5283                         break;
5284                 case CKM_DSA_SHA512:
5285                         mechanism = AsymMech::DSA_SHA512;
5286                         bAllowMultiPartOp = true;
5287                         isDSA = true;
5288                         break;
5289 #ifdef WITH_ECC
5290                 case CKM_ECDSA:
5291                         mechanism = AsymMech::ECDSA;
5292                         bAllowMultiPartOp = false;
5293                         isECDSA = true;
5294                         break;
5295 #endif
5296 #ifdef WITH_GOST
5297                 case CKM_GOSTR3410:
5298                         mechanism = AsymMech::GOST;
5299                         bAllowMultiPartOp = false;
5300                         break;
5301                 case CKM_GOSTR3410_WITH_GOSTR3411:
5302                         mechanism = AsymMech::GOST_GOST;
5303                         bAllowMultiPartOp = true;
5304                         break;
5305 #endif
5306                 default:
5307                         return CKR_MECHANISM_INVALID;
5308         }
5309
5310         AsymmetricAlgorithm* asymCrypto = NULL;
5311         PublicKey* publicKey = NULL;
5312         if (isRSA)
5313         {
5314                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
5315                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5316
5317                 publicKey = asymCrypto->newPublicKey();
5318                 if (publicKey == NULL)
5319                 {
5320                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5321                         return CKR_HOST_MEMORY;
5322                 }
5323
5324                 if (getRSAPublicKey((RSAPublicKey*)publicKey, token, key) != CKR_OK)
5325                 {
5326                         asymCrypto->recyclePublicKey(publicKey);
5327                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5328                         return CKR_GENERAL_ERROR;
5329                 }
5330         }
5331         else if (isDSA)
5332         {
5333                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
5334                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5335
5336                 publicKey = asymCrypto->newPublicKey();
5337                 if (publicKey == NULL)
5338                 {
5339                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5340                         return CKR_HOST_MEMORY;
5341                 }
5342
5343                 if (getDSAPublicKey((DSAPublicKey*)publicKey, token, key) != CKR_OK)
5344                 {
5345                         asymCrypto->recyclePublicKey(publicKey);
5346                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5347                         return CKR_GENERAL_ERROR;
5348                 }
5349         }
5350 #ifdef WITH_ECC
5351         else if (isECDSA)
5352         {
5353                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
5354                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5355
5356                 publicKey = asymCrypto->newPublicKey();
5357                 if (publicKey == NULL)
5358                 {
5359                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5360                         return CKR_HOST_MEMORY;
5361                 }
5362
5363                 if (getECPublicKey((ECPublicKey*)publicKey, token, key) != CKR_OK)
5364                 {
5365                         asymCrypto->recyclePublicKey(publicKey);
5366                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5367                         return CKR_GENERAL_ERROR;
5368                 }
5369         }
5370 #endif
5371         else
5372         {
5373 #ifdef WITH_GOST
5374                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
5375                 if (asymCrypto == NULL) return CKR_MECHANISM_INVALID;
5376
5377                 publicKey = asymCrypto->newPublicKey();
5378                 if (publicKey == NULL)
5379                 {
5380                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5381                         return CKR_HOST_MEMORY;
5382                 }
5383
5384                 if (getGOSTPublicKey((GOSTPublicKey*)publicKey, token, key) != CKR_OK)
5385                 {
5386                         asymCrypto->recyclePublicKey(publicKey);
5387                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5388                         return CKR_GENERAL_ERROR;
5389                 }
5390 #else
5391                 return CKR_MECHANISM_INVALID;
5392 #endif
5393         }
5394
5395         // Initialize verifying
5396         if (bAllowMultiPartOp && !asymCrypto->verifyInit(publicKey,mechanism,param,paramLen))
5397         {
5398                 asymCrypto->recyclePublicKey(publicKey);
5399                 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
5400                 return CKR_MECHANISM_INVALID;
5401         }
5402
5403         session->setOpType(SESSION_OP_VERIFY);
5404         session->setAsymmetricCryptoOp(asymCrypto);
5405         session->setMechanism(mechanism);
5406         session->setParameters(param, paramLen);
5407         session->setAllowMultiPartOp(bAllowMultiPartOp);
5408         session->setAllowSinglePartOp(true);
5409         session->setPublicKey(publicKey);
5410
5411         return CKR_OK;
5412 }
5413
5414 // Initialise a verification operation using the specified key and mechanism
5415 CK_RV SoftHSM::C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey)
5416 {
5417         if (isMacMechanism(pMechanism))
5418                 return MacVerifyInit(hSession, pMechanism, hKey);
5419         else
5420                 return AsymVerifyInit(hSession, pMechanism, hKey);
5421 }
5422
5423 // MacAlgorithm version of C_Verify
5424 static CK_RV MacVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5425 {
5426         MacAlgorithm* mac = session->getMacOp();
5427         if (mac == NULL || !session->getAllowSinglePartOp())
5428         {
5429                 session->resetOp();
5430                 return CKR_OPERATION_NOT_INITIALIZED;
5431         }
5432
5433         // Size of the signature
5434         CK_ULONG size = mac->getMacSize();
5435
5436         // Check buffer size
5437         if (ulSignatureLen != size)
5438         {
5439                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5440                 session->resetOp();
5441                 return CKR_SIGNATURE_LEN_RANGE;
5442         }
5443
5444         // Get the data
5445         ByteString data(pData, ulDataLen);
5446
5447         // Verify the data
5448         if (!mac->verifyUpdate(data))
5449         {
5450                 session->resetOp();
5451                 return CKR_GENERAL_ERROR;
5452         }
5453
5454         // Get the signature
5455         ByteString signature(pSignature, ulSignatureLen);
5456
5457         // Verify the signature
5458         if (!mac->verifyFinal(signature))
5459         {
5460                 session->resetOp();
5461                 return CKR_SIGNATURE_INVALID;
5462         }
5463
5464         session->resetOp();
5465         return CKR_OK;
5466 }
5467
5468 // AsymmetricAlgorithm version of C_Verify
5469 static CK_RV AsymVerify(Session* session, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5470 {
5471         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5472         AsymMech::Type mechanism = session->getMechanism();
5473         PublicKey* publicKey = session->getPublicKey();
5474         size_t paramLen;
5475         void* param = session->getParameters(paramLen);
5476         if (asymCrypto == NULL || !session->getAllowSinglePartOp() || publicKey == NULL)
5477         {
5478                 session->resetOp();
5479                 return CKR_OPERATION_NOT_INITIALIZED;
5480         }
5481
5482         // Size of the signature
5483         CK_ULONG size = publicKey->getOutputLength();
5484
5485         // Check buffer size
5486         if (ulSignatureLen != size)
5487         {
5488                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5489                 session->resetOp();
5490                 return CKR_SIGNATURE_LEN_RANGE;
5491         }
5492
5493         // Get the data
5494         ByteString data;
5495
5496         // We must allow input length <= k and therfore need to prepend the data with zeroes.
5497         if (mechanism == AsymMech::RSA) {
5498                 data.wipe(size-ulDataLen);
5499         }
5500
5501         data += ByteString(pData, ulDataLen);
5502         ByteString signature(pSignature, ulSignatureLen);
5503
5504         // Verify the data
5505         if (session->getAllowMultiPartOp())
5506         {
5507                 if (!asymCrypto->verifyUpdate(data) ||
5508                     !asymCrypto->verifyFinal(signature))
5509                 {
5510                         session->resetOp();
5511                         return CKR_SIGNATURE_INVALID;
5512                 }
5513         }
5514         else if (!asymCrypto->verify(publicKey,data,signature,mechanism,param,paramLen))
5515         {
5516                 session->resetOp();
5517                 return CKR_SIGNATURE_INVALID;
5518         }
5519
5520         session->resetOp();
5521         return CKR_OK;
5522 }
5523
5524 // Perform a single pass verification operation
5525 CK_RV SoftHSM::C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5526 {
5527         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5528
5529         if (pData == NULL_PTR) return CKR_ARGUMENTS_BAD;
5530         if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5531
5532         // Get the session
5533         Session* session = (Session*)handleManager->getSession(hSession);
5534         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5535
5536         // Check if we are doing the correct operation
5537         if (session->getOpType() != SESSION_OP_VERIFY)
5538                 return CKR_OPERATION_NOT_INITIALIZED;
5539
5540         if (session->getMacOp() != NULL)
5541                 return MacVerify(session, pData, ulDataLen,
5542                                  pSignature, ulSignatureLen);
5543         else
5544                 return AsymVerify(session, pData, ulDataLen,
5545                                   pSignature, ulSignatureLen);
5546 }
5547
5548 // MacAlgorithm version of C_VerifyUpdate
5549 static CK_RV MacVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5550 {
5551         MacAlgorithm* mac = session->getMacOp();
5552         if (mac == NULL || !session->getAllowMultiPartOp())
5553         {
5554                 session->resetOp();
5555                 return CKR_OPERATION_NOT_INITIALIZED;
5556         }
5557
5558         // Get the part
5559         ByteString part(pPart, ulPartLen);
5560
5561         // Verify the data
5562         if (!mac->verifyUpdate(part))
5563         {
5564                 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5565                 session->resetOp();
5566                 return CKR_GENERAL_ERROR;
5567         }
5568
5569         session->setAllowSinglePartOp(false);
5570         return CKR_OK;
5571 }
5572
5573 // AsymmetricAlgorithm version of C_VerifyUpdate
5574 static CK_RV AsymVerifyUpdate(Session* session, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5575 {
5576         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5577         if (asymCrypto == NULL || !session->getAllowMultiPartOp())
5578         {
5579                 session->resetOp();
5580                 return CKR_OPERATION_NOT_INITIALIZED;
5581         }
5582
5583         // Get the part
5584         ByteString part(pPart, ulPartLen);
5585
5586         // Verify the data
5587         if (!asymCrypto->verifyUpdate(part))
5588         {
5589                 // verifyUpdate can't fail for a logical reason, so we assume total breakdown.
5590                 session->resetOp();
5591                 return CKR_GENERAL_ERROR;
5592         }
5593
5594         session->setAllowSinglePartOp(false);
5595         return CKR_OK;
5596 }
5597
5598 // Update a running verification operation with additional data
5599 CK_RV SoftHSM::C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen)
5600 {
5601         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5602
5603         if (pPart == NULL_PTR) return CKR_ARGUMENTS_BAD;
5604
5605         // Get the session
5606         Session* session = (Session*)handleManager->getSession(hSession);
5607         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5608
5609         // Check if we are doing the correct operation
5610         if (session->getOpType() != SESSION_OP_VERIFY)
5611                 return CKR_OPERATION_NOT_INITIALIZED;
5612
5613         if (session->getMacOp() != NULL)
5614                 return MacVerifyUpdate(session, pPart, ulPartLen);
5615         else
5616                 return AsymVerifyUpdate(session, pPart, ulPartLen);
5617 }
5618
5619 // MacAlgorithm version of C_SignFinal
5620 static CK_RV MacVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5621 {
5622         MacAlgorithm* mac = session->getMacOp();
5623         if (mac == NULL)
5624         {
5625                 session->resetOp();
5626                 return CKR_OPERATION_NOT_INITIALIZED;
5627         }
5628
5629         // Size of the signature
5630         CK_ULONG size = mac->getMacSize();
5631
5632         // Check buffer size
5633         if (ulSignatureLen != size)
5634         {
5635                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5636                 session->resetOp();
5637                 return CKR_SIGNATURE_LEN_RANGE;
5638         }
5639
5640         // Get the signature
5641         ByteString signature(pSignature, ulSignatureLen);
5642
5643         // Verify the data
5644         if (!mac->verifyFinal(signature))
5645         {
5646                 session->resetOp();
5647                 return CKR_SIGNATURE_INVALID;
5648         }
5649
5650         session->resetOp();
5651         return CKR_OK;
5652 }
5653
5654 // AsymmetricAlgorithm version of C_VerifyFinal
5655 static CK_RV AsymVerifyFinal(Session* session, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5656 {
5657         AsymmetricAlgorithm* asymCrypto = session->getAsymmetricCryptoOp();
5658         PublicKey* publicKey = session->getPublicKey();
5659         if (asymCrypto == NULL || publicKey == NULL)
5660         {
5661                 session->resetOp();
5662                 return CKR_OPERATION_NOT_INITIALIZED;
5663         }
5664
5665         // Size of the signature
5666         CK_ULONG size = publicKey->getOutputLength();
5667
5668         // Check buffer size
5669         if (ulSignatureLen != size)
5670         {
5671                 ERROR_MSG("The size of the signature differs from the size of the mechanism");
5672                 session->resetOp();
5673                 return CKR_SIGNATURE_LEN_RANGE;
5674         }
5675
5676         // Get the data
5677         ByteString signature(pSignature, ulSignatureLen);
5678
5679         // Verify the data
5680         if (!asymCrypto->verifyFinal(signature))
5681         {
5682                 session->resetOp();
5683                 return CKR_SIGNATURE_INVALID;
5684         }
5685
5686         session->resetOp();
5687         return CKR_OK;
5688 }
5689
5690 // Finalise the verification operation and check the signature
5691 CK_RV SoftHSM::C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
5692 {
5693         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5694
5695         if (pSignature == NULL_PTR) return CKR_ARGUMENTS_BAD;
5696
5697         // Get the session
5698         Session* session = (Session*)handleManager->getSession(hSession);
5699         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5700
5701         // Check if we are doing the correct operation
5702         if (session->getOpType() != SESSION_OP_VERIFY || !session->getAllowMultiPartOp())
5703                 return CKR_OPERATION_NOT_INITIALIZED;
5704
5705         if (session->getMacOp() != NULL)
5706                 return MacVerifyFinal(session, pSignature, ulSignatureLen);
5707         else
5708                 return AsymVerifyFinal(session, pSignature, ulSignatureLen);
5709 }
5710
5711 // Initialise a verification operation the allows recovery of the signed data from the signature
5712 CK_RV SoftHSM::C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR /*pMechanism*/, CK_OBJECT_HANDLE /*hKey*/)
5713 {
5714         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5715
5716         // Get the session
5717         Session* session = (Session*)handleManager->getSession(hSession);
5718         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5719
5720         // Check if we have another operation
5721         if (session->getOpType() != SESSION_OP_NONE) return CKR_OPERATION_ACTIVE;
5722
5723         return CKR_FUNCTION_NOT_SUPPORTED;
5724 }
5725
5726 // Perform a single part verification operation and recover the signed data
5727 CK_RV SoftHSM::C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pSignature*/, CK_ULONG /*ulSignatureLen*/, CK_BYTE_PTR /*pData*/, CK_ULONG_PTR /*pulDataLen*/)
5728 {
5729         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5730
5731         // Get the session
5732         Session* session = (Session*)handleManager->getSession(hSession);
5733         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5734
5735         return CKR_FUNCTION_NOT_SUPPORTED;
5736 }
5737
5738 // Update a running multi-part encryption and digesting operation
5739 CK_RV SoftHSM::C_DigestEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5740 {
5741         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5742
5743         // Get the session
5744         Session* session = (Session*)handleManager->getSession(hSession);
5745         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5746
5747         return CKR_FUNCTION_NOT_SUPPORTED;
5748 }
5749
5750 // Update a running multi-part decryption and digesting operation
5751 CK_RV SoftHSM::C_DecryptDigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pDecryptedPart*/, CK_ULONG_PTR /*pulDecryptedPartLen*/)
5752 {
5753         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5754
5755         // Get the session
5756         Session* session = (Session*)handleManager->getSession(hSession);
5757         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5758
5759         return CKR_FUNCTION_NOT_SUPPORTED;
5760 }
5761
5762 // Update a running multi-part signing and encryption operation
5763 CK_RV SoftHSM::C_SignEncryptUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pPart*/, CK_ULONG /*ulPartLen*/, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG_PTR /*pulEncryptedPartLen*/)
5764 {
5765         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5766
5767         // Get the session
5768         Session* session = (Session*)handleManager->getSession(hSession);
5769         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5770
5771         return CKR_FUNCTION_NOT_SUPPORTED;
5772 }
5773
5774 // Update a running multi-part decryption and verification operation
5775 CK_RV SoftHSM::C_DecryptVerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR /*pEncryptedPart*/, CK_ULONG /*ulEncryptedPartLen*/, CK_BYTE_PTR /*pPart*/, CK_ULONG_PTR /*pulPartLen*/)
5776 {
5777         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5778
5779         // Get the session
5780         Session* session = (Session*)handleManager->getSession(hSession);
5781         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5782
5783         return CKR_FUNCTION_NOT_SUPPORTED;
5784 }
5785
5786 // Generate a secret key or a domain parameter set using the specified mechanism
5787 CK_RV SoftHSM::C_GenerateKey(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey)
5788 {
5789         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5790
5791         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5792         if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5793
5794         // Get the session
5795         Session* session = (Session*)handleManager->getSession(hSession);
5796         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5797
5798         // Check the mechanism, only accept DSA and DH parameters
5799         // and symmetric ciphers
5800         CK_OBJECT_CLASS objClass;
5801         CK_KEY_TYPE keyType;
5802         switch (pMechanism->mechanism)
5803         {
5804                 case CKM_DSA_PARAMETER_GEN:
5805                         objClass = CKO_DOMAIN_PARAMETERS;
5806                         keyType = CKK_DSA;
5807                         break;
5808                 case CKM_DH_PKCS_PARAMETER_GEN:
5809                         objClass = CKO_DOMAIN_PARAMETERS;
5810                         keyType = CKK_DH;
5811                         break;
5812 #ifndef WITH_FIPS
5813                 case CKM_DES_KEY_GEN:
5814                         objClass = CKO_SECRET_KEY;
5815                         keyType = CKK_DES;
5816                         break;
5817 #endif
5818                 case CKM_DES2_KEY_GEN:
5819                         objClass = CKO_SECRET_KEY;
5820                         keyType = CKK_DES2;
5821                         break;
5822                 case CKM_DES3_KEY_GEN:
5823                         objClass = CKO_SECRET_KEY;
5824                         keyType = CKK_DES3;
5825                         break;
5826                 case CKM_AES_KEY_GEN:
5827                         objClass = CKO_SECRET_KEY;
5828                         keyType = CKK_AES;
5829                         break;
5830                 default:
5831                         return CKR_MECHANISM_INVALID;
5832         }
5833
5834         // Extract information from the template that is needed to create the object.
5835         CK_BBOOL isOnToken = CK_FALSE;
5836         CK_BBOOL isPrivate = CK_TRUE;
5837         CK_CERTIFICATE_TYPE dummy;
5838         bool isImplicit = true;
5839         extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
5840
5841         // Report errors and/or unexpected usage.
5842         if (objClass != CKO_SECRET_KEY && objClass != CKO_DOMAIN_PARAMETERS)
5843                 return CKR_ATTRIBUTE_VALUE_INVALID;
5844         if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN &&
5845             (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DSA))
5846                 return CKR_TEMPLATE_INCONSISTENT;
5847         if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN &&
5848             (objClass != CKO_DOMAIN_PARAMETERS || keyType != CKK_DH))
5849                 return CKR_TEMPLATE_INCONSISTENT;
5850         if (pMechanism->mechanism == CKM_DES_KEY_GEN &&
5851             (objClass != CKO_SECRET_KEY || keyType != CKK_DES))
5852                 return CKR_TEMPLATE_INCONSISTENT;
5853         if (pMechanism->mechanism == CKM_DES2_KEY_GEN &&
5854             (objClass != CKO_SECRET_KEY || keyType != CKK_DES2))
5855                 return CKR_TEMPLATE_INCONSISTENT;
5856         if (pMechanism->mechanism == CKM_DES3_KEY_GEN &&
5857             (objClass != CKO_SECRET_KEY || keyType != CKK_DES3))
5858                 return CKR_TEMPLATE_INCONSISTENT;
5859         if (pMechanism->mechanism == CKM_AES_KEY_GEN &&
5860             (objClass != CKO_SECRET_KEY || keyType != CKK_AES))
5861                 return CKR_TEMPLATE_INCONSISTENT;
5862
5863         // Check authorization
5864         CK_RV rv = haveWrite(session->getState(), isOnToken, isPrivate);
5865         if (rv != CKR_OK)
5866         {
5867                 if (rv == CKR_USER_NOT_LOGGED_IN)
5868                         INFO_MSG("User is not authorized");
5869                 if (rv == CKR_SESSION_READ_ONLY)
5870                         INFO_MSG("Session is read-only");
5871
5872                 return rv;
5873         }
5874
5875         // Generate DSA domain parameters
5876         if (pMechanism->mechanism == CKM_DSA_PARAMETER_GEN)
5877         {
5878                 return this->generateDSAParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5879         }
5880
5881         // Generate DH domain parameters
5882         if (pMechanism->mechanism == CKM_DH_PKCS_PARAMETER_GEN)
5883         {
5884                 return this->generateDHParameters(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5885         }
5886
5887         // Generate DES secret key
5888         if (pMechanism->mechanism == CKM_DES_KEY_GEN)
5889         {
5890                 return this->generateDES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5891         }
5892
5893         // Generate DES2 secret key
5894         if (pMechanism->mechanism == CKM_DES2_KEY_GEN)
5895         {
5896                 return this->generateDES2(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5897         }
5898
5899         // Generate DES3 secret key
5900         if (pMechanism->mechanism == CKM_DES3_KEY_GEN)
5901         {
5902                 return this->generateDES3(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5903         }
5904
5905         // Generate AES secret key
5906         if (pMechanism->mechanism == CKM_AES_KEY_GEN)
5907         {
5908                 return this->generateAES(hSession, pTemplate, ulCount, phKey, isOnToken, isPrivate);
5909         }
5910
5911         return CKR_GENERAL_ERROR;
5912 }
5913
5914 // Generate a key-pair using the specified mechanism
5915 CK_RV SoftHSM::C_GenerateKeyPair
5916 (
5917         CK_SESSION_HANDLE hSession,
5918         CK_MECHANISM_PTR pMechanism,
5919         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
5920         CK_ULONG ulPublicKeyAttributeCount,
5921         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
5922         CK_ULONG ulPrivateKeyAttributeCount,
5923         CK_OBJECT_HANDLE_PTR phPublicKey,
5924         CK_OBJECT_HANDLE_PTR phPrivateKey
5925 )
5926 {
5927         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
5928
5929         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
5930         if (phPublicKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5931         if (phPrivateKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
5932
5933         // Get the session
5934         Session* session = (Session*)handleManager->getSession(hSession);
5935         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
5936
5937         // Check the mechanism, only accept RSA, DSA, EC and DH key pair generation.
5938         CK_KEY_TYPE keyType;
5939         switch (pMechanism->mechanism)
5940         {
5941                 case CKM_RSA_PKCS_KEY_PAIR_GEN:
5942                         keyType = CKK_RSA;
5943                         break;
5944                 case CKM_DSA_KEY_PAIR_GEN:
5945                         keyType = CKK_DSA;
5946                         break;
5947                 case CKM_DH_PKCS_KEY_PAIR_GEN:
5948                         keyType = CKK_DH;
5949                         break;
5950 #ifdef WITH_ECC
5951                 case CKM_EC_KEY_PAIR_GEN:
5952                         keyType = CKK_EC;
5953                         break;
5954 #endif
5955 #ifdef WITH_GOST
5956                 case CKM_GOSTR3410_KEY_PAIR_GEN:
5957                         keyType = CKK_GOSTR3410;
5958                         break;
5959 #endif
5960                 default:
5961                         return CKR_MECHANISM_INVALID;
5962         }
5963         CK_CERTIFICATE_TYPE dummy;
5964
5965         // Extract information from the public key template that is needed to create the object.
5966         CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
5967         CK_BBOOL ispublicKeyToken = CK_FALSE;
5968         CK_BBOOL ispublicKeyPrivate = CK_FALSE;
5969         bool isPublicKeyImplicit = true;
5970         extractObjectInformation(pPublicKeyTemplate, ulPublicKeyAttributeCount, publicKeyClass, keyType, dummy, ispublicKeyToken, ispublicKeyPrivate, isPublicKeyImplicit);
5971
5972         // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5973         if (publicKeyClass != CKO_PUBLIC_KEY)
5974                 return CKR_ATTRIBUTE_VALUE_INVALID;
5975         if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5976                 return CKR_TEMPLATE_INCONSISTENT;
5977         if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5978                 return CKR_TEMPLATE_INCONSISTENT;
5979         if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
5980                 return CKR_TEMPLATE_INCONSISTENT;
5981         if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
5982                 return CKR_TEMPLATE_INCONSISTENT;
5983         if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
5984                 return CKR_TEMPLATE_INCONSISTENT;
5985
5986         // Extract information from the private key template that is needed to create the object.
5987         CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
5988         CK_BBOOL isprivateKeyToken = CK_FALSE;
5989         CK_BBOOL isprivateKeyPrivate = CK_TRUE;
5990         bool isPrivateKeyImplicit = true;
5991         extractObjectInformation(pPrivateKeyTemplate, ulPrivateKeyAttributeCount, privateKeyClass, keyType, dummy, isprivateKeyToken, isprivateKeyPrivate, isPrivateKeyImplicit);
5992
5993         // Report errors caused by accidental template mix-ups in the application using this cryptoki lib.
5994         if (privateKeyClass != CKO_PRIVATE_KEY)
5995                 return CKR_ATTRIBUTE_VALUE_INVALID;
5996         if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN && keyType != CKK_RSA)
5997                 return CKR_TEMPLATE_INCONSISTENT;
5998         if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN && keyType != CKK_DSA)
5999                 return CKR_TEMPLATE_INCONSISTENT;
6000         if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN && keyType != CKK_EC)
6001                 return CKR_TEMPLATE_INCONSISTENT;
6002         if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN && keyType != CKK_DH)
6003                 return CKR_TEMPLATE_INCONSISTENT;
6004         if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN && keyType != CKK_GOSTR3410)
6005                 return CKR_TEMPLATE_INCONSISTENT;
6006
6007         // Check user credentials
6008         CK_RV rv = haveWrite(session->getState(), ispublicKeyToken || isprivateKeyToken, ispublicKeyPrivate || isprivateKeyPrivate);
6009         if (rv != CKR_OK)
6010         {
6011                 if (rv == CKR_USER_NOT_LOGGED_IN)
6012                         INFO_MSG("User is not authorized");
6013                 if (rv == CKR_SESSION_READ_ONLY)
6014                         INFO_MSG("Session is read-only");
6015
6016                 return rv;
6017         }
6018
6019         // Generate RSA keys
6020         if (pMechanism->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN)
6021         {
6022                         return this->generateRSA(hSession,
6023                                                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
6024                                                                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6025                                                                          phPublicKey, phPrivateKey,
6026                                                                          ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6027         }
6028
6029         // Generate DSA keys
6030         if (pMechanism->mechanism == CKM_DSA_KEY_PAIR_GEN)
6031         {
6032                         return this->generateDSA(hSession,
6033                                                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
6034                                                                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6035                                                                          phPublicKey, phPrivateKey,
6036                                                                          ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6037         }
6038
6039         // Generate EC keys
6040         if (pMechanism->mechanism == CKM_EC_KEY_PAIR_GEN)
6041         {
6042                         return this->generateEC(hSession,
6043                                                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
6044                                                                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6045                                                                          phPublicKey, phPrivateKey,
6046                                                                          ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6047         }
6048
6049         // Generate DH keys
6050         if (pMechanism->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN)
6051         {
6052                         return this->generateDH(hSession,
6053                                                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
6054                                                                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6055                                                                          phPublicKey, phPrivateKey,
6056                                                                          ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6057         }
6058
6059         // Generate GOST keys
6060         if (pMechanism->mechanism == CKM_GOSTR3410_KEY_PAIR_GEN)
6061         {
6062                         return this->generateGOST(hSession,
6063                                                                          pPublicKeyTemplate, ulPublicKeyAttributeCount,
6064                                                                          pPrivateKeyTemplate, ulPrivateKeyAttributeCount,
6065                                                                          phPublicKey, phPrivateKey,
6066                                                                          ispublicKeyToken, ispublicKeyPrivate, isprivateKeyToken, isprivateKeyPrivate);
6067         }
6068
6069         return CKR_GENERAL_ERROR;
6070 }
6071
6072 // Internal: Wrap blob using symmetric key
6073 CK_RV SoftHSM::WrapKeySym
6074 (
6075         CK_MECHANISM_PTR pMechanism,
6076         Token* token,
6077         OSObject* wrapKey,
6078         ByteString& keydata,
6079         ByteString& wrapped
6080 )
6081 {
6082         // Get the symmetric algorithm matching the mechanism
6083         SymAlgo::Type algo = SymAlgo::Unknown;
6084         SymWrap::Type mode = SymWrap::Unknown;
6085         size_t bb = 8;
6086 #ifdef HAVE_AES_KEY_WRAP
6087         CK_ULONG wrappedlen = keydata.size();
6088
6089         // [PKCS#11 v2.40, 2.14.3 AES Key Wrap]
6090         // A key whose length is not a multiple of the AES Key Wrap block
6091         // size (8 bytes) will be zero padded to fit.
6092         CK_ULONG alignment = wrappedlen % 8;
6093         if (alignment != 0)
6094         {
6095                 keydata.resize(wrappedlen + 8 - alignment);
6096                 memset(&keydata[wrappedlen], 0, 8 - alignment);
6097                 wrappedlen = keydata.size();
6098         }
6099 #endif
6100         switch(pMechanism->mechanism) {
6101 #ifdef HAVE_AES_KEY_WRAP
6102                 case CKM_AES_KEY_WRAP:
6103                         if ((wrappedlen < 16) || ((wrappedlen % 8) != 0))
6104                                 return CKR_KEY_SIZE_RANGE;
6105                         algo = SymAlgo::AES;
6106                         mode = SymWrap::AES_KEYWRAP;
6107                         break;
6108 #endif
6109 #ifdef HAVE_AES_KEY_WRAP_PAD
6110                 case CKM_AES_KEY_WRAP_PAD:
6111                         algo = SymAlgo::AES;
6112                         mode = SymWrap::AES_KEYWRAP_PAD;
6113                         break;
6114 #endif
6115                 default:
6116                         return CKR_MECHANISM_INVALID;
6117         }
6118         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6119         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6120
6121         SymmetricKey* wrappingkey = new SymmetricKey();
6122
6123         if (getSymmetricKey(wrappingkey, token, wrapKey) != CKR_OK)
6124         {
6125                 cipher->recycleKey(wrappingkey);
6126                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6127                 return CKR_GENERAL_ERROR;
6128         }
6129
6130         // adjust key bit length
6131         wrappingkey->setBitLen(wrappingkey->getKeyBits().size() * bb);
6132
6133         // Wrap the key
6134         if (!cipher->wrapKey(wrappingkey, mode, keydata, wrapped))
6135         {
6136                 cipher->recycleKey(wrappingkey);
6137                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6138                 return CKR_GENERAL_ERROR;
6139         }
6140
6141         cipher->recycleKey(wrappingkey);
6142         CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6143         return CKR_OK;
6144 }
6145
6146 // Internal: Wrap blob using asymmetric key
6147 CK_RV SoftHSM::WrapKeyAsym
6148 (
6149         CK_MECHANISM_PTR pMechanism,
6150         Token* token,
6151         OSObject* wrapKey,
6152         ByteString& keydata,
6153         ByteString& wrapped
6154 )
6155 {
6156         const size_t bb = 8;
6157         AsymAlgo::Type algo = AsymAlgo::Unknown;
6158         AsymMech::Type mech = AsymMech::Unknown;
6159
6160         CK_ULONG modulus_length;
6161         switch(pMechanism->mechanism) {
6162                 case CKM_RSA_PKCS:
6163                 case CKM_RSA_PKCS_OAEP:
6164                         algo = AsymAlgo::RSA;
6165                         if (!wrapKey->attributeExists(CKA_MODULUS_BITS))
6166                                 return CKR_GENERAL_ERROR;
6167                         modulus_length = wrapKey->getUnsignedLongValue(CKA_MODULUS_BITS, 0);
6168                         // adjust key bit length
6169                         modulus_length /= bb;
6170                         break;
6171
6172                 default:
6173                         return CKR_MECHANISM_INVALID;
6174         }
6175
6176         switch(pMechanism->mechanism) {
6177                 case CKM_RSA_PKCS:
6178                         mech = AsymMech::RSA_PKCS;
6179                         // RFC 3447 section 7.2.1
6180                         if (keydata.size() > modulus_length - 11)
6181                                 return CKR_KEY_SIZE_RANGE;
6182                         break;
6183
6184                 case CKM_RSA_PKCS_OAEP:
6185                         mech = AsymMech::RSA_PKCS_OAEP;
6186                         // SHA-1 is the only supported option
6187                         // PKCS#11 2.40 draft 2 section 2.1.8: input length <= k-2-2hashLen
6188                         if (keydata.size() > modulus_length - 2 - 2 * 160 / 8)
6189                                 return CKR_KEY_SIZE_RANGE;
6190                         break;
6191
6192                 default:
6193                         return CKR_MECHANISM_INVALID;
6194         }
6195
6196         AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6197         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6198
6199         PublicKey* publicKey = cipher->newPublicKey();
6200         if (publicKey == NULL)
6201         {
6202                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6203                 return CKR_HOST_MEMORY;
6204         }
6205
6206         switch(pMechanism->mechanism) {
6207                 case CKM_RSA_PKCS:
6208                 case CKM_RSA_PKCS_OAEP:
6209                         if (getRSAPublicKey((RSAPublicKey*)publicKey, token, wrapKey) != CKR_OK)
6210                         {
6211                                 cipher->recyclePublicKey(publicKey);
6212                                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6213                                 return CKR_GENERAL_ERROR;
6214                         }
6215                         break;
6216
6217                 default:
6218                         return CKR_MECHANISM_INVALID;
6219         }
6220         // Wrap the key
6221         if (!cipher->wrapKey(publicKey, keydata, wrapped, mech))
6222         {
6223                 cipher->recyclePublicKey(publicKey);
6224                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6225                 return CKR_GENERAL_ERROR;
6226         }
6227
6228         cipher->recyclePublicKey(publicKey);
6229         CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6230
6231         return CKR_OK;
6232 }
6233
6234
6235 // Wrap the specified key using the specified wrapping key and mechanism
6236 CK_RV SoftHSM::C_WrapKey
6237 (
6238         CK_SESSION_HANDLE hSession,
6239         CK_MECHANISM_PTR pMechanism,
6240         CK_OBJECT_HANDLE hWrappingKey,
6241         CK_OBJECT_HANDLE hKey,
6242         CK_BYTE_PTR pWrappedKey,
6243         CK_ULONG_PTR pulWrappedKeyLen
6244 )
6245 {
6246         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6247
6248         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6249         if (pulWrappedKeyLen == NULL_PTR) return CKR_ARGUMENTS_BAD;
6250
6251         // Get the session
6252         Session* session = (Session*)handleManager->getSession(hSession);
6253         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6254
6255         CK_RV rv;
6256         // Check the mechanism, only accept advanced AES key wrapping and RSA
6257         switch(pMechanism->mechanism)
6258         {
6259 #ifdef HAVE_AES_KEY_WRAP
6260                 case CKM_AES_KEY_WRAP:
6261 #endif
6262 #ifdef HAVE_AES_KEY_WRAP_PAD
6263                 case CKM_AES_KEY_WRAP_PAD:
6264 #endif
6265                 case CKM_RSA_PKCS:
6266                         // Does not handle optional init vector
6267                         if (pMechanism->pParameter != NULL_PTR ||
6268                             pMechanism->ulParameterLen != 0)
6269                                 return CKR_ARGUMENTS_BAD;
6270                         break;
6271                 case CKM_RSA_PKCS_OAEP:
6272                         rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6273                         if (rv != CKR_OK)
6274                                 return rv;
6275                         break;
6276
6277                 default:
6278                         return CKR_MECHANISM_INVALID;
6279         }
6280
6281         // Get the token
6282         Token* token = session->getToken();
6283         if (token == NULL) return CKR_GENERAL_ERROR;
6284
6285         // Check the wrapping key handle.
6286         OSObject *wrapKey = (OSObject *)handleManager->getObject(hWrappingKey);
6287         if (wrapKey == NULL_PTR || !wrapKey->isValid()) return CKR_WRAPPING_KEY_HANDLE_INVALID;
6288
6289         CK_BBOOL isWrapKeyOnToken = wrapKey->getBooleanValue(CKA_TOKEN, false);
6290         CK_BBOOL isWrapKeyPrivate = wrapKey->getBooleanValue(CKA_PRIVATE, true);
6291
6292         // Check user credentials for the wrapping key
6293         rv = haveRead(session->getState(), isWrapKeyOnToken, isWrapKeyPrivate);
6294         if (rv != CKR_OK)
6295         {
6296                 if (rv == CKR_USER_NOT_LOGGED_IN)
6297                         INFO_MSG("User is not authorized");
6298
6299                 return rv;
6300         }
6301
6302         // Check wrapping key class and type
6303         if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6304                 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6305         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PUBLIC_KEY)
6306                 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6307         if (pMechanism->mechanism == CKM_AES_KEY_WRAP && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6308                 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6309         if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6310                 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6311         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && wrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6312                 return CKR_WRAPPING_KEY_TYPE_INCONSISTENT;
6313
6314         // Check if the wrapping key can be used for wrapping
6315         if (wrapKey->getBooleanValue(CKA_WRAP, false) == false)
6316                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6317
6318     // Check if the specified mechanism is allowed for the wrapping key
6319     if (!isMechanismPermitted(wrapKey, pMechanism))
6320                 return CKR_MECHANISM_INVALID;
6321
6322         // Check the to be wrapped key handle.
6323         OSObject *key = (OSObject *)handleManager->getObject(hKey);
6324         if (key == NULL_PTR || !key->isValid()) return CKR_KEY_HANDLE_INVALID;
6325
6326         CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6327         CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6328
6329         // Check user credentials for the to be wrapped key
6330         rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6331         if (rv != CKR_OK)
6332         {
6333                 if (rv == CKR_USER_NOT_LOGGED_IN)
6334                         INFO_MSG("User is not authorized");
6335
6336                 return rv;
6337         }
6338
6339         // Check if the to be wrapped key can be wrapped
6340         if (key->getBooleanValue(CKA_EXTRACTABLE, false) == false)
6341                 return CKR_KEY_UNEXTRACTABLE;
6342         if (key->getBooleanValue(CKA_WRAP_WITH_TRUSTED, false) && wrapKey->getBooleanValue(CKA_TRUSTED, false) == false)
6343                 return CKR_KEY_NOT_WRAPPABLE;
6344
6345         // Check the class
6346         CK_OBJECT_CLASS keyClass = key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6347         if (keyClass != CKO_SECRET_KEY && keyClass != CKO_PRIVATE_KEY)
6348                 return CKR_KEY_NOT_WRAPPABLE;
6349         // CKM_RSA_PKCS and CKM_RSA_PKCS_OAEP can be used only on SECRET keys: PKCS#11 2.40 draft 2 section 2.1.6 PKCS #1 v1.5 RSA & section 2.1.8 PKCS #1 RSA OAEP
6350         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && keyClass != CKO_SECRET_KEY)
6351                 return CKR_KEY_NOT_WRAPPABLE;
6352
6353         // Verify the wrap template attribute
6354         if (wrapKey->attributeExists(CKA_WRAP_TEMPLATE))
6355         {
6356                 OSAttribute attr = wrapKey->getAttribute(CKA_WRAP_TEMPLATE);
6357
6358                 if (attr.isAttributeMapAttribute())
6359                 {
6360                         typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6361
6362                         const attrmap_type& map = attr.getAttributeMapValue();
6363
6364                         for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6365                         {
6366                                 if (!key->attributeExists(it->first))
6367                                 {
6368                                         return CKR_KEY_NOT_WRAPPABLE;
6369                                 }
6370
6371                                 OSAttribute keyAttr = key->getAttribute(it->first);
6372                                 ByteString v1, v2;
6373                                 if (!keyAttr.peekValue(v1) || !it->second.peekValue(v2) || (v1 != v2))
6374                                 {
6375                                         return CKR_KEY_NOT_WRAPPABLE;
6376                                 }
6377                         }
6378                 }
6379         }
6380
6381         // Get the key data to encrypt
6382         ByteString keydata;
6383         if (keyClass == CKO_SECRET_KEY)
6384         {
6385                 if (isKeyPrivate)
6386                 {
6387                         bool bOK = token->decrypt(key->getByteStringValue(CKA_VALUE), keydata);
6388                         if (!bOK) return CKR_GENERAL_ERROR;
6389                 }
6390                 else
6391                 {
6392                         keydata = key->getByteStringValue(CKA_VALUE);
6393                 }
6394         }
6395         else
6396         {
6397                 CK_KEY_TYPE keyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6398                 AsymAlgo::Type alg = AsymAlgo::Unknown;
6399                 switch (keyType) {
6400                         case CKK_RSA:
6401                                 alg = AsymAlgo::RSA;
6402                                 break;
6403                         case CKK_DSA:
6404                                 alg = AsymAlgo::DSA;
6405                                 break;
6406                         case CKK_DH:
6407                                 alg = AsymAlgo::DH;
6408                                 break;
6409 #ifdef WITH_ECC
6410                         case CKK_EC:
6411                                 // can be ecdh too but it doesn't matter
6412                                 alg = AsymAlgo::ECDSA;
6413                                 break;
6414 #endif
6415 #ifdef WITH_GOST
6416                         case CKK_GOSTR3410:
6417                                 alg = AsymAlgo::GOST;
6418                                 break;
6419 #endif
6420                         default:
6421                                 return CKR_KEY_NOT_WRAPPABLE;
6422                 }
6423                 AsymmetricAlgorithm* asymCrypto = NULL;
6424                 PrivateKey* privateKey = NULL;
6425                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6426                 if (asymCrypto == NULL)
6427                         return CKR_GENERAL_ERROR;
6428                 privateKey = asymCrypto->newPrivateKey();
6429                 if (privateKey == NULL)
6430                 {
6431                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6432                         return CKR_HOST_MEMORY;
6433                 }
6434                 switch (keyType) {
6435                         case CKK_RSA:
6436                                 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6437                                 break;
6438                         case CKK_DSA:
6439                                 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6440                                 break;
6441                         case CKK_DH:
6442                                 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6443                                 break;
6444 #ifdef WITH_ECC
6445                         case CKK_EC:
6446                                 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6447                                 break;
6448 #endif
6449 #ifdef WITH_GOST
6450                         case CKK_GOSTR3410:
6451                                 rv = getGOSTPrivateKey((GOSTPrivateKey*)privateKey, token, key);
6452                                 break;
6453 #endif
6454                 }
6455                 if (rv != CKR_OK)
6456                 {
6457                         asymCrypto->recyclePrivateKey(privateKey);
6458                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6459                         return CKR_GENERAL_ERROR;
6460                 }
6461                 keydata = privateKey->PKCS8Encode();
6462                 asymCrypto->recyclePrivateKey(privateKey);
6463                 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6464         }
6465         if (keydata.size() == 0)
6466                 return CKR_KEY_NOT_WRAPPABLE;
6467
6468         keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6469         ByteString wrapped;
6470         if (keyClass == CKO_SECRET_KEY)
6471                 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6472         else
6473                 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6474         if (rv != CKR_OK)
6475                 return rv;
6476
6477         if (pWrappedKey != NULL) {
6478                 if (*pulWrappedKeyLen >= wrapped.size())
6479                         memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6480                 else
6481                         rv = CKR_BUFFER_TOO_SMALL;
6482         }
6483
6484         *pulWrappedKeyLen = wrapped.size();
6485         return rv;
6486 }
6487
6488 // Internal: Unwrap blob using symmetric key
6489 CK_RV SoftHSM::UnwrapKeySym
6490 (
6491         CK_MECHANISM_PTR pMechanism,
6492         ByteString& wrapped,
6493         Token* token,
6494         OSObject* unwrapKey,
6495         ByteString& keydata
6496 )
6497 {
6498         // Get the symmetric algorithm matching the mechanism
6499         SymAlgo::Type algo = SymAlgo::Unknown;
6500         SymWrap::Type mode = SymWrap::Unknown;
6501         size_t bb = 8;
6502         switch(pMechanism->mechanism) {
6503 #ifdef HAVE_AES_KEY_WRAP
6504                 case CKM_AES_KEY_WRAP:
6505                         algo = SymAlgo::AES;
6506                         mode = SymWrap::AES_KEYWRAP;
6507                         break;
6508 #endif
6509 #ifdef HAVE_AES_KEY_WRAP_PAD
6510                 case CKM_AES_KEY_WRAP_PAD:
6511                         algo = SymAlgo::AES;
6512                         mode = SymWrap::AES_KEYWRAP_PAD;
6513                         break;
6514 #endif
6515                 default:
6516                         return CKR_MECHANISM_INVALID;
6517         }
6518         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6519         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6520
6521         SymmetricKey* unwrappingkey = new SymmetricKey();
6522
6523         if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6524         {
6525                 cipher->recycleKey(unwrappingkey);
6526                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6527                 return CKR_GENERAL_ERROR;
6528         }
6529
6530         // adjust key bit length
6531         unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6532
6533         // Unwrap the key
6534         CK_RV rv = CKR_OK;
6535         if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6536                 rv = CKR_GENERAL_ERROR;
6537         cipher->recycleKey(unwrappingkey);
6538         CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6539         return rv;
6540 }
6541
6542 // Internal: Unwrap blob using asymmetric key
6543 CK_RV SoftHSM::UnwrapKeyAsym
6544 (
6545         CK_MECHANISM_PTR pMechanism,
6546         ByteString& wrapped,
6547         Token* token,
6548         OSObject* unwrapKey,
6549         ByteString& keydata
6550 )
6551 {
6552         // Get the symmetric algorithm matching the mechanism
6553         AsymAlgo::Type algo = AsymAlgo::Unknown;
6554         AsymMech::Type mode = AsymMech::Unknown;
6555         switch(pMechanism->mechanism) {
6556                 case CKM_RSA_PKCS:
6557                         algo = AsymAlgo::RSA;
6558                         mode = AsymMech::RSA_PKCS;
6559                         break;
6560
6561                 case CKM_RSA_PKCS_OAEP:
6562                         algo = AsymAlgo::RSA;
6563                         mode = AsymMech::RSA_PKCS_OAEP;
6564                         break;
6565
6566                 default:
6567                         return CKR_MECHANISM_INVALID;
6568         }
6569         AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6570         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6571
6572         PrivateKey* unwrappingkey = cipher->newPrivateKey();
6573         if (unwrappingkey == NULL)
6574         {
6575                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6576                 return CKR_HOST_MEMORY;
6577         }
6578
6579         switch(pMechanism->mechanism) {
6580                 case CKM_RSA_PKCS:
6581                 case CKM_RSA_PKCS_OAEP:
6582                         if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6583                         {
6584                                 cipher->recyclePrivateKey(unwrappingkey);
6585                                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6586                                 return CKR_GENERAL_ERROR;
6587                         }
6588                         break;
6589
6590                 default:
6591                         return CKR_MECHANISM_INVALID;
6592         }
6593
6594         // Unwrap the key
6595         CK_RV rv = CKR_OK;
6596         if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6597                 rv = CKR_GENERAL_ERROR;
6598         cipher->recyclePrivateKey(unwrappingkey);
6599         CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6600         return rv;
6601 }
6602
6603 // Unwrap the specified key using the specified unwrapping key
6604 CK_RV SoftHSM::C_UnwrapKey
6605 (
6606         CK_SESSION_HANDLE hSession,
6607         CK_MECHANISM_PTR pMechanism,
6608         CK_OBJECT_HANDLE hUnwrappingKey,
6609         CK_BYTE_PTR pWrappedKey,
6610         CK_ULONG ulWrappedKeyLen,
6611         CK_ATTRIBUTE_PTR pTemplate,
6612         CK_ULONG ulCount,
6613         CK_OBJECT_HANDLE_PTR hKey
6614 )
6615 {
6616         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6617
6618         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6619         if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6620         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6621         if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6622
6623         // Get the session
6624         Session* session = (Session*)handleManager->getSession(hSession);
6625         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6626
6627         CK_RV rv;
6628         // Check the mechanism
6629         switch(pMechanism->mechanism)
6630         {
6631 #ifdef HAVE_AES_KEY_WRAP
6632                 case CKM_AES_KEY_WRAP:
6633                         if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
6634                                 return CKR_WRAPPED_KEY_LEN_RANGE;
6635                         // Does not handle optional init vector
6636                         if (pMechanism->pParameter != NULL_PTR ||
6637                             pMechanism->ulParameterLen != 0)
6638                                 return CKR_ARGUMENTS_BAD;
6639                         break;
6640 #endif
6641 #ifdef HAVE_AES_KEY_WRAP_PAD
6642                 case CKM_AES_KEY_WRAP_PAD:
6643                         if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6644                                 return CKR_WRAPPED_KEY_LEN_RANGE;
6645                         // Does not handle optional init vector
6646                         if (pMechanism->pParameter != NULL_PTR ||
6647                             pMechanism->ulParameterLen != 0)
6648                                 return CKR_ARGUMENTS_BAD;
6649                         break;
6650 #endif
6651                 case CKM_RSA_PKCS:
6652                         // Input length checks needs to be done later when unwrapping key is known
6653                         break;
6654                 case CKM_RSA_PKCS_OAEP:
6655                         rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6656                         if (rv != CKR_OK)
6657                                 return rv;
6658                         break;
6659
6660                 default:
6661                         return CKR_MECHANISM_INVALID;
6662         }
6663
6664         // Get the token
6665         Token* token = session->getToken();
6666         if (token == NULL) return CKR_GENERAL_ERROR;
6667
6668         // Check the unwrapping key handle.
6669         OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6670         if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6671
6672         CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6673         CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6674
6675         // Check user credentials
6676         rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6677         if (rv != CKR_OK)
6678         {
6679                 if (rv == CKR_USER_NOT_LOGGED_IN)
6680                         INFO_MSG("User is not authorized");
6681
6682                 return rv;
6683         }
6684
6685         // Check unwrapping key class and type
6686         if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6687                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6688         if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6689                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6690         if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6691                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6692         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6693                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6694         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6695                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6696
6697         // Check if the unwrapping key can be used for unwrapping
6698         if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6699                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6700
6701         // Check if the specified mechanism is allowed for the unwrap key
6702         if (!isMechanismPermitted(unwrapKey, pMechanism))
6703                 return CKR_MECHANISM_INVALID;
6704
6705         // Extract information from the template that is needed to create the object.
6706         CK_OBJECT_CLASS objClass;
6707         CK_KEY_TYPE keyType;
6708         CK_BBOOL isOnToken = CK_FALSE;
6709         CK_BBOOL isPrivate = CK_TRUE;
6710         CK_CERTIFICATE_TYPE dummy;
6711         bool isImplicit = false;
6712         rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6713         if (rv != CKR_OK)
6714         {
6715                 ERROR_MSG("Mandatory attribute not present in template");
6716                 return rv;
6717         }
6718
6719         // Report errors and/or unexpected usage.
6720         if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6721                 return CKR_ATTRIBUTE_VALUE_INVALID;
6722         // Key type will be handled at object creation
6723
6724         // Check authorization
6725         rv = haveWrite(session->getState(), isOnToken, isPrivate);
6726         if (rv != CKR_OK)
6727         {
6728                 if (rv == CKR_USER_NOT_LOGGED_IN)
6729                         INFO_MSG("User is not authorized");
6730                 if (rv == CKR_SESSION_READ_ONLY)
6731                         INFO_MSG("Session is read-only");
6732
6733                 return rv;
6734         }
6735
6736         // Build unwrapped key template
6737         const CK_ULONG maxAttribs = 32;
6738         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6739                 { CKA_CLASS, &objClass, sizeof(objClass) },
6740                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6741                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6742                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6743         };
6744         CK_ULONG secretAttribsCount = 4;
6745
6746         // Add the additional
6747         if (ulCount > (maxAttribs - secretAttribsCount))
6748                 return CKR_TEMPLATE_INCONSISTENT;
6749         for (CK_ULONG i = 0; i < ulCount; ++i)
6750         {
6751                 switch (pTemplate[i].type)
6752                 {
6753                         case CKA_CLASS:
6754                         case CKA_TOKEN:
6755                         case CKA_PRIVATE:
6756                         case CKA_KEY_TYPE:
6757                                 continue;
6758                         default:
6759                                 secretAttribs[secretAttribsCount++] = pTemplate[i];
6760                 }
6761         }
6762
6763         // Apply the unwrap template
6764         if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6765         {
6766                 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6767
6768                 if (unwrapAttr.isAttributeMapAttribute())
6769                 {
6770                         typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6771
6772                         const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6773
6774                         for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6775                         {
6776                                 CK_ATTRIBUTE* attr = NULL;
6777                                 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6778                                 {
6779                                         if (it->first == secretAttribs[i].type)
6780                                         {
6781                                                 if (attr != NULL)
6782                                                 {
6783                                                         return CKR_TEMPLATE_INCONSISTENT;
6784                                                 }
6785                                                 attr = &secretAttribs[i];
6786                                                 ByteString value;
6787                                                 it->second.peekValue(value);
6788                                                 if (attr->ulValueLen != value.size())
6789                                                 {
6790                                                         return CKR_TEMPLATE_INCONSISTENT;
6791                                                 }
6792                                                 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6793                                                 {
6794                                                         return CKR_TEMPLATE_INCONSISTENT;
6795                                                 }
6796                                         }
6797                                 }
6798                                 if (attr == NULL)
6799                                 {
6800                                         return CKR_TEMPLATE_INCONSISTENT;
6801                                 }
6802                         }
6803                 }
6804         }
6805
6806         *hKey = CK_INVALID_HANDLE;
6807
6808         // Unwrap the key
6809         ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6810         ByteString keydata;
6811         if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6812                 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6813         else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6814                 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6815         else
6816                 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6817         if (rv != CKR_OK)
6818                 return rv;
6819
6820         // Create the secret object using C_CreateObject
6821         rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6822
6823         // Store the attributes that are being supplied
6824         if (rv == CKR_OK)
6825         {
6826                 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6827                 if (osobject == NULL_PTR || !osobject->isValid())
6828                         rv = CKR_FUNCTION_FAILED;
6829                 if (osobject->startTransaction())
6830                 {
6831                         bool bOK = true;
6832
6833                         // Common Attributes
6834                         bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6835
6836                         // Common Secret Key Attributes
6837                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6838                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6839
6840                         // Secret Attributes
6841                         if (objClass == CKO_SECRET_KEY)
6842                         {
6843                                 ByteString value;
6844                                 if (isPrivate)
6845                                         token->encrypt(keydata, value);
6846                                 else
6847                                         value = keydata;
6848                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6849                         }
6850                         else if (keyType == CKK_RSA)
6851                         {
6852                                 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6853                         }
6854                         else if (keyType == CKK_DSA)
6855                         {
6856                                 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6857                         }
6858                         else if (keyType == CKK_DH)
6859                         {
6860                                 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6861                         }
6862 #ifdef WITH_ECC
6863                         else if (keyType == CKK_EC)
6864                         {
6865                                 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6866                         }
6867 #endif
6868 #ifdef WITH_GOST
6869                         else if (keyType == CKK_GOSTR3410)
6870                         {
6871                                 bOK = bOK && setGOSTPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6872                         }
6873 #endif
6874                         else
6875                                 bOK = false;
6876
6877                         if (bOK)
6878                                 bOK = osobject->commitTransaction();
6879                         else
6880                                 osobject->abortTransaction();
6881
6882                         if (!bOK)
6883                                 rv = CKR_FUNCTION_FAILED;
6884                 }
6885                 else
6886                         rv = CKR_FUNCTION_FAILED;
6887         }
6888
6889         // Remove secret that may have been created already when the function fails.
6890         if (rv != CKR_OK)
6891         {
6892                 if (*hKey != CK_INVALID_HANDLE)
6893                 {
6894                         OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6895                         handleManager->destroyObject(*hKey);
6896                         if (obj) obj->destroyObject();
6897                         *hKey = CK_INVALID_HANDLE;
6898                 }
6899
6900         }
6901
6902         return rv;
6903 }
6904
6905 // Derive a key from the specified base key
6906 CK_RV SoftHSM::C_DeriveKey
6907 (
6908         CK_SESSION_HANDLE hSession,
6909         CK_MECHANISM_PTR pMechanism,
6910         CK_OBJECT_HANDLE hBaseKey,
6911         CK_ATTRIBUTE_PTR pTemplate,
6912         CK_ULONG ulCount,
6913         CK_OBJECT_HANDLE_PTR phKey
6914 )
6915 {
6916         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6917
6918         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6919         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6920         if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6921
6922         // Get the session
6923         Session* session = (Session*)handleManager->getSession(hSession);
6924         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6925
6926         // Check the mechanism, only accept DH and ECDH derive
6927         switch (pMechanism->mechanism)
6928         {
6929                 case CKM_DH_PKCS_DERIVE:
6930 #ifdef WITH_ECC
6931                 case CKM_ECDH1_DERIVE:
6932 #endif
6933 #ifndef WITH_FIPS
6934                 case CKM_DES_ECB_ENCRYPT_DATA:
6935                 case CKM_DES_CBC_ENCRYPT_DATA:
6936 #endif
6937                 case CKM_DES3_ECB_ENCRYPT_DATA:
6938                 case CKM_DES3_CBC_ENCRYPT_DATA:
6939                 case CKM_AES_ECB_ENCRYPT_DATA:
6940                 case CKM_AES_CBC_ENCRYPT_DATA:
6941                         break;
6942                 default:
6943                         ERROR_MSG("Invalid mechanism");
6944                         return CKR_MECHANISM_INVALID;
6945         }
6946
6947         // Get the token
6948         Token* token = session->getToken();
6949         if (token == NULL) return CKR_GENERAL_ERROR;
6950
6951         // Check the key handle.
6952         OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6953         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6954
6955         CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6956         CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6957
6958         // Check user credentials
6959         CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6960         if (rv != CKR_OK)
6961         {
6962                 if (rv == CKR_USER_NOT_LOGGED_IN)
6963                         INFO_MSG("User is not authorized");
6964
6965                 return rv;
6966         }
6967
6968         // Check if key can be used for derive
6969         if (!key->getBooleanValue(CKA_DERIVE, false))
6970                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6971
6972         // Check if the specified mechanism is allowed for the key
6973         if (!isMechanismPermitted(key, pMechanism))
6974                 return CKR_MECHANISM_INVALID;
6975
6976         // Extract information from the template that is needed to create the object.
6977         CK_OBJECT_CLASS objClass;
6978         CK_KEY_TYPE keyType;
6979         CK_BBOOL isOnToken = CK_FALSE;
6980         CK_BBOOL isPrivate = CK_TRUE;
6981         CK_CERTIFICATE_TYPE dummy;
6982         bool isImplicit = false;
6983         rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6984         if (rv != CKR_OK)
6985         {
6986                 ERROR_MSG("Mandatory attribute not present in template");
6987                 return rv;
6988         }
6989
6990         // Report errors and/or unexpected usage.
6991         if (objClass != CKO_SECRET_KEY)
6992                 return CKR_ATTRIBUTE_VALUE_INVALID;
6993         if (keyType != CKK_GENERIC_SECRET &&
6994             keyType != CKK_DES &&
6995             keyType != CKK_DES2 &&
6996             keyType != CKK_DES3 &&
6997             keyType != CKK_AES)
6998                 return CKR_TEMPLATE_INCONSISTENT;
6999
7000         // Check authorization
7001         rv = haveWrite(session->getState(), isOnToken, isPrivate);
7002         if (rv != CKR_OK)
7003         {
7004                 if (rv == CKR_USER_NOT_LOGGED_IN)
7005                         INFO_MSG("User is not authorized");
7006                 if (rv == CKR_SESSION_READ_ONLY)
7007                         INFO_MSG("Session is read-only");
7008
7009                 return rv;
7010         }
7011
7012         // Derive DH secret
7013         if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
7014         {
7015                 // Check key class and type
7016                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
7017                         return CKR_KEY_TYPE_INCONSISTENT;
7018                 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
7019                         return CKR_KEY_TYPE_INCONSISTENT;
7020
7021                 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7022         }
7023
7024 #ifdef WITH_ECC
7025         // Derive ECDH secret
7026         if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
7027         {
7028                 // Check key class and type
7029                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
7030                         return CKR_KEY_TYPE_INCONSISTENT;
7031                 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
7032                         return CKR_KEY_TYPE_INCONSISTENT;
7033
7034                 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7035         }
7036 #endif
7037
7038         // Derive symmetric secret
7039         if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
7040             pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
7041             pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
7042             pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
7043             pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
7044             pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
7045         {
7046                 // Check key class and type
7047                 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
7048                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
7049                         return CKR_KEY_TYPE_INCONSISTENT;
7050                 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
7051                     baseKeyType != CKK_DES)
7052                         return CKR_KEY_TYPE_INCONSISTENT;
7053                 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
7054                     baseKeyType != CKK_DES)
7055                         return CKR_KEY_TYPE_INCONSISTENT;
7056                 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
7057                     baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
7058                         return CKR_KEY_TYPE_INCONSISTENT;
7059                 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
7060                     baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
7061                         return CKR_KEY_TYPE_INCONSISTENT;
7062                 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
7063                     baseKeyType != CKK_AES)
7064                         return CKR_KEY_TYPE_INCONSISTENT;
7065                 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
7066                     baseKeyType != CKK_AES)
7067                         return CKR_KEY_TYPE_INCONSISTENT;
7068
7069                 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
7070         }
7071
7072         return CKR_MECHANISM_INVALID;
7073 }
7074
7075 // Seed the random number generator with new data
7076 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
7077 {
7078         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7079
7080         if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
7081
7082         // Get the session
7083         Session* session = (Session*)handleManager->getSession(hSession);
7084         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7085
7086         // Get the RNG
7087         RNG* rng = CryptoFactory::i()->getRNG();
7088         if (rng == NULL) return CKR_GENERAL_ERROR;
7089
7090         // Seed the RNG
7091         ByteString seed(pSeed, ulSeedLen);
7092         rng->seed(seed);
7093
7094         return CKR_OK;
7095 }
7096
7097 // Generate the specified amount of random data
7098 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
7099 {
7100         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7101
7102         if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
7103
7104         // Get the session
7105         Session* session = (Session*)handleManager->getSession(hSession);
7106         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7107
7108         // Get the RNG
7109         RNG* rng = CryptoFactory::i()->getRNG();
7110         if (rng == NULL) return CKR_GENERAL_ERROR;
7111
7112         // Generate random data
7113         ByteString randomData;
7114         if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
7115
7116         // Return random data
7117         if (ulRandomLen != 0)
7118         {
7119                 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
7120         }
7121
7122         return CKR_OK;
7123 }
7124
7125 // Legacy function
7126 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
7127 {
7128         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7129
7130         // Get the session
7131         Session* session = (Session*)handleManager->getSession(hSession);
7132         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7133
7134         return CKR_FUNCTION_NOT_PARALLEL;
7135 }
7136
7137 // Legacy function
7138 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
7139 {
7140         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
7141
7142         // Get the session
7143         Session* session = (Session*)handleManager->getSession(hSession);
7144         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
7145
7146         return CKR_FUNCTION_NOT_PARALLEL;
7147 }
7148
7149 // Wait or poll for a slot event on the specified slot
7150 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
7151 {
7152         return CKR_FUNCTION_NOT_SUPPORTED;
7153 }
7154
7155 // Generate an AES secret key
7156 CK_RV SoftHSM::generateAES
7157 (CK_SESSION_HANDLE hSession,
7158         CK_ATTRIBUTE_PTR pTemplate,
7159         CK_ULONG ulCount,
7160         CK_OBJECT_HANDLE_PTR phKey,
7161         CK_BBOOL isOnToken,
7162         CK_BBOOL isPrivate)
7163 {
7164         *phKey = CK_INVALID_HANDLE;
7165
7166         // Get the session
7167         Session* session = (Session*)handleManager->getSession(hSession);
7168         if (session == NULL)
7169                 return CKR_SESSION_HANDLE_INVALID;
7170
7171         // Get the token
7172         Token* token = session->getToken();
7173         if (token == NULL)
7174                 return CKR_GENERAL_ERROR;
7175
7176         // Extract desired parameter information
7177         size_t keyLen = 0;
7178         bool checkValue = true;
7179         for (CK_ULONG i = 0; i < ulCount; i++)
7180         {
7181                 switch (pTemplate[i].type)
7182                 {
7183                         case CKA_VALUE_LEN:
7184                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
7185                                 {
7186                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
7187                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7188                                 }
7189                                 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
7190                                 break;
7191                         case CKA_CHECK_VALUE:
7192                                 if (pTemplate[i].ulValueLen > 0)
7193                                 {
7194                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7195                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7196                                 }
7197                                 checkValue = false;
7198                                 break;
7199                         default:
7200                                 break;
7201                 }
7202         }
7203
7204         // CKA_VALUE_LEN must be specified
7205         if (keyLen == 0)
7206         {
7207                 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
7208                 return CKR_TEMPLATE_INCOMPLETE;
7209         }
7210
7211         // keyLen must be 16, 24, or 32
7212         if (keyLen != 16 && keyLen != 24 && keyLen != 32)
7213         {
7214                 INFO_MSG("bad AES key length");
7215                 return CKR_ATTRIBUTE_VALUE_INVALID;
7216         }
7217
7218         // Generate the secret key
7219         AESKey* key = new AESKey(keyLen * 8);
7220         SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
7221         if (aes == NULL)
7222         {
7223                 ERROR_MSG("Could not get SymmetricAlgorithm");
7224                 delete key;
7225                 return CKR_GENERAL_ERROR;
7226         }
7227         RNG* rng = CryptoFactory::i()->getRNG();
7228         if (rng == NULL)
7229         {
7230                 ERROR_MSG("Could not get RNG");
7231                 aes->recycleKey(key);
7232                 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7233                 return CKR_GENERAL_ERROR;
7234         }
7235         if (!aes->generateKey(*key, rng))
7236         {
7237                 ERROR_MSG("Could not generate AES secret key");
7238                 aes->recycleKey(key);
7239                 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7240                 return CKR_GENERAL_ERROR;
7241         }
7242
7243         CK_RV rv = CKR_OK;
7244
7245         // Create the secret key object using C_CreateObject
7246         const CK_ULONG maxAttribs = 32;
7247         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7248         CK_KEY_TYPE keyType = CKK_AES;
7249         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7250                 { CKA_CLASS, &objClass, sizeof(objClass) },
7251                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7252                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7253                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7254         };
7255         CK_ULONG keyAttribsCount = 4;
7256
7257         // Add the additional
7258         if (ulCount > (maxAttribs - keyAttribsCount))
7259                 rv = CKR_TEMPLATE_INCONSISTENT;
7260         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7261         {
7262                 switch (pTemplate[i].type)
7263                 {
7264                         case CKA_CLASS:
7265                         case CKA_TOKEN:
7266                         case CKA_PRIVATE:
7267                         case CKA_KEY_TYPE:
7268                         case CKA_CHECK_VALUE:
7269                                 continue;
7270                 default:
7271                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7272                 }
7273         }
7274
7275         if (rv == CKR_OK)
7276                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7277
7278         // Store the attributes that are being supplied
7279         if (rv == CKR_OK)
7280         {
7281                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7282                 if (osobject == NULL_PTR || !osobject->isValid()) {
7283                         rv = CKR_FUNCTION_FAILED;
7284                 } else if (osobject->startTransaction()) {
7285                         bool bOK = true;
7286
7287                         // Common Attributes
7288                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7289                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
7290                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7291
7292                         // Common Secret Key Attributes
7293                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7294                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7295                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7296                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7297
7298                         // AES Secret Key Attributes
7299                         ByteString value;
7300                         ByteString kcv;
7301                         if (isPrivate)
7302                         {
7303                                 token->encrypt(key->getKeyBits(), value);
7304                                 token->encrypt(key->getKeyCheckValue(), kcv);
7305                         }
7306                         else
7307                         {
7308                                 value = key->getKeyBits();
7309                                 kcv = key->getKeyCheckValue();
7310                         }
7311                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7312                         if (checkValue)
7313                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7314
7315                         if (bOK)
7316                                 bOK = osobject->commitTransaction();
7317                         else
7318                                 osobject->abortTransaction();
7319
7320                         if (!bOK)
7321                                 rv = CKR_FUNCTION_FAILED;
7322                 } else
7323                         rv = CKR_FUNCTION_FAILED;
7324         }
7325
7326         // Clean up
7327         aes->recycleKey(key);
7328         CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7329
7330         // Remove the key that may have been created already when the function fails.
7331         if (rv != CKR_OK)
7332         {
7333                 if (*phKey != CK_INVALID_HANDLE)
7334                 {
7335                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7336                         handleManager->destroyObject(*phKey);
7337                         if (oskey) oskey->destroyObject();
7338                         *phKey = CK_INVALID_HANDLE;
7339                 }
7340         }
7341
7342         return rv;
7343 }
7344
7345 // Generate a DES secret key
7346 CK_RV SoftHSM::generateDES
7347 (CK_SESSION_HANDLE hSession,
7348         CK_ATTRIBUTE_PTR pTemplate,
7349         CK_ULONG ulCount,
7350         CK_OBJECT_HANDLE_PTR phKey,
7351         CK_BBOOL isOnToken,
7352         CK_BBOOL isPrivate)
7353 {
7354         *phKey = CK_INVALID_HANDLE;
7355
7356         // Get the session
7357         Session* session = (Session*)handleManager->getSession(hSession);
7358         if (session == NULL)
7359                 return CKR_SESSION_HANDLE_INVALID;
7360
7361         // Get the token
7362         Token* token = session->getToken();
7363         if (token == NULL)
7364                 return CKR_GENERAL_ERROR;
7365
7366         // Extract desired parameter information
7367         bool checkValue = true;
7368         for (CK_ULONG i = 0; i < ulCount; i++)
7369         {
7370                 switch (pTemplate[i].type)
7371                 {
7372                         case CKA_CHECK_VALUE:
7373                                 if (pTemplate[i].ulValueLen > 0)
7374                                 {
7375                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7376                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7377                                 }
7378                                 checkValue = false;
7379                                 break;
7380                         default:
7381                                 break;
7382                 }
7383         }
7384
7385         // Generate the secret key
7386         DESKey* key = new DESKey(56);
7387         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7388         if (des == NULL)
7389         {
7390                 ERROR_MSG("Could not get SymmetricAlgorithm");
7391                 delete key;
7392                 return CKR_GENERAL_ERROR;
7393         }
7394         RNG* rng = CryptoFactory::i()->getRNG();
7395         if (rng == NULL)
7396         {
7397                 ERROR_MSG("Could not get RNG");
7398                 des->recycleKey(key);
7399                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7400                 return CKR_GENERAL_ERROR;
7401         }
7402         if (!des->generateKey(*key, rng))
7403         {
7404                 ERROR_MSG("Could not generate DES secret key");
7405                 des->recycleKey(key);
7406                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7407                 return CKR_GENERAL_ERROR;
7408         }
7409
7410         CK_RV rv = CKR_OK;
7411
7412         // Create the secret key object using C_CreateObject
7413         const CK_ULONG maxAttribs = 32;
7414         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7415         CK_KEY_TYPE keyType = CKK_DES;
7416         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7417                 { CKA_CLASS, &objClass, sizeof(objClass) },
7418                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7419                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7420                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7421         };
7422         CK_ULONG keyAttribsCount = 4;
7423
7424         // Add the additional
7425         if (ulCount > (maxAttribs - keyAttribsCount))
7426                 rv = CKR_TEMPLATE_INCONSISTENT;
7427         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7428         {
7429                 switch (pTemplate[i].type)
7430                 {
7431                         case CKA_CLASS:
7432                         case CKA_TOKEN:
7433                         case CKA_PRIVATE:
7434                         case CKA_KEY_TYPE:
7435                         case CKA_CHECK_VALUE:
7436                                 continue;
7437                 default:
7438                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7439                 }
7440         }
7441
7442         if (rv == CKR_OK)
7443                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7444
7445         // Store the attributes that are being supplied
7446         if (rv == CKR_OK)
7447         {
7448                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7449                 if (osobject == NULL_PTR || !osobject->isValid()) {
7450                         rv = CKR_FUNCTION_FAILED;
7451                 } else if (osobject->startTransaction()) {
7452                         bool bOK = true;
7453
7454                         // Common Attributes
7455                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7456                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7457                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7458
7459                         // Common Secret Key Attributes
7460                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7461                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7462                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7463                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7464
7465                         // DES Secret Key Attributes
7466                         ByteString value;
7467                         ByteString kcv;
7468                         if (isPrivate)
7469                         {
7470                                 token->encrypt(key->getKeyBits(), value);
7471                                 token->encrypt(key->getKeyCheckValue(), kcv);
7472                         }
7473                         else
7474                         {
7475                                 value = key->getKeyBits();
7476                                 kcv = key->getKeyCheckValue();
7477                         }
7478                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7479                         if (checkValue)
7480                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7481
7482                         if (bOK)
7483                                 bOK = osobject->commitTransaction();
7484                         else
7485                                 osobject->abortTransaction();
7486
7487                         if (!bOK)
7488                                 rv = CKR_FUNCTION_FAILED;
7489                 } else
7490                         rv = CKR_FUNCTION_FAILED;
7491         }
7492
7493         // Clean up
7494         des->recycleKey(key);
7495         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7496
7497         // Remove the key that may have been created already when the function fails.
7498         if (rv != CKR_OK)
7499         {
7500                 if (*phKey != CK_INVALID_HANDLE)
7501                 {
7502                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7503                         handleManager->destroyObject(*phKey);
7504                         if (oskey) oskey->destroyObject();
7505                         *phKey = CK_INVALID_HANDLE;
7506                 }
7507         }
7508
7509         return rv;
7510 }
7511
7512 // Generate a DES2 secret key
7513 CK_RV SoftHSM::generateDES2
7514 (CK_SESSION_HANDLE hSession,
7515         CK_ATTRIBUTE_PTR pTemplate,
7516         CK_ULONG ulCount,
7517         CK_OBJECT_HANDLE_PTR phKey,
7518         CK_BBOOL isOnToken,
7519         CK_BBOOL isPrivate)
7520 {
7521         *phKey = CK_INVALID_HANDLE;
7522
7523         // Get the session
7524         Session* session = (Session*)handleManager->getSession(hSession);
7525         if (session == NULL)
7526                 return CKR_SESSION_HANDLE_INVALID;
7527
7528         // Get the token
7529         Token* token = session->getToken();
7530         if (token == NULL)
7531                 return CKR_GENERAL_ERROR;
7532
7533         // Extract desired parameter information
7534         bool checkValue = true;
7535         for (CK_ULONG i = 0; i < ulCount; i++)
7536         {
7537                 switch (pTemplate[i].type)
7538                 {
7539                         case CKA_CHECK_VALUE:
7540                                 if (pTemplate[i].ulValueLen > 0)
7541                                 {
7542                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7543                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7544                                 }
7545                                 checkValue = false;
7546                                 break;
7547                         default:
7548                                 break;
7549                 }
7550         }
7551
7552         // Generate the secret key
7553         DESKey* key = new DESKey(112);
7554         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7555         if (des == NULL)
7556         {
7557                 ERROR_MSG("Could not get SymmetricAlgorith");
7558                 delete key;
7559                 return CKR_GENERAL_ERROR;
7560         }
7561         RNG* rng = CryptoFactory::i()->getRNG();
7562         if (rng == NULL)
7563         {
7564                 ERROR_MSG("Could not get RNG");
7565                 des->recycleKey(key);
7566                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7567                 return CKR_GENERAL_ERROR;
7568         }
7569         if (!des->generateKey(*key, rng))
7570         {
7571                 ERROR_MSG("Could not generate DES secret key");
7572                 des->recycleKey(key);
7573                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7574                 return CKR_GENERAL_ERROR;
7575         }
7576
7577         CK_RV rv = CKR_OK;
7578
7579         // Create the secret key object using C_CreateObject
7580         const CK_ULONG maxAttribs = 32;
7581         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7582         CK_KEY_TYPE keyType = CKK_DES2;
7583         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7584                 { CKA_CLASS, &objClass, sizeof(objClass) },
7585                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7586                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7587                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7588         };
7589         CK_ULONG keyAttribsCount = 4;
7590
7591         // Add the additional
7592         if (ulCount > (maxAttribs - keyAttribsCount))
7593                 rv = CKR_TEMPLATE_INCONSISTENT;
7594         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7595         {
7596                 switch (pTemplate[i].type)
7597                 {
7598                         case CKA_CLASS:
7599                         case CKA_TOKEN:
7600                         case CKA_PRIVATE:
7601                         case CKA_KEY_TYPE:
7602                         case CKA_CHECK_VALUE:
7603                                 continue;
7604                 default:
7605                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7606                 }
7607         }
7608
7609         if (rv == CKR_OK)
7610                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7611
7612         // Store the attributes that are being supplied
7613         if (rv == CKR_OK)
7614         {
7615                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7616                 if (osobject == NULL_PTR || !osobject->isValid()) {
7617                         rv = CKR_FUNCTION_FAILED;
7618                 } else if (osobject->startTransaction()) {
7619                         bool bOK = true;
7620
7621                         // Common Attributes
7622                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7623                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7624                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7625
7626                         // Common Secret Key Attributes
7627                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7628                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7629                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7630                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7631
7632                         // DES Secret Key Attributes
7633                         ByteString value;
7634                         ByteString kcv;
7635                         if (isPrivate)
7636                         {
7637                                 token->encrypt(key->getKeyBits(), value);
7638                                 token->encrypt(key->getKeyCheckValue(), kcv);
7639                         }
7640                         else
7641                         {
7642                                 value = key->getKeyBits();
7643                                 kcv = key->getKeyCheckValue();
7644                         }
7645                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7646                         if (checkValue)
7647                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7648
7649                         if (bOK)
7650                                 bOK = osobject->commitTransaction();
7651                         else
7652                                 osobject->abortTransaction();
7653
7654                         if (!bOK)
7655                                 rv = CKR_FUNCTION_FAILED;
7656                 } else
7657                         rv = CKR_FUNCTION_FAILED;
7658         }
7659
7660         // Clean up
7661         des->recycleKey(key);
7662         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7663
7664         // Remove the key that may have been created already when the function fails.
7665         if (rv != CKR_OK)
7666         {
7667                 if (*phKey != CK_INVALID_HANDLE)
7668                 {
7669                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7670                         handleManager->destroyObject(*phKey);
7671                         if (oskey) oskey->destroyObject();
7672                         *phKey = CK_INVALID_HANDLE;
7673                 }
7674         }
7675
7676         return rv;
7677 }
7678
7679 // Generate a DES3 secret key
7680 CK_RV SoftHSM::generateDES3
7681 (CK_SESSION_HANDLE hSession,
7682         CK_ATTRIBUTE_PTR pTemplate,
7683         CK_ULONG ulCount,
7684         CK_OBJECT_HANDLE_PTR phKey,
7685         CK_BBOOL isOnToken,
7686         CK_BBOOL isPrivate)
7687 {
7688         *phKey = CK_INVALID_HANDLE;
7689
7690         // Get the session
7691         Session* session = (Session*)handleManager->getSession(hSession);
7692         if (session == NULL)
7693                 return CKR_SESSION_HANDLE_INVALID;
7694
7695         // Get the token
7696         Token* token = session->getToken();
7697         if (token == NULL)
7698                 return CKR_GENERAL_ERROR;
7699
7700         // Extract desired parameter information
7701         bool checkValue = true;
7702         for (CK_ULONG i = 0; i < ulCount; i++)
7703         {
7704                 switch (pTemplate[i].type)
7705                 {
7706                         case CKA_CHECK_VALUE:
7707                                 if (pTemplate[i].ulValueLen > 0)
7708                                 {
7709                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7710                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7711                                 }
7712                                 checkValue = false;
7713                                 break;
7714                         default:
7715                                 break;
7716                 }
7717         }
7718
7719         // Generate the secret key
7720         DESKey* key = new DESKey(168);
7721         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7722         if (des == NULL)
7723         {
7724                 ERROR_MSG("Could not get SymmetricAlgorithm");
7725                 delete key;
7726                 return CKR_GENERAL_ERROR;
7727         }
7728         RNG* rng = CryptoFactory::i()->getRNG();
7729         if (rng == NULL)
7730         {
7731                 ERROR_MSG("Could not get RNG");
7732                 des->recycleKey(key);
7733                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7734                 return CKR_GENERAL_ERROR;
7735         }
7736         if (!des->generateKey(*key, rng))
7737         {
7738                 ERROR_MSG("Could not generate DES secret key");
7739                 des->recycleKey(key);
7740                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7741                 return CKR_GENERAL_ERROR;
7742         }
7743
7744         CK_RV rv = CKR_OK;
7745
7746         // Create the secret key object using C_CreateObject
7747         const CK_ULONG maxAttribs = 32;
7748         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7749         CK_KEY_TYPE keyType = CKK_DES3;
7750         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7751                 { CKA_CLASS, &objClass, sizeof(objClass) },
7752                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7753                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7754                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7755         };
7756         CK_ULONG keyAttribsCount = 4;
7757
7758         // Add the additional
7759         if (ulCount > (maxAttribs - keyAttribsCount))
7760                 rv = CKR_TEMPLATE_INCONSISTENT;
7761         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7762         {
7763                 switch (pTemplate[i].type)
7764                 {
7765                         case CKA_CLASS:
7766                         case CKA_TOKEN:
7767                         case CKA_PRIVATE:
7768                         case CKA_KEY_TYPE:
7769                         case CKA_CHECK_VALUE:
7770                                 continue;
7771                 default:
7772                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7773                 }
7774         }
7775
7776         if (rv == CKR_OK)
7777                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7778
7779         // Store the attributes that are being supplied
7780         if (rv == CKR_OK)
7781         {
7782                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7783                 if (osobject == NULL_PTR || !osobject->isValid()) {
7784                         rv = CKR_FUNCTION_FAILED;
7785                 } else if (osobject->startTransaction()) {
7786                         bool bOK = true;
7787
7788                         // Common Attributes
7789                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7790                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7791                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7792
7793                         // Common Secret Key Attributes
7794                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7795                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7796                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7797                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7798
7799                         // DES Secret Key Attributes
7800                         ByteString value;
7801                         ByteString kcv;
7802                         if (isPrivate)
7803                         {
7804                                 token->encrypt(key->getKeyBits(), value);
7805                                 token->encrypt(key->getKeyCheckValue(), kcv);
7806                         }
7807                         else
7808                         {
7809                                 value = key->getKeyBits();
7810                                 kcv = key->getKeyCheckValue();
7811                         }
7812                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7813                         if (checkValue)
7814                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7815
7816                         if (bOK)
7817                                 bOK = osobject->commitTransaction();
7818                         else
7819                                 osobject->abortTransaction();
7820
7821                         if (!bOK)
7822                                 rv = CKR_FUNCTION_FAILED;
7823                 } else
7824                         rv = CKR_FUNCTION_FAILED;
7825         }
7826
7827         // Clean up
7828         des->recycleKey(key);
7829         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7830
7831         // Remove the key that may have been created already when the function fails.
7832         if (rv != CKR_OK)
7833         {
7834                 if (*phKey != CK_INVALID_HANDLE)
7835                 {
7836                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7837                         handleManager->destroyObject(*phKey);
7838                         if (oskey) oskey->destroyObject();
7839                         *phKey = CK_INVALID_HANDLE;
7840                 }
7841         }
7842
7843         return rv;
7844 }
7845
7846 // Generate an RSA key pair
7847 CK_RV SoftHSM::generateRSA
7848 (CK_SESSION_HANDLE hSession,
7849         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7850         CK_ULONG ulPublicKeyAttributeCount,
7851         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7852         CK_ULONG ulPrivateKeyAttributeCount,
7853         CK_OBJECT_HANDLE_PTR phPublicKey,
7854         CK_OBJECT_HANDLE_PTR phPrivateKey,
7855         CK_BBOOL isPublicKeyOnToken,
7856         CK_BBOOL isPublicKeyPrivate,
7857         CK_BBOOL isPrivateKeyOnToken,
7858         CK_BBOOL isPrivateKeyPrivate
7859 )
7860 {
7861         *phPublicKey = CK_INVALID_HANDLE;
7862         *phPrivateKey = CK_INVALID_HANDLE;
7863
7864         // Get the session
7865         Session* session = (Session*)handleManager->getSession(hSession);
7866         if (session == NULL)
7867                 return CKR_SESSION_HANDLE_INVALID;
7868
7869         // Get the token
7870         Token* token = session->getToken();
7871         if (token == NULL)
7872                 return CKR_GENERAL_ERROR;
7873
7874         // Extract desired key information: bitlen and public exponent
7875         size_t bitLen = 0;
7876         ByteString exponent("010001");
7877         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7878         {
7879                 switch (pPublicKeyTemplate[i].type)
7880                 {
7881                         case CKA_MODULUS_BITS:
7882                                 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7883                                 {
7884                                         INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7885                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7886                                 }
7887                                 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7888                                 break;
7889                         case CKA_PUBLIC_EXPONENT:
7890                                 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7891                                 break;
7892                         default:
7893                                 break;
7894                 }
7895         }
7896
7897         // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7898         if (bitLen == 0) {
7899                 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7900                 return CKR_TEMPLATE_INCOMPLETE;
7901         }
7902
7903         // Set the parameters
7904         RSAParameters p;
7905         p.setE(exponent);
7906         p.setBitLength(bitLen);
7907
7908         // Generate key pair
7909         AsymmetricKeyPair* kp = NULL;
7910         AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7911         if (rsa == NULL)
7912                 return CKR_GENERAL_ERROR;
7913         if (!rsa->generateKeyPair(&kp, &p))
7914         {
7915                 ERROR_MSG("Could not generate key pair");
7916                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7917                 return CKR_GENERAL_ERROR;
7918         }
7919
7920         RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7921         RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7922
7923         CK_RV rv = CKR_OK;
7924
7925         // Create a public key using C_CreateObject
7926         if (rv == CKR_OK)
7927         {
7928                 const CK_ULONG maxAttribs = 32;
7929                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7930                 CK_KEY_TYPE publicKeyType = CKK_RSA;
7931                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7932                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7933                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7934                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7935                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7936                 };
7937                 CK_ULONG publicKeyAttribsCount = 4;
7938
7939                 // Add the additional
7940                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7941                         rv = CKR_TEMPLATE_INCONSISTENT;
7942                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7943                 {
7944                         switch (pPublicKeyTemplate[i].type)
7945                         {
7946                                 case CKA_CLASS:
7947                                 case CKA_TOKEN:
7948                                 case CKA_PRIVATE:
7949                                 case CKA_KEY_TYPE:
7950                                 case CKA_PUBLIC_EXPONENT:
7951                                         continue;
7952                                 default:
7953                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7954                         }
7955                 }
7956
7957                 if (rv == CKR_OK)
7958                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7959
7960                 // Store the attributes that are being supplied by the key generation to the object
7961                 if (rv == CKR_OK)
7962                 {
7963                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7964                         if (osobject == NULL_PTR || !osobject->isValid()) {
7965                                 rv = CKR_FUNCTION_FAILED;
7966                         } else if (osobject->startTransaction()) {
7967                                 bool bOK = true;
7968
7969                                 // Common Key Attributes
7970                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7971                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7972                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7973
7974                                 // RSA Public Key Attributes
7975                                 ByteString modulus;
7976                                 ByteString publicExponent;
7977                                 if (isPublicKeyPrivate)
7978                                 {
7979                                         token->encrypt(pub->getN(), modulus);
7980                                         token->encrypt(pub->getE(), publicExponent);
7981                                 }
7982                                 else
7983                                 {
7984                                         modulus = pub->getN();
7985                                         publicExponent = pub->getE();
7986                                 }
7987                                 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7988                                 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7989
7990                                 if (bOK)
7991                                         bOK = osobject->commitTransaction();
7992                                 else
7993                                         osobject->abortTransaction();
7994
7995                                 if (!bOK)
7996                                         rv = CKR_FUNCTION_FAILED;
7997                         } else
7998                                 rv = CKR_FUNCTION_FAILED;
7999                 }
8000         }
8001
8002         // Create a private key using C_CreateObject
8003         if (rv == CKR_OK)
8004         {
8005                 const CK_ULONG maxAttribs = 32;
8006                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8007                 CK_KEY_TYPE privateKeyType = CKK_RSA;
8008                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8009                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8010                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8011                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8012                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8013                 };
8014                 CK_ULONG privateKeyAttribsCount = 4;
8015                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8016                         rv = CKR_TEMPLATE_INCONSISTENT;
8017                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8018                 {
8019                         switch (pPrivateKeyTemplate[i].type)
8020                         {
8021                                 case CKA_CLASS:
8022                                 case CKA_TOKEN:
8023                                 case CKA_PRIVATE:
8024                                 case CKA_KEY_TYPE:
8025                                         continue;
8026                                 default:
8027                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8028                         }
8029                 }
8030
8031                 if (rv == CKR_OK)
8032                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8033
8034                 // Store the attributes that are being supplied by the key generation to the object
8035                 if (rv == CKR_OK)
8036                 {
8037                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8038                         if (osobject == NULL_PTR || !osobject->isValid()) {
8039                                 rv = CKR_FUNCTION_FAILED;
8040                         } else if (osobject->startTransaction()) {
8041                                 bool bOK = true;
8042
8043                                 // Common Key Attributes
8044                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8045                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
8046                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8047
8048                                 // Common Private Key Attributes
8049                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8050                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8051                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8052                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8053
8054                                 // RSA Private Key Attributes
8055                                 ByteString modulus;
8056                                 ByteString publicExponent;
8057                                 ByteString privateExponent;
8058                                 ByteString prime1;
8059                                 ByteString prime2;
8060                                 ByteString exponent1;
8061                                 ByteString exponent2;
8062                                 ByteString coefficient;
8063                                 if (isPrivateKeyPrivate)
8064                                 {
8065                                         token->encrypt(priv->getN(), modulus);
8066                                         token->encrypt(priv->getE(), publicExponent);
8067                                         token->encrypt(priv->getD(), privateExponent);
8068                                         token->encrypt(priv->getP(), prime1);
8069                                         token->encrypt(priv->getQ(), prime2);
8070                                         token->encrypt(priv->getDP1(), exponent1);
8071                                         token->encrypt(priv->getDQ1(), exponent2);
8072                                         token->encrypt(priv->getPQ(), coefficient);
8073                                 }
8074                                 else
8075                                 {
8076                                         modulus = priv->getN();
8077                                         publicExponent = priv->getE();
8078                                         privateExponent = priv->getD();
8079                                         prime1 = priv->getP();
8080                                         prime2 = priv->getQ();
8081                                         exponent1 =  priv->getDP1();
8082                                         exponent2 = priv->getDQ1();
8083                                         coefficient = priv->getPQ();
8084                                 }
8085                                 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
8086                                 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
8087                                 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
8088                                 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
8089                                 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
8090                                 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
8091                                 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
8092                                 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
8093
8094                                 if (bOK)
8095                                         bOK = osobject->commitTransaction();
8096                                 else
8097                                         osobject->abortTransaction();
8098
8099                                 if (!bOK)
8100                                         rv = CKR_FUNCTION_FAILED;
8101                         } else
8102                                 rv = CKR_FUNCTION_FAILED;
8103                 }
8104         }
8105
8106         // Clean up
8107         rsa->recycleKeyPair(kp);
8108         CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
8109
8110         // Remove keys that may have been created already when the function fails.
8111         if (rv != CKR_OK)
8112         {
8113                 if (*phPrivateKey != CK_INVALID_HANDLE)
8114                 {
8115                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8116                         handleManager->destroyObject(*phPrivateKey);
8117                         if (ospriv) ospriv->destroyObject();
8118                         *phPrivateKey = CK_INVALID_HANDLE;
8119                 }
8120
8121                 if (*phPublicKey != CK_INVALID_HANDLE)
8122                 {
8123                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8124                         handleManager->destroyObject(*phPublicKey);
8125                         if (ospub) ospub->destroyObject();
8126                         *phPublicKey = CK_INVALID_HANDLE;
8127                 }
8128         }
8129
8130         return rv;
8131 }
8132
8133 // Generate a DSA key pair
8134 CK_RV SoftHSM::generateDSA
8135 (CK_SESSION_HANDLE hSession,
8136         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8137         CK_ULONG ulPublicKeyAttributeCount,
8138         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8139         CK_ULONG ulPrivateKeyAttributeCount,
8140         CK_OBJECT_HANDLE_PTR phPublicKey,
8141         CK_OBJECT_HANDLE_PTR phPrivateKey,
8142         CK_BBOOL isPublicKeyOnToken,
8143         CK_BBOOL isPublicKeyPrivate,
8144         CK_BBOOL isPrivateKeyOnToken,
8145         CK_BBOOL isPrivateKeyPrivate)
8146 {
8147         *phPublicKey = CK_INVALID_HANDLE;
8148         *phPrivateKey = CK_INVALID_HANDLE;
8149
8150         // Get the session
8151         Session* session = (Session*)handleManager->getSession(hSession);
8152         if (session == NULL)
8153                 return CKR_SESSION_HANDLE_INVALID;
8154
8155         // Get the token
8156         Token* token = session->getToken();
8157         if (token == NULL)
8158                 return CKR_GENERAL_ERROR;
8159
8160         // Extract desired key information
8161         ByteString prime;
8162         ByteString subprime;
8163         ByteString generator;
8164         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8165         {
8166                 switch (pPublicKeyTemplate[i].type)
8167                 {
8168                         case CKA_PRIME:
8169                                 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8170                                 break;
8171                         case CKA_SUBPRIME:
8172                                 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8173                                 break;
8174                         case CKA_BASE:
8175                                 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8176                                 break;
8177                         default:
8178                                 break;
8179                 }
8180         }
8181
8182         // The parameters must be specified to be able to generate a key pair.
8183         if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
8184                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8185                 return CKR_TEMPLATE_INCOMPLETE;
8186         }
8187
8188         // Set the parameters
8189         DSAParameters p;
8190         p.setP(prime);
8191         p.setQ(subprime);
8192         p.setG(generator);
8193
8194         // Generate key pair
8195         AsymmetricKeyPair* kp = NULL;
8196         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8197         if (dsa == NULL) return CKR_GENERAL_ERROR;
8198         if (!dsa->generateKeyPair(&kp, &p))
8199         {
8200                 ERROR_MSG("Could not generate key pair");
8201                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8202                 return CKR_GENERAL_ERROR;
8203         }
8204
8205         DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
8206         DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
8207
8208         CK_RV rv = CKR_OK;
8209
8210         // Create a public key using C_CreateObject
8211         if (rv == CKR_OK)
8212         {
8213                 const CK_ULONG maxAttribs = 32;
8214                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8215                 CK_KEY_TYPE publicKeyType = CKK_DSA;
8216                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8217                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8218                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8219                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8220                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8221                 };
8222                 CK_ULONG publicKeyAttribsCount = 4;
8223
8224                 // Add the additional
8225                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8226                         rv = CKR_TEMPLATE_INCONSISTENT;
8227                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8228                 {
8229                         switch (pPublicKeyTemplate[i].type)
8230                         {
8231                                 case CKA_CLASS:
8232                                 case CKA_TOKEN:
8233                                 case CKA_PRIVATE:
8234                                 case CKA_KEY_TYPE:
8235                                         continue;
8236                                 default:
8237                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8238                         }
8239                 }
8240
8241                 if (rv == CKR_OK)
8242                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8243
8244                 // Store the attributes that are being supplied by the key generation to the object
8245                 if (rv == CKR_OK)
8246                 {
8247                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8248                         if (osobject == NULL_PTR || !osobject->isValid()) {
8249                                 rv = CKR_FUNCTION_FAILED;
8250                         } else if (osobject->startTransaction()) {
8251                                 bool bOK = true;
8252
8253                                 // Common Key Attributes
8254                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8255                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8256                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8257
8258                                 // DSA Public Key Attributes
8259                                 ByteString value;
8260                                 if (isPublicKeyPrivate)
8261                                 {
8262                                         token->encrypt(pub->getY(), value);
8263                                 }
8264                                 else
8265                                 {
8266                                         value = pub->getY();
8267                                 }
8268                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8269
8270                                 if (bOK)
8271                                         bOK = osobject->commitTransaction();
8272                                 else
8273                                         osobject->abortTransaction();
8274
8275                                 if (!bOK)
8276                                         rv = CKR_FUNCTION_FAILED;
8277                         } else
8278                                 rv = CKR_FUNCTION_FAILED;
8279                 }
8280         }
8281
8282         // Create a private key using C_CreateObject
8283         if (rv == CKR_OK)
8284         {
8285                 const CK_ULONG maxAttribs = 32;
8286                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8287                 CK_KEY_TYPE privateKeyType = CKK_DSA;
8288                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8289                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8290                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8291                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8292                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8293                 };
8294                 CK_ULONG privateKeyAttribsCount = 4;
8295                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8296                         rv = CKR_TEMPLATE_INCONSISTENT;
8297                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8298                 {
8299                         switch (pPrivateKeyTemplate[i].type)
8300                         {
8301                                 case CKA_CLASS:
8302                                 case CKA_TOKEN:
8303                                 case CKA_PRIVATE:
8304                                 case CKA_KEY_TYPE:
8305                                         continue;
8306                                 default:
8307                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8308                         }
8309                 }
8310
8311                 if (rv == CKR_OK)
8312                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8313
8314                 // Store the attributes that are being supplied by the key generation to the object
8315                 if (rv == CKR_OK)
8316                 {
8317                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8318                         if (osobject == NULL_PTR || !osobject->isValid()) {
8319                                 rv = CKR_FUNCTION_FAILED;
8320                         } else if (osobject->startTransaction()) {
8321                                 bool bOK = true;
8322
8323                                 // Common Key Attributes
8324                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8325                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8326                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8327
8328                                 // Common Private Key Attributes
8329                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8330                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8331                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8332                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8333
8334                                 // DSA Private Key Attributes
8335                                 ByteString bPrime;
8336                                 ByteString bSubprime;
8337                                 ByteString bGenerator;
8338                                 ByteString bValue;
8339                                 if (isPrivateKeyPrivate)
8340                                 {
8341                                         token->encrypt(priv->getP(), bPrime);
8342                                         token->encrypt(priv->getQ(), bSubprime);
8343                                         token->encrypt(priv->getG(), bGenerator);
8344                                         token->encrypt(priv->getX(), bValue);
8345                                 }
8346                                 else
8347                                 {
8348                                         bPrime = priv->getP();
8349                                         bSubprime = priv->getQ();
8350                                         bGenerator = priv->getG();
8351                                         bValue = priv->getX();
8352                                 }
8353                                 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8354                                 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8355                                 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8356                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8357
8358                                 if (bOK)
8359                                         bOK = osobject->commitTransaction();
8360                                 else
8361                                         osobject->abortTransaction();
8362
8363                                 if (!bOK)
8364                                         rv = CKR_FUNCTION_FAILED;
8365                         } else
8366                                 rv = CKR_FUNCTION_FAILED;
8367                 }
8368         }
8369
8370         // Clean up
8371         dsa->recycleKeyPair(kp);
8372         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8373
8374         // Remove keys that may have been created already when the function fails.
8375         if (rv != CKR_OK)
8376         {
8377                 if (*phPrivateKey != CK_INVALID_HANDLE)
8378                 {
8379                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8380                         handleManager->destroyObject(*phPrivateKey);
8381                         if (ospriv) ospriv->destroyObject();
8382                         *phPrivateKey = CK_INVALID_HANDLE;
8383                 }
8384
8385                 if (*phPublicKey != CK_INVALID_HANDLE)
8386                 {
8387                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8388                         handleManager->destroyObject(*phPublicKey);
8389                         if (ospub) ospub->destroyObject();
8390                         *phPublicKey = CK_INVALID_HANDLE;
8391                 }
8392         }
8393
8394         return rv;
8395 }
8396
8397 // Generate a DSA domain parameter set
8398 CK_RV SoftHSM::generateDSAParameters
8399 (CK_SESSION_HANDLE hSession,
8400         CK_ATTRIBUTE_PTR pTemplate,
8401         CK_ULONG ulCount,
8402         CK_OBJECT_HANDLE_PTR phKey,
8403         CK_BBOOL isOnToken,
8404         CK_BBOOL isPrivate)
8405 {
8406         *phKey = CK_INVALID_HANDLE;
8407
8408         // Get the session
8409         Session* session = (Session*)handleManager->getSession(hSession);
8410         if (session == NULL)
8411                 return CKR_SESSION_HANDLE_INVALID;
8412
8413         // Get the token
8414         Token* token = session->getToken();
8415         if (token == NULL)
8416                 return CKR_GENERAL_ERROR;
8417
8418         // Extract desired parameter information
8419         size_t bitLen = 0;
8420         size_t qLen = 0;
8421         for (CK_ULONG i = 0; i < ulCount; i++)
8422         {
8423                 switch (pTemplate[i].type)
8424                 {
8425                         case CKA_PRIME_BITS:
8426                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8427                                 {
8428                                         INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8429                                         return CKR_ATTRIBUTE_VALUE_INVALID;
8430                                 }
8431                                 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8432                                 break;
8433                         case CKA_SUBPRIME_BITS:
8434                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8435                                 {
8436                                         INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8437                                         return CKR_ATTRIBUTE_VALUE_INVALID;
8438                                 }
8439                                 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8440                                 break;
8441                         default:
8442                                 break;
8443                 }
8444         }
8445
8446         // CKA_PRIME_BITS must be specified
8447         if (bitLen == 0)
8448         {
8449                 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8450                 return CKR_TEMPLATE_INCOMPLETE;
8451         }
8452
8453         // No real choice for CKA_SUBPRIME_BITS
8454         if ((qLen != 0) &&
8455             (((bitLen >= 2048) && (qLen != 256)) ||
8456              ((bitLen < 2048) && (qLen != 160))))
8457                 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8458
8459
8460         // Generate domain parameters
8461         AsymmetricParameters* p = NULL;
8462         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8463         if (dsa == NULL) return CKR_GENERAL_ERROR;
8464         if (!dsa->generateParameters(&p, (void *)bitLen))
8465         {
8466                 ERROR_MSG("Could not generate parameters");
8467                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8468                 return CKR_GENERAL_ERROR;
8469         }
8470
8471         DSAParameters* params = (DSAParameters*) p;
8472
8473         CK_RV rv = CKR_OK;
8474
8475         // Create the domain parameter object using C_CreateObject
8476         const CK_ULONG maxAttribs = 32;
8477         CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8478         CK_KEY_TYPE keyType = CKK_DSA;
8479         CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8480                 { CKA_CLASS, &objClass, sizeof(objClass) },
8481                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8482                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8483                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8484         };
8485         CK_ULONG paramsAttribsCount = 4;
8486
8487         // Add the additional
8488         if (ulCount > (maxAttribs - paramsAttribsCount))
8489                 rv = CKR_TEMPLATE_INCONSISTENT;
8490         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8491         {
8492                 switch (pTemplate[i].type)
8493                 {
8494                         case CKA_CLASS:
8495                         case CKA_TOKEN:
8496                         case CKA_PRIVATE:
8497                         case CKA_KEY_TYPE:
8498                                 continue;
8499                 default:
8500                         paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8501                 }
8502         }
8503
8504         if (rv == CKR_OK)
8505                 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8506
8507         // Store the attributes that are being supplied
8508         if (rv == CKR_OK)
8509         {
8510                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8511                 if (osobject == NULL_PTR || !osobject->isValid()) {
8512                         rv = CKR_FUNCTION_FAILED;
8513                 } else if (osobject->startTransaction()) {
8514                         bool bOK = true;
8515
8516                         // Common Attributes
8517                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8518                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8519                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8520
8521                         // DSA Domain Parameters Attributes
8522                         ByteString prime;
8523                         ByteString subprime;
8524                         ByteString generator;
8525                         if (isPrivate)
8526                         {
8527                                 token->encrypt(params->getP(), prime);
8528                                 token->encrypt(params->getQ(), subprime);
8529                                 token->encrypt(params->getG(), generator);
8530                         }
8531                         else
8532                         {
8533                                 prime = params->getP();
8534                                 subprime = params->getQ();
8535                                 generator = params->getG();
8536                         }
8537                         bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8538                         bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8539                         bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8540
8541                         if (bOK)
8542                                 bOK = osobject->commitTransaction();
8543                         else
8544                                 osobject->abortTransaction();
8545
8546                         if (!bOK)
8547                                 rv = CKR_FUNCTION_FAILED;
8548                 } else
8549                         rv = CKR_FUNCTION_FAILED;
8550         }
8551
8552         // Clean up
8553         dsa->recycleParameters(p);
8554         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8555
8556         // Remove parameters that may have been created already when the function fails.
8557         if (rv != CKR_OK)
8558         {
8559                 if (*phKey != CK_INVALID_HANDLE)
8560                 {
8561                         OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8562                         handleManager->destroyObject(*phKey);
8563                         if (osparams) osparams->destroyObject();
8564                         *phKey = CK_INVALID_HANDLE;
8565                 }
8566         }
8567
8568         return rv;
8569 }
8570
8571 // Generate an EC key pair
8572 CK_RV SoftHSM::generateEC
8573 (CK_SESSION_HANDLE hSession,
8574         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8575         CK_ULONG ulPublicKeyAttributeCount,
8576         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8577         CK_ULONG ulPrivateKeyAttributeCount,
8578         CK_OBJECT_HANDLE_PTR phPublicKey,
8579         CK_OBJECT_HANDLE_PTR phPrivateKey,
8580         CK_BBOOL isPublicKeyOnToken,
8581         CK_BBOOL isPublicKeyPrivate,
8582         CK_BBOOL isPrivateKeyOnToken,
8583         CK_BBOOL isPrivateKeyPrivate)
8584 {
8585         *phPublicKey = CK_INVALID_HANDLE;
8586         *phPrivateKey = CK_INVALID_HANDLE;
8587
8588         // Get the session
8589         Session* session = (Session*)handleManager->getSession(hSession);
8590         if (session == NULL)
8591                 return CKR_SESSION_HANDLE_INVALID;
8592
8593         // Get the token
8594         Token* token = session->getToken();
8595         if (token == NULL)
8596                 return CKR_GENERAL_ERROR;
8597
8598         // Extract desired key information
8599         ByteString params;
8600         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8601         {
8602                 switch (pPublicKeyTemplate[i].type)
8603                 {
8604                         case CKA_EC_PARAMS:
8605                                 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8606                                 break;
8607                         default:
8608                                 break;
8609                 }
8610         }
8611
8612         // The parameters must be specified to be able to generate a key pair.
8613         if (params.size() == 0) {
8614                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8615                 return CKR_TEMPLATE_INCOMPLETE;
8616         }
8617
8618         // Set the parameters
8619         ECParameters p;
8620         p.setEC(params);
8621
8622         // Generate key pair
8623         AsymmetricKeyPair* kp = NULL;
8624         AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8625         if (ec == NULL) return CKR_GENERAL_ERROR;
8626         if (!ec->generateKeyPair(&kp, &p))
8627         {
8628                 ERROR_MSG("Could not generate key pair");
8629                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8630                 return CKR_GENERAL_ERROR;
8631         }
8632
8633         ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8634         ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8635
8636         CK_RV rv = CKR_OK;
8637
8638         // Create a public key using C_CreateObject
8639         if (rv == CKR_OK)
8640         {
8641                 const CK_ULONG maxAttribs = 32;
8642                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8643                 CK_KEY_TYPE publicKeyType = CKK_EC;
8644                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8645                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8646                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8647                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8648                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8649                 };
8650                 CK_ULONG publicKeyAttribsCount = 4;
8651
8652                 // Add the additional
8653                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8654                         rv = CKR_TEMPLATE_INCONSISTENT;
8655                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8656                 {
8657                         switch (pPublicKeyTemplate[i].type)
8658                         {
8659                                 case CKA_CLASS:
8660                                 case CKA_TOKEN:
8661                                 case CKA_PRIVATE:
8662                                 case CKA_KEY_TYPE:
8663                                         continue;
8664                                 default:
8665                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8666                         }
8667                 }
8668
8669                 if (rv == CKR_OK)
8670                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8671
8672                 // Store the attributes that are being supplied by the key generation to the object
8673                 if (rv == CKR_OK)
8674                 {
8675                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8676                         if (osobject == NULL_PTR || !osobject->isValid()) {
8677                                 rv = CKR_FUNCTION_FAILED;
8678                         } else if (osobject->startTransaction()) {
8679                                 bool bOK = true;
8680
8681                                 // Common Key Attributes
8682                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8683                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8684                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8685
8686                                 // EC Public Key Attributes
8687                                 ByteString point;
8688                                 if (isPublicKeyPrivate)
8689                                 {
8690                                         token->encrypt(pub->getQ(), point);
8691                                 }
8692                                 else
8693                                 {
8694                                         point = pub->getQ();
8695                                 }
8696                                 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8697
8698                                 if (bOK)
8699                                         bOK = osobject->commitTransaction();
8700                                 else
8701                                         osobject->abortTransaction();
8702
8703                                 if (!bOK)
8704                                         rv = CKR_FUNCTION_FAILED;
8705                         } else
8706                                 rv = CKR_FUNCTION_FAILED;
8707                 }
8708         }
8709
8710         // Create a private key using C_CreateObject
8711         if (rv == CKR_OK)
8712         {
8713                 const CK_ULONG maxAttribs = 32;
8714                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8715                 CK_KEY_TYPE privateKeyType = CKK_EC;
8716                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8717                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8718                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8719                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8720                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8721                 };
8722                 CK_ULONG privateKeyAttribsCount = 4;
8723                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8724                         rv = CKR_TEMPLATE_INCONSISTENT;
8725                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8726                 {
8727                         switch (pPrivateKeyTemplate[i].type)
8728                         {
8729                                 case CKA_CLASS:
8730                                 case CKA_TOKEN:
8731                                 case CKA_PRIVATE:
8732                                 case CKA_KEY_TYPE:
8733                                         continue;
8734                                 default:
8735                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8736                         }
8737                 }
8738
8739                 if (rv == CKR_OK)
8740                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8741
8742                 // Store the attributes that are being supplied by the key generation to the object
8743                 if (rv == CKR_OK)
8744                 {
8745                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8746                         if (osobject == NULL_PTR || !osobject->isValid()) {
8747                                 rv = CKR_FUNCTION_FAILED;
8748                         } else if (osobject->startTransaction()) {
8749                                 bool bOK = true;
8750
8751                                 // Common Key Attributes
8752                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8753                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8754                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8755
8756                                 // Common Private Key Attributes
8757                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8758                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8759                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8760                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8761
8762                                 // EC Private Key Attributes
8763                                 ByteString group;
8764                                 ByteString value;
8765                                 if (isPrivateKeyPrivate)
8766                                 {
8767                                         token->encrypt(priv->getEC(), group);
8768                                         token->encrypt(priv->getD(), value);
8769                                 }
8770                                 else
8771                                 {
8772                                         group = priv->getEC();
8773                                         value = priv->getD();
8774                                 }
8775                                 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8776                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8777
8778                                 if (bOK)
8779                                         bOK = osobject->commitTransaction();
8780                                 else
8781                                         osobject->abortTransaction();
8782
8783                                 if (!bOK)
8784                                         rv = CKR_FUNCTION_FAILED;
8785                         } else
8786                                 rv = CKR_FUNCTION_FAILED;
8787                 }
8788         }
8789
8790         // Clean up
8791         ec->recycleKeyPair(kp);
8792         CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8793
8794         // Remove keys that may have been created already when the function fails.
8795         if (rv != CKR_OK)
8796         {
8797                 if (*phPrivateKey != CK_INVALID_HANDLE)
8798                 {
8799                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8800                         handleManager->destroyObject(*phPrivateKey);
8801                         if (ospriv) ospriv->destroyObject();
8802                         *phPrivateKey = CK_INVALID_HANDLE;
8803                 }
8804
8805                 if (*phPublicKey != CK_INVALID_HANDLE)
8806                 {
8807                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8808                         handleManager->destroyObject(*phPublicKey);
8809                         if (ospub) ospub->destroyObject();
8810                         *phPublicKey = CK_INVALID_HANDLE;
8811                 }
8812         }
8813
8814         return rv;
8815 }
8816
8817 // Generate a DH key pair
8818 CK_RV SoftHSM::generateDH
8819 (CK_SESSION_HANDLE hSession,
8820         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8821         CK_ULONG ulPublicKeyAttributeCount,
8822         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8823         CK_ULONG ulPrivateKeyAttributeCount,
8824         CK_OBJECT_HANDLE_PTR phPublicKey,
8825         CK_OBJECT_HANDLE_PTR phPrivateKey,
8826         CK_BBOOL isPublicKeyOnToken,
8827         CK_BBOOL isPublicKeyPrivate,
8828         CK_BBOOL isPrivateKeyOnToken,
8829         CK_BBOOL isPrivateKeyPrivate)
8830 {
8831         *phPublicKey = CK_INVALID_HANDLE;
8832         *phPrivateKey = CK_INVALID_HANDLE;
8833
8834         // Get the session
8835         Session* session = (Session*)handleManager->getSession(hSession);
8836         if (session == NULL)
8837                 return CKR_SESSION_HANDLE_INVALID;
8838
8839         // Get the token
8840         Token* token = session->getToken();
8841         if (token == NULL)
8842                 return CKR_GENERAL_ERROR;
8843
8844         // Extract desired key information
8845         ByteString prime;
8846         ByteString generator;
8847         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8848         {
8849                 switch (pPublicKeyTemplate[i].type)
8850                 {
8851                         case CKA_PRIME:
8852                                 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8853                                 break;
8854                         case CKA_BASE:
8855                                 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8856                                 break;
8857                         default:
8858                                 break;
8859                 }
8860         }
8861
8862         // The parameters must be specified to be able to generate a key pair.
8863         if (prime.size() == 0 || generator.size() == 0) {
8864                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8865                 return CKR_TEMPLATE_INCOMPLETE;
8866         }
8867
8868         // Extract optional bit length
8869         size_t bitLen = 0;
8870         for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8871         {
8872                 switch (pPrivateKeyTemplate[i].type)
8873                 {
8874                         case CKA_VALUE_BITS:
8875                                 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8876                                 break;
8877                         default:
8878                                 break;
8879                 }
8880         }
8881
8882         // Set the parameters
8883         DHParameters p;
8884         p.setP(prime);
8885         p.setG(generator);
8886         p.setXBitLength(bitLen);
8887
8888         // Generate key pair
8889         AsymmetricKeyPair* kp = NULL;
8890         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8891         if (dh == NULL) return CKR_GENERAL_ERROR;
8892         if (!dh->generateKeyPair(&kp, &p))
8893         {
8894                 ERROR_MSG("Could not generate key pair");
8895                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8896                 return CKR_GENERAL_ERROR;
8897         }
8898
8899         DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8900         DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8901
8902         CK_RV rv = CKR_OK;
8903
8904         // Create a public key using C_CreateObject
8905         if (rv == CKR_OK)
8906         {
8907                 const CK_ULONG maxAttribs = 32;
8908                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8909                 CK_KEY_TYPE publicKeyType = CKK_DH;
8910                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8911                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8912                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8913                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8914                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8915                 };
8916                 CK_ULONG publicKeyAttribsCount = 4;
8917
8918                 // Add the additional
8919                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8920                         rv = CKR_TEMPLATE_INCONSISTENT;
8921                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8922                 {
8923                         switch (pPublicKeyTemplate[i].type)
8924                         {
8925                                 case CKA_CLASS:
8926                                 case CKA_TOKEN:
8927                                 case CKA_PRIVATE:
8928                                 case CKA_KEY_TYPE:
8929                                         continue;
8930                                 default:
8931                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8932                         }
8933                 }
8934
8935                 if (rv == CKR_OK)
8936                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8937
8938                 // Store the attributes that are being supplied by the key generation to the object
8939                 if (rv == CKR_OK)
8940                 {
8941                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8942                         if (osobject == NULL_PTR || !osobject->isValid()) {
8943                                 rv = CKR_FUNCTION_FAILED;
8944                         } else if (osobject->startTransaction()) {
8945                                 bool bOK = true;
8946
8947                                 // Common Key Attributes
8948                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8949                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8950                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8951
8952                                 // DH Public Key Attributes
8953                                 ByteString value;
8954                                 if (isPublicKeyPrivate)
8955                                 {
8956                                         token->encrypt(pub->getY(), value);
8957                                 }
8958                                 else
8959                                 {
8960                                         value = pub->getY();
8961                                 }
8962                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8963
8964                                 if (bOK)
8965                                         bOK = osobject->commitTransaction();
8966                                 else
8967                                         osobject->abortTransaction();
8968
8969                                 if (!bOK)
8970                                         rv = CKR_FUNCTION_FAILED;
8971                         } else
8972                                 rv = CKR_FUNCTION_FAILED;
8973                 }
8974         }
8975
8976         // Create a private key using C_CreateObject
8977         if (rv == CKR_OK)
8978         {
8979                 const CK_ULONG maxAttribs = 32;
8980                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8981                 CK_KEY_TYPE privateKeyType = CKK_DH;
8982                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8983                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8984                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8985                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8986                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8987                 };
8988                 CK_ULONG privateKeyAttribsCount = 4;
8989                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8990                         rv = CKR_TEMPLATE_INCONSISTENT;
8991                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8992                 {
8993                         switch (pPrivateKeyTemplate[i].type)
8994                         {
8995                                 case CKA_CLASS:
8996                                 case CKA_TOKEN:
8997                                 case CKA_PRIVATE:
8998                                 case CKA_KEY_TYPE:
8999                                         continue;
9000                                 default:
9001                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9002                         }
9003                 }
9004
9005                 if (rv == CKR_OK)
9006                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9007
9008                 // Store the attributes that are being supplied by the key generation to the object
9009                 if (rv == CKR_OK)
9010                 {
9011                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9012                         if (osobject == NULL_PTR || !osobject->isValid()) {
9013                                 rv = CKR_FUNCTION_FAILED;
9014                         } else if (osobject->startTransaction()) {
9015                                 bool bOK = true;
9016
9017                                 // Common Key Attributes
9018                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9019                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
9020                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9021
9022                                 // Common Private Key Attributes
9023                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9024                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9025                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9026                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9027
9028                                 // DH Private Key Attributes
9029                                 ByteString bPrime;
9030                                 ByteString bGenerator;
9031                                 ByteString bValue;
9032                                 if (isPrivateKeyPrivate)
9033                                 {
9034                                         token->encrypt(priv->getP(), bPrime);
9035                                         token->encrypt(priv->getG(), bGenerator);
9036                                         token->encrypt(priv->getX(), bValue);
9037                                 }
9038                                 else
9039                                 {
9040                                         bPrime = priv->getP();
9041                                         bGenerator = priv->getG();
9042                                         bValue = priv->getX();
9043                                 }
9044                                 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
9045                                 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
9046                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
9047
9048                                 if (bitLen == 0)
9049                                 {
9050                                         bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
9051                                 }
9052
9053                                 if (bOK)
9054                                         bOK = osobject->commitTransaction();
9055                                 else
9056                                         osobject->abortTransaction();
9057
9058                                 if (!bOK)
9059                                         rv = CKR_FUNCTION_FAILED;
9060                         } else
9061                                 rv = CKR_FUNCTION_FAILED;
9062                 }
9063         }
9064
9065         // Clean up
9066         dh->recycleKeyPair(kp);
9067         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9068
9069         // Remove keys that may have been created already when the function fails.
9070         if (rv != CKR_OK)
9071         {
9072                 if (*phPrivateKey != CK_INVALID_HANDLE)
9073                 {
9074                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9075                         handleManager->destroyObject(*phPrivateKey);
9076                         if (ospriv) ospriv->destroyObject();
9077                         *phPrivateKey = CK_INVALID_HANDLE;
9078                 }
9079
9080                 if (*phPublicKey != CK_INVALID_HANDLE)
9081                 {
9082                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9083                         handleManager->destroyObject(*phPublicKey);
9084                         if (ospub) ospub->destroyObject();
9085                         *phPublicKey = CK_INVALID_HANDLE;
9086                 }
9087         }
9088
9089         return rv;
9090 }
9091
9092 // Generate a DH domain parameter set
9093 CK_RV SoftHSM::generateDHParameters
9094 (CK_SESSION_HANDLE hSession,
9095         CK_ATTRIBUTE_PTR pTemplate,
9096         CK_ULONG ulCount,
9097         CK_OBJECT_HANDLE_PTR phKey,
9098         CK_BBOOL isOnToken,
9099         CK_BBOOL isPrivate)
9100 {
9101         *phKey = CK_INVALID_HANDLE;
9102
9103         // Get the session
9104         Session* session = (Session*)handleManager->getSession(hSession);
9105         if (session == NULL)
9106                 return CKR_SESSION_HANDLE_INVALID;
9107
9108         // Get the token
9109         Token* token = session->getToken();
9110         if (token == NULL)
9111                 return CKR_GENERAL_ERROR;
9112
9113         // Extract desired parameter information
9114         size_t bitLen = 0;
9115         for (CK_ULONG i = 0; i < ulCount; i++)
9116         {
9117                 switch (pTemplate[i].type)
9118                 {
9119                         case CKA_PRIME_BITS:
9120                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9121                                 {
9122                                         INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
9123                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9124                                 }
9125                                 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
9126                                 break;
9127                         default:
9128                                 break;
9129                 }
9130         }
9131
9132         // CKA_PRIME_BITS must be specified
9133         if (bitLen == 0)
9134         {
9135                 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
9136                 return CKR_TEMPLATE_INCOMPLETE;
9137         }
9138
9139         // Generate domain parameters
9140         AsymmetricParameters* p = NULL;
9141         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9142         if (dh == NULL) return CKR_GENERAL_ERROR;
9143         if (!dh->generateParameters(&p, (void *)bitLen))
9144         {
9145                 ERROR_MSG("Could not generate parameters");
9146                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9147                 return CKR_GENERAL_ERROR;
9148         }
9149
9150         DHParameters* params = (DHParameters*) p;
9151
9152         CK_RV rv = CKR_OK;
9153
9154         // Create the domain parameter object using C_CreateObject
9155         const CK_ULONG maxAttribs = 32;
9156         CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
9157         CK_KEY_TYPE keyType = CKK_DH;
9158         CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
9159                 { CKA_CLASS, &objClass, sizeof(objClass) },
9160                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9161                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9162                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9163         };
9164         CK_ULONG paramsAttribsCount = 4;
9165
9166         // Add the additional
9167         if (ulCount > (maxAttribs - paramsAttribsCount))
9168                 rv = CKR_TEMPLATE_INCONSISTENT;
9169         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9170         {
9171                 switch (pTemplate[i].type)
9172                 {
9173                         case CKA_CLASS:
9174                         case CKA_TOKEN:
9175                         case CKA_PRIVATE:
9176                         case CKA_KEY_TYPE:
9177                                 continue;
9178                 default:
9179                         paramsAttribs[paramsAttribsCount++] = pTemplate[i];
9180                 }
9181         }
9182
9183         if (rv == CKR_OK)
9184                 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
9185
9186         // Store the attributes that are being supplied
9187         if (rv == CKR_OK)
9188         {
9189                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9190                 if (osobject == NULL_PTR || !osobject->isValid()) {
9191                         rv = CKR_FUNCTION_FAILED;
9192                 } else if (osobject->startTransaction()) {
9193                         bool bOK = true;
9194
9195                         // Common Attributes
9196                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9197                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
9198                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9199
9200                         // DH Domain Parameters Attributes
9201                         ByteString prime;
9202                         ByteString generator;
9203                         if (isPrivate)
9204                         {
9205                                 token->encrypt(params->getP(), prime);
9206                                 token->encrypt(params->getG(), generator);
9207                         }
9208                         else
9209                         {
9210                                 prime = params->getP();
9211                                 generator = params->getG();
9212                         }
9213                         bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
9214                         bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
9215
9216                         if (bOK)
9217                                 bOK = osobject->commitTransaction();
9218                         else
9219                                 osobject->abortTransaction();
9220
9221                         if (!bOK)
9222                                 rv = CKR_FUNCTION_FAILED;
9223                 } else
9224                         rv = CKR_FUNCTION_FAILED;
9225         }
9226
9227         // Clean up
9228         dh->recycleParameters(p);
9229         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9230
9231         // Remove parameters that may have been created already when the function fails.
9232         if (rv != CKR_OK)
9233         {
9234                 if (*phKey != CK_INVALID_HANDLE)
9235                 {
9236                         OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
9237                         handleManager->destroyObject(*phKey);
9238                         if (osparams) osparams->destroyObject();
9239                         *phKey = CK_INVALID_HANDLE;
9240                 }
9241         }
9242
9243         return rv;
9244 }
9245
9246 // Generate a GOST key pair
9247 CK_RV SoftHSM::generateGOST
9248 (CK_SESSION_HANDLE hSession,
9249         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
9250         CK_ULONG ulPublicKeyAttributeCount,
9251         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
9252         CK_ULONG ulPrivateKeyAttributeCount,
9253         CK_OBJECT_HANDLE_PTR phPublicKey,
9254         CK_OBJECT_HANDLE_PTR phPrivateKey,
9255         CK_BBOOL isPublicKeyOnToken,
9256         CK_BBOOL isPublicKeyPrivate,
9257         CK_BBOOL isPrivateKeyOnToken,
9258         CK_BBOOL isPrivateKeyPrivate)
9259 {
9260         *phPublicKey = CK_INVALID_HANDLE;
9261         *phPrivateKey = CK_INVALID_HANDLE;
9262
9263         // Get the session
9264         Session* session = (Session*)handleManager->getSession(hSession);
9265         if (session == NULL)
9266                 return CKR_SESSION_HANDLE_INVALID;
9267
9268         // Get the token
9269         Token* token = session->getToken();
9270         if (token == NULL)
9271                 return CKR_GENERAL_ERROR;
9272
9273         // Extract desired key information
9274         ByteString param_3410;
9275         ByteString param_3411;
9276         ByteString param_28147;
9277         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
9278         {
9279                 switch (pPublicKeyTemplate[i].type)
9280                 {
9281                         case CKA_GOSTR3410_PARAMS:
9282                                 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9283                                 break;
9284                         case CKA_GOSTR3411_PARAMS:
9285                                 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9286                                 break;
9287                         case CKA_GOST28147_PARAMS:
9288                                 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
9289                                 break;
9290                         default:
9291                                 break;
9292                 }
9293         }
9294
9295         // The parameters must be specified to be able to generate a key pair.
9296         if (param_3410.size() == 0 || param_3411.size() == 0) {
9297                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
9298                 return CKR_TEMPLATE_INCOMPLETE;
9299         }
9300
9301         // Set the parameters
9302         ECParameters p;
9303         p.setEC(param_3410);
9304
9305         // Generate key pair
9306         AsymmetricKeyPair* kp = NULL;
9307         AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9308         if (gost == NULL) return CKR_GENERAL_ERROR;
9309         if (!gost->generateKeyPair(&kp, &p))
9310         {
9311                 ERROR_MSG("Could not generate key pair");
9312                 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9313                 return CKR_GENERAL_ERROR;
9314         }
9315
9316         GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9317         GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9318
9319         CK_RV rv = CKR_OK;
9320
9321         // Create a public key using C_CreateObject
9322         if (rv == CKR_OK)
9323         {
9324                 const CK_ULONG maxAttribs = 32;
9325                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9326                 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9327                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9328                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9329                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9330                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9331                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9332                 };
9333                 CK_ULONG publicKeyAttribsCount = 4;
9334
9335                 // Add the additional
9336                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9337                         rv = CKR_TEMPLATE_INCONSISTENT;
9338                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9339                 {
9340                         switch (pPublicKeyTemplate[i].type)
9341                         {
9342                                 case CKA_CLASS:
9343                                 case CKA_TOKEN:
9344                                 case CKA_PRIVATE:
9345                                 case CKA_KEY_TYPE:
9346                                         continue;
9347                                 default:
9348                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9349                         }
9350                 }
9351
9352                 if (rv == CKR_OK)
9353                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9354
9355                 // Store the attributes that are being supplied by the key generation to the object
9356                 if (rv == CKR_OK)
9357                 {
9358                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9359                         if (osobject == NULL_PTR || !osobject->isValid()) {
9360                                 rv = CKR_FUNCTION_FAILED;
9361                         } else if (osobject->startTransaction()) {
9362                                 bool bOK = true;
9363
9364                                 // Common Key Attributes
9365                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9366                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9367                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9368
9369                                 // EC Public Key Attributes
9370                                 ByteString point;
9371                                 if (isPublicKeyPrivate)
9372                                 {
9373                                         token->encrypt(pub->getQ(), point);
9374                                 }
9375                                 else
9376                                 {
9377                                         point = pub->getQ();
9378                                 }
9379                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9380
9381                                 if (bOK)
9382                                         bOK = osobject->commitTransaction();
9383                                 else
9384                                         osobject->abortTransaction();
9385
9386                                 if (!bOK)
9387                                         rv = CKR_FUNCTION_FAILED;
9388                         } else
9389                                 rv = CKR_FUNCTION_FAILED;
9390                 }
9391         }
9392
9393         // Create a private key using C_CreateObject
9394         if (rv == CKR_OK)
9395         {
9396                 const CK_ULONG maxAttribs = 32;
9397                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9398                 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9399                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9400                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9401                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9402                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9403                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9404                 };
9405                 CK_ULONG privateKeyAttribsCount = 4;
9406                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9407                         rv = CKR_TEMPLATE_INCONSISTENT;
9408                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9409                 {
9410                         switch (pPrivateKeyTemplate[i].type)
9411                         {
9412                                 case CKA_CLASS:
9413                                 case CKA_TOKEN:
9414                                 case CKA_PRIVATE:
9415                                 case CKA_KEY_TYPE:
9416                                         continue;
9417                                 default:
9418                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9419                         }
9420                 }
9421
9422                 if (rv == CKR_OK)
9423                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9424
9425                 // Store the attributes that are being supplied by the key generation to the object
9426                 if (rv == CKR_OK)
9427                 {
9428                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9429                         if (osobject == NULL_PTR || !osobject->isValid()) {
9430                                 rv = CKR_FUNCTION_FAILED;
9431                         } else if (osobject->startTransaction()) {
9432                                 bool bOK = true;
9433
9434                                 // Common Key Attributes
9435                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9436                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9437                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9438
9439                                 // Common Private Key Attributes
9440                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9441                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9442                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9443                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9444
9445                                 // GOST Private Key Attributes
9446                                 ByteString value;
9447                                 ByteString param_a;
9448                                 ByteString param_b;
9449                                 ByteString param_c;
9450                                 if (isPrivateKeyPrivate)
9451                                 {
9452                                         token->encrypt(priv->getD(), value);
9453                                         token->encrypt(priv->getEC(), param_a);
9454                                         token->encrypt(param_3411, param_b);
9455                                         token->encrypt(param_28147, param_c);
9456                                 }
9457                                 else
9458                                 {
9459                                         value = priv->getD();
9460                                         param_a = priv->getEC();
9461                                         param_b = param_3411;
9462                                         param_c = param_28147;
9463                                 }
9464                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9465                                 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9466                                 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9467                                 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9468
9469                                 if (bOK)
9470                                         bOK = osobject->commitTransaction();
9471                                 else
9472                                         osobject->abortTransaction();
9473
9474                                 if (!bOK)
9475                                         rv = CKR_FUNCTION_FAILED;
9476                         } else
9477                                   rv = CKR_FUNCTION_FAILED;
9478                 }
9479         }
9480
9481         // Clean up
9482         gost->recycleKeyPair(kp);
9483         CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9484
9485         // Remove keys that may have been created already when the function fails.
9486         if (rv != CKR_OK)
9487         {
9488                 if (*phPrivateKey != CK_INVALID_HANDLE)
9489                 {
9490                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9491                         handleManager->destroyObject(*phPrivateKey);
9492                         if (ospriv) ospriv->destroyObject();
9493                         *phPrivateKey = CK_INVALID_HANDLE;
9494                 }
9495
9496                 if (*phPublicKey != CK_INVALID_HANDLE)
9497                 {
9498                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9499                         handleManager->destroyObject(*phPublicKey);
9500                         if (ospub) ospub->destroyObject();
9501                         *phPublicKey = CK_INVALID_HANDLE;
9502                 }
9503         }
9504
9505         return rv;
9506 }
9507
9508 // Derive a DH secret
9509 CK_RV SoftHSM::deriveDH
9510 (CK_SESSION_HANDLE hSession,
9511         CK_MECHANISM_PTR pMechanism,
9512         CK_OBJECT_HANDLE hBaseKey,
9513         CK_ATTRIBUTE_PTR pTemplate,
9514         CK_ULONG ulCount,
9515         CK_OBJECT_HANDLE_PTR phKey,
9516         CK_KEY_TYPE keyType,
9517         CK_BBOOL isOnToken,
9518         CK_BBOOL isPrivate)
9519 {
9520         *phKey = CK_INVALID_HANDLE;
9521
9522         if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9523         if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9524
9525         // Get the session
9526         Session* session = (Session*)handleManager->getSession(hSession);
9527         if (session == NULL)
9528                 return CKR_SESSION_HANDLE_INVALID;
9529
9530         // Get the token
9531         Token* token = session->getToken();
9532         if (token == NULL)
9533                 return CKR_GENERAL_ERROR;
9534
9535         // Extract desired parameter information
9536         size_t byteLen = 0;
9537         bool checkValue = true;
9538         for (CK_ULONG i = 0; i < ulCount; i++)
9539         {
9540                 switch (pTemplate[i].type)
9541                 {
9542                         case CKA_VALUE:
9543                                 INFO_MSG("CKA_VALUE must not be included");
9544                                 return CKR_ATTRIBUTE_READ_ONLY;
9545                         case CKA_VALUE_LEN:
9546                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9547                                 {
9548                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9549                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9550                                 }
9551                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9552                                 break;
9553                         case CKA_CHECK_VALUE:
9554                                 if (pTemplate[i].ulValueLen > 0)
9555                                 {
9556                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9557                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9558                                 }
9559                                 checkValue = false;
9560                                 break;
9561                         default:
9562                                 break;
9563                 }
9564         }
9565
9566         // Check the length
9567         switch (keyType)
9568         {
9569                 case CKK_GENERIC_SECRET:
9570                         if (byteLen == 0)
9571                         {
9572                                 INFO_MSG("CKA_VALUE_LEN must be set");
9573                                 return CKR_TEMPLATE_INCOMPLETE;
9574                         }
9575                         break;
9576 #ifndef WITH_FIPS
9577                 case CKK_DES:
9578                         if (byteLen != 0)
9579                         {
9580                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9581                                 return CKR_ATTRIBUTE_READ_ONLY;
9582                         }
9583                         byteLen = 8;
9584                         break;
9585 #endif
9586                 case CKK_DES2:
9587                         if (byteLen != 0)
9588                         {
9589                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9590                                 return CKR_ATTRIBUTE_READ_ONLY;
9591                         }
9592                         byteLen = 16;
9593                         break;
9594                 case CKK_DES3:
9595                         if (byteLen != 0)
9596                         {
9597                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9598                                 return CKR_ATTRIBUTE_READ_ONLY;
9599                         }
9600                         byteLen = 24;
9601                         break;
9602                 case CKK_AES:
9603                         if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9604                         {
9605                                 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9606                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9607                         }
9608                         break;
9609                 default:
9610                         return CKR_ATTRIBUTE_VALUE_INVALID;
9611         }
9612
9613         // Get the base key handle
9614         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9615         if (baseKey == NULL || !baseKey->isValid())
9616                 return CKR_KEY_HANDLE_INVALID;
9617
9618         // Get the DH algorithm handler
9619         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9620         if (dh == NULL)
9621                 return CKR_MECHANISM_INVALID;
9622
9623         // Get the keys
9624         PrivateKey* privateKey = dh->newPrivateKey();
9625         if (privateKey == NULL)
9626         {
9627                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9628                 return CKR_HOST_MEMORY;
9629         }
9630         if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9631         {
9632                 dh->recyclePrivateKey(privateKey);
9633                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9634                 return CKR_GENERAL_ERROR;
9635         }
9636
9637         ByteString mechParameters;
9638         mechParameters.resize(pMechanism->ulParameterLen);
9639         memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9640         PublicKey* publicKey = dh->newPublicKey();
9641         if (publicKey == NULL)
9642         {
9643                 dh->recyclePrivateKey(privateKey);
9644                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9645                 return CKR_HOST_MEMORY;
9646         }
9647         if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9648         {
9649                 dh->recyclePrivateKey(privateKey);
9650                 dh->recyclePublicKey(publicKey);
9651                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9652                 return CKR_GENERAL_ERROR;
9653         }
9654
9655         // Derive the secret
9656         SymmetricKey* secret = NULL;
9657         CK_RV rv = CKR_OK;
9658         if (!dh->deriveKey(&secret, publicKey, privateKey))
9659                 rv = CKR_GENERAL_ERROR;
9660         dh->recyclePrivateKey(privateKey);
9661         dh->recyclePublicKey(publicKey);
9662
9663         // Create the secret object using C_CreateObject
9664         const CK_ULONG maxAttribs = 32;
9665         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9666         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9667                 { CKA_CLASS, &objClass, sizeof(objClass) },
9668                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9669                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9670                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9671         };
9672         CK_ULONG secretAttribsCount = 4;
9673
9674         // Add the additional
9675         if (ulCount > (maxAttribs - secretAttribsCount))
9676                 rv = CKR_TEMPLATE_INCONSISTENT;
9677         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9678         {
9679                 switch (pTemplate[i].type)
9680                 {
9681                         case CKA_CLASS:
9682                         case CKA_TOKEN:
9683                         case CKA_PRIVATE:
9684                         case CKA_KEY_TYPE:
9685                         case CKA_CHECK_VALUE:
9686                                 continue;
9687                 default:
9688                         secretAttribs[secretAttribsCount++] = pTemplate[i];
9689                 }
9690         }
9691
9692         if (rv == CKR_OK)
9693                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9694
9695         // Store the attributes that are being supplied
9696         if (rv == CKR_OK)
9697         {
9698                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9699                 if (osobject == NULL_PTR || !osobject->isValid()) {
9700                         rv = CKR_FUNCTION_FAILED;
9701                 } else if (osobject->startTransaction()) {
9702                         bool bOK = true;
9703
9704                         // Common Attributes
9705                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9706
9707                         // Common Secret Key Attributes
9708                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9709                         {
9710                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9711                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9712                         }
9713                         else
9714                         {
9715                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9716                         }
9717                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9718                         {
9719                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9720                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9721                         }
9722                         else
9723                         {
9724                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9725                         }
9726
9727                         // Secret Attributes
9728                         ByteString secretValue = secret->getKeyBits();
9729                         ByteString value;
9730                         ByteString plainKCV;
9731                         ByteString kcv;
9732
9733                         if (byteLen > secretValue.size())
9734                         {
9735                                 INFO_MSG("The derived secret is too short");
9736                                 bOK = false;
9737                         }
9738                         else
9739                         {
9740                                 // Truncate value when requested, remove from the leading end
9741                                 if (byteLen < secretValue.size())
9742                                         secretValue.split(secretValue.size() - byteLen);
9743
9744                                 // Fix the odd parity for DES
9745                                 if (keyType == CKK_DES ||
9746                                     keyType == CKK_DES2 ||
9747                                     keyType == CKK_DES3)
9748                                 {
9749                                         for (size_t i = 0; i < secretValue.size(); i++)
9750                                         {
9751                                                 secretValue[i] = odd_parity[secretValue[i]];
9752                                         }
9753                                 }
9754
9755                                 // Get the KCV
9756                                 switch (keyType)
9757                                 {
9758                                         case CKK_GENERIC_SECRET:
9759                                                 secret->setBitLen(byteLen * 8);
9760                                                 plainKCV = secret->getKeyCheckValue();
9761                                                 break;
9762                                         case CKK_DES:
9763                                         case CKK_DES2:
9764                                         case CKK_DES3:
9765                                                 secret->setBitLen(byteLen * 7);
9766                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9767                                                 break;
9768                                         case CKK_AES:
9769                                                 secret->setBitLen(byteLen * 8);
9770                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9771                                                 break;
9772                                         default:
9773                                                 bOK = false;
9774                                                 break;
9775                                 }
9776
9777                                 if (isPrivate)
9778                                 {
9779                                         token->encrypt(secretValue, value);
9780                                         token->encrypt(plainKCV, kcv);
9781                                 }
9782                                 else
9783                                 {
9784                                         value = secretValue;
9785                                         kcv = plainKCV;
9786                                 }
9787                         }
9788                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9789                         if (checkValue)
9790                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9791
9792                         if (bOK)
9793                                 bOK = osobject->commitTransaction();
9794                         else
9795                                 osobject->abortTransaction();
9796
9797                         if (!bOK)
9798                                 rv = CKR_FUNCTION_FAILED;
9799                 } else
9800                         rv = CKR_FUNCTION_FAILED;
9801         }
9802
9803         // Clean up
9804         dh->recycleSymmetricKey(secret);
9805         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9806
9807         // Remove secret that may have been created already when the function fails.
9808         if (rv != CKR_OK)
9809         {
9810                 if (*phKey != CK_INVALID_HANDLE)
9811                 {
9812                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9813                         handleManager->destroyObject(*phKey);
9814                         if (ossecret) ossecret->destroyObject();
9815                         *phKey = CK_INVALID_HANDLE;
9816                 }
9817         }
9818
9819         return rv;
9820 }
9821
9822 // Derive an ECDH secret
9823 CK_RV SoftHSM::deriveECDH
9824 (CK_SESSION_HANDLE hSession,
9825         CK_MECHANISM_PTR pMechanism,
9826         CK_OBJECT_HANDLE hBaseKey,
9827         CK_ATTRIBUTE_PTR pTemplate,
9828         CK_ULONG ulCount,
9829         CK_OBJECT_HANDLE_PTR phKey,
9830         CK_KEY_TYPE keyType,
9831         CK_BBOOL isOnToken,
9832         CK_BBOOL isPrivate)
9833 {
9834 #ifdef WITH_ECC
9835         *phKey = CK_INVALID_HANDLE;
9836
9837         if ((pMechanism->pParameter == NULL_PTR) ||
9838             (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9839         {
9840                 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9841                 return CKR_MECHANISM_PARAM_INVALID;
9842         }
9843         if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9844         {
9845                 DEBUG_MSG("kdf must be CKD_NULL");
9846                 return CKR_MECHANISM_PARAM_INVALID;
9847         }
9848         if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9849             (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9850         {
9851                 DEBUG_MSG("there must be no shared data");
9852                 return CKR_MECHANISM_PARAM_INVALID;
9853         }
9854         if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9855             (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9856         {
9857                 DEBUG_MSG("there must be a public data");
9858                 return CKR_MECHANISM_PARAM_INVALID;
9859         }
9860
9861         // Get the session
9862         Session* session = (Session*)handleManager->getSession(hSession);
9863         if (session == NULL)
9864                 return CKR_SESSION_HANDLE_INVALID;
9865
9866         // Get the token
9867         Token* token = session->getToken();
9868         if (token == NULL)
9869                 return CKR_GENERAL_ERROR;
9870
9871         // Extract desired parameter information
9872         size_t byteLen = 0;
9873         bool checkValue = true;
9874         for (CK_ULONG i = 0; i < ulCount; i++)
9875         {
9876                 switch (pTemplate[i].type)
9877                 {
9878                         case CKA_VALUE:
9879                                 INFO_MSG("CKA_VALUE must not be included");
9880                                 return CKR_ATTRIBUTE_READ_ONLY;
9881                         case CKA_VALUE_LEN:
9882                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9883                                 {
9884                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9885                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9886                                 }
9887                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9888                                 break;
9889                         case CKA_CHECK_VALUE:
9890                                 if (pTemplate[i].ulValueLen > 0)
9891                                 {
9892                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9893                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9894                                 }
9895                                 checkValue = false;
9896                                 break;
9897                         default:
9898                                 break;
9899                 }
9900         }
9901
9902         // Check the length
9903         // byteLen == 0 impiles return max size the ECC can derive
9904         switch (keyType)
9905         {
9906                 case CKK_GENERIC_SECRET:
9907                         break;
9908 #ifndef WITH_FIPS
9909                 case CKK_DES:
9910                         if (byteLen != 0 && byteLen != 8)
9911                         {
9912                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9913                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9914                         }
9915                         byteLen = 8;
9916                         break;
9917 #endif
9918                 case CKK_DES2:
9919                         if (byteLen != 0 && byteLen != 16)
9920                         {
9921                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9922                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9923                         }
9924                         byteLen = 16;
9925                         break;
9926                 case CKK_DES3:
9927                         if (byteLen != 0 && byteLen != 24)
9928                         {
9929                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9930                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9931                         }
9932                         byteLen = 24;
9933                         break;
9934                 case CKK_AES:
9935                         if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9936                         {
9937                                 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9938                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9939                         }
9940                         break;
9941                 default:
9942                         return CKR_ATTRIBUTE_VALUE_INVALID;
9943         }
9944
9945         // Get the base key handle
9946         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9947         if (baseKey == NULL || !baseKey->isValid())
9948                 return CKR_KEY_HANDLE_INVALID;
9949
9950         // Get the ECDH algorithm handler
9951         AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9952         if (ecdh == NULL)
9953                 return CKR_MECHANISM_INVALID;
9954
9955         // Get the keys
9956         PrivateKey* privateKey = ecdh->newPrivateKey();
9957         if (privateKey == NULL)
9958         {
9959                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9960                 return CKR_HOST_MEMORY;
9961         }
9962         if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9963         {
9964                 ecdh->recyclePrivateKey(privateKey);
9965                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9966                 return CKR_GENERAL_ERROR;
9967         }
9968
9969         ByteString publicData;
9970         publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9971         memcpy(&publicData[0],
9972                CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9973                CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9974         PublicKey* publicKey = ecdh->newPublicKey();
9975         if (publicKey == NULL)
9976         {
9977                 ecdh->recyclePrivateKey(privateKey);
9978                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9979                 return CKR_HOST_MEMORY;
9980         }
9981         if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9982         {
9983                 ecdh->recyclePrivateKey(privateKey);
9984                 ecdh->recyclePublicKey(publicKey);
9985                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9986                 return CKR_GENERAL_ERROR;
9987         }
9988
9989         // Derive the secret
9990         SymmetricKey* secret = NULL;
9991         CK_RV rv = CKR_OK;
9992         if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9993                 rv = CKR_GENERAL_ERROR;
9994         ecdh->recyclePrivateKey(privateKey);
9995         ecdh->recyclePublicKey(publicKey);
9996
9997         // Create the secret object using C_CreateObject
9998         const CK_ULONG maxAttribs = 32;
9999         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10000         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10001                 { CKA_CLASS, &objClass, sizeof(objClass) },
10002                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10003                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10004                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10005         };
10006         CK_ULONG secretAttribsCount = 4;
10007
10008         // Add the additional
10009         if (ulCount > (maxAttribs - secretAttribsCount))
10010                 rv = CKR_TEMPLATE_INCONSISTENT;
10011         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10012         {
10013                 switch (pTemplate[i].type)
10014                 {
10015                         case CKA_CLASS:
10016                         case CKA_TOKEN:
10017                         case CKA_PRIVATE:
10018                         case CKA_KEY_TYPE:
10019                         case CKA_CHECK_VALUE:
10020                                 continue;
10021                 default:
10022                         secretAttribs[secretAttribsCount++] = pTemplate[i];
10023                 }
10024         }
10025
10026         if (rv == CKR_OK)
10027                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10028
10029         // Store the attributes that are being supplied
10030         if (rv == CKR_OK)
10031         {
10032                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10033                 if (osobject == NULL_PTR || !osobject->isValid()) {
10034                         rv = CKR_FUNCTION_FAILED;
10035                 } else if (osobject->startTransaction()) {
10036                         bool bOK = true;
10037
10038                         // Common Attributes
10039                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10040
10041                         // Common Secret Key Attributes
10042                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10043                         {
10044                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10045                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10046                         }
10047                         else
10048                         {
10049                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10050                         }
10051                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10052                         {
10053                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10054                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10055                         }
10056                         else
10057                         {
10058                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10059                         }
10060
10061                         // Secret Attributes
10062                         ByteString secretValue = secret->getKeyBits();
10063                         ByteString value;
10064                         ByteString plainKCV;
10065                         ByteString kcv;
10066
10067                         // For generic and AES keys:
10068                         // default to return max size available.
10069                         if (byteLen == 0)
10070                         {
10071                                 switch (keyType)
10072                                 {
10073                                         case CKK_GENERIC_SECRET:
10074                                                 byteLen = secretValue.size();
10075                                                 break;
10076                                         case CKK_AES:
10077                                                 if (secretValue.size() >= 32)
10078                                                         byteLen = 32;
10079                                                 else if (secretValue.size() >= 24)
10080                                                         byteLen = 24;
10081                                                 else
10082                                                         byteLen = 16;
10083                                 }
10084                         }
10085
10086                         if (byteLen > secretValue.size())
10087                         {
10088                                 INFO_MSG("The derived secret is too short");
10089                                 bOK = false;
10090                         }
10091                         else
10092                         {
10093                                 // Truncate value when requested, remove from the leading end
10094                                 if (byteLen < secretValue.size())
10095                                         secretValue.split(secretValue.size() - byteLen);
10096
10097                                 // Fix the odd parity for DES
10098                                 if (keyType == CKK_DES ||
10099                                     keyType == CKK_DES2 ||
10100                                     keyType == CKK_DES3)
10101                                 {
10102                                         for (size_t i = 0; i < secretValue.size(); i++)
10103                                         {
10104                                                 secretValue[i] = odd_parity[secretValue[i]];
10105                                         }
10106                                 }
10107
10108                                 // Get the KCV
10109                                 switch (keyType)
10110                                 {
10111                                         case CKK_GENERIC_SECRET:
10112                                                 secret->setBitLen(byteLen * 8);
10113                                                 plainKCV = secret->getKeyCheckValue();
10114                                                 break;
10115                                         case CKK_DES:
10116                                         case CKK_DES2:
10117                                         case CKK_DES3:
10118                                                 secret->setBitLen(byteLen * 7);
10119                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10120                                                 break;
10121                                         case CKK_AES:
10122                                                 secret->setBitLen(byteLen * 8);
10123                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10124                                                 break;
10125                                         default:
10126                                                 bOK = false;
10127                                                 break;
10128                                 }
10129
10130                                 if (isPrivate)
10131                                 {
10132                                         token->encrypt(secretValue, value);
10133                                         token->encrypt(plainKCV, kcv);
10134                                 }
10135                                 else
10136                                 {
10137                                         value = secretValue;
10138                                         kcv = plainKCV;
10139                                 }
10140                         }
10141                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10142                         if (checkValue)
10143                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10144
10145                         if (bOK)
10146                                 bOK = osobject->commitTransaction();
10147                         else
10148                                 osobject->abortTransaction();
10149
10150                         if (!bOK)
10151                                 rv = CKR_FUNCTION_FAILED;
10152                 } else
10153                         rv = CKR_FUNCTION_FAILED;
10154         }
10155
10156         // Clean up
10157         ecdh->recycleSymmetricKey(secret);
10158         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
10159
10160         // Remove secret that may have been created already when the function fails.
10161         if (rv != CKR_OK)
10162         {
10163                 if (*phKey != CK_INVALID_HANDLE)
10164                 {
10165                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10166                         handleManager->destroyObject(*phKey);
10167                         if (ossecret) ossecret->destroyObject();
10168                         *phKey = CK_INVALID_HANDLE;
10169                 }
10170         }
10171
10172         return rv;
10173 #else
10174         return CKR_MECHANISM_INVALID;
10175 #endif
10176 }
10177
10178 // Derive an symmetric secret
10179 CK_RV SoftHSM::deriveSymmetric
10180 (CK_SESSION_HANDLE hSession,
10181         CK_MECHANISM_PTR pMechanism,
10182         CK_OBJECT_HANDLE hBaseKey,
10183         CK_ATTRIBUTE_PTR pTemplate,
10184         CK_ULONG ulCount,
10185         CK_OBJECT_HANDLE_PTR phKey,
10186         CK_KEY_TYPE keyType,
10187         CK_BBOOL isOnToken,
10188         CK_BBOOL isPrivate)
10189 {
10190         *phKey = CK_INVALID_HANDLE;
10191
10192         if (pMechanism->pParameter == NULL_PTR)
10193         {
10194                 DEBUG_MSG("pParameter must be supplied");
10195                 return CKR_MECHANISM_PARAM_INVALID;
10196         }
10197
10198         ByteString data;
10199
10200         if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
10201             pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
10202             pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10203         {
10204                 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10205                 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10206                 if (ulLen == 0 || pData == NULL_PTR)
10207                 {
10208                         DEBUG_MSG("There must be data in the parameter");
10209                         return CKR_MECHANISM_PARAM_INVALID;
10210                 }
10211                 if (ulLen % 8 != 0)
10212                 {
10213                         DEBUG_MSG("The data must be a multiple of 8 bytes long");
10214                         return CKR_MECHANISM_PARAM_INVALID;
10215                 }
10216                 data.resize(ulLen);
10217                 memcpy(&data[0],
10218                        pData,
10219                        ulLen);
10220         }
10221         else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
10222                  pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
10223                  pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
10224         {
10225                 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10226                 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10227                 if (length == 0 || pData == NULL_PTR)
10228                 {
10229                         DEBUG_MSG("There must be data in the parameter");
10230                         return CKR_MECHANISM_PARAM_INVALID;
10231                 }
10232                 if (length % 8 != 0)
10233                 {
10234                         DEBUG_MSG("The data must be a multiple of 8 bytes long");
10235                         return CKR_MECHANISM_PARAM_INVALID;
10236                 }
10237                 data.resize(length);
10238                 memcpy(&data[0],
10239                        pData,
10240                        length);
10241         }
10242         else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
10243                  pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
10244         {
10245                 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
10246                 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
10247                 if (ulLen == 0 || pData == NULL_PTR)
10248                 {
10249                         DEBUG_MSG("There must be data in the parameter");
10250                         return CKR_MECHANISM_PARAM_INVALID;
10251                 }
10252                 if (ulLen % 16 != 0)
10253                 {
10254                         DEBUG_MSG("The data must be a multiple of 16 bytes long");
10255                         return CKR_MECHANISM_PARAM_INVALID;
10256                 }
10257                 data.resize(ulLen);
10258                 memcpy(&data[0],
10259                        pData,
10260                        ulLen);
10261         }
10262         else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
10263                  pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
10264         {
10265                 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
10266                 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
10267                 if (length == 0 || pData == NULL_PTR)
10268                 {
10269                         DEBUG_MSG("There must be data in the parameter");
10270                         return CKR_MECHANISM_PARAM_INVALID;
10271                 }
10272                 if (length % 16 != 0)
10273                 {
10274                         DEBUG_MSG("The data must be a multiple of 16 bytes long");
10275                         return CKR_MECHANISM_PARAM_INVALID;
10276                 }
10277                 data.resize(length);
10278                 memcpy(&data[0],
10279                        pData,
10280                        length);
10281         }
10282         else
10283         {
10284                 DEBUG_MSG("pParameter is invalid");
10285                 return CKR_MECHANISM_PARAM_INVALID;
10286         }
10287
10288         // Get the session
10289         Session* session = (Session*)handleManager->getSession(hSession);
10290         if (session == NULL)
10291                 return CKR_SESSION_HANDLE_INVALID;
10292
10293         // Get the token
10294         Token* token = session->getToken();
10295         if (token == NULL)
10296                 return CKR_GENERAL_ERROR;
10297
10298         // Extract desired parameter information
10299         size_t byteLen = 0;
10300         bool checkValue = true;
10301         for (CK_ULONG i = 0; i < ulCount; i++)
10302         {
10303                 switch (pTemplate[i].type)
10304                 {
10305                         case CKA_VALUE:
10306                                 INFO_MSG("CKA_VALUE must not be included");
10307                                 return CKR_ATTRIBUTE_READ_ONLY;
10308                         case CKA_VALUE_LEN:
10309                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10310                                 {
10311                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10312                                         return CKR_ATTRIBUTE_VALUE_INVALID;
10313                                 }
10314                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10315                                 break;
10316                         case CKA_CHECK_VALUE:
10317                                 if (pTemplate[i].ulValueLen > 0)
10318                                 {
10319                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10320                                         return CKR_ATTRIBUTE_VALUE_INVALID;
10321                                 }
10322                                 checkValue = false;
10323                                 break;
10324                         default:
10325                                 break;
10326                 }
10327         }
10328
10329         // Check the length
10330         switch (keyType)
10331         {
10332                 case CKK_GENERIC_SECRET:
10333                         if (byteLen == 0)
10334                         {
10335                                 INFO_MSG("CKA_VALUE_LEN must be set");
10336                                 return CKR_TEMPLATE_INCOMPLETE;
10337                         }
10338                         break;
10339 #ifndef WITH_FIPS
10340                 case CKK_DES:
10341                         if (byteLen != 0)
10342                         {
10343                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10344                                 return CKR_ATTRIBUTE_READ_ONLY;
10345                         }
10346                         byteLen = 8;
10347                         break;
10348 #endif
10349                 case CKK_DES2:
10350                         if (byteLen != 0)
10351                         {
10352                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10353                                 return CKR_ATTRIBUTE_READ_ONLY;
10354                         }
10355                         byteLen = 16;
10356                         break;
10357                 case CKK_DES3:
10358                         if (byteLen != 0)
10359                         {
10360                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10361                                 return CKR_ATTRIBUTE_READ_ONLY;
10362                         }
10363                         byteLen = 24;
10364                         break;
10365                 case CKK_AES:
10366                         if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10367                         {
10368                                 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10369                                 return CKR_ATTRIBUTE_VALUE_INVALID;
10370                         }
10371                         break;
10372                 default:
10373                         return CKR_ATTRIBUTE_VALUE_INVALID;
10374         }
10375
10376         // Get the symmetric algorithm matching the mechanism
10377         SymAlgo::Type algo = SymAlgo::Unknown;
10378         SymMode::Type mode = SymMode::Unknown;
10379         bool padding = false;
10380         ByteString iv;
10381         size_t bb = 8;
10382         switch(pMechanism->mechanism) {
10383 #ifndef WITH_FIPS
10384                 case CKM_DES_ECB_ENCRYPT_DATA:
10385                         algo = SymAlgo::DES;
10386                         mode = SymMode::ECB;
10387                         bb = 7;
10388                         break;
10389                 case CKM_DES_CBC_ENCRYPT_DATA:
10390                         algo = SymAlgo::DES;
10391                         mode = SymMode::CBC;
10392                         bb = 7;
10393                         iv.resize(8);
10394                         memcpy(&iv[0],
10395                                &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10396                                8);
10397                         break;
10398 #endif
10399                 case CKM_DES3_ECB_ENCRYPT_DATA:
10400                         algo = SymAlgo::DES3;
10401                         mode = SymMode::ECB;
10402                         bb = 7;
10403                         break;
10404                 case CKM_DES3_CBC_ENCRYPT_DATA:
10405                         algo = SymAlgo::DES3;
10406                         mode = SymMode::CBC;
10407                         bb = 7;
10408                         iv.resize(8);
10409                         memcpy(&iv[0],
10410                                &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10411                                8);
10412                         break;
10413                 case CKM_AES_ECB_ENCRYPT_DATA:
10414                         algo = SymAlgo::AES;
10415                         mode = SymMode::ECB;
10416                         break;
10417                 case CKM_AES_CBC_ENCRYPT_DATA:
10418                         algo = SymAlgo::AES;
10419                         mode = SymMode::CBC;
10420                         iv.resize(16);
10421                         memcpy(&iv[0],
10422                                &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10423                                16);
10424                         break;
10425                 default:
10426                         return CKR_MECHANISM_INVALID;
10427         }
10428
10429         // Check the key handle
10430         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10431         if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10432
10433         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10434         if (cipher == NULL) return CKR_MECHANISM_INVALID;
10435
10436         SymmetricKey* secretkey = new SymmetricKey();
10437
10438         if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10439         {
10440                 cipher->recycleKey(secretkey);
10441                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10442                 return CKR_GENERAL_ERROR;
10443         }
10444
10445         // adjust key bit length
10446         secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10447
10448         // Initialize encryption
10449         if (!cipher->encryptInit(secretkey, mode, iv, padding))
10450         {
10451                 cipher->recycleKey(secretkey);
10452                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10453                 return CKR_MECHANISM_INVALID;
10454         }
10455
10456         // Get the data
10457         ByteString secretValue;
10458
10459         // Encrypt the data
10460         if (!cipher->encryptUpdate(data, secretValue))
10461         {
10462                 cipher->recycleKey(secretkey);
10463                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10464                 return CKR_GENERAL_ERROR;
10465         }
10466
10467         // Finalize encryption
10468         ByteString encryptedFinal;
10469         if (!cipher->encryptFinal(encryptedFinal))
10470         {
10471                 cipher->recycleKey(secretkey);
10472                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10473                 return CKR_GENERAL_ERROR;
10474         }
10475         cipher->recycleKey(secretkey);
10476         CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10477         secretValue += encryptedFinal;
10478
10479         // Create the secret object using C_CreateObject
10480         const CK_ULONG maxAttribs = 32;
10481         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10482         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10483                 { CKA_CLASS, &objClass, sizeof(objClass) },
10484                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10485                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10486                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10487         };
10488         CK_ULONG secretAttribsCount = 4;
10489
10490         // Add the additional
10491         CK_RV rv = CKR_OK;
10492         if (ulCount > (maxAttribs - secretAttribsCount))
10493                 rv = CKR_TEMPLATE_INCONSISTENT;
10494         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10495         {
10496                 switch (pTemplate[i].type)
10497                 {
10498                         case CKA_CLASS:
10499                         case CKA_TOKEN:
10500                         case CKA_PRIVATE:
10501                         case CKA_KEY_TYPE:
10502                         case CKA_CHECK_VALUE:
10503                                 continue;
10504                         default:
10505                                 secretAttribs[secretAttribsCount++] = pTemplate[i];
10506                 }
10507         }
10508
10509         if (rv == CKR_OK)
10510                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10511
10512         // Store the attributes that are being supplied
10513         if (rv == CKR_OK)
10514         {
10515                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10516                 if (osobject == NULL_PTR || !osobject->isValid()) {
10517                         rv = CKR_FUNCTION_FAILED;
10518                 } else if (osobject->startTransaction()) {
10519                         bool bOK = true;
10520
10521                         // Common Attributes
10522                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10523
10524                         // Common Secret Key Attributes
10525                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10526                         {
10527                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10528                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10529                         }
10530                         else
10531                         {
10532                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10533                         }
10534                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10535                         {
10536                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10537                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10538                         }
10539                         else
10540                         {
10541                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10542                         }
10543
10544                         ByteString value;
10545                         ByteString plainKCV;
10546                         ByteString kcv;
10547
10548                         if (byteLen > secretValue.size())
10549                         {
10550                                 INFO_MSG("The derived secret is too short");
10551                                 bOK = false;
10552                         }
10553                         else
10554                         {
10555                                 // Truncate value when requested, remove from the trailing end
10556                                 if (byteLen < secretValue.size())
10557                                         secretValue.resize(byteLen);
10558
10559                                 // Fix the odd parity for DES
10560                                 if (keyType == CKK_DES ||
10561                                     keyType == CKK_DES2 ||
10562                                     keyType == CKK_DES3)
10563                                 {
10564                                         for (size_t i = 0; i < secretValue.size(); i++)
10565                                         {
10566                                                 secretValue[i] = odd_parity[secretValue[i]];
10567                                         }
10568                                 }
10569
10570                                 // Get the KCV
10571                                 SymmetricKey* secret = new SymmetricKey();
10572                                 secret->setKeyBits(secretValue);
10573                                 switch (keyType)
10574                                 {
10575                                         case CKK_GENERIC_SECRET:
10576                                                 secret->setBitLen(byteLen * 8);
10577                                                 plainKCV = secret->getKeyCheckValue();
10578                                                 break;
10579                                         case CKK_DES:
10580                                         case CKK_DES2:
10581                                         case CKK_DES3:
10582                                                 secret->setBitLen(byteLen * 7);
10583                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10584                                                 break;
10585                                         case CKK_AES:
10586                                                 secret->setBitLen(byteLen * 8);
10587                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10588                                                 break;
10589                                         default:
10590                                                 bOK = false;
10591                                                 break;
10592                                 }
10593                                 delete secret;
10594
10595                                 if (isPrivate)
10596                                 {
10597                                         token->encrypt(secretValue, value);
10598                                         token->encrypt(plainKCV, kcv);
10599                                 }
10600                                 else
10601                                 {
10602                                         value = secretValue;
10603                                         kcv = plainKCV;
10604                                 }
10605                         }
10606                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10607                         if (checkValue)
10608                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10609
10610                         if (bOK)
10611                                 bOK = osobject->commitTransaction();
10612                         else
10613                                 osobject->abortTransaction();
10614
10615                         if (!bOK)
10616                                 rv = CKR_FUNCTION_FAILED;
10617                 } else
10618                         rv = CKR_FUNCTION_FAILED;
10619         }
10620
10621         // Remove secret that may have been created already when the function fails.
10622         if (rv != CKR_OK)
10623         {
10624                 if (*phKey != CK_INVALID_HANDLE)
10625                 {
10626                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10627                         handleManager->destroyObject(*phKey);
10628                         if (ossecret) ossecret->destroyObject();
10629                         *phKey = CK_INVALID_HANDLE;
10630                 }
10631         }
10632
10633         return rv;
10634 }
10635
10636 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10637 {
10638         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10639
10640         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10641         if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10642
10643         // Get the session
10644         Session* session = (Session*)handleManager->getSession(hSession);
10645         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10646
10647         // Get the slot
10648         Slot* slot = session->getSlot();
10649         if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10650
10651         // Get the token
10652         Token* token = session->getToken();
10653         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10654
10655         // Extract information from the template that is needed to create the object.
10656         CK_OBJECT_CLASS objClass = CKO_DATA;
10657         CK_KEY_TYPE keyType = CKK_RSA;
10658         CK_CERTIFICATE_TYPE certType = CKC_X_509;
10659         CK_BBOOL isOnToken = CK_FALSE;
10660         CK_BBOOL isPrivate = CK_TRUE;
10661         bool isImplicit = false;
10662         CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10663         if (rv != CKR_OK)
10664         {
10665                 ERROR_MSG("Mandatory attribute not present in template");
10666                 return rv;
10667         }
10668
10669         // Check user credentials
10670         rv = haveWrite(session->getState(), isOnToken, isPrivate);
10671         if (rv != CKR_OK)
10672         {
10673                 if (rv == CKR_USER_NOT_LOGGED_IN)
10674                         INFO_MSG("User is not authorized");
10675                 if (rv == CKR_SESSION_READ_ONLY)
10676                         INFO_MSG("Session is read-only");
10677
10678                 return rv;
10679         }
10680
10681         // Change order of attributes
10682         const CK_ULONG maxAttribs = 32;
10683         CK_ATTRIBUTE attribs[maxAttribs];
10684         CK_ATTRIBUTE saveAttribs[maxAttribs];
10685         CK_ULONG attribsCount = 0;
10686         CK_ULONG saveAttribsCount = 0;
10687         if (ulCount > maxAttribs)
10688         {
10689                 return CKR_TEMPLATE_INCONSISTENT;
10690         }
10691         for (CK_ULONG i=0; i < ulCount; i++)
10692         {
10693                 switch (pTemplate[i].type)
10694                 {
10695                         case CKA_CHECK_VALUE:
10696                                 saveAttribs[saveAttribsCount++] = pTemplate[i];
10697                                 break;
10698                         default:
10699                                 attribs[attribsCount++] = pTemplate[i];
10700                 }
10701         }
10702         for (CK_ULONG i=0; i < saveAttribsCount; i++)
10703         {
10704                 attribs[attribsCount++] = saveAttribs[i];
10705         }
10706
10707         P11Object* p11object = NULL;
10708         rv = newP11Object(objClass,keyType,certType,&p11object);
10709         if (rv != CKR_OK)
10710                 return rv;
10711
10712         // Create the object in session or on the token
10713         OSObject *object = NULL_PTR;
10714         if (isOnToken)
10715         {
10716                 object = (OSObject*) token->createObject();
10717         }
10718         else
10719         {
10720                 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10721         }
10722
10723         if (object == NULL || !p11object->init(object))
10724         {
10725                 delete p11object;
10726                 return CKR_GENERAL_ERROR;
10727         }
10728
10729         rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10730         delete p11object;
10731         if (rv != CKR_OK)
10732                 return rv;
10733
10734         if (op == OBJECT_OP_CREATE)
10735         {
10736                 if (objClass == CKO_PUBLIC_KEY &&
10737                     (!object->startTransaction() ||
10738                     !object->setAttribute(CKA_LOCAL, false) ||
10739                     !object->commitTransaction()))
10740                 {
10741                         return CKR_GENERAL_ERROR;
10742                 }
10743
10744                 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10745                     (!object->startTransaction() ||
10746                     !object->setAttribute(CKA_LOCAL, false) ||
10747                     !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10748                     !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10749                     !object->commitTransaction()))
10750                 {
10751                         return CKR_GENERAL_ERROR;
10752                 }
10753         }
10754
10755         if (isOnToken)
10756         {
10757                 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10758         } else {
10759                 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10760         }
10761
10762         return CKR_OK;
10763 }
10764
10765 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10766 {
10767         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10768         if (token == NULL) return CKR_ARGUMENTS_BAD;
10769         if (key == NULL) return CKR_ARGUMENTS_BAD;
10770
10771         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10772         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10773
10774         // RSA Private Key Attributes
10775         ByteString modulus;
10776         ByteString publicExponent;
10777         ByteString privateExponent;
10778         ByteString prime1;
10779         ByteString prime2;
10780         ByteString exponent1;
10781         ByteString exponent2;
10782         ByteString coefficient;
10783         if (isKeyPrivate)
10784         {
10785                 bool bOK = true;
10786                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10787                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10788                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10789                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10790                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10791                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10792                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10793                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10794                 if (!bOK)
10795                         return CKR_GENERAL_ERROR;
10796         }
10797         else
10798         {
10799                 modulus = key->getByteStringValue(CKA_MODULUS);
10800                 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10801                 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10802                 prime1 = key->getByteStringValue(CKA_PRIME_1);
10803                 prime2 = key->getByteStringValue(CKA_PRIME_2);
10804                 exponent1 =  key->getByteStringValue(CKA_EXPONENT_1);
10805                 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10806                 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10807         }
10808
10809         privateKey->setN(modulus);
10810         privateKey->setE(publicExponent);
10811         privateKey->setD(privateExponent);
10812         privateKey->setP(prime1);
10813         privateKey->setQ(prime2);
10814         privateKey->setDP1(exponent1);
10815         privateKey->setDQ1(exponent2);
10816         privateKey->setPQ(coefficient);
10817
10818         return CKR_OK;
10819 }
10820
10821 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10822 {
10823         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10824         if (token == NULL) return CKR_ARGUMENTS_BAD;
10825         if (key == NULL) return CKR_ARGUMENTS_BAD;
10826
10827         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10828         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10829
10830         // RSA Public Key Attributes
10831         ByteString modulus;
10832         ByteString publicExponent;
10833         if (isKeyPrivate)
10834         {
10835                 bool bOK = true;
10836                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10837                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10838                 if (!bOK)
10839                         return CKR_GENERAL_ERROR;
10840         }
10841         else
10842         {
10843                 modulus = key->getByteStringValue(CKA_MODULUS);
10844                 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10845         }
10846
10847         publicKey->setN(modulus);
10848         publicKey->setE(publicExponent);
10849
10850         return CKR_OK;
10851 }
10852
10853 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10854 {
10855         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10856         if (token == NULL) return CKR_ARGUMENTS_BAD;
10857         if (key == NULL) return CKR_ARGUMENTS_BAD;
10858
10859         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10860         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10861
10862         // DSA Private Key Attributes
10863         ByteString prime;
10864         ByteString subprime;
10865         ByteString generator;
10866         ByteString value;
10867         if (isKeyPrivate)
10868         {
10869                 bool bOK = true;
10870                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10871                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10872                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10873                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10874                 if (!bOK)
10875                         return CKR_GENERAL_ERROR;
10876         }
10877         else
10878         {
10879                 prime = key->getByteStringValue(CKA_PRIME);
10880                 subprime = key->getByteStringValue(CKA_SUBPRIME);
10881                 generator = key->getByteStringValue(CKA_BASE);
10882                 value = key->getByteStringValue(CKA_VALUE);
10883         }
10884
10885         privateKey->setP(prime);
10886         privateKey->setQ(subprime);
10887         privateKey->setG(generator);
10888         privateKey->setX(value);
10889
10890         return CKR_OK;
10891 }
10892
10893 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10894 {
10895         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10896         if (token == NULL) return CKR_ARGUMENTS_BAD;
10897         if (key == NULL) return CKR_ARGUMENTS_BAD;
10898
10899         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10900         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10901
10902         // DSA Public Key Attributes
10903         ByteString prime;
10904         ByteString subprime;
10905         ByteString generator;
10906         ByteString value;
10907         if (isKeyPrivate)
10908         {
10909                 bool bOK = true;
10910                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10911                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10912                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10913                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10914                 if (!bOK)
10915                         return CKR_GENERAL_ERROR;
10916         }
10917         else
10918         {
10919                 prime = key->getByteStringValue(CKA_PRIME);
10920                 subprime = key->getByteStringValue(CKA_SUBPRIME);
10921                 generator = key->getByteStringValue(CKA_BASE);
10922                 value = key->getByteStringValue(CKA_VALUE);
10923         }
10924
10925         publicKey->setP(prime);
10926         publicKey->setQ(subprime);
10927         publicKey->setG(generator);
10928         publicKey->setY(value);
10929
10930         return CKR_OK;
10931 }
10932
10933 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10934 {
10935         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10936         if (token == NULL) return CKR_ARGUMENTS_BAD;
10937         if (key == NULL) return CKR_ARGUMENTS_BAD;
10938
10939         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10940         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10941
10942         // EC Private Key Attributes
10943         ByteString group;
10944         ByteString value;
10945         if (isKeyPrivate)
10946         {
10947                 bool bOK = true;
10948                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10949                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10950                 if (!bOK)
10951                         return CKR_GENERAL_ERROR;
10952         }
10953         else
10954         {
10955                 group = key->getByteStringValue(CKA_EC_PARAMS);
10956                 value = key->getByteStringValue(CKA_VALUE);
10957         }
10958
10959         privateKey->setEC(group);
10960         privateKey->setD(value);
10961
10962         return CKR_OK;
10963 }
10964
10965 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10966 {
10967         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10968         if (token == NULL) return CKR_ARGUMENTS_BAD;
10969         if (key == NULL) return CKR_ARGUMENTS_BAD;
10970
10971         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10972         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10973
10974         // EC Public Key Attributes
10975         ByteString group;
10976         ByteString point;
10977         if (isKeyPrivate)
10978         {
10979                 bool bOK = true;
10980                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10981                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10982                 if (!bOK)
10983                         return CKR_GENERAL_ERROR;
10984         }
10985         else
10986         {
10987                 group = key->getByteStringValue(CKA_EC_PARAMS);
10988                 point = key->getByteStringValue(CKA_EC_POINT);
10989         }
10990
10991         publicKey->setEC(group);
10992         publicKey->setQ(point);
10993
10994         return CKR_OK;
10995 }
10996
10997 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10998 {
10999         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11000         if (token == NULL) return CKR_ARGUMENTS_BAD;
11001         if (key == NULL) return CKR_ARGUMENTS_BAD;
11002
11003         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11004         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11005
11006         // DH Private Key Attributes
11007         ByteString prime;
11008         ByteString generator;
11009         ByteString value;
11010         if (isKeyPrivate)
11011         {
11012                 bool bOK = true;
11013                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
11014                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
11015                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
11016                 if (!bOK)
11017                         return CKR_GENERAL_ERROR;
11018         }
11019         else
11020         {
11021                 prime = key->getByteStringValue(CKA_PRIME);
11022                 generator = key->getByteStringValue(CKA_BASE);
11023                 value = key->getByteStringValue(CKA_VALUE);
11024         }
11025
11026         privateKey->setP(prime);
11027         privateKey->setG(generator);
11028         privateKey->setX(value);
11029
11030         return CKR_OK;
11031 }
11032
11033 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
11034 {
11035         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11036         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11037
11038         // Copy Domain Parameters from Private Key
11039         publicKey->setP(privateKey->getP());
11040         publicKey->setG(privateKey->getG());
11041
11042         // Set value
11043         publicKey->setY(pubParams);
11044
11045         return CKR_OK;
11046 }
11047
11048 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
11049 {
11050         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11051         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11052
11053         // Copy Domain Parameters from Private Key
11054         publicKey->setEC(privateKey->getEC());
11055
11056         // Set value
11057         ByteString data = getECDHPubData(pubData);
11058         publicKey->setQ(data);
11059
11060         return CKR_OK;
11061 }
11062
11063 // ECDH pubData can be in RAW or DER format.
11064 // Need to convert RAW as SoftHSM uses DER.
11065 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
11066 {
11067         size_t len = pubData.size();
11068         size_t controlOctets = 2;
11069         if (len == 65 || len == 97 || len == 133)
11070         {
11071                 // Raw: Length matches the public key size of P-256, P-384, or P-521
11072                 controlOctets = 0;
11073         }
11074         else if (len < controlOctets || pubData[0] != 0x04)
11075         {
11076                 // Raw: Too short or does not start with 0x04
11077                 controlOctets = 0;
11078         }
11079         else if (pubData[1] < 0x80)
11080         {
11081                 // Raw: Length octet does not match remaining data length
11082                 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
11083         }
11084         else
11085         {
11086                 size_t lengthOctets = pubData[1] & 0x7F;
11087                 controlOctets += lengthOctets;
11088
11089                 if (controlOctets >= len)
11090                 {
11091                         // Raw: Too short
11092                         controlOctets = 0;
11093                 }
11094                 else
11095                 {
11096                         ByteString length(&pubData[2], lengthOctets);
11097
11098                         if (length.long_val() != (len - controlOctets))
11099                         {
11100                                 // Raw: Length octets does not match remaining data length
11101                                 controlOctets = 0;
11102                         }
11103                 }
11104         }
11105
11106         // DER format
11107         if (controlOctets != 0) return pubData;
11108
11109         // RAW format
11110         ByteString header;
11111         if (len < 0x80)
11112         {
11113                 header.resize(2);
11114                 header[0] = (unsigned char)0x04;
11115                 header[1] = (unsigned char)(len & 0x7F);
11116         }
11117         else
11118         {
11119                 // Count significate bytes
11120                 size_t bytes = sizeof(size_t);
11121                 for(; bytes > 0; bytes--)
11122                 {
11123                         size_t value = len >> ((bytes - 1) * 8);
11124                         if (value & 0xFF) break;
11125                 }
11126
11127                 // Set header data
11128                 header.resize(2 + bytes);
11129                 header[0] = (unsigned char)0x04;
11130                 header[1] = (unsigned char)(0x80 | bytes);
11131                 for (size_t i = 1; i <= bytes; i++)
11132                 {
11133                         header[2+bytes-i] = (unsigned char) (len & 0xFF);
11134                         len >>= 8;
11135                 }
11136         }
11137
11138         return header + pubData;
11139 }
11140
11141 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
11142 {
11143         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
11144         if (token == NULL) return CKR_ARGUMENTS_BAD;
11145         if (key == NULL) return CKR_ARGUMENTS_BAD;
11146
11147         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11148         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11149
11150         // GOST Private Key Attributes
11151         ByteString value;
11152         ByteString param;
11153         if (isKeyPrivate)
11154         {
11155                 bool bOK = true;
11156                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
11157                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11158                 if (!bOK)
11159                         return CKR_GENERAL_ERROR;
11160         }
11161         else
11162         {
11163                 value = key->getByteStringValue(CKA_VALUE);
11164                 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11165         }
11166
11167         privateKey->setD(value);
11168         privateKey->setEC(param);
11169
11170         return CKR_OK;
11171 }
11172
11173 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
11174 {
11175         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
11176         if (token == NULL) return CKR_ARGUMENTS_BAD;
11177         if (key == NULL) return CKR_ARGUMENTS_BAD;
11178
11179         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11180         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11181
11182         // GOST Public Key Attributes
11183         ByteString point;
11184         ByteString param;
11185         if (isKeyPrivate)
11186         {
11187                 bool bOK = true;
11188                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
11189                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
11190                 if (!bOK)
11191                         return CKR_GENERAL_ERROR;
11192         }
11193         else
11194         {
11195                 point = key->getByteStringValue(CKA_VALUE);
11196                 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
11197         }
11198
11199         publicKey->setQ(point);
11200         publicKey->setEC(param);
11201
11202         return CKR_OK;
11203 }
11204
11205 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
11206 {
11207         if (skey == NULL) return CKR_ARGUMENTS_BAD;
11208         if (token == NULL) return CKR_ARGUMENTS_BAD;
11209         if (key == NULL) return CKR_ARGUMENTS_BAD;
11210
11211         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
11212         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
11213
11214         ByteString keybits;
11215         if (isKeyPrivate)
11216         {
11217                 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
11218                         return CKR_GENERAL_ERROR;
11219         }
11220         else
11221         {
11222                 keybits = key->getByteStringValue(CKA_VALUE);
11223         }
11224
11225         skey->setKeyBits(keybits);
11226
11227         return CKR_OK;
11228 }
11229
11230 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11231 {
11232         AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
11233         if (rsa == NULL)
11234                 return false;
11235         PrivateKey* priv = rsa->newPrivateKey();
11236         if (priv == NULL)
11237         {
11238                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11239                 return false;
11240         }
11241         if (!priv->PKCS8Decode(ber))
11242         {
11243                 rsa->recyclePrivateKey(priv);
11244                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11245                 return false;
11246         }
11247         // RSA Private Key Attributes
11248         ByteString modulus;
11249         ByteString publicExponent;
11250         ByteString privateExponent;
11251         ByteString prime1;
11252         ByteString prime2;
11253         ByteString exponent1;
11254         ByteString exponent2;
11255         ByteString coefficient;
11256         if (isPrivate)
11257         {
11258                 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
11259                 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
11260                 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
11261                 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
11262                 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
11263                 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
11264                 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
11265                 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
11266         }
11267         else
11268         {
11269                 modulus = ((RSAPrivateKey*)priv)->getN();
11270                 publicExponent = ((RSAPrivateKey*)priv)->getE();
11271                 privateExponent = ((RSAPrivateKey*)priv)->getD();
11272                 prime1 = ((RSAPrivateKey*)priv)->getP();
11273                 prime2 = ((RSAPrivateKey*)priv)->getQ();
11274                 exponent1 =  ((RSAPrivateKey*)priv)->getDP1();
11275                 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
11276                 coefficient = ((RSAPrivateKey*)priv)->getPQ();
11277         }
11278         bool bOK = true;
11279         bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
11280         bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
11281         bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
11282         bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
11283         bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
11284         bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
11285         bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
11286         bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
11287
11288         rsa->recyclePrivateKey(priv);
11289         CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
11290
11291         return bOK;
11292 }
11293
11294 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11295 {
11296         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
11297         if (dsa == NULL)
11298                 return false;
11299         PrivateKey* priv = dsa->newPrivateKey();
11300         if (priv == NULL)
11301         {
11302                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11303                 return false;
11304         }
11305         if (!priv->PKCS8Decode(ber))
11306         {
11307                 dsa->recyclePrivateKey(priv);
11308                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11309                 return false;
11310         }
11311         // DSA Private Key Attributes
11312         ByteString prime;
11313         ByteString subprime;
11314         ByteString generator;
11315         ByteString value;
11316         if (isPrivate)
11317         {
11318                 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11319                 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11320                 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11321                 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11322         }
11323         else
11324         {
11325                 prime = ((DSAPrivateKey*)priv)->getP();
11326                 subprime = ((DSAPrivateKey*)priv)->getQ();
11327                 generator = ((DSAPrivateKey*)priv)->getG();
11328                 value = ((DSAPrivateKey*)priv)->getX();
11329         }
11330         bool bOK = true;
11331         bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11332         bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11333         bOK = bOK && key->setAttribute(CKA_BASE, generator);
11334         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11335
11336         dsa->recyclePrivateKey(priv);
11337         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11338
11339         return bOK;
11340 }
11341
11342 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11343 {
11344         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11345         if (dh == NULL)
11346                 return false;
11347         PrivateKey* priv = dh->newPrivateKey();
11348         if (priv == NULL)
11349         {
11350                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11351                 return false;
11352         }
11353         if (!priv->PKCS8Decode(ber))
11354         {
11355                 dh->recyclePrivateKey(priv);
11356                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11357                 return false;
11358         }
11359         // DH Private Key Attributes
11360         ByteString prime;
11361         ByteString generator;
11362         ByteString value;
11363         if (isPrivate)
11364         {
11365                 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11366                 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11367                 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11368         }
11369         else
11370         {
11371                 prime = ((DHPrivateKey*)priv)->getP();
11372                 generator = ((DHPrivateKey*)priv)->getG();
11373                 value = ((DHPrivateKey*)priv)->getX();
11374         }
11375         bool bOK = true;
11376         bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11377         bOK = bOK && key->setAttribute(CKA_BASE, generator);
11378         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11379
11380         dh->recyclePrivateKey(priv);
11381         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11382
11383         return bOK;
11384 }
11385
11386 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11387 {
11388         AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11389         if (ecc == NULL)
11390                 return false;
11391         PrivateKey* priv = ecc->newPrivateKey();
11392         if (priv == NULL)
11393         {
11394                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11395                 return false;
11396         }
11397         if (!priv->PKCS8Decode(ber))
11398         {
11399                 ecc->recyclePrivateKey(priv);
11400                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11401                 return false;
11402         }
11403         // EC Private Key Attributes
11404         ByteString group;
11405         ByteString value;
11406         if (isPrivate)
11407         {
11408                 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11409                 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11410         }
11411         else
11412         {
11413                 group = ((ECPrivateKey*)priv)->getEC();
11414                 value = ((ECPrivateKey*)priv)->getD();
11415         }
11416         bool bOK = true;
11417         bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11418         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11419
11420         ecc->recyclePrivateKey(priv);
11421         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11422
11423         return bOK;
11424 }
11425
11426 bool SoftHSM::setGOSTPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11427 {
11428         AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
11429         if (gost == NULL)
11430                 return false;
11431         PrivateKey* priv = gost->newPrivateKey();
11432         if (priv == NULL)
11433         {
11434                 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11435                 return false;
11436         }
11437         if (!priv->PKCS8Decode(ber))
11438         {
11439                 gost->recyclePrivateKey(priv);
11440                 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11441                 return false;
11442         }
11443         // GOST Private Key Attributes
11444         ByteString value;
11445         ByteString param_a;
11446         if (isPrivate)
11447         {
11448                 token->encrypt(((GOSTPrivateKey*)priv)->getD(), value);
11449                 token->encrypt(((GOSTPrivateKey*)priv)->getEC(), param_a);
11450         }
11451         else
11452         {
11453                 value = ((GOSTPrivateKey*)priv)->getD();
11454                 param_a = ((GOSTPrivateKey*)priv)->getEC();
11455         }
11456         bool bOK = true;
11457         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11458         bOK = bOK && key->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
11459
11460         gost->recyclePrivateKey(priv);
11461         CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
11462
11463         return bOK;
11464 }
11465
11466 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11467 {
11468         // This is a programming error
11469         if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11470                 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11471                 return CKR_GENERAL_ERROR;
11472         }
11473
11474         if (pMechanism->pParameter == NULL_PTR ||
11475             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11476         {
11477                 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11478                 return CKR_ARGUMENTS_BAD;
11479         }
11480
11481         CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11482         if (params->hashAlg != CKM_SHA_1)
11483         {
11484                 ERROR_MSG("hashAlg must be CKM_SHA_1");
11485                 return CKR_ARGUMENTS_BAD;
11486         }
11487         if (params->mgf != CKG_MGF1_SHA1)
11488         {
11489                 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11490                 return CKR_ARGUMENTS_BAD;
11491         }
11492         if (params->source != CKZ_DATA_SPECIFIED)
11493         {
11494                 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11495                 return CKR_ARGUMENTS_BAD;
11496         }
11497         if (params->pSourceData != NULL)
11498         {
11499                 ERROR_MSG("pSourceData must be NULL");
11500                 return CKR_ARGUMENTS_BAD;
11501         }
11502         if (params->ulSourceDataLen != 0)
11503         {
11504                 ERROR_MSG("ulSourceDataLen must be 0");
11505                 return CKR_ARGUMENTS_BAD;
11506         }
11507         return CKR_OK;
11508 }
11509
11510 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11511         OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11512         std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11513         if (allowed.empty()) {
11514                 return true;
11515         }
11516
11517         return allowed.find(pMechanism->mechanism) != allowed.end();
11518 }