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