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