b06efc2c46dd5924540858d35b373ae89f145ff3
[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                         default:
6135                                 return CKR_KEY_NOT_WRAPPABLE;
6136                 }
6137                 AsymmetricAlgorithm* asymCrypto = NULL;
6138                 PrivateKey* privateKey = NULL;
6139                 asymCrypto = CryptoFactory::i()->getAsymmetricAlgorithm(alg);
6140                 if (asymCrypto == NULL)
6141                         return CKR_GENERAL_ERROR;
6142                 privateKey = asymCrypto->newPrivateKey();
6143                 if (privateKey == NULL)
6144                 {
6145                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6146                         return CKR_HOST_MEMORY;
6147                 }
6148                 switch (keyType) {
6149                         case CKK_RSA:
6150                                 rv = getRSAPrivateKey((RSAPrivateKey*)privateKey, token, key);
6151                                 break;
6152                         case CKK_DSA:
6153                                 rv = getDSAPrivateKey((DSAPrivateKey*)privateKey, token, key);
6154                                 break;
6155                         case CKK_DH:
6156                                 rv = getDHPrivateKey((DHPrivateKey*)privateKey, token, key);
6157                                 break;
6158 #ifdef WITH_ECC
6159                         case CKK_EC:
6160                                 rv = getECPrivateKey((ECPrivateKey*)privateKey, token, key);
6161                                 break;
6162 #endif
6163                 }
6164                 if (rv != CKR_OK)
6165                 {
6166                         asymCrypto->recyclePrivateKey(privateKey);
6167                         CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6168                         return CKR_GENERAL_ERROR;
6169                 }
6170                 keydata = privateKey->PKCS8Encode();
6171                 asymCrypto->recyclePrivateKey(privateKey);
6172                 CryptoFactory::i()->recycleAsymmetricAlgorithm(asymCrypto);
6173         }
6174         if (keydata.size() == 0)
6175                 return CKR_KEY_NOT_WRAPPABLE;
6176
6177         keyClass = wrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED);
6178         ByteString wrapped;
6179         if (keyClass == CKO_SECRET_KEY)
6180                 rv = SoftHSM::WrapKeySym(pMechanism, token, wrapKey, keydata, wrapped);
6181         else
6182                 rv = SoftHSM::WrapKeyAsym(pMechanism, token, wrapKey, keydata, wrapped);
6183         if (rv != CKR_OK)
6184                 return rv;
6185
6186         if (pWrappedKey != NULL) {
6187                 if (*pulWrappedKeyLen >= wrapped.size())
6188                         memcpy(pWrappedKey, wrapped.byte_str(), wrapped.size());
6189                 else
6190                         rv = CKR_BUFFER_TOO_SMALL;
6191         }
6192
6193         *pulWrappedKeyLen = wrapped.size();
6194         return rv;
6195 }
6196
6197 // Internal: Unwrap blob using symmetric key
6198 CK_RV SoftHSM::UnwrapKeySym
6199 (
6200         CK_MECHANISM_PTR pMechanism,
6201         ByteString& wrapped,
6202         Token* token,
6203         OSObject* unwrapKey,
6204         ByteString& keydata
6205 )
6206 {
6207         // Get the symmetric algorithm matching the mechanism
6208         SymAlgo::Type algo = SymAlgo::Unknown;
6209         SymWrap::Type mode = SymWrap::Unknown;
6210         size_t bb = 8;
6211         switch(pMechanism->mechanism) {
6212 #ifdef HAVE_AES_KEY_WRAP
6213                 case CKM_AES_KEY_WRAP:
6214                         algo = SymAlgo::AES;
6215                         mode = SymWrap::AES_KEYWRAP;
6216                         break;
6217 #endif
6218 #ifdef HAVE_AES_KEY_WRAP_PAD
6219                 case CKM_AES_KEY_WRAP_PAD:
6220                         algo = SymAlgo::AES;
6221                         mode = SymWrap::AES_KEYWRAP_PAD;
6222                         break;
6223 #endif
6224                 default:
6225                         return CKR_MECHANISM_INVALID;
6226         }
6227         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
6228         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6229
6230         SymmetricKey* unwrappingkey = new SymmetricKey();
6231
6232         if (getSymmetricKey(unwrappingkey, token, unwrapKey) != CKR_OK)
6233         {
6234                 cipher->recycleKey(unwrappingkey);
6235                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6236                 return CKR_GENERAL_ERROR;
6237         }
6238
6239         // adjust key bit length
6240         unwrappingkey->setBitLen(unwrappingkey->getKeyBits().size() * bb);
6241
6242         // Unwrap the key
6243         CK_RV rv = CKR_OK;
6244         if (!cipher->unwrapKey(unwrappingkey, mode, wrapped, keydata))
6245                 rv = CKR_GENERAL_ERROR;
6246         cipher->recycleKey(unwrappingkey);
6247         CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
6248         return rv;
6249 }
6250
6251 // Internal: Unwrap blob using asymmetric key
6252 CK_RV SoftHSM::UnwrapKeyAsym
6253 (
6254         CK_MECHANISM_PTR pMechanism,
6255         ByteString& wrapped,
6256         Token* token,
6257         OSObject* unwrapKey,
6258         ByteString& keydata
6259 )
6260 {
6261         // Get the symmetric algorithm matching the mechanism
6262         AsymAlgo::Type algo = AsymAlgo::Unknown;
6263         AsymMech::Type mode = AsymMech::Unknown;
6264         switch(pMechanism->mechanism) {
6265                 case CKM_RSA_PKCS:
6266                         algo = AsymAlgo::RSA;
6267                         mode = AsymMech::RSA_PKCS;
6268                         break;
6269
6270                 case CKM_RSA_PKCS_OAEP:
6271                         algo = AsymAlgo::RSA;
6272                         mode = AsymMech::RSA_PKCS_OAEP;
6273                         break;
6274
6275                 default:
6276                         return CKR_MECHANISM_INVALID;
6277         }
6278         AsymmetricAlgorithm* cipher = CryptoFactory::i()->getAsymmetricAlgorithm(algo);
6279         if (cipher == NULL) return CKR_MECHANISM_INVALID;
6280
6281         PrivateKey* unwrappingkey = cipher->newPrivateKey();
6282         if (unwrappingkey == NULL)
6283         {
6284                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6285                 return CKR_HOST_MEMORY;
6286         }
6287
6288         switch(pMechanism->mechanism) {
6289                 case CKM_RSA_PKCS:
6290                 case CKM_RSA_PKCS_OAEP:
6291                         if (getRSAPrivateKey((RSAPrivateKey*)unwrappingkey, token, unwrapKey) != CKR_OK)
6292                         {
6293                                 cipher->recyclePrivateKey(unwrappingkey);
6294                                 CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6295                                 return CKR_GENERAL_ERROR;
6296                         }
6297                         break;
6298
6299                 default:
6300                         return CKR_MECHANISM_INVALID;
6301         }
6302
6303         // Unwrap the key
6304         CK_RV rv = CKR_OK;
6305         if (!cipher->unwrapKey(unwrappingkey, wrapped, keydata, mode))
6306                 rv = CKR_GENERAL_ERROR;
6307         cipher->recyclePrivateKey(unwrappingkey);
6308         CryptoFactory::i()->recycleAsymmetricAlgorithm(cipher);
6309         return rv;
6310 }
6311
6312 // Unwrap the specified key using the specified unwrapping key
6313 CK_RV SoftHSM::C_UnwrapKey
6314 (
6315         CK_SESSION_HANDLE hSession,
6316         CK_MECHANISM_PTR pMechanism,
6317         CK_OBJECT_HANDLE hUnwrappingKey,
6318         CK_BYTE_PTR pWrappedKey,
6319         CK_ULONG ulWrappedKeyLen,
6320         CK_ATTRIBUTE_PTR pTemplate,
6321         CK_ULONG ulCount,
6322         CK_OBJECT_HANDLE_PTR hKey
6323 )
6324 {
6325         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6326
6327         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6328         if (pWrappedKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6329         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6330         if (hKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6331
6332         // Get the session
6333         Session* session = (Session*)handleManager->getSession(hSession);
6334         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6335
6336         CK_RV rv;
6337         // Check the mechanism
6338         switch(pMechanism->mechanism)
6339         {
6340 #ifdef HAVE_AES_KEY_WRAP
6341                 case CKM_AES_KEY_WRAP:
6342                         if ((ulWrappedKeyLen < 24) || ((ulWrappedKeyLen % 8) != 0))
6343                                 return CKR_WRAPPED_KEY_LEN_RANGE;
6344                         // Does not handle optional init vector
6345                         if (pMechanism->pParameter != NULL_PTR ||
6346                             pMechanism->ulParameterLen != 0)
6347                                 return CKR_ARGUMENTS_BAD;
6348                         break;
6349 #endif
6350 #ifdef HAVE_AES_KEY_WRAP_PAD
6351                 case CKM_AES_KEY_WRAP_PAD:
6352                         if ((ulWrappedKeyLen < 16) || ((ulWrappedKeyLen % 8) != 0))
6353                                 return CKR_WRAPPED_KEY_LEN_RANGE;
6354                         // Does not handle optional init vector
6355                         if (pMechanism->pParameter != NULL_PTR ||
6356                             pMechanism->ulParameterLen != 0)
6357                                 return CKR_ARGUMENTS_BAD;
6358                         break;
6359 #endif
6360                 case CKM_RSA_PKCS:
6361                         // Input length checks needs to be done later when unwrapping key is known
6362                         break;
6363                 case CKM_RSA_PKCS_OAEP:
6364                         rv = MechParamCheckRSAPKCSOAEP(pMechanism);
6365                         if (rv != CKR_OK)
6366                                 return rv;
6367                         break;
6368
6369                 default:
6370                         return CKR_MECHANISM_INVALID;
6371         }
6372
6373         // Get the token
6374         Token* token = session->getToken();
6375         if (token == NULL) return CKR_GENERAL_ERROR;
6376
6377         // Check the unwrapping key handle.
6378         OSObject *unwrapKey = (OSObject *)handleManager->getObject(hUnwrappingKey);
6379         if (unwrapKey == NULL_PTR || !unwrapKey->isValid()) return CKR_UNWRAPPING_KEY_HANDLE_INVALID;
6380
6381         CK_BBOOL isUnwrapKeyOnToken = unwrapKey->getBooleanValue(CKA_TOKEN, false);
6382         CK_BBOOL isUnwrapKeyPrivate = unwrapKey->getBooleanValue(CKA_PRIVATE, true);
6383
6384         // Check user credentials
6385         rv = haveRead(session->getState(), isUnwrapKeyOnToken, isUnwrapKeyPrivate);
6386         if (rv != CKR_OK)
6387         {
6388                 if (rv == CKR_USER_NOT_LOGGED_IN)
6389                         INFO_MSG("User is not authorized");
6390
6391                 return rv;
6392         }
6393
6394         // Check unwrapping key class and type
6395         if ((pMechanism->mechanism == CKM_AES_KEY_WRAP || pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6396                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6397         if (pMechanism->mechanism == CKM_AES_KEY_WRAP && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6398                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6399         if (pMechanism->mechanism == CKM_AES_KEY_WRAP_PAD && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_AES)
6400                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6401         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6402                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6403         if ((pMechanism->mechanism == CKM_RSA_PKCS || pMechanism->mechanism == CKM_RSA_PKCS_OAEP) && unwrapKey->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_RSA)
6404                 return CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6405
6406         // Check if the unwrapping key can be used for unwrapping
6407         if (unwrapKey->getBooleanValue(CKA_UNWRAP, false) == false)
6408                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6409
6410         // Check if the specified mechanism is allowed for the unwrap key
6411         if (!isMechanismPermitted(unwrapKey, pMechanism))
6412                 return CKR_MECHANISM_INVALID;
6413
6414         // Extract information from the template that is needed to create the object.
6415         CK_OBJECT_CLASS objClass;
6416         CK_KEY_TYPE keyType;
6417         CK_BBOOL isOnToken = CK_FALSE;
6418         CK_BBOOL isPrivate = CK_TRUE;
6419         CK_CERTIFICATE_TYPE dummy;
6420         bool isImplicit = false;
6421         rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6422         if (rv != CKR_OK)
6423         {
6424                 ERROR_MSG("Mandatory attribute not present in template");
6425                 return rv;
6426         }
6427
6428         // Report errors and/or unexpected usage.
6429         if (objClass != CKO_SECRET_KEY && objClass != CKO_PRIVATE_KEY)
6430                 return CKR_ATTRIBUTE_VALUE_INVALID;
6431         // Key type will be handled at object creation
6432
6433         // Check authorization
6434         rv = haveWrite(session->getState(), isOnToken, isPrivate);
6435         if (rv != CKR_OK)
6436         {
6437                 if (rv == CKR_USER_NOT_LOGGED_IN)
6438                         INFO_MSG("User is not authorized");
6439                 if (rv == CKR_SESSION_READ_ONLY)
6440                         INFO_MSG("Session is read-only");
6441
6442                 return rv;
6443         }
6444
6445         // Build unwrapped key template
6446         const CK_ULONG maxAttribs = 32;
6447         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
6448                 { CKA_CLASS, &objClass, sizeof(objClass) },
6449                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6450                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6451                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) }
6452         };
6453         CK_ULONG secretAttribsCount = 4;
6454
6455         // Add the additional
6456         if (ulCount > (maxAttribs - secretAttribsCount))
6457                 return CKR_TEMPLATE_INCONSISTENT;
6458         for (CK_ULONG i = 0; i < ulCount; ++i)
6459         {
6460                 switch (pTemplate[i].type)
6461                 {
6462                         case CKA_CLASS:
6463                         case CKA_TOKEN:
6464                         case CKA_PRIVATE:
6465                         case CKA_KEY_TYPE:
6466                                 continue;
6467                         default:
6468                                 secretAttribs[secretAttribsCount++] = pTemplate[i];
6469                 }
6470         }
6471
6472         // Apply the unwrap template
6473         if (unwrapKey->attributeExists(CKA_UNWRAP_TEMPLATE))
6474         {
6475                 OSAttribute unwrapAttr = unwrapKey->getAttribute(CKA_UNWRAP_TEMPLATE);
6476
6477                 if (unwrapAttr.isAttributeMapAttribute())
6478                 {
6479                         typedef std::map<CK_ATTRIBUTE_TYPE,OSAttribute> attrmap_type;
6480
6481                         const attrmap_type& map = unwrapAttr.getAttributeMapValue();
6482
6483                         for (attrmap_type::const_iterator it = map.begin(); it != map.end(); ++it)
6484                         {
6485                                 CK_ATTRIBUTE* attr = NULL;
6486                                 for (CK_ULONG i = 0; i < secretAttribsCount; ++i)
6487                                 {
6488                                         if (it->first == secretAttribs[i].type)
6489                                         {
6490                                                 if (attr != NULL)
6491                                                 {
6492                                                         return CKR_TEMPLATE_INCONSISTENT;
6493                                                 }
6494                                                 attr = &secretAttribs[i];
6495                                                 ByteString value;
6496                                                 it->second.peekValue(value);
6497                                                 if (attr->ulValueLen != value.size())
6498                                                 {
6499                                                         return CKR_TEMPLATE_INCONSISTENT;
6500                                                 }
6501                                                 if (memcmp(attr->pValue, value.const_byte_str(), value.size()) != 0)
6502                                                 {
6503                                                         return CKR_TEMPLATE_INCONSISTENT;
6504                                                 }
6505                                         }
6506                                 }
6507                                 if (attr == NULL)
6508                                 {
6509                                         return CKR_TEMPLATE_INCONSISTENT;
6510                                 }
6511                         }
6512                 }
6513         }
6514
6515         *hKey = CK_INVALID_HANDLE;
6516
6517         // Unwrap the key
6518         ByteString wrapped(pWrappedKey, ulWrappedKeyLen);
6519         ByteString keydata;
6520         if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_SECRET_KEY)
6521                 rv = UnwrapKeySym(pMechanism, wrapped, token, unwrapKey, keydata);
6522         else if (unwrapKey->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) == CKO_PRIVATE_KEY)
6523                 rv = UnwrapKeyAsym(pMechanism, wrapped, token, unwrapKey, keydata);
6524         else
6525                 rv = CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT;
6526         if (rv != CKR_OK)
6527                 return rv;
6528
6529         // Create the secret object using C_CreateObject
6530         rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, hKey, OBJECT_OP_UNWRAP);
6531
6532         // Store the attributes that are being supplied
6533         if (rv == CKR_OK)
6534         {
6535                 OSObject* osobject = (OSObject*)handleManager->getObject(*hKey);
6536                 if (osobject == NULL_PTR || !osobject->isValid())
6537                         rv = CKR_FUNCTION_FAILED;
6538                 if (osobject->startTransaction())
6539                 {
6540                         bool bOK = true;
6541
6542                         // Common Attributes
6543                         bOK = bOK && osobject->setAttribute(CKA_LOCAL, false);
6544
6545                         // Common Secret Key Attributes
6546                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE, false);
6547                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, false);
6548
6549                         // Secret Attributes
6550                         if (objClass == CKO_SECRET_KEY)
6551                         {
6552                                 ByteString value;
6553                                 if (isPrivate)
6554                                         token->encrypt(keydata, value);
6555                                 else
6556                                         value = keydata;
6557                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
6558                         }
6559                         else if (keyType == CKK_RSA)
6560                         {
6561                                 bOK = bOK && setRSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6562                         }
6563                         else if (keyType == CKK_DSA)
6564                         {
6565                                 bOK = bOK && setDSAPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6566                         }
6567                         else if (keyType == CKK_DH)
6568                         {
6569                                 bOK = bOK && setDHPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6570                         }
6571                         else if (keyType == CKK_EC)
6572                         {
6573                                 bOK = bOK && setECPrivateKey(osobject, keydata, token, isPrivate != CK_FALSE);
6574                         }
6575                         else
6576                                 bOK = false;
6577
6578                         if (bOK)
6579                                 bOK = osobject->commitTransaction();
6580                         else
6581                                 osobject->abortTransaction();
6582
6583                         if (!bOK)
6584                                 rv = CKR_FUNCTION_FAILED;
6585                 }
6586                 else
6587                         rv = CKR_FUNCTION_FAILED;
6588         }
6589
6590         // Remove secret that may have been created already when the function fails.
6591         if (rv != CKR_OK)
6592         {
6593                 if (*hKey != CK_INVALID_HANDLE)
6594                 {
6595                         OSObject* obj = (OSObject*)handleManager->getObject(*hKey);
6596                         handleManager->destroyObject(*hKey);
6597                         if (obj) obj->destroyObject();
6598                         *hKey = CK_INVALID_HANDLE;
6599                 }
6600
6601         }
6602
6603         return rv;
6604 }
6605
6606 // Derive a key from the specified base key
6607 CK_RV SoftHSM::C_DeriveKey
6608 (
6609         CK_SESSION_HANDLE hSession,
6610         CK_MECHANISM_PTR pMechanism,
6611         CK_OBJECT_HANDLE hBaseKey,
6612         CK_ATTRIBUTE_PTR pTemplate,
6613         CK_ULONG ulCount,
6614         CK_OBJECT_HANDLE_PTR phKey
6615 )
6616 {
6617         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6618
6619         if (pMechanism == NULL_PTR) return CKR_ARGUMENTS_BAD;
6620         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
6621         if (phKey == NULL_PTR) return CKR_ARGUMENTS_BAD;
6622
6623         // Get the session
6624         Session* session = (Session*)handleManager->getSession(hSession);
6625         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6626
6627         // Check the mechanism, only accept DH and ECDH derive
6628         switch (pMechanism->mechanism)
6629         {
6630                 case CKM_DH_PKCS_DERIVE:
6631 #ifdef WITH_ECC
6632                 case CKM_ECDH1_DERIVE:
6633 #endif
6634 #ifndef WITH_FIPS
6635                 case CKM_DES_ECB_ENCRYPT_DATA:
6636                 case CKM_DES_CBC_ENCRYPT_DATA:
6637 #endif
6638                 case CKM_DES3_ECB_ENCRYPT_DATA:
6639                 case CKM_DES3_CBC_ENCRYPT_DATA:
6640                 case CKM_AES_ECB_ENCRYPT_DATA:
6641                 case CKM_AES_CBC_ENCRYPT_DATA:
6642                         break;
6643                 default:
6644                         ERROR_MSG("Invalid mechanism");
6645                         return CKR_MECHANISM_INVALID;
6646         }
6647
6648         // Get the token
6649         Token* token = session->getToken();
6650         if (token == NULL) return CKR_GENERAL_ERROR;
6651
6652         // Check the key handle.
6653         OSObject *key = (OSObject *)handleManager->getObject(hBaseKey);
6654         if (key == NULL_PTR || !key->isValid()) return CKR_OBJECT_HANDLE_INVALID;
6655
6656         CK_BBOOL isKeyOnToken = key->getBooleanValue(CKA_TOKEN, false);
6657         CK_BBOOL isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, true);
6658
6659         // Check user credentials
6660         CK_RV rv = haveRead(session->getState(), isKeyOnToken, isKeyPrivate);
6661         if (rv != CKR_OK)
6662         {
6663                 if (rv == CKR_USER_NOT_LOGGED_IN)
6664                         INFO_MSG("User is not authorized");
6665
6666                 return rv;
6667         }
6668
6669         // Check if key can be used for derive
6670         if (!key->getBooleanValue(CKA_DERIVE, false))
6671                 return CKR_KEY_FUNCTION_NOT_PERMITTED;
6672
6673         // Check if the specified mechanism is allowed for the key
6674         if (!isMechanismPermitted(key, pMechanism))
6675                 return CKR_MECHANISM_INVALID;
6676
6677         // Extract information from the template that is needed to create the object.
6678         CK_OBJECT_CLASS objClass;
6679         CK_KEY_TYPE keyType;
6680         CK_BBOOL isOnToken = CK_FALSE;
6681         CK_BBOOL isPrivate = CK_TRUE;
6682         CK_CERTIFICATE_TYPE dummy;
6683         bool isImplicit = false;
6684         rv = extractObjectInformation(pTemplate, ulCount, objClass, keyType, dummy, isOnToken, isPrivate, isImplicit);
6685         if (rv != CKR_OK)
6686         {
6687                 ERROR_MSG("Mandatory attribute not present in template");
6688                 return rv;
6689         }
6690
6691         // Report errors and/or unexpected usage.
6692         if (objClass != CKO_SECRET_KEY)
6693                 return CKR_ATTRIBUTE_VALUE_INVALID;
6694         if (keyType != CKK_GENERIC_SECRET &&
6695             keyType != CKK_DES &&
6696             keyType != CKK_DES2 &&
6697             keyType != CKK_DES3 &&
6698             keyType != CKK_AES)
6699                 return CKR_TEMPLATE_INCONSISTENT;
6700
6701         // Check authorization
6702         rv = haveWrite(session->getState(), isOnToken, isPrivate);
6703         if (rv != CKR_OK)
6704         {
6705                 if (rv == CKR_USER_NOT_LOGGED_IN)
6706                         INFO_MSG("User is not authorized");
6707                 if (rv == CKR_SESSION_READ_ONLY)
6708                         INFO_MSG("Session is read-only");
6709
6710                 return rv;
6711         }
6712
6713         // Derive DH secret
6714         if (pMechanism->mechanism == CKM_DH_PKCS_DERIVE)
6715         {
6716                 // Check key class and type
6717                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6718                         return CKR_KEY_TYPE_INCONSISTENT;
6719                 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_DH)
6720                         return CKR_KEY_TYPE_INCONSISTENT;
6721
6722                 return this->deriveDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6723         }
6724
6725 #ifdef WITH_ECC
6726         // Derive ECDH secret
6727         if (pMechanism->mechanism == CKM_ECDH1_DERIVE)
6728         {
6729                 // Check key class and type
6730                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_PRIVATE_KEY)
6731                         return CKR_KEY_TYPE_INCONSISTENT;
6732                 if (key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED) != CKK_EC)
6733                         return CKR_KEY_TYPE_INCONSISTENT;
6734
6735                 return this->deriveECDH(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6736         }
6737 #endif
6738
6739         // Derive symmetric secret
6740         if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
6741             pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
6742             pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA ||
6743             pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA ||
6744             pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA ||
6745             pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA)
6746         {
6747                 // Check key class and type
6748                 CK_KEY_TYPE baseKeyType = key->getUnsignedLongValue(CKA_KEY_TYPE, CKK_VENDOR_DEFINED);
6749                 if (key->getUnsignedLongValue(CKA_CLASS, CKO_VENDOR_DEFINED) != CKO_SECRET_KEY)
6750                         return CKR_KEY_TYPE_INCONSISTENT;
6751                 if (pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA &&
6752                     baseKeyType != CKK_DES)
6753                         return CKR_KEY_TYPE_INCONSISTENT;
6754                 if (pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA &&
6755                     baseKeyType != CKK_DES)
6756                         return CKR_KEY_TYPE_INCONSISTENT;
6757                 if (pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA &&
6758                     baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6759                         return CKR_KEY_TYPE_INCONSISTENT;
6760                 if (pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA &&
6761                     baseKeyType != CKK_DES2 && baseKeyType != CKK_DES3)
6762                         return CKR_KEY_TYPE_INCONSISTENT;
6763                 if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
6764                     baseKeyType != CKK_AES)
6765                         return CKR_KEY_TYPE_INCONSISTENT;
6766                 if (pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA &&
6767                     baseKeyType != CKK_AES)
6768                         return CKR_KEY_TYPE_INCONSISTENT;
6769
6770                 return this->deriveSymmetric(hSession, pMechanism, hBaseKey, pTemplate, ulCount, phKey, keyType, isOnToken, isPrivate);
6771         }
6772
6773         return CKR_MECHANISM_INVALID;
6774 }
6775
6776 // Seed the random number generator with new data
6777 CK_RV SoftHSM::C_SeedRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen)
6778 {
6779         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6780
6781         if (pSeed == NULL_PTR) return CKR_ARGUMENTS_BAD;
6782
6783         // Get the session
6784         Session* session = (Session*)handleManager->getSession(hSession);
6785         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6786
6787         // Get the RNG
6788         RNG* rng = CryptoFactory::i()->getRNG();
6789         if (rng == NULL) return CKR_GENERAL_ERROR;
6790
6791         // Seed the RNG
6792         ByteString seed(pSeed, ulSeedLen);
6793         rng->seed(seed);
6794
6795         return CKR_OK;
6796 }
6797
6798 // Generate the specified amount of random data
6799 CK_RV SoftHSM::C_GenerateRandom(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pRandomData, CK_ULONG ulRandomLen)
6800 {
6801         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6802
6803         if (pRandomData == NULL_PTR) return CKR_ARGUMENTS_BAD;
6804
6805         // Get the session
6806         Session* session = (Session*)handleManager->getSession(hSession);
6807         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6808
6809         // Get the RNG
6810         RNG* rng = CryptoFactory::i()->getRNG();
6811         if (rng == NULL) return CKR_GENERAL_ERROR;
6812
6813         // Generate random data
6814         ByteString randomData;
6815         if (!rng->generateRandom(randomData, ulRandomLen)) return CKR_GENERAL_ERROR;
6816
6817         // Return random data
6818         if (ulRandomLen != 0)
6819         {
6820                 memcpy(pRandomData, randomData.byte_str(), ulRandomLen);
6821         }
6822
6823         return CKR_OK;
6824 }
6825
6826 // Legacy function
6827 CK_RV SoftHSM::C_GetFunctionStatus(CK_SESSION_HANDLE hSession)
6828 {
6829         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6830
6831         // Get the session
6832         Session* session = (Session*)handleManager->getSession(hSession);
6833         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6834
6835         return CKR_FUNCTION_NOT_PARALLEL;
6836 }
6837
6838 // Legacy function
6839 CK_RV SoftHSM::C_CancelFunction(CK_SESSION_HANDLE hSession)
6840 {
6841         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
6842
6843         // Get the session
6844         Session* session = (Session*)handleManager->getSession(hSession);
6845         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
6846
6847         return CKR_FUNCTION_NOT_PARALLEL;
6848 }
6849
6850 // Wait or poll for a slot event on the specified slot
6851 CK_RV SoftHSM::C_WaitForSlotEvent(CK_FLAGS /*flags*/, CK_SLOT_ID_PTR /*pSlot*/, CK_VOID_PTR /*pReserved*/)
6852 {
6853         return CKR_FUNCTION_NOT_SUPPORTED;
6854 }
6855
6856 // Generate an AES secret key
6857 CK_RV SoftHSM::generateAES
6858 (CK_SESSION_HANDLE hSession,
6859         CK_ATTRIBUTE_PTR pTemplate,
6860         CK_ULONG ulCount,
6861         CK_OBJECT_HANDLE_PTR phKey,
6862         CK_BBOOL isOnToken,
6863         CK_BBOOL isPrivate)
6864 {
6865         *phKey = CK_INVALID_HANDLE;
6866
6867         // Get the session
6868         Session* session = (Session*)handleManager->getSession(hSession);
6869         if (session == NULL)
6870                 return CKR_SESSION_HANDLE_INVALID;
6871
6872         // Get the token
6873         Token* token = session->getToken();
6874         if (token == NULL)
6875                 return CKR_GENERAL_ERROR;
6876
6877         // Extract desired parameter information
6878         size_t keyLen = 0;
6879         bool checkValue = true;
6880         for (CK_ULONG i = 0; i < ulCount; i++)
6881         {
6882                 switch (pTemplate[i].type)
6883                 {
6884                         case CKA_VALUE_LEN:
6885                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
6886                                 {
6887                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
6888                                         return CKR_ATTRIBUTE_VALUE_INVALID;
6889                                 }
6890                                 keyLen = *(CK_ULONG*)pTemplate[i].pValue;
6891                                 break;
6892                         case CKA_CHECK_VALUE:
6893                                 if (pTemplate[i].ulValueLen > 0)
6894                                 {
6895                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
6896                                         return CKR_ATTRIBUTE_VALUE_INVALID;
6897                                 }
6898                                 checkValue = false;
6899                                 break;
6900                         default:
6901                                 break;
6902                 }
6903         }
6904
6905         // CKA_VALUE_LEN must be specified
6906         if (keyLen == 0)
6907         {
6908                 INFO_MSG("Missing CKA_VALUE_LEN in pTemplate");
6909                 return CKR_TEMPLATE_INCOMPLETE;
6910         }
6911
6912         // keyLen must be 16, 24, or 32
6913         if (keyLen != 16 && keyLen != 24 && keyLen != 32)
6914         {
6915                 INFO_MSG("bad AES key length");
6916                 return CKR_ATTRIBUTE_VALUE_INVALID;
6917         }
6918
6919         // Generate the secret key
6920         AESKey* key = new AESKey(keyLen * 8);
6921         SymmetricAlgorithm* aes = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::AES);
6922         if (aes == NULL)
6923         {
6924                 ERROR_MSG("Could not get SymmetricAlgorithm");
6925                 delete key;
6926                 return CKR_GENERAL_ERROR;
6927         }
6928         RNG* rng = CryptoFactory::i()->getRNG();
6929         if (rng == NULL)
6930         {
6931                 ERROR_MSG("Could not get RNG");
6932                 aes->recycleKey(key);
6933                 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6934                 return CKR_GENERAL_ERROR;
6935         }
6936         if (!aes->generateKey(*key, rng))
6937         {
6938                 ERROR_MSG("Could not generate AES secret key");
6939                 aes->recycleKey(key);
6940                 CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
6941                 return CKR_GENERAL_ERROR;
6942         }
6943
6944         CK_RV rv = CKR_OK;
6945
6946         // Create the secret key object using C_CreateObject
6947         const CK_ULONG maxAttribs = 32;
6948         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
6949         CK_KEY_TYPE keyType = CKK_AES;
6950         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
6951                 { CKA_CLASS, &objClass, sizeof(objClass) },
6952                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
6953                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
6954                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
6955         };
6956         CK_ULONG keyAttribsCount = 4;
6957
6958         // Add the additional
6959         if (ulCount > (maxAttribs - keyAttribsCount))
6960                 rv = CKR_TEMPLATE_INCONSISTENT;
6961         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
6962         {
6963                 switch (pTemplate[i].type)
6964                 {
6965                         case CKA_CLASS:
6966                         case CKA_TOKEN:
6967                         case CKA_PRIVATE:
6968                         case CKA_KEY_TYPE:
6969                         case CKA_CHECK_VALUE:
6970                                 continue;
6971                 default:
6972                         keyAttribs[keyAttribsCount++] = pTemplate[i];
6973                 }
6974         }
6975
6976         if (rv == CKR_OK)
6977                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
6978
6979         // Store the attributes that are being supplied
6980         if (rv == CKR_OK)
6981         {
6982                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
6983                 if (osobject == NULL_PTR || !osobject->isValid()) {
6984                         rv = CKR_FUNCTION_FAILED;
6985                 } else if (osobject->startTransaction()) {
6986                         bool bOK = true;
6987
6988                         // Common Attributes
6989                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
6990                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_AES_KEY_GEN;
6991                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
6992
6993                         // Common Secret Key Attributes
6994                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
6995                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
6996                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
6997                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
6998
6999                         // AES Secret Key Attributes
7000                         ByteString value;
7001                         ByteString kcv;
7002                         if (isPrivate)
7003                         {
7004                                 token->encrypt(key->getKeyBits(), value);
7005                                 token->encrypt(key->getKeyCheckValue(), kcv);
7006                         }
7007                         else
7008                         {
7009                                 value = key->getKeyBits();
7010                                 kcv = key->getKeyCheckValue();
7011                         }
7012                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7013                         if (checkValue)
7014                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7015
7016                         if (bOK)
7017                                 bOK = osobject->commitTransaction();
7018                         else
7019                                 osobject->abortTransaction();
7020
7021                         if (!bOK)
7022                                 rv = CKR_FUNCTION_FAILED;
7023                 } else
7024                         rv = CKR_FUNCTION_FAILED;
7025         }
7026
7027         // Clean up
7028         aes->recycleKey(key);
7029         CryptoFactory::i()->recycleSymmetricAlgorithm(aes);
7030
7031         // Remove the key that may have been created already when the function fails.
7032         if (rv != CKR_OK)
7033         {
7034                 if (*phKey != CK_INVALID_HANDLE)
7035                 {
7036                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7037                         handleManager->destroyObject(*phKey);
7038                         if (oskey) oskey->destroyObject();
7039                         *phKey = CK_INVALID_HANDLE;
7040                 }
7041         }
7042
7043         return rv;
7044 }
7045
7046 // Generate a DES secret key
7047 CK_RV SoftHSM::generateDES
7048 (CK_SESSION_HANDLE hSession,
7049         CK_ATTRIBUTE_PTR pTemplate,
7050         CK_ULONG ulCount,
7051         CK_OBJECT_HANDLE_PTR phKey,
7052         CK_BBOOL isOnToken,
7053         CK_BBOOL isPrivate)
7054 {
7055         *phKey = CK_INVALID_HANDLE;
7056
7057         // Get the session
7058         Session* session = (Session*)handleManager->getSession(hSession);
7059         if (session == NULL)
7060                 return CKR_SESSION_HANDLE_INVALID;
7061
7062         // Get the token
7063         Token* token = session->getToken();
7064         if (token == NULL)
7065                 return CKR_GENERAL_ERROR;
7066
7067         // Extract desired parameter information
7068         bool checkValue = true;
7069         for (CK_ULONG i = 0; i < ulCount; i++)
7070         {
7071                 switch (pTemplate[i].type)
7072                 {
7073                         case CKA_CHECK_VALUE:
7074                                 if (pTemplate[i].ulValueLen > 0)
7075                                 {
7076                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7077                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7078                                 }
7079                                 checkValue = false;
7080                                 break;
7081                         default:
7082                                 break;
7083                 }
7084         }
7085
7086         // Generate the secret key
7087         DESKey* key = new DESKey(56);
7088         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES);
7089         if (des == NULL)
7090         {
7091                 ERROR_MSG("Could not get SymmetricAlgorithm");
7092                 delete key;
7093                 return CKR_GENERAL_ERROR;
7094         }
7095         RNG* rng = CryptoFactory::i()->getRNG();
7096         if (rng == NULL)
7097         {
7098                 ERROR_MSG("Could not get RNG");
7099                 des->recycleKey(key);
7100                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7101                 return CKR_GENERAL_ERROR;
7102         }
7103         if (!des->generateKey(*key, rng))
7104         {
7105                 ERROR_MSG("Could not generate DES secret key");
7106                 des->recycleKey(key);
7107                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7108                 return CKR_GENERAL_ERROR;
7109         }
7110
7111         CK_RV rv = CKR_OK;
7112
7113         // Create the secret key object using C_CreateObject
7114         const CK_ULONG maxAttribs = 32;
7115         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7116         CK_KEY_TYPE keyType = CKK_DES;
7117         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7118                 { CKA_CLASS, &objClass, sizeof(objClass) },
7119                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7120                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7121                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7122         };
7123         CK_ULONG keyAttribsCount = 4;
7124
7125         // Add the additional
7126         if (ulCount > (maxAttribs - keyAttribsCount))
7127                 rv = CKR_TEMPLATE_INCONSISTENT;
7128         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7129         {
7130                 switch (pTemplate[i].type)
7131                 {
7132                         case CKA_CLASS:
7133                         case CKA_TOKEN:
7134                         case CKA_PRIVATE:
7135                         case CKA_KEY_TYPE:
7136                         case CKA_CHECK_VALUE:
7137                                 continue;
7138                 default:
7139                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7140                 }
7141         }
7142
7143         if (rv == CKR_OK)
7144                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7145
7146         // Store the attributes that are being supplied
7147         if (rv == CKR_OK)
7148         {
7149                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7150                 if (osobject == NULL_PTR || !osobject->isValid()) {
7151                         rv = CKR_FUNCTION_FAILED;
7152                 } else if (osobject->startTransaction()) {
7153                         bool bOK = true;
7154
7155                         // Common Attributes
7156                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7157                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES_KEY_GEN;
7158                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7159
7160                         // Common Secret Key Attributes
7161                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7162                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7163                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7164                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7165
7166                         // DES Secret Key Attributes
7167                         ByteString value;
7168                         ByteString kcv;
7169                         if (isPrivate)
7170                         {
7171                                 token->encrypt(key->getKeyBits(), value);
7172                                 token->encrypt(key->getKeyCheckValue(), kcv);
7173                         }
7174                         else
7175                         {
7176                                 value = key->getKeyBits();
7177                                 kcv = key->getKeyCheckValue();
7178                         }
7179                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7180                         if (checkValue)
7181                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7182
7183                         if (bOK)
7184                                 bOK = osobject->commitTransaction();
7185                         else
7186                                 osobject->abortTransaction();
7187
7188                         if (!bOK)
7189                                 rv = CKR_FUNCTION_FAILED;
7190                 } else
7191                         rv = CKR_FUNCTION_FAILED;
7192         }
7193
7194         // Clean up
7195         des->recycleKey(key);
7196         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7197
7198         // Remove the key that may have been created already when the function fails.
7199         if (rv != CKR_OK)
7200         {
7201                 if (*phKey != CK_INVALID_HANDLE)
7202                 {
7203                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7204                         handleManager->destroyObject(*phKey);
7205                         if (oskey) oskey->destroyObject();
7206                         *phKey = CK_INVALID_HANDLE;
7207                 }
7208         }
7209
7210         return rv;
7211 }
7212
7213 // Generate a DES2 secret key
7214 CK_RV SoftHSM::generateDES2
7215 (CK_SESSION_HANDLE hSession,
7216         CK_ATTRIBUTE_PTR pTemplate,
7217         CK_ULONG ulCount,
7218         CK_OBJECT_HANDLE_PTR phKey,
7219         CK_BBOOL isOnToken,
7220         CK_BBOOL isPrivate)
7221 {
7222         *phKey = CK_INVALID_HANDLE;
7223
7224         // Get the session
7225         Session* session = (Session*)handleManager->getSession(hSession);
7226         if (session == NULL)
7227                 return CKR_SESSION_HANDLE_INVALID;
7228
7229         // Get the token
7230         Token* token = session->getToken();
7231         if (token == NULL)
7232                 return CKR_GENERAL_ERROR;
7233
7234         // Extract desired parameter information
7235         bool checkValue = true;
7236         for (CK_ULONG i = 0; i < ulCount; i++)
7237         {
7238                 switch (pTemplate[i].type)
7239                 {
7240                         case CKA_CHECK_VALUE:
7241                                 if (pTemplate[i].ulValueLen > 0)
7242                                 {
7243                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7244                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7245                                 }
7246                                 checkValue = false;
7247                                 break;
7248                         default:
7249                                 break;
7250                 }
7251         }
7252
7253         // Generate the secret key
7254         DESKey* key = new DESKey(112);
7255         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7256         if (des == NULL)
7257         {
7258                 ERROR_MSG("Could not get SymmetricAlgorith");
7259                 delete key;
7260                 return CKR_GENERAL_ERROR;
7261         }
7262         RNG* rng = CryptoFactory::i()->getRNG();
7263         if (rng == NULL)
7264         {
7265                 ERROR_MSG("Could not get RNG");
7266                 des->recycleKey(key);
7267                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7268                 return CKR_GENERAL_ERROR;
7269         }
7270         if (!des->generateKey(*key, rng))
7271         {
7272                 ERROR_MSG("Could not generate DES secret key");
7273                 des->recycleKey(key);
7274                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7275                 return CKR_GENERAL_ERROR;
7276         }
7277
7278         CK_RV rv = CKR_OK;
7279
7280         // Create the secret key object using C_CreateObject
7281         const CK_ULONG maxAttribs = 32;
7282         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7283         CK_KEY_TYPE keyType = CKK_DES2;
7284         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7285                 { CKA_CLASS, &objClass, sizeof(objClass) },
7286                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7287                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7288                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7289         };
7290         CK_ULONG keyAttribsCount = 4;
7291
7292         // Add the additional
7293         if (ulCount > (maxAttribs - keyAttribsCount))
7294                 rv = CKR_TEMPLATE_INCONSISTENT;
7295         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7296         {
7297                 switch (pTemplate[i].type)
7298                 {
7299                         case CKA_CLASS:
7300                         case CKA_TOKEN:
7301                         case CKA_PRIVATE:
7302                         case CKA_KEY_TYPE:
7303                         case CKA_CHECK_VALUE:
7304                                 continue;
7305                 default:
7306                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7307                 }
7308         }
7309
7310         if (rv == CKR_OK)
7311                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7312
7313         // Store the attributes that are being supplied
7314         if (rv == CKR_OK)
7315         {
7316                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7317                 if (osobject == NULL_PTR || !osobject->isValid()) {
7318                         rv = CKR_FUNCTION_FAILED;
7319                 } else if (osobject->startTransaction()) {
7320                         bool bOK = true;
7321
7322                         // Common Attributes
7323                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7324                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES2_KEY_GEN;
7325                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7326
7327                         // Common Secret Key Attributes
7328                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7329                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7330                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7331                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7332
7333                         // DES Secret Key Attributes
7334                         ByteString value;
7335                         ByteString kcv;
7336                         if (isPrivate)
7337                         {
7338                                 token->encrypt(key->getKeyBits(), value);
7339                                 token->encrypt(key->getKeyCheckValue(), kcv);
7340                         }
7341                         else
7342                         {
7343                                 value = key->getKeyBits();
7344                                 kcv = key->getKeyCheckValue();
7345                         }
7346                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7347                         if (checkValue)
7348                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7349
7350                         if (bOK)
7351                                 bOK = osobject->commitTransaction();
7352                         else
7353                                 osobject->abortTransaction();
7354
7355                         if (!bOK)
7356                                 rv = CKR_FUNCTION_FAILED;
7357                 } else
7358                         rv = CKR_FUNCTION_FAILED;
7359         }
7360
7361         // Clean up
7362         des->recycleKey(key);
7363         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7364
7365         // Remove the key that may have been created already when the function fails.
7366         if (rv != CKR_OK)
7367         {
7368                 if (*phKey != CK_INVALID_HANDLE)
7369                 {
7370                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7371                         handleManager->destroyObject(*phKey);
7372                         if (oskey) oskey->destroyObject();
7373                         *phKey = CK_INVALID_HANDLE;
7374                 }
7375         }
7376
7377         return rv;
7378 }
7379
7380 // Generate a DES3 secret key
7381 CK_RV SoftHSM::generateDES3
7382 (CK_SESSION_HANDLE hSession,
7383         CK_ATTRIBUTE_PTR pTemplate,
7384         CK_ULONG ulCount,
7385         CK_OBJECT_HANDLE_PTR phKey,
7386         CK_BBOOL isOnToken,
7387         CK_BBOOL isPrivate)
7388 {
7389         *phKey = CK_INVALID_HANDLE;
7390
7391         // Get the session
7392         Session* session = (Session*)handleManager->getSession(hSession);
7393         if (session == NULL)
7394                 return CKR_SESSION_HANDLE_INVALID;
7395
7396         // Get the token
7397         Token* token = session->getToken();
7398         if (token == NULL)
7399                 return CKR_GENERAL_ERROR;
7400
7401         // Extract desired parameter information
7402         bool checkValue = true;
7403         for (CK_ULONG i = 0; i < ulCount; i++)
7404         {
7405                 switch (pTemplate[i].type)
7406                 {
7407                         case CKA_CHECK_VALUE:
7408                                 if (pTemplate[i].ulValueLen > 0)
7409                                 {
7410                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
7411                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7412                                 }
7413                                 checkValue = false;
7414                                 break;
7415                         default:
7416                                 break;
7417                 }
7418         }
7419
7420         // Generate the secret key
7421         DESKey* key = new DESKey(168);
7422         SymmetricAlgorithm* des = CryptoFactory::i()->getSymmetricAlgorithm(SymAlgo::DES3);
7423         if (des == NULL)
7424         {
7425                 ERROR_MSG("Could not get SymmetricAlgorithm");
7426                 delete key;
7427                 return CKR_GENERAL_ERROR;
7428         }
7429         RNG* rng = CryptoFactory::i()->getRNG();
7430         if (rng == NULL)
7431         {
7432                 ERROR_MSG("Could not get RNG");
7433                 des->recycleKey(key);
7434                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7435                 return CKR_GENERAL_ERROR;
7436         }
7437         if (!des->generateKey(*key, rng))
7438         {
7439                 ERROR_MSG("Could not generate DES secret key");
7440                 des->recycleKey(key);
7441                 CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7442                 return CKR_GENERAL_ERROR;
7443         }
7444
7445         CK_RV rv = CKR_OK;
7446
7447         // Create the secret key object using C_CreateObject
7448         const CK_ULONG maxAttribs = 32;
7449         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
7450         CK_KEY_TYPE keyType = CKK_DES3;
7451         CK_ATTRIBUTE keyAttribs[maxAttribs] = {
7452                 { CKA_CLASS, &objClass, sizeof(objClass) },
7453                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
7454                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
7455                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
7456         };
7457         CK_ULONG keyAttribsCount = 4;
7458
7459         // Add the additional
7460         if (ulCount > (maxAttribs - keyAttribsCount))
7461                 rv = CKR_TEMPLATE_INCONSISTENT;
7462         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
7463         {
7464                 switch (pTemplate[i].type)
7465                 {
7466                         case CKA_CLASS:
7467                         case CKA_TOKEN:
7468                         case CKA_PRIVATE:
7469                         case CKA_KEY_TYPE:
7470                         case CKA_CHECK_VALUE:
7471                                 continue;
7472                 default:
7473                         keyAttribs[keyAttribsCount++] = pTemplate[i];
7474                 }
7475         }
7476
7477         if (rv == CKR_OK)
7478                 rv = this->CreateObject(hSession, keyAttribs, keyAttribsCount, phKey,OBJECT_OP_GENERATE);
7479
7480         // Store the attributes that are being supplied
7481         if (rv == CKR_OK)
7482         {
7483                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
7484                 if (osobject == NULL_PTR || !osobject->isValid()) {
7485                         rv = CKR_FUNCTION_FAILED;
7486                 } else if (osobject->startTransaction()) {
7487                         bool bOK = true;
7488
7489                         // Common Attributes
7490                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7491                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DES3_KEY_GEN;
7492                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7493
7494                         // Common Secret Key Attributes
7495                         bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7496                         bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7497                         bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7498                         bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7499
7500                         // DES Secret Key Attributes
7501                         ByteString value;
7502                         ByteString kcv;
7503                         if (isPrivate)
7504                         {
7505                                 token->encrypt(key->getKeyBits(), value);
7506                                 token->encrypt(key->getKeyCheckValue(), kcv);
7507                         }
7508                         else
7509                         {
7510                                 value = key->getKeyBits();
7511                                 kcv = key->getKeyCheckValue();
7512                         }
7513                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7514                         if (checkValue)
7515                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
7516
7517                         if (bOK)
7518                                 bOK = osobject->commitTransaction();
7519                         else
7520                                 osobject->abortTransaction();
7521
7522                         if (!bOK)
7523                                 rv = CKR_FUNCTION_FAILED;
7524                 } else
7525                         rv = CKR_FUNCTION_FAILED;
7526         }
7527
7528         // Clean up
7529         des->recycleKey(key);
7530         CryptoFactory::i()->recycleSymmetricAlgorithm(des);
7531
7532         // Remove the key that may have been created already when the function fails.
7533         if (rv != CKR_OK)
7534         {
7535                 if (*phKey != CK_INVALID_HANDLE)
7536                 {
7537                         OSObject* oskey = (OSObject*)handleManager->getObject(*phKey);
7538                         handleManager->destroyObject(*phKey);
7539                         if (oskey) oskey->destroyObject();
7540                         *phKey = CK_INVALID_HANDLE;
7541                 }
7542         }
7543
7544         return rv;
7545 }
7546
7547 // Generate an RSA key pair
7548 CK_RV SoftHSM::generateRSA
7549 (CK_SESSION_HANDLE hSession,
7550         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7551         CK_ULONG ulPublicKeyAttributeCount,
7552         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7553         CK_ULONG ulPrivateKeyAttributeCount,
7554         CK_OBJECT_HANDLE_PTR phPublicKey,
7555         CK_OBJECT_HANDLE_PTR phPrivateKey,
7556         CK_BBOOL isPublicKeyOnToken,
7557         CK_BBOOL isPublicKeyPrivate,
7558         CK_BBOOL isPrivateKeyOnToken,
7559         CK_BBOOL isPrivateKeyPrivate
7560 )
7561 {
7562         *phPublicKey = CK_INVALID_HANDLE;
7563         *phPrivateKey = CK_INVALID_HANDLE;
7564
7565         // Get the session
7566         Session* session = (Session*)handleManager->getSession(hSession);
7567         if (session == NULL)
7568                 return CKR_SESSION_HANDLE_INVALID;
7569
7570         // Get the token
7571         Token* token = session->getToken();
7572         if (token == NULL)
7573                 return CKR_GENERAL_ERROR;
7574
7575         // Extract desired key information: bitlen and public exponent
7576         size_t bitLen = 0;
7577         ByteString exponent("010001");
7578         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7579         {
7580                 switch (pPublicKeyTemplate[i].type)
7581                 {
7582                         case CKA_MODULUS_BITS:
7583                                 if (pPublicKeyTemplate[i].ulValueLen != sizeof(CK_ULONG))
7584                                 {
7585                                         INFO_MSG("CKA_MODULUS_BITS does not have the size of CK_ULONG");
7586                                         return CKR_ATTRIBUTE_VALUE_INVALID;
7587                                 }
7588                                 bitLen = *(CK_ULONG*)pPublicKeyTemplate[i].pValue;
7589                                 break;
7590                         case CKA_PUBLIC_EXPONENT:
7591                                 exponent = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7592                                 break;
7593                         default:
7594                                 break;
7595                 }
7596         }
7597
7598         // CKA_MODULUS_BITS must be specified to be able to generate a key pair.
7599         if (bitLen == 0) {
7600                 INFO_MSG("Missing CKA_MODULUS_BITS in pPublicKeyTemplate");
7601                 return CKR_TEMPLATE_INCOMPLETE;
7602         }
7603
7604         // Set the parameters
7605         RSAParameters p;
7606         p.setE(exponent);
7607         p.setBitLength(bitLen);
7608
7609         // Generate key pair
7610         AsymmetricKeyPair* kp = NULL;
7611         AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
7612         if (rsa == NULL)
7613                 return CKR_GENERAL_ERROR;
7614         if (!rsa->generateKeyPair(&kp, &p))
7615         {
7616                 ERROR_MSG("Could not generate key pair");
7617                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7618                 return CKR_GENERAL_ERROR;
7619         }
7620
7621         RSAPublicKey* pub = (RSAPublicKey*) kp->getPublicKey();
7622         RSAPrivateKey* priv = (RSAPrivateKey*) kp->getPrivateKey();
7623
7624         CK_RV rv = CKR_OK;
7625
7626         // Create a public key using C_CreateObject
7627         if (rv == CKR_OK)
7628         {
7629                 const CK_ULONG maxAttribs = 32;
7630                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7631                 CK_KEY_TYPE publicKeyType = CKK_RSA;
7632                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7633                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7634                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7635                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7636                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7637                 };
7638                 CK_ULONG publicKeyAttribsCount = 4;
7639
7640                 // Add the additional
7641                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7642                         rv = CKR_TEMPLATE_INCONSISTENT;
7643                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7644                 {
7645                         switch (pPublicKeyTemplate[i].type)
7646                         {
7647                                 case CKA_CLASS:
7648                                 case CKA_TOKEN:
7649                                 case CKA_PRIVATE:
7650                                 case CKA_KEY_TYPE:
7651                                 case CKA_PUBLIC_EXPONENT:
7652                                         continue;
7653                                 default:
7654                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7655                         }
7656                 }
7657
7658                 if (rv == CKR_OK)
7659                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7660
7661                 // Store the attributes that are being supplied by the key generation to the object
7662                 if (rv == CKR_OK)
7663                 {
7664                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7665                         if (osobject == NULL_PTR || !osobject->isValid()) {
7666                                 rv = CKR_FUNCTION_FAILED;
7667                         } else if (osobject->startTransaction()) {
7668                                 bool bOK = true;
7669
7670                                 // Common Key Attributes
7671                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7672                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7673                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7674
7675                                 // RSA Public Key Attributes
7676                                 ByteString modulus;
7677                                 ByteString publicExponent;
7678                                 if (isPublicKeyPrivate)
7679                                 {
7680                                         token->encrypt(pub->getN(), modulus);
7681                                         token->encrypt(pub->getE(), publicExponent);
7682                                 }
7683                                 else
7684                                 {
7685                                         modulus = pub->getN();
7686                                         publicExponent = pub->getE();
7687                                 }
7688                                 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7689                                 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7690
7691                                 if (bOK)
7692                                         bOK = osobject->commitTransaction();
7693                                 else
7694                                         osobject->abortTransaction();
7695
7696                                 if (!bOK)
7697                                         rv = CKR_FUNCTION_FAILED;
7698                         } else
7699                                 rv = CKR_FUNCTION_FAILED;
7700                 }
7701         }
7702
7703         // Create a private key using C_CreateObject
7704         if (rv == CKR_OK)
7705         {
7706                 const CK_ULONG maxAttribs = 32;
7707                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7708                 CK_KEY_TYPE privateKeyType = CKK_RSA;
7709                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7710                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7711                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7712                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7713                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7714                 };
7715                 CK_ULONG privateKeyAttribsCount = 4;
7716                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7717                         rv = CKR_TEMPLATE_INCONSISTENT;
7718                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
7719                 {
7720                         switch (pPrivateKeyTemplate[i].type)
7721                         {
7722                                 case CKA_CLASS:
7723                                 case CKA_TOKEN:
7724                                 case CKA_PRIVATE:
7725                                 case CKA_KEY_TYPE:
7726                                         continue;
7727                                 default:
7728                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
7729                         }
7730                 }
7731
7732                 if (rv == CKR_OK)
7733                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
7734
7735                 // Store the attributes that are being supplied by the key generation to the object
7736                 if (rv == CKR_OK)
7737                 {
7738                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
7739                         if (osobject == NULL_PTR || !osobject->isValid()) {
7740                                 rv = CKR_FUNCTION_FAILED;
7741                         } else if (osobject->startTransaction()) {
7742                                 bool bOK = true;
7743
7744                                 // Common Key Attributes
7745                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7746                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_RSA_PKCS_KEY_PAIR_GEN;
7747                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7748
7749                                 // Common Private Key Attributes
7750                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
7751                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
7752                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
7753                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
7754
7755                                 // RSA Private Key Attributes
7756                                 ByteString modulus;
7757                                 ByteString publicExponent;
7758                                 ByteString privateExponent;
7759                                 ByteString prime1;
7760                                 ByteString prime2;
7761                                 ByteString exponent1;
7762                                 ByteString exponent2;
7763                                 ByteString coefficient;
7764                                 if (isPrivateKeyPrivate)
7765                                 {
7766                                         token->encrypt(priv->getN(), modulus);
7767                                         token->encrypt(priv->getE(), publicExponent);
7768                                         token->encrypt(priv->getD(), privateExponent);
7769                                         token->encrypt(priv->getP(), prime1);
7770                                         token->encrypt(priv->getQ(), prime2);
7771                                         token->encrypt(priv->getDP1(), exponent1);
7772                                         token->encrypt(priv->getDQ1(), exponent2);
7773                                         token->encrypt(priv->getPQ(), coefficient);
7774                                 }
7775                                 else
7776                                 {
7777                                         modulus = priv->getN();
7778                                         publicExponent = priv->getE();
7779                                         privateExponent = priv->getD();
7780                                         prime1 = priv->getP();
7781                                         prime2 = priv->getQ();
7782                                         exponent1 =  priv->getDP1();
7783                                         exponent2 = priv->getDQ1();
7784                                         coefficient = priv->getPQ();
7785                                 }
7786                                 bOK = bOK && osobject->setAttribute(CKA_MODULUS, modulus);
7787                                 bOK = bOK && osobject->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
7788                                 bOK = bOK && osobject->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
7789                                 bOK = bOK && osobject->setAttribute(CKA_PRIME_1, prime1);
7790                                 bOK = bOK && osobject->setAttribute(CKA_PRIME_2, prime2);
7791                                 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_1,exponent1);
7792                                 bOK = bOK && osobject->setAttribute(CKA_EXPONENT_2, exponent2);
7793                                 bOK = bOK && osobject->setAttribute(CKA_COEFFICIENT, coefficient);
7794
7795                                 if (bOK)
7796                                         bOK = osobject->commitTransaction();
7797                                 else
7798                                         osobject->abortTransaction();
7799
7800                                 if (!bOK)
7801                                         rv = CKR_FUNCTION_FAILED;
7802                         } else
7803                                 rv = CKR_FUNCTION_FAILED;
7804                 }
7805         }
7806
7807         // Clean up
7808         rsa->recycleKeyPair(kp);
7809         CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
7810
7811         // Remove keys that may have been created already when the function fails.
7812         if (rv != CKR_OK)
7813         {
7814                 if (*phPrivateKey != CK_INVALID_HANDLE)
7815                 {
7816                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
7817                         handleManager->destroyObject(*phPrivateKey);
7818                         if (ospriv) ospriv->destroyObject();
7819                         *phPrivateKey = CK_INVALID_HANDLE;
7820                 }
7821
7822                 if (*phPublicKey != CK_INVALID_HANDLE)
7823                 {
7824                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
7825                         handleManager->destroyObject(*phPublicKey);
7826                         if (ospub) ospub->destroyObject();
7827                         *phPublicKey = CK_INVALID_HANDLE;
7828                 }
7829         }
7830
7831         return rv;
7832 }
7833
7834 // Generate a DSA key pair
7835 CK_RV SoftHSM::generateDSA
7836 (CK_SESSION_HANDLE hSession,
7837         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
7838         CK_ULONG ulPublicKeyAttributeCount,
7839         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
7840         CK_ULONG ulPrivateKeyAttributeCount,
7841         CK_OBJECT_HANDLE_PTR phPublicKey,
7842         CK_OBJECT_HANDLE_PTR phPrivateKey,
7843         CK_BBOOL isPublicKeyOnToken,
7844         CK_BBOOL isPublicKeyPrivate,
7845         CK_BBOOL isPrivateKeyOnToken,
7846         CK_BBOOL isPrivateKeyPrivate)
7847 {
7848         *phPublicKey = CK_INVALID_HANDLE;
7849         *phPrivateKey = CK_INVALID_HANDLE;
7850
7851         // Get the session
7852         Session* session = (Session*)handleManager->getSession(hSession);
7853         if (session == NULL)
7854                 return CKR_SESSION_HANDLE_INVALID;
7855
7856         // Get the token
7857         Token* token = session->getToken();
7858         if (token == NULL)
7859                 return CKR_GENERAL_ERROR;
7860
7861         // Extract desired key information
7862         ByteString prime;
7863         ByteString subprime;
7864         ByteString generator;
7865         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
7866         {
7867                 switch (pPublicKeyTemplate[i].type)
7868                 {
7869                         case CKA_PRIME:
7870                                 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7871                                 break;
7872                         case CKA_SUBPRIME:
7873                                 subprime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7874                                 break;
7875                         case CKA_BASE:
7876                                 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
7877                                 break;
7878                         default:
7879                                 break;
7880                 }
7881         }
7882
7883         // The parameters must be specified to be able to generate a key pair.
7884         if (prime.size() == 0 || subprime.size() == 0 || generator.size() == 0) {
7885                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
7886                 return CKR_TEMPLATE_INCOMPLETE;
7887         }
7888
7889         // Set the parameters
7890         DSAParameters p;
7891         p.setP(prime);
7892         p.setQ(subprime);
7893         p.setG(generator);
7894
7895         // Generate key pair
7896         AsymmetricKeyPair* kp = NULL;
7897         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
7898         if (dsa == NULL) return CKR_GENERAL_ERROR;
7899         if (!dsa->generateKeyPair(&kp, &p))
7900         {
7901                 ERROR_MSG("Could not generate key pair");
7902                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
7903                 return CKR_GENERAL_ERROR;
7904         }
7905
7906         DSAPublicKey* pub = (DSAPublicKey*) kp->getPublicKey();
7907         DSAPrivateKey* priv = (DSAPrivateKey*) kp->getPrivateKey();
7908
7909         CK_RV rv = CKR_OK;
7910
7911         // Create a public key using C_CreateObject
7912         if (rv == CKR_OK)
7913         {
7914                 const CK_ULONG maxAttribs = 32;
7915                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
7916                 CK_KEY_TYPE publicKeyType = CKK_DSA;
7917                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
7918                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
7919                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
7920                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
7921                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
7922                 };
7923                 CK_ULONG publicKeyAttribsCount = 4;
7924
7925                 // Add the additional
7926                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
7927                         rv = CKR_TEMPLATE_INCONSISTENT;
7928                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
7929                 {
7930                         switch (pPublicKeyTemplate[i].type)
7931                         {
7932                                 case CKA_CLASS:
7933                                 case CKA_TOKEN:
7934                                 case CKA_PRIVATE:
7935                                 case CKA_KEY_TYPE:
7936                                         continue;
7937                                 default:
7938                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
7939                         }
7940                 }
7941
7942                 if (rv == CKR_OK)
7943                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
7944
7945                 // Store the attributes that are being supplied by the key generation to the object
7946                 if (rv == CKR_OK)
7947                 {
7948                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
7949                         if (osobject == NULL_PTR || !osobject->isValid()) {
7950                                 rv = CKR_FUNCTION_FAILED;
7951                         } else if (osobject->startTransaction()) {
7952                                 bool bOK = true;
7953
7954                                 // Common Key Attributes
7955                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
7956                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
7957                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
7958
7959                                 // DSA Public Key Attributes
7960                                 ByteString value;
7961                                 if (isPublicKeyPrivate)
7962                                 {
7963                                         token->encrypt(pub->getY(), value);
7964                                 }
7965                                 else
7966                                 {
7967                                         value = pub->getY();
7968                                 }
7969                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
7970
7971                                 if (bOK)
7972                                         bOK = osobject->commitTransaction();
7973                                 else
7974                                         osobject->abortTransaction();
7975
7976                                 if (!bOK)
7977                                         rv = CKR_FUNCTION_FAILED;
7978                         } else
7979                                 rv = CKR_FUNCTION_FAILED;
7980                 }
7981         }
7982
7983         // Create a private key using C_CreateObject
7984         if (rv == CKR_OK)
7985         {
7986                 const CK_ULONG maxAttribs = 32;
7987                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
7988                 CK_KEY_TYPE privateKeyType = CKK_DSA;
7989                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
7990                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
7991                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
7992                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
7993                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
7994                 };
7995                 CK_ULONG privateKeyAttribsCount = 4;
7996                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
7997                         rv = CKR_TEMPLATE_INCONSISTENT;
7998                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
7999                 {
8000                         switch (pPrivateKeyTemplate[i].type)
8001                         {
8002                                 case CKA_CLASS:
8003                                 case CKA_TOKEN:
8004                                 case CKA_PRIVATE:
8005                                 case CKA_KEY_TYPE:
8006                                         continue;
8007                                 default:
8008                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8009                         }
8010                 }
8011
8012                 if (rv == CKR_OK)
8013                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8014
8015                 // Store the attributes that are being supplied by the key generation to the object
8016                 if (rv == CKR_OK)
8017                 {
8018                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8019                         if (osobject == NULL_PTR || !osobject->isValid()) {
8020                                 rv = CKR_FUNCTION_FAILED;
8021                         } else if (osobject->startTransaction()) {
8022                                 bool bOK = true;
8023
8024                                 // Common Key Attributes
8025                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8026                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_KEY_PAIR_GEN;
8027                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8028
8029                                 // Common Private Key Attributes
8030                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8031                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8032                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8033                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8034
8035                                 // DSA Private Key Attributes
8036                                 ByteString bPrime;
8037                                 ByteString bSubprime;
8038                                 ByteString bGenerator;
8039                                 ByteString bValue;
8040                                 if (isPrivateKeyPrivate)
8041                                 {
8042                                         token->encrypt(priv->getP(), bPrime);
8043                                         token->encrypt(priv->getQ(), bSubprime);
8044                                         token->encrypt(priv->getG(), bGenerator);
8045                                         token->encrypt(priv->getX(), bValue);
8046                                 }
8047                                 else
8048                                 {
8049                                         bPrime = priv->getP();
8050                                         bSubprime = priv->getQ();
8051                                         bGenerator = priv->getG();
8052                                         bValue = priv->getX();
8053                                 }
8054                                 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8055                                 bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, bSubprime);
8056                                 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8057                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8058
8059                                 if (bOK)
8060                                         bOK = osobject->commitTransaction();
8061                                 else
8062                                         osobject->abortTransaction();
8063
8064                                 if (!bOK)
8065                                         rv = CKR_FUNCTION_FAILED;
8066                         } else
8067                                 rv = CKR_FUNCTION_FAILED;
8068                 }
8069         }
8070
8071         // Clean up
8072         dsa->recycleKeyPair(kp);
8073         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8074
8075         // Remove keys that may have been created already when the function fails.
8076         if (rv != CKR_OK)
8077         {
8078                 if (*phPrivateKey != CK_INVALID_HANDLE)
8079                 {
8080                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8081                         handleManager->destroyObject(*phPrivateKey);
8082                         if (ospriv) ospriv->destroyObject();
8083                         *phPrivateKey = CK_INVALID_HANDLE;
8084                 }
8085
8086                 if (*phPublicKey != CK_INVALID_HANDLE)
8087                 {
8088                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8089                         handleManager->destroyObject(*phPublicKey);
8090                         if (ospub) ospub->destroyObject();
8091                         *phPublicKey = CK_INVALID_HANDLE;
8092                 }
8093         }
8094
8095         return rv;
8096 }
8097
8098 // Generate a DSA domain parameter set
8099 CK_RV SoftHSM::generateDSAParameters
8100 (CK_SESSION_HANDLE hSession,
8101         CK_ATTRIBUTE_PTR pTemplate,
8102         CK_ULONG ulCount,
8103         CK_OBJECT_HANDLE_PTR phKey,
8104         CK_BBOOL isOnToken,
8105         CK_BBOOL isPrivate)
8106 {
8107         *phKey = CK_INVALID_HANDLE;
8108
8109         // Get the session
8110         Session* session = (Session*)handleManager->getSession(hSession);
8111         if (session == NULL)
8112                 return CKR_SESSION_HANDLE_INVALID;
8113
8114         // Get the token
8115         Token* token = session->getToken();
8116         if (token == NULL)
8117                 return CKR_GENERAL_ERROR;
8118
8119         // Extract desired parameter information
8120         size_t bitLen = 0;
8121         size_t qLen = 0;
8122         for (CK_ULONG i = 0; i < ulCount; i++)
8123         {
8124                 switch (pTemplate[i].type)
8125                 {
8126                         case CKA_PRIME_BITS:
8127                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8128                                 {
8129                                         INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8130                                         return CKR_ATTRIBUTE_VALUE_INVALID;
8131                                 }
8132                                 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8133                                 break;
8134                         case CKA_SUBPRIME_BITS:
8135                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8136                                 {
8137                                         INFO_MSG("CKA_SUBPRIME_BITS does not have the size of CK_ULONG");
8138                                         return CKR_ATTRIBUTE_VALUE_INVALID;
8139                                 }
8140                                 qLen = *(CK_ULONG*)pTemplate[i].pValue;
8141                                 break;
8142                         default:
8143                                 break;
8144                 }
8145         }
8146
8147         // CKA_PRIME_BITS must be specified
8148         if (bitLen == 0)
8149         {
8150                 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8151                 return CKR_TEMPLATE_INCOMPLETE;
8152         }
8153
8154         // No real choice for CKA_SUBPRIME_BITS
8155         if ((qLen != 0) &&
8156             (((bitLen >= 2048) && (qLen != 256)) ||
8157              ((bitLen < 2048) && (qLen != 160))))
8158                 INFO_MSG("CKA_SUBPRIME_BITS is ignored");
8159
8160
8161         // Generate domain parameters
8162         AsymmetricParameters* p = NULL;
8163         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
8164         if (dsa == NULL) return CKR_GENERAL_ERROR;
8165         if (!dsa->generateParameters(&p, (void *)bitLen))
8166         {
8167                 ERROR_MSG("Could not generate parameters");
8168                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8169                 return CKR_GENERAL_ERROR;
8170         }
8171
8172         DSAParameters* params = (DSAParameters*) p;
8173
8174         CK_RV rv = CKR_OK;
8175
8176         // Create the domain parameter object using C_CreateObject
8177         const CK_ULONG maxAttribs = 32;
8178         CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8179         CK_KEY_TYPE keyType = CKK_DSA;
8180         CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8181                 { CKA_CLASS, &objClass, sizeof(objClass) },
8182                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8183                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8184                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8185         };
8186         CK_ULONG paramsAttribsCount = 4;
8187
8188         // Add the additional
8189         if (ulCount > (maxAttribs - paramsAttribsCount))
8190                 rv = CKR_TEMPLATE_INCONSISTENT;
8191         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8192         {
8193                 switch (pTemplate[i].type)
8194                 {
8195                         case CKA_CLASS:
8196                         case CKA_TOKEN:
8197                         case CKA_PRIVATE:
8198                         case CKA_KEY_TYPE:
8199                                 continue;
8200                 default:
8201                         paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8202                 }
8203         }
8204
8205         if (rv == CKR_OK)
8206                 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8207
8208         // Store the attributes that are being supplied
8209         if (rv == CKR_OK)
8210         {
8211                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8212                 if (osobject == NULL_PTR || !osobject->isValid()) {
8213                         rv = CKR_FUNCTION_FAILED;
8214                 } else if (osobject->startTransaction()) {
8215                         bool bOK = true;
8216
8217                         // Common Attributes
8218                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8219                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DSA_PARAMETER_GEN;
8220                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8221
8222                         // DSA Domain Parameters Attributes
8223                         ByteString prime;
8224                         ByteString subprime;
8225                         ByteString generator;
8226                         if (isPrivate)
8227                         {
8228                                 token->encrypt(params->getP(), prime);
8229                                 token->encrypt(params->getQ(), subprime);
8230                                 token->encrypt(params->getG(), generator);
8231                         }
8232                         else
8233                         {
8234                                 prime = params->getP();
8235                                 subprime = params->getQ();
8236                                 generator = params->getG();
8237                         }
8238                         bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8239                         bOK = bOK && osobject->setAttribute(CKA_SUBPRIME, subprime);
8240                         bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8241
8242                         if (bOK)
8243                                 bOK = osobject->commitTransaction();
8244                         else
8245                                 osobject->abortTransaction();
8246
8247                         if (!bOK)
8248                                 rv = CKR_FUNCTION_FAILED;
8249                 } else
8250                         rv = CKR_FUNCTION_FAILED;
8251         }
8252
8253         // Clean up
8254         dsa->recycleParameters(p);
8255         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
8256
8257         // Remove parameters that may have been created already when the function fails.
8258         if (rv != CKR_OK)
8259         {
8260                 if (*phKey != CK_INVALID_HANDLE)
8261                 {
8262                         OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8263                         handleManager->destroyObject(*phKey);
8264                         if (osparams) osparams->destroyObject();
8265                         *phKey = CK_INVALID_HANDLE;
8266                 }
8267         }
8268
8269         return rv;
8270 }
8271
8272 // Generate an EC key pair
8273 CK_RV SoftHSM::generateEC
8274 (CK_SESSION_HANDLE hSession,
8275         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8276         CK_ULONG ulPublicKeyAttributeCount,
8277         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8278         CK_ULONG ulPrivateKeyAttributeCount,
8279         CK_OBJECT_HANDLE_PTR phPublicKey,
8280         CK_OBJECT_HANDLE_PTR phPrivateKey,
8281         CK_BBOOL isPublicKeyOnToken,
8282         CK_BBOOL isPublicKeyPrivate,
8283         CK_BBOOL isPrivateKeyOnToken,
8284         CK_BBOOL isPrivateKeyPrivate)
8285 {
8286         *phPublicKey = CK_INVALID_HANDLE;
8287         *phPrivateKey = CK_INVALID_HANDLE;
8288
8289         // Get the session
8290         Session* session = (Session*)handleManager->getSession(hSession);
8291         if (session == NULL)
8292                 return CKR_SESSION_HANDLE_INVALID;
8293
8294         // Get the token
8295         Token* token = session->getToken();
8296         if (token == NULL)
8297                 return CKR_GENERAL_ERROR;
8298
8299         // Extract desired key information
8300         ByteString params;
8301         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8302         {
8303                 switch (pPublicKeyTemplate[i].type)
8304                 {
8305                         case CKA_EC_PARAMS:
8306                                 params = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8307                                 break;
8308                         default:
8309                                 break;
8310                 }
8311         }
8312
8313         // The parameters must be specified to be able to generate a key pair.
8314         if (params.size() == 0) {
8315                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8316                 return CKR_TEMPLATE_INCOMPLETE;
8317         }
8318
8319         // Set the parameters
8320         ECParameters p;
8321         p.setEC(params);
8322
8323         // Generate key pair
8324         AsymmetricKeyPair* kp = NULL;
8325         AsymmetricAlgorithm* ec = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
8326         if (ec == NULL) return CKR_GENERAL_ERROR;
8327         if (!ec->generateKeyPair(&kp, &p))
8328         {
8329                 ERROR_MSG("Could not generate key pair");
8330                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8331                 return CKR_GENERAL_ERROR;
8332         }
8333
8334         ECPublicKey* pub = (ECPublicKey*) kp->getPublicKey();
8335         ECPrivateKey* priv = (ECPrivateKey*) kp->getPrivateKey();
8336
8337         CK_RV rv = CKR_OK;
8338
8339         // Create a public key using C_CreateObject
8340         if (rv == CKR_OK)
8341         {
8342                 const CK_ULONG maxAttribs = 32;
8343                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8344                 CK_KEY_TYPE publicKeyType = CKK_EC;
8345                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8346                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8347                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8348                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8349                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8350                 };
8351                 CK_ULONG publicKeyAttribsCount = 4;
8352
8353                 // Add the additional
8354                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8355                         rv = CKR_TEMPLATE_INCONSISTENT;
8356                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8357                 {
8358                         switch (pPublicKeyTemplate[i].type)
8359                         {
8360                                 case CKA_CLASS:
8361                                 case CKA_TOKEN:
8362                                 case CKA_PRIVATE:
8363                                 case CKA_KEY_TYPE:
8364                                         continue;
8365                                 default:
8366                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8367                         }
8368                 }
8369
8370                 if (rv == CKR_OK)
8371                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8372
8373                 // Store the attributes that are being supplied by the key generation to the object
8374                 if (rv == CKR_OK)
8375                 {
8376                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8377                         if (osobject == NULL_PTR || !osobject->isValid()) {
8378                                 rv = CKR_FUNCTION_FAILED;
8379                         } else if (osobject->startTransaction()) {
8380                                 bool bOK = true;
8381
8382                                 // Common Key Attributes
8383                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8384                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8385                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8386
8387                                 // EC Public Key Attributes
8388                                 ByteString point;
8389                                 if (isPublicKeyPrivate)
8390                                 {
8391                                         token->encrypt(pub->getQ(), point);
8392                                 }
8393                                 else
8394                                 {
8395                                         point = pub->getQ();
8396                                 }
8397                                 bOK = bOK && osobject->setAttribute(CKA_EC_POINT, point);
8398
8399                                 if (bOK)
8400                                         bOK = osobject->commitTransaction();
8401                                 else
8402                                         osobject->abortTransaction();
8403
8404                                 if (!bOK)
8405                                         rv = CKR_FUNCTION_FAILED;
8406                         } else
8407                                 rv = CKR_FUNCTION_FAILED;
8408                 }
8409         }
8410
8411         // Create a private key using C_CreateObject
8412         if (rv == CKR_OK)
8413         {
8414                 const CK_ULONG maxAttribs = 32;
8415                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8416                 CK_KEY_TYPE privateKeyType = CKK_EC;
8417                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8418                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8419                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8420                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8421                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8422                 };
8423                 CK_ULONG privateKeyAttribsCount = 4;
8424                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8425                         rv = CKR_TEMPLATE_INCONSISTENT;
8426                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8427                 {
8428                         switch (pPrivateKeyTemplate[i].type)
8429                         {
8430                                 case CKA_CLASS:
8431                                 case CKA_TOKEN:
8432                                 case CKA_PRIVATE:
8433                                 case CKA_KEY_TYPE:
8434                                         continue;
8435                                 default:
8436                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8437                         }
8438                 }
8439
8440                 if (rv == CKR_OK)
8441                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8442
8443                 // Store the attributes that are being supplied by the key generation to the object
8444                 if (rv == CKR_OK)
8445                 {
8446                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8447                         if (osobject == NULL_PTR || !osobject->isValid()) {
8448                                 rv = CKR_FUNCTION_FAILED;
8449                         } else if (osobject->startTransaction()) {
8450                                 bool bOK = true;
8451
8452                                 // Common Key Attributes
8453                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8454                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
8455                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8456
8457                                 // Common Private Key Attributes
8458                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8459                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8460                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8461                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8462
8463                                 // EC Private Key Attributes
8464                                 ByteString group;
8465                                 ByteString value;
8466                                 if (isPrivateKeyPrivate)
8467                                 {
8468                                         token->encrypt(priv->getEC(), group);
8469                                         token->encrypt(priv->getD(), value);
8470                                 }
8471                                 else
8472                                 {
8473                                         group = priv->getEC();
8474                                         value = priv->getD();
8475                                 }
8476                                 bOK = bOK && osobject->setAttribute(CKA_EC_PARAMS, group);
8477                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8478
8479                                 if (bOK)
8480                                         bOK = osobject->commitTransaction();
8481                                 else
8482                                         osobject->abortTransaction();
8483
8484                                 if (!bOK)
8485                                         rv = CKR_FUNCTION_FAILED;
8486                         } else
8487                                 rv = CKR_FUNCTION_FAILED;
8488                 }
8489         }
8490
8491         // Clean up
8492         ec->recycleKeyPair(kp);
8493         CryptoFactory::i()->recycleAsymmetricAlgorithm(ec);
8494
8495         // Remove keys that may have been created already when the function fails.
8496         if (rv != CKR_OK)
8497         {
8498                 if (*phPrivateKey != CK_INVALID_HANDLE)
8499                 {
8500                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8501                         handleManager->destroyObject(*phPrivateKey);
8502                         if (ospriv) ospriv->destroyObject();
8503                         *phPrivateKey = CK_INVALID_HANDLE;
8504                 }
8505
8506                 if (*phPublicKey != CK_INVALID_HANDLE)
8507                 {
8508                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8509                         handleManager->destroyObject(*phPublicKey);
8510                         if (ospub) ospub->destroyObject();
8511                         *phPublicKey = CK_INVALID_HANDLE;
8512                 }
8513         }
8514
8515         return rv;
8516 }
8517
8518 // Generate a DH key pair
8519 CK_RV SoftHSM::generateDH
8520 (CK_SESSION_HANDLE hSession,
8521         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8522         CK_ULONG ulPublicKeyAttributeCount,
8523         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8524         CK_ULONG ulPrivateKeyAttributeCount,
8525         CK_OBJECT_HANDLE_PTR phPublicKey,
8526         CK_OBJECT_HANDLE_PTR phPrivateKey,
8527         CK_BBOOL isPublicKeyOnToken,
8528         CK_BBOOL isPublicKeyPrivate,
8529         CK_BBOOL isPrivateKeyOnToken,
8530         CK_BBOOL isPrivateKeyPrivate)
8531 {
8532         *phPublicKey = CK_INVALID_HANDLE;
8533         *phPrivateKey = CK_INVALID_HANDLE;
8534
8535         // Get the session
8536         Session* session = (Session*)handleManager->getSession(hSession);
8537         if (session == NULL)
8538                 return CKR_SESSION_HANDLE_INVALID;
8539
8540         // Get the token
8541         Token* token = session->getToken();
8542         if (token == NULL)
8543                 return CKR_GENERAL_ERROR;
8544
8545         // Extract desired key information
8546         ByteString prime;
8547         ByteString generator;
8548         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8549         {
8550                 switch (pPublicKeyTemplate[i].type)
8551                 {
8552                         case CKA_PRIME:
8553                                 prime = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8554                                 break;
8555                         case CKA_BASE:
8556                                 generator = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8557                                 break;
8558                         default:
8559                                 break;
8560                 }
8561         }
8562
8563         // The parameters must be specified to be able to generate a key pair.
8564         if (prime.size() == 0 || generator.size() == 0) {
8565                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8566                 return CKR_TEMPLATE_INCOMPLETE;
8567         }
8568
8569         // Extract optional bit length
8570         size_t bitLen = 0;
8571         for (CK_ULONG i = 0; i < ulPrivateKeyAttributeCount; i++)
8572         {
8573                 switch (pPrivateKeyTemplate[i].type)
8574                 {
8575                         case CKA_VALUE_BITS:
8576                                 bitLen = *(CK_ULONG*)pPrivateKeyTemplate[i].pValue;
8577                                 break;
8578                         default:
8579                                 break;
8580                 }
8581         }
8582
8583         // Set the parameters
8584         DHParameters p;
8585         p.setP(prime);
8586         p.setG(generator);
8587         p.setXBitLength(bitLen);
8588
8589         // Generate key pair
8590         AsymmetricKeyPair* kp = NULL;
8591         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8592         if (dh == NULL) return CKR_GENERAL_ERROR;
8593         if (!dh->generateKeyPair(&kp, &p))
8594         {
8595                 ERROR_MSG("Could not generate key pair");
8596                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8597                 return CKR_GENERAL_ERROR;
8598         }
8599
8600         DHPublicKey* pub = (DHPublicKey*) kp->getPublicKey();
8601         DHPrivateKey* priv = (DHPrivateKey*) kp->getPrivateKey();
8602
8603         CK_RV rv = CKR_OK;
8604
8605         // Create a public key using C_CreateObject
8606         if (rv == CKR_OK)
8607         {
8608                 const CK_ULONG maxAttribs = 32;
8609                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
8610                 CK_KEY_TYPE publicKeyType = CKK_DH;
8611                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
8612                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
8613                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
8614                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
8615                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
8616                 };
8617                 CK_ULONG publicKeyAttribsCount = 4;
8618
8619                 // Add the additional
8620                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
8621                         rv = CKR_TEMPLATE_INCONSISTENT;
8622                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
8623                 {
8624                         switch (pPublicKeyTemplate[i].type)
8625                         {
8626                                 case CKA_CLASS:
8627                                 case CKA_TOKEN:
8628                                 case CKA_PRIVATE:
8629                                 case CKA_KEY_TYPE:
8630                                         continue;
8631                                 default:
8632                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
8633                         }
8634                 }
8635
8636                 if (rv == CKR_OK)
8637                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
8638
8639                 // Store the attributes that are being supplied by the key generation to the object
8640                 if (rv == CKR_OK)
8641                 {
8642                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
8643                         if (osobject == NULL_PTR || !osobject->isValid()) {
8644                                 rv = CKR_FUNCTION_FAILED;
8645                         } else if (osobject->startTransaction()) {
8646                                 bool bOK = true;
8647
8648                                 // Common Key Attributes
8649                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8650                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8651                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8652
8653                                 // DH Public Key Attributes
8654                                 ByteString value;
8655                                 if (isPublicKeyPrivate)
8656                                 {
8657                                         token->encrypt(pub->getY(), value);
8658                                 }
8659                                 else
8660                                 {
8661                                         value = pub->getY();
8662                                 }
8663                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
8664
8665                                 if (bOK)
8666                                         bOK = osobject->commitTransaction();
8667                                 else
8668                                         osobject->abortTransaction();
8669
8670                                 if (!bOK)
8671                                         rv = CKR_FUNCTION_FAILED;
8672                         } else
8673                                 rv = CKR_FUNCTION_FAILED;
8674                 }
8675         }
8676
8677         // Create a private key using C_CreateObject
8678         if (rv == CKR_OK)
8679         {
8680                 const CK_ULONG maxAttribs = 32;
8681                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
8682                 CK_KEY_TYPE privateKeyType = CKK_DH;
8683                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
8684                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
8685                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
8686                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
8687                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
8688                 };
8689                 CK_ULONG privateKeyAttribsCount = 4;
8690                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
8691                         rv = CKR_TEMPLATE_INCONSISTENT;
8692                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
8693                 {
8694                         switch (pPrivateKeyTemplate[i].type)
8695                         {
8696                                 case CKA_CLASS:
8697                                 case CKA_TOKEN:
8698                                 case CKA_PRIVATE:
8699                                 case CKA_KEY_TYPE:
8700                                         continue;
8701                                 default:
8702                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
8703                         }
8704                 }
8705
8706                 if (rv == CKR_OK)
8707                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
8708
8709                 // Store the attributes that are being supplied by the key generation to the object
8710                 if (rv == CKR_OK)
8711                 {
8712                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
8713                         if (osobject == NULL_PTR || !osobject->isValid()) {
8714                                 rv = CKR_FUNCTION_FAILED;
8715                         } else if (osobject->startTransaction()) {
8716                                 bool bOK = true;
8717
8718                                 // Common Key Attributes
8719                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8720                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_KEY_PAIR_GEN;
8721                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8722
8723                                 // Common Private Key Attributes
8724                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
8725                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
8726                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
8727                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
8728
8729                                 // DH Private Key Attributes
8730                                 ByteString bPrime;
8731                                 ByteString bGenerator;
8732                                 ByteString bValue;
8733                                 if (isPrivateKeyPrivate)
8734                                 {
8735                                         token->encrypt(priv->getP(), bPrime);
8736                                         token->encrypt(priv->getG(), bGenerator);
8737                                         token->encrypt(priv->getX(), bValue);
8738                                 }
8739                                 else
8740                                 {
8741                                         bPrime = priv->getP();
8742                                         bGenerator = priv->getG();
8743                                         bValue = priv->getX();
8744                                 }
8745                                 bOK = bOK && osobject->setAttribute(CKA_PRIME, bPrime);
8746                                 bOK = bOK && osobject->setAttribute(CKA_BASE, bGenerator);
8747                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, bValue);
8748
8749                                 if (bitLen == 0)
8750                                 {
8751                                         bOK = bOK && osobject->setAttribute(CKA_VALUE_BITS, (unsigned long)priv->getX().bits());
8752                                 }
8753
8754                                 if (bOK)
8755                                         bOK = osobject->commitTransaction();
8756                                 else
8757                                         osobject->abortTransaction();
8758
8759                                 if (!bOK)
8760                                         rv = CKR_FUNCTION_FAILED;
8761                         } else
8762                                 rv = CKR_FUNCTION_FAILED;
8763                 }
8764         }
8765
8766         // Clean up
8767         dh->recycleKeyPair(kp);
8768         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8769
8770         // Remove keys that may have been created already when the function fails.
8771         if (rv != CKR_OK)
8772         {
8773                 if (*phPrivateKey != CK_INVALID_HANDLE)
8774                 {
8775                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
8776                         handleManager->destroyObject(*phPrivateKey);
8777                         if (ospriv) ospriv->destroyObject();
8778                         *phPrivateKey = CK_INVALID_HANDLE;
8779                 }
8780
8781                 if (*phPublicKey != CK_INVALID_HANDLE)
8782                 {
8783                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
8784                         handleManager->destroyObject(*phPublicKey);
8785                         if (ospub) ospub->destroyObject();
8786                         *phPublicKey = CK_INVALID_HANDLE;
8787                 }
8788         }
8789
8790         return rv;
8791 }
8792
8793 // Generate a DH domain parameter set
8794 CK_RV SoftHSM::generateDHParameters
8795 (CK_SESSION_HANDLE hSession,
8796         CK_ATTRIBUTE_PTR pTemplate,
8797         CK_ULONG ulCount,
8798         CK_OBJECT_HANDLE_PTR phKey,
8799         CK_BBOOL isOnToken,
8800         CK_BBOOL isPrivate)
8801 {
8802         *phKey = CK_INVALID_HANDLE;
8803
8804         // Get the session
8805         Session* session = (Session*)handleManager->getSession(hSession);
8806         if (session == NULL)
8807                 return CKR_SESSION_HANDLE_INVALID;
8808
8809         // Get the token
8810         Token* token = session->getToken();
8811         if (token == NULL)
8812                 return CKR_GENERAL_ERROR;
8813
8814         // Extract desired parameter information
8815         size_t bitLen = 0;
8816         for (CK_ULONG i = 0; i < ulCount; i++)
8817         {
8818                 switch (pTemplate[i].type)
8819                 {
8820                         case CKA_PRIME_BITS:
8821                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
8822                                 {
8823                                         INFO_MSG("CKA_PRIME_BITS does not have the size of CK_ULONG");
8824                                         return CKR_ATTRIBUTE_VALUE_INVALID;
8825                                 }
8826                                 bitLen = *(CK_ULONG*)pTemplate[i].pValue;
8827                                 break;
8828                         default:
8829                                 break;
8830                 }
8831         }
8832
8833         // CKA_PRIME_BITS must be specified
8834         if (bitLen == 0)
8835         {
8836                 INFO_MSG("Missing CKA_PRIME_BITS in pTemplate");
8837                 return CKR_TEMPLATE_INCOMPLETE;
8838         }
8839
8840         // Generate domain parameters
8841         AsymmetricParameters* p = NULL;
8842         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
8843         if (dh == NULL) return CKR_GENERAL_ERROR;
8844         if (!dh->generateParameters(&p, (void *)bitLen))
8845         {
8846                 ERROR_MSG("Could not generate parameters");
8847                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8848                 return CKR_GENERAL_ERROR;
8849         }
8850
8851         DHParameters* params = (DHParameters*) p;
8852
8853         CK_RV rv = CKR_OK;
8854
8855         // Create the domain parameter object using C_CreateObject
8856         const CK_ULONG maxAttribs = 32;
8857         CK_OBJECT_CLASS objClass = CKO_DOMAIN_PARAMETERS;
8858         CK_KEY_TYPE keyType = CKK_DH;
8859         CK_ATTRIBUTE paramsAttribs[maxAttribs] = {
8860                 { CKA_CLASS, &objClass, sizeof(objClass) },
8861                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
8862                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
8863                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
8864         };
8865         CK_ULONG paramsAttribsCount = 4;
8866
8867         // Add the additional
8868         if (ulCount > (maxAttribs - paramsAttribsCount))
8869                 rv = CKR_TEMPLATE_INCONSISTENT;
8870         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
8871         {
8872                 switch (pTemplate[i].type)
8873                 {
8874                         case CKA_CLASS:
8875                         case CKA_TOKEN:
8876                         case CKA_PRIVATE:
8877                         case CKA_KEY_TYPE:
8878                                 continue;
8879                 default:
8880                         paramsAttribs[paramsAttribsCount++] = pTemplate[i];
8881                 }
8882         }
8883
8884         if (rv == CKR_OK)
8885                 rv = this->CreateObject(hSession, paramsAttribs, paramsAttribsCount, phKey,OBJECT_OP_GENERATE);
8886
8887         // Store the attributes that are being supplied
8888         if (rv == CKR_OK)
8889         {
8890                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
8891                 if (osobject == NULL_PTR || !osobject->isValid()) {
8892                         rv = CKR_FUNCTION_FAILED;
8893                 } else if (osobject->startTransaction()) {
8894                         bool bOK = true;
8895
8896                         // Common Attributes
8897                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
8898                         CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_DH_PKCS_PARAMETER_GEN;
8899                         bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
8900
8901                         // DH Domain Parameters Attributes
8902                         ByteString prime;
8903                         ByteString generator;
8904                         if (isPrivate)
8905                         {
8906                                 token->encrypt(params->getP(), prime);
8907                                 token->encrypt(params->getG(), generator);
8908                         }
8909                         else
8910                         {
8911                                 prime = params->getP();
8912                                 generator = params->getG();
8913                         }
8914                         bOK = bOK && osobject->setAttribute(CKA_PRIME, prime);
8915                         bOK = bOK && osobject->setAttribute(CKA_BASE, generator);
8916
8917                         if (bOK)
8918                                 bOK = osobject->commitTransaction();
8919                         else
8920                                 osobject->abortTransaction();
8921
8922                         if (!bOK)
8923                                 rv = CKR_FUNCTION_FAILED;
8924                 } else
8925                         rv = CKR_FUNCTION_FAILED;
8926         }
8927
8928         // Clean up
8929         dh->recycleParameters(p);
8930         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
8931
8932         // Remove parameters that may have been created already when the function fails.
8933         if (rv != CKR_OK)
8934         {
8935                 if (*phKey != CK_INVALID_HANDLE)
8936                 {
8937                         OSObject* osparams = (OSObject*)handleManager->getObject(*phKey);
8938                         handleManager->destroyObject(*phKey);
8939                         if (osparams) osparams->destroyObject();
8940                         *phKey = CK_INVALID_HANDLE;
8941                 }
8942         }
8943
8944         return rv;
8945 }
8946
8947 // Generate a GOST key pair
8948 CK_RV SoftHSM::generateGOST
8949 (CK_SESSION_HANDLE hSession,
8950         CK_ATTRIBUTE_PTR pPublicKeyTemplate,
8951         CK_ULONG ulPublicKeyAttributeCount,
8952         CK_ATTRIBUTE_PTR pPrivateKeyTemplate,
8953         CK_ULONG ulPrivateKeyAttributeCount,
8954         CK_OBJECT_HANDLE_PTR phPublicKey,
8955         CK_OBJECT_HANDLE_PTR phPrivateKey,
8956         CK_BBOOL isPublicKeyOnToken,
8957         CK_BBOOL isPublicKeyPrivate,
8958         CK_BBOOL isPrivateKeyOnToken,
8959         CK_BBOOL isPrivateKeyPrivate)
8960 {
8961         *phPublicKey = CK_INVALID_HANDLE;
8962         *phPrivateKey = CK_INVALID_HANDLE;
8963
8964         // Get the session
8965         Session* session = (Session*)handleManager->getSession(hSession);
8966         if (session == NULL)
8967                 return CKR_SESSION_HANDLE_INVALID;
8968
8969         // Get the token
8970         Token* token = session->getToken();
8971         if (token == NULL)
8972                 return CKR_GENERAL_ERROR;
8973
8974         // Extract desired key information
8975         ByteString param_3410;
8976         ByteString param_3411;
8977         ByteString param_28147;
8978         for (CK_ULONG i = 0; i < ulPublicKeyAttributeCount; i++)
8979         {
8980                 switch (pPublicKeyTemplate[i].type)
8981                 {
8982                         case CKA_GOSTR3410_PARAMS:
8983                                 param_3410 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8984                                 break;
8985                         case CKA_GOSTR3411_PARAMS:
8986                                 param_3411 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8987                                 break;
8988                         case CKA_GOST28147_PARAMS:
8989                                 param_28147 = ByteString((unsigned char*)pPublicKeyTemplate[i].pValue, pPublicKeyTemplate[i].ulValueLen);
8990                                 break;
8991                         default:
8992                                 break;
8993                 }
8994         }
8995
8996         // The parameters must be specified to be able to generate a key pair.
8997         if (param_3410.size() == 0 || param_3411.size() == 0) {
8998                 INFO_MSG("Missing parameter(s) in pPublicKeyTemplate");
8999                 return CKR_TEMPLATE_INCOMPLETE;
9000         }
9001
9002         // Set the parameters
9003         ECParameters p;
9004         p.setEC(param_3410);
9005
9006         // Generate key pair
9007         AsymmetricKeyPair* kp = NULL;
9008         AsymmetricAlgorithm* gost = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::GOST);
9009         if (gost == NULL) return CKR_GENERAL_ERROR;
9010         if (!gost->generateKeyPair(&kp, &p))
9011         {
9012                 ERROR_MSG("Could not generate key pair");
9013                 CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9014                 return CKR_GENERAL_ERROR;
9015         }
9016
9017         GOSTPublicKey* pub = (GOSTPublicKey*) kp->getPublicKey();
9018         GOSTPrivateKey* priv = (GOSTPrivateKey*) kp->getPrivateKey();
9019
9020         CK_RV rv = CKR_OK;
9021
9022         // Create a public key using C_CreateObject
9023         if (rv == CKR_OK)
9024         {
9025                 const CK_ULONG maxAttribs = 32;
9026                 CK_OBJECT_CLASS publicKeyClass = CKO_PUBLIC_KEY;
9027                 CK_KEY_TYPE publicKeyType = CKK_GOSTR3410;
9028                 CK_ATTRIBUTE publicKeyAttribs[maxAttribs] = {
9029                         { CKA_CLASS, &publicKeyClass, sizeof(publicKeyClass) },
9030                         { CKA_TOKEN, &isPublicKeyOnToken, sizeof(isPublicKeyOnToken) },
9031                         { CKA_PRIVATE, &isPublicKeyPrivate, sizeof(isPublicKeyPrivate) },
9032                         { CKA_KEY_TYPE, &publicKeyType, sizeof(publicKeyType) },
9033                 };
9034                 CK_ULONG publicKeyAttribsCount = 4;
9035
9036                 // Add the additional
9037                 if (ulPublicKeyAttributeCount > (maxAttribs - publicKeyAttribsCount))
9038                         rv = CKR_TEMPLATE_INCONSISTENT;
9039                 for (CK_ULONG i=0; i < ulPublicKeyAttributeCount && rv == CKR_OK; ++i)
9040                 {
9041                         switch (pPublicKeyTemplate[i].type)
9042                         {
9043                                 case CKA_CLASS:
9044                                 case CKA_TOKEN:
9045                                 case CKA_PRIVATE:
9046                                 case CKA_KEY_TYPE:
9047                                         continue;
9048                                 default:
9049                                         publicKeyAttribs[publicKeyAttribsCount++] = pPublicKeyTemplate[i];
9050                         }
9051                 }
9052
9053                 if (rv == CKR_OK)
9054                         rv = this->CreateObject(hSession,publicKeyAttribs,publicKeyAttribsCount,phPublicKey,OBJECT_OP_GENERATE);
9055
9056                 // Store the attributes that are being supplied by the key generation to the object
9057                 if (rv == CKR_OK)
9058                 {
9059                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPublicKey);
9060                         if (osobject == NULL_PTR || !osobject->isValid()) {
9061                                 rv = CKR_FUNCTION_FAILED;
9062                         } else if (osobject->startTransaction()) {
9063                                 bool bOK = true;
9064
9065                                 // Common Key Attributes
9066                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9067                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9068                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9069
9070                                 // EC Public Key Attributes
9071                                 ByteString point;
9072                                 if (isPublicKeyPrivate)
9073                                 {
9074                                         token->encrypt(pub->getQ(), point);
9075                                 }
9076                                 else
9077                                 {
9078                                         point = pub->getQ();
9079                                 }
9080                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, point);
9081
9082                                 if (bOK)
9083                                         bOK = osobject->commitTransaction();
9084                                 else
9085                                         osobject->abortTransaction();
9086
9087                                 if (!bOK)
9088                                         rv = CKR_FUNCTION_FAILED;
9089                         } else
9090                                 rv = CKR_FUNCTION_FAILED;
9091                 }
9092         }
9093
9094         // Create a private key using C_CreateObject
9095         if (rv == CKR_OK)
9096         {
9097                 const CK_ULONG maxAttribs = 32;
9098                 CK_OBJECT_CLASS privateKeyClass = CKO_PRIVATE_KEY;
9099                 CK_KEY_TYPE privateKeyType = CKK_GOSTR3410;
9100                 CK_ATTRIBUTE privateKeyAttribs[maxAttribs] = {
9101                         { CKA_CLASS, &privateKeyClass, sizeof(privateKeyClass) },
9102                         { CKA_TOKEN, &isPrivateKeyOnToken, sizeof(isPrivateKeyOnToken) },
9103                         { CKA_PRIVATE, &isPrivateKeyPrivate, sizeof(isPrivateKeyPrivate) },
9104                         { CKA_KEY_TYPE, &privateKeyType, sizeof(privateKeyType) },
9105                 };
9106                 CK_ULONG privateKeyAttribsCount = 4;
9107                 if (ulPrivateKeyAttributeCount > (maxAttribs - privateKeyAttribsCount))
9108                         rv = CKR_TEMPLATE_INCONSISTENT;
9109                 for (CK_ULONG i=0; i < ulPrivateKeyAttributeCount && rv == CKR_OK; ++i)
9110                 {
9111                         switch (pPrivateKeyTemplate[i].type)
9112                         {
9113                                 case CKA_CLASS:
9114                                 case CKA_TOKEN:
9115                                 case CKA_PRIVATE:
9116                                 case CKA_KEY_TYPE:
9117                                         continue;
9118                                 default:
9119                                         privateKeyAttribs[privateKeyAttribsCount++] = pPrivateKeyTemplate[i];
9120                         }
9121                 }
9122
9123                 if (rv == CKR_OK)
9124                         rv = this->CreateObject(hSession,privateKeyAttribs,privateKeyAttribsCount,phPrivateKey,OBJECT_OP_GENERATE);
9125
9126                 // Store the attributes that are being supplied by the key generation to the object
9127                 if (rv == CKR_OK)
9128                 {
9129                         OSObject* osobject = (OSObject*)handleManager->getObject(*phPrivateKey);
9130                         if (osobject == NULL_PTR || !osobject->isValid()) {
9131                                 rv = CKR_FUNCTION_FAILED;
9132                         } else if (osobject->startTransaction()) {
9133                                 bool bOK = true;
9134
9135                                 // Common Key Attributes
9136                                 bOK = bOK && osobject->setAttribute(CKA_LOCAL,true);
9137                                 CK_ULONG ulKeyGenMechanism = (CK_ULONG)CKM_EC_KEY_PAIR_GEN;
9138                                 bOK = bOK && osobject->setAttribute(CKA_KEY_GEN_MECHANISM,ulKeyGenMechanism);
9139
9140                                 // Common Private Key Attributes
9141                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9142                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9143                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9144                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE, bNeverExtractable);
9145
9146                                 // GOST Private Key Attributes
9147                                 ByteString value;
9148                                 ByteString param_a;
9149                                 ByteString param_b;
9150                                 ByteString param_c;
9151                                 if (isPrivateKeyPrivate)
9152                                 {
9153                                         token->encrypt(priv->getD(), value);
9154                                         token->encrypt(priv->getEC(), param_a);
9155                                         token->encrypt(param_3411, param_b);
9156                                         token->encrypt(param_28147, param_c);
9157                                 }
9158                                 else
9159                                 {
9160                                         value = priv->getD();
9161                                         param_a = priv->getEC();
9162                                         param_b = param_3411;
9163                                         param_c = param_28147;
9164                                 }
9165                                 bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9166                                 bOK = bOK && osobject->setAttribute(CKA_GOSTR3410_PARAMS, param_a);
9167                                 bOK = bOK && osobject->setAttribute(CKA_GOSTR3411_PARAMS, param_b);
9168                                 bOK = bOK && osobject->setAttribute(CKA_GOST28147_PARAMS, param_c);
9169
9170                                 if (bOK)
9171                                         bOK = osobject->commitTransaction();
9172                                 else
9173                                         osobject->abortTransaction();
9174
9175                                 if (!bOK)
9176                                         rv = CKR_FUNCTION_FAILED;
9177                         } else
9178                                   rv = CKR_FUNCTION_FAILED;
9179                 }
9180         }
9181
9182         // Clean up
9183         gost->recycleKeyPair(kp);
9184         CryptoFactory::i()->recycleAsymmetricAlgorithm(gost);
9185
9186         // Remove keys that may have been created already when the function fails.
9187         if (rv != CKR_OK)
9188         {
9189                 if (*phPrivateKey != CK_INVALID_HANDLE)
9190                 {
9191                         OSObject* ospriv = (OSObject*)handleManager->getObject(*phPrivateKey);
9192                         handleManager->destroyObject(*phPrivateKey);
9193                         if (ospriv) ospriv->destroyObject();
9194                         *phPrivateKey = CK_INVALID_HANDLE;
9195                 }
9196
9197                 if (*phPublicKey != CK_INVALID_HANDLE)
9198                 {
9199                         OSObject* ospub = (OSObject*)handleManager->getObject(*phPublicKey);
9200                         handleManager->destroyObject(*phPublicKey);
9201                         if (ospub) ospub->destroyObject();
9202                         *phPublicKey = CK_INVALID_HANDLE;
9203                 }
9204         }
9205
9206         return rv;
9207 }
9208
9209 // Derive a DH secret
9210 CK_RV SoftHSM::deriveDH
9211 (CK_SESSION_HANDLE hSession,
9212         CK_MECHANISM_PTR pMechanism,
9213         CK_OBJECT_HANDLE hBaseKey,
9214         CK_ATTRIBUTE_PTR pTemplate,
9215         CK_ULONG ulCount,
9216         CK_OBJECT_HANDLE_PTR phKey,
9217         CK_KEY_TYPE keyType,
9218         CK_BBOOL isOnToken,
9219         CK_BBOOL isPrivate)
9220 {
9221         *phKey = CK_INVALID_HANDLE;
9222
9223         if (pMechanism->pParameter == NULL_PTR) return CKR_MECHANISM_PARAM_INVALID;
9224         if (pMechanism->ulParameterLen == 0) return CKR_MECHANISM_PARAM_INVALID;
9225
9226         // Get the session
9227         Session* session = (Session*)handleManager->getSession(hSession);
9228         if (session == NULL)
9229                 return CKR_SESSION_HANDLE_INVALID;
9230
9231         // Get the token
9232         Token* token = session->getToken();
9233         if (token == NULL)
9234                 return CKR_GENERAL_ERROR;
9235
9236         // Extract desired parameter information
9237         size_t byteLen = 0;
9238         bool checkValue = true;
9239         for (CK_ULONG i = 0; i < ulCount; i++)
9240         {
9241                 switch (pTemplate[i].type)
9242                 {
9243                         case CKA_VALUE:
9244                                 INFO_MSG("CKA_VALUE must not be included");
9245                                 return CKR_ATTRIBUTE_READ_ONLY;
9246                         case CKA_VALUE_LEN:
9247                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9248                                 {
9249                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9250                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9251                                 }
9252                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9253                                 break;
9254                         case CKA_CHECK_VALUE:
9255                                 if (pTemplate[i].ulValueLen > 0)
9256                                 {
9257                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9258                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9259                                 }
9260                                 checkValue = false;
9261                                 break;
9262                         default:
9263                                 break;
9264                 }
9265         }
9266
9267         // Check the length
9268         switch (keyType)
9269         {
9270                 case CKK_GENERIC_SECRET:
9271                         if (byteLen == 0)
9272                         {
9273                                 INFO_MSG("CKA_VALUE_LEN must be set");
9274                                 return CKR_TEMPLATE_INCOMPLETE;
9275                         }
9276                         break;
9277 #ifndef WITH_FIPS
9278                 case CKK_DES:
9279                         if (byteLen != 0)
9280                         {
9281                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9282                                 return CKR_ATTRIBUTE_READ_ONLY;
9283                         }
9284                         byteLen = 8;
9285                         break;
9286 #endif
9287                 case CKK_DES2:
9288                         if (byteLen != 0)
9289                         {
9290                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9291                                 return CKR_ATTRIBUTE_READ_ONLY;
9292                         }
9293                         byteLen = 16;
9294                         break;
9295                 case CKK_DES3:
9296                         if (byteLen != 0)
9297                         {
9298                                 INFO_MSG("CKA_VALUE_LEN must not be set");
9299                                 return CKR_ATTRIBUTE_READ_ONLY;
9300                         }
9301                         byteLen = 24;
9302                         break;
9303                 case CKK_AES:
9304                         if (byteLen != 16 && byteLen != 24 && byteLen != 32)
9305                         {
9306                                 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
9307                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9308                         }
9309                         break;
9310                 default:
9311                         return CKR_ATTRIBUTE_VALUE_INVALID;
9312         }
9313
9314         // Get the base key handle
9315         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9316         if (baseKey == NULL || !baseKey->isValid())
9317                 return CKR_KEY_HANDLE_INVALID;
9318
9319         // Get the DH algorithm handler
9320         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
9321         if (dh == NULL)
9322                 return CKR_MECHANISM_INVALID;
9323
9324         // Get the keys
9325         PrivateKey* privateKey = dh->newPrivateKey();
9326         if (privateKey == NULL)
9327         {
9328                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9329                 return CKR_HOST_MEMORY;
9330         }
9331         if (getDHPrivateKey((DHPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9332         {
9333                 dh->recyclePrivateKey(privateKey);
9334                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9335                 return CKR_GENERAL_ERROR;
9336         }
9337
9338         ByteString mechParameters;
9339         mechParameters.resize(pMechanism->ulParameterLen);
9340         memcpy(&mechParameters[0], pMechanism->pParameter, pMechanism->ulParameterLen);
9341         PublicKey* publicKey = dh->newPublicKey();
9342         if (publicKey == NULL)
9343         {
9344                 dh->recyclePrivateKey(privateKey);
9345                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9346                 return CKR_HOST_MEMORY;
9347         }
9348         if (getDHPublicKey((DHPublicKey*)publicKey, (DHPrivateKey*)privateKey, mechParameters) != CKR_OK)
9349         {
9350                 dh->recyclePrivateKey(privateKey);
9351                 dh->recyclePublicKey(publicKey);
9352                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9353                 return CKR_GENERAL_ERROR;
9354         }
9355
9356         // Derive the secret
9357         SymmetricKey* secret = NULL;
9358         CK_RV rv = CKR_OK;
9359         if (!dh->deriveKey(&secret, publicKey, privateKey))
9360                 rv = CKR_GENERAL_ERROR;
9361         dh->recyclePrivateKey(privateKey);
9362         dh->recyclePublicKey(publicKey);
9363
9364         // Create the secret object using C_CreateObject
9365         const CK_ULONG maxAttribs = 32;
9366         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9367         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9368                 { CKA_CLASS, &objClass, sizeof(objClass) },
9369                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9370                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9371                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9372         };
9373         CK_ULONG secretAttribsCount = 4;
9374
9375         // Add the additional
9376         if (ulCount > (maxAttribs - secretAttribsCount))
9377                 rv = CKR_TEMPLATE_INCONSISTENT;
9378         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9379         {
9380                 switch (pTemplate[i].type)
9381                 {
9382                         case CKA_CLASS:
9383                         case CKA_TOKEN:
9384                         case CKA_PRIVATE:
9385                         case CKA_KEY_TYPE:
9386                         case CKA_CHECK_VALUE:
9387                                 continue;
9388                 default:
9389                         secretAttribs[secretAttribsCount++] = pTemplate[i];
9390                 }
9391         }
9392
9393         if (rv == CKR_OK)
9394                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9395
9396         // Store the attributes that are being supplied
9397         if (rv == CKR_OK)
9398         {
9399                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9400                 if (osobject == NULL_PTR || !osobject->isValid()) {
9401                         rv = CKR_FUNCTION_FAILED;
9402                 } else if (osobject->startTransaction()) {
9403                         bool bOK = true;
9404
9405                         // Common Attributes
9406                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9407
9408                         // Common Secret Key Attributes
9409                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9410                         {
9411                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9412                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9413                         }
9414                         else
9415                         {
9416                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9417                         }
9418                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9419                         {
9420                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9421                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9422                         }
9423                         else
9424                         {
9425                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9426                         }
9427
9428                         // Secret Attributes
9429                         ByteString secretValue = secret->getKeyBits();
9430                         ByteString value;
9431                         ByteString plainKCV;
9432                         ByteString kcv;
9433
9434                         if (byteLen > secretValue.size())
9435                         {
9436                                 INFO_MSG("The derived secret is too short");
9437                                 bOK = false;
9438                         }
9439                         else
9440                         {
9441                                 // Truncate value when requested, remove from the leading end
9442                                 if (byteLen < secretValue.size())
9443                                         secretValue.split(secretValue.size() - byteLen);
9444
9445                                 // Fix the odd parity for DES
9446                                 if (keyType == CKK_DES ||
9447                                     keyType == CKK_DES2 ||
9448                                     keyType == CKK_DES3)
9449                                 {
9450                                         for (size_t i = 0; i < secretValue.size(); i++)
9451                                         {
9452                                                 secretValue[i] = odd_parity[secretValue[i]];
9453                                         }
9454                                 }
9455
9456                                 // Get the KCV
9457                                 switch (keyType)
9458                                 {
9459                                         case CKK_GENERIC_SECRET:
9460                                                 secret->setBitLen(byteLen * 8);
9461                                                 plainKCV = secret->getKeyCheckValue();
9462                                                 break;
9463                                         case CKK_DES:
9464                                         case CKK_DES2:
9465                                         case CKK_DES3:
9466                                                 secret->setBitLen(byteLen * 7);
9467                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9468                                                 break;
9469                                         case CKK_AES:
9470                                                 secret->setBitLen(byteLen * 8);
9471                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9472                                                 break;
9473                                         default:
9474                                                 bOK = false;
9475                                                 break;
9476                                 }
9477
9478                                 if (isPrivate)
9479                                 {
9480                                         token->encrypt(secretValue, value);
9481                                         token->encrypt(plainKCV, kcv);
9482                                 }
9483                                 else
9484                                 {
9485                                         value = secretValue;
9486                                         kcv = plainKCV;
9487                                 }
9488                         }
9489                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9490                         if (checkValue)
9491                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9492
9493                         if (bOK)
9494                                 bOK = osobject->commitTransaction();
9495                         else
9496                                 osobject->abortTransaction();
9497
9498                         if (!bOK)
9499                                 rv = CKR_FUNCTION_FAILED;
9500                 } else
9501                         rv = CKR_FUNCTION_FAILED;
9502         }
9503
9504         // Clean up
9505         dh->recycleSymmetricKey(secret);
9506         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
9507
9508         // Remove secret that may have been created already when the function fails.
9509         if (rv != CKR_OK)
9510         {
9511                 if (*phKey != CK_INVALID_HANDLE)
9512                 {
9513                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9514                         handleManager->destroyObject(*phKey);
9515                         if (ossecret) ossecret->destroyObject();
9516                         *phKey = CK_INVALID_HANDLE;
9517                 }
9518         }
9519
9520         return rv;
9521 }
9522
9523 // Derive an ECDH secret
9524 CK_RV SoftHSM::deriveECDH
9525 (CK_SESSION_HANDLE hSession,
9526         CK_MECHANISM_PTR pMechanism,
9527         CK_OBJECT_HANDLE hBaseKey,
9528         CK_ATTRIBUTE_PTR pTemplate,
9529         CK_ULONG ulCount,
9530         CK_OBJECT_HANDLE_PTR phKey,
9531         CK_KEY_TYPE keyType,
9532         CK_BBOOL isOnToken,
9533         CK_BBOOL isPrivate)
9534 {
9535 #ifdef WITH_ECC
9536         *phKey = CK_INVALID_HANDLE;
9537
9538         if ((pMechanism->pParameter == NULL_PTR) ||
9539             (pMechanism->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)))
9540         {
9541                 DEBUG_MSG("pParameter must be of type CK_ECDH1_DERIVE_PARAMS");
9542                 return CKR_MECHANISM_PARAM_INVALID;
9543         }
9544         if (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->kdf != CKD_NULL)
9545         {
9546                 DEBUG_MSG("kdf must be CKD_NULL");
9547                 return CKR_MECHANISM_PARAM_INVALID;
9548         }
9549         if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulSharedDataLen != 0) ||
9550             (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pSharedData != NULL_PTR))
9551         {
9552                 DEBUG_MSG("there must be no shared data");
9553                 return CKR_MECHANISM_PARAM_INVALID;
9554         }
9555         if ((CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen == 0) ||
9556             (CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData == NULL_PTR))
9557         {
9558                 DEBUG_MSG("there must be a public data");
9559                 return CKR_MECHANISM_PARAM_INVALID;
9560         }
9561
9562         // Get the session
9563         Session* session = (Session*)handleManager->getSession(hSession);
9564         if (session == NULL)
9565                 return CKR_SESSION_HANDLE_INVALID;
9566
9567         // Get the token
9568         Token* token = session->getToken();
9569         if (token == NULL)
9570                 return CKR_GENERAL_ERROR;
9571
9572         // Extract desired parameter information
9573         size_t byteLen = 0;
9574         bool checkValue = true;
9575         for (CK_ULONG i = 0; i < ulCount; i++)
9576         {
9577                 switch (pTemplate[i].type)
9578                 {
9579                         case CKA_VALUE:
9580                                 INFO_MSG("CKA_VALUE must not be included");
9581                                 return CKR_ATTRIBUTE_READ_ONLY;
9582                         case CKA_VALUE_LEN:
9583                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
9584                                 {
9585                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
9586                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9587                                 }
9588                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
9589                                 break;
9590                         case CKA_CHECK_VALUE:
9591                                 if (pTemplate[i].ulValueLen > 0)
9592                                 {
9593                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
9594                                         return CKR_ATTRIBUTE_VALUE_INVALID;
9595                                 }
9596                                 checkValue = false;
9597                                 break;
9598                         default:
9599                                 break;
9600                 }
9601         }
9602
9603         // Check the length
9604         // byteLen == 0 impiles return max size the ECC can derive
9605         switch (keyType)
9606         {
9607                 case CKK_GENERIC_SECRET:
9608                         break;
9609 #ifndef WITH_FIPS
9610                 case CKK_DES:
9611                         if (byteLen != 0 && byteLen != 8)
9612                         {
9613                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 8");
9614                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9615                         }
9616                         byteLen = 8;
9617                         break;
9618 #endif
9619                 case CKK_DES2:
9620                         if (byteLen != 0 && byteLen != 16)
9621                         {
9622                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 16");
9623                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9624                         }
9625                         byteLen = 16;
9626                         break;
9627                 case CKK_DES3:
9628                         if (byteLen != 0 && byteLen != 24)
9629                         {
9630                                 INFO_MSG("CKA_VALUE_LEN must be 0 or 24");
9631                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9632                         }
9633                         byteLen = 24;
9634                         break;
9635                 case CKK_AES:
9636                         if (byteLen != 0 && byteLen != 16 && byteLen != 24 && byteLen != 32)
9637                         {
9638                                 INFO_MSG("CKA_VALUE_LEN must be 0, 16, 24, or 32");
9639                                 return CKR_ATTRIBUTE_VALUE_INVALID;
9640                         }
9641                         break;
9642                 default:
9643                         return CKR_ATTRIBUTE_VALUE_INVALID;
9644         }
9645
9646         // Get the base key handle
9647         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
9648         if (baseKey == NULL || !baseKey->isValid())
9649                 return CKR_KEY_HANDLE_INVALID;
9650
9651         // Get the ECDH algorithm handler
9652         AsymmetricAlgorithm* ecdh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDH);
9653         if (ecdh == NULL)
9654                 return CKR_MECHANISM_INVALID;
9655
9656         // Get the keys
9657         PrivateKey* privateKey = ecdh->newPrivateKey();
9658         if (privateKey == NULL)
9659         {
9660                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9661                 return CKR_HOST_MEMORY;
9662         }
9663         if (getECPrivateKey((ECPrivateKey*)privateKey, token, baseKey) != CKR_OK)
9664         {
9665                 ecdh->recyclePrivateKey(privateKey);
9666                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9667                 return CKR_GENERAL_ERROR;
9668         }
9669
9670         ByteString publicData;
9671         publicData.resize(CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9672         memcpy(&publicData[0],
9673                CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->pPublicData,
9674                CK_ECDH1_DERIVE_PARAMS_PTR(pMechanism->pParameter)->ulPublicDataLen);
9675         PublicKey* publicKey = ecdh->newPublicKey();
9676         if (publicKey == NULL)
9677         {
9678                 ecdh->recyclePrivateKey(privateKey);
9679                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9680                 return CKR_HOST_MEMORY;
9681         }
9682         if (getECDHPublicKey((ECPublicKey*)publicKey, (ECPrivateKey*)privateKey, publicData) != CKR_OK)
9683         {
9684                 ecdh->recyclePrivateKey(privateKey);
9685                 ecdh->recyclePublicKey(publicKey);
9686                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9687                 return CKR_GENERAL_ERROR;
9688         }
9689
9690         // Derive the secret
9691         SymmetricKey* secret = NULL;
9692         CK_RV rv = CKR_OK;
9693         if (!ecdh->deriveKey(&secret, publicKey, privateKey))
9694                 rv = CKR_GENERAL_ERROR;
9695         ecdh->recyclePrivateKey(privateKey);
9696         ecdh->recyclePublicKey(publicKey);
9697
9698         // Create the secret object using C_CreateObject
9699         const CK_ULONG maxAttribs = 32;
9700         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
9701         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
9702                 { CKA_CLASS, &objClass, sizeof(objClass) },
9703                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
9704                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
9705                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
9706         };
9707         CK_ULONG secretAttribsCount = 4;
9708
9709         // Add the additional
9710         if (ulCount > (maxAttribs - secretAttribsCount))
9711                 rv = CKR_TEMPLATE_INCONSISTENT;
9712         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
9713         {
9714                 switch (pTemplate[i].type)
9715                 {
9716                         case CKA_CLASS:
9717                         case CKA_TOKEN:
9718                         case CKA_PRIVATE:
9719                         case CKA_KEY_TYPE:
9720                         case CKA_CHECK_VALUE:
9721                                 continue;
9722                 default:
9723                         secretAttribs[secretAttribsCount++] = pTemplate[i];
9724                 }
9725         }
9726
9727         if (rv == CKR_OK)
9728                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
9729
9730         // Store the attributes that are being supplied
9731         if (rv == CKR_OK)
9732         {
9733                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
9734                 if (osobject == NULL_PTR || !osobject->isValid()) {
9735                         rv = CKR_FUNCTION_FAILED;
9736                 } else if (osobject->startTransaction()) {
9737                         bool bOK = true;
9738
9739                         // Common Attributes
9740                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
9741
9742                         // Common Secret Key Attributes
9743                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
9744                         {
9745                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
9746                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
9747                         }
9748                         else
9749                         {
9750                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
9751                         }
9752                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
9753                         {
9754                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
9755                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
9756                         }
9757                         else
9758                         {
9759                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
9760                         }
9761
9762                         // Secret Attributes
9763                         ByteString secretValue = secret->getKeyBits();
9764                         ByteString value;
9765                         ByteString plainKCV;
9766                         ByteString kcv;
9767
9768                         // For generic and AES keys:
9769                         // default to return max size available.
9770                         if (byteLen == 0)
9771                         {
9772                                 switch (keyType)
9773                                 {
9774                                         case CKK_GENERIC_SECRET:
9775                                                 byteLen = secretValue.size();
9776                                                 break;
9777                                         case CKK_AES:
9778                                                 if (secretValue.size() >= 32)
9779                                                         byteLen = 32;
9780                                                 else if (secretValue.size() >= 24)
9781                                                         byteLen = 24;
9782                                                 else
9783                                                         byteLen = 16;
9784                                 }
9785                         }
9786
9787                         if (byteLen > secretValue.size())
9788                         {
9789                                 INFO_MSG("The derived secret is too short");
9790                                 bOK = false;
9791                         }
9792                         else
9793                         {
9794                                 // Truncate value when requested, remove from the leading end
9795                                 if (byteLen < secretValue.size())
9796                                         secretValue.split(secretValue.size() - byteLen);
9797
9798                                 // Fix the odd parity for DES
9799                                 if (keyType == CKK_DES ||
9800                                     keyType == CKK_DES2 ||
9801                                     keyType == CKK_DES3)
9802                                 {
9803                                         for (size_t i = 0; i < secretValue.size(); i++)
9804                                         {
9805                                                 secretValue[i] = odd_parity[secretValue[i]];
9806                                         }
9807                                 }
9808
9809                                 // Get the KCV
9810                                 switch (keyType)
9811                                 {
9812                                         case CKK_GENERIC_SECRET:
9813                                                 secret->setBitLen(byteLen * 8);
9814                                                 plainKCV = secret->getKeyCheckValue();
9815                                                 break;
9816                                         case CKK_DES:
9817                                         case CKK_DES2:
9818                                         case CKK_DES3:
9819                                                 secret->setBitLen(byteLen * 7);
9820                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
9821                                                 break;
9822                                         case CKK_AES:
9823                                                 secret->setBitLen(byteLen * 8);
9824                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
9825                                                 break;
9826                                         default:
9827                                                 bOK = false;
9828                                                 break;
9829                                 }
9830
9831                                 if (isPrivate)
9832                                 {
9833                                         token->encrypt(secretValue, value);
9834                                         token->encrypt(plainKCV, kcv);
9835                                 }
9836                                 else
9837                                 {
9838                                         value = secretValue;
9839                                         kcv = plainKCV;
9840                                 }
9841                         }
9842                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
9843                         if (checkValue)
9844                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
9845
9846                         if (bOK)
9847                                 bOK = osobject->commitTransaction();
9848                         else
9849                                 osobject->abortTransaction();
9850
9851                         if (!bOK)
9852                                 rv = CKR_FUNCTION_FAILED;
9853                 } else
9854                         rv = CKR_FUNCTION_FAILED;
9855         }
9856
9857         // Clean up
9858         ecdh->recycleSymmetricKey(secret);
9859         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecdh);
9860
9861         // Remove secret that may have been created already when the function fails.
9862         if (rv != CKR_OK)
9863         {
9864                 if (*phKey != CK_INVALID_HANDLE)
9865                 {
9866                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
9867                         handleManager->destroyObject(*phKey);
9868                         if (ossecret) ossecret->destroyObject();
9869                         *phKey = CK_INVALID_HANDLE;
9870                 }
9871         }
9872
9873         return rv;
9874 #else
9875         return CKR_MECHANISM_INVALID;
9876 #endif
9877 }
9878
9879 // Derive an symmetric secret
9880 CK_RV SoftHSM::deriveSymmetric
9881 (CK_SESSION_HANDLE hSession,
9882         CK_MECHANISM_PTR pMechanism,
9883         CK_OBJECT_HANDLE hBaseKey,
9884         CK_ATTRIBUTE_PTR pTemplate,
9885         CK_ULONG ulCount,
9886         CK_OBJECT_HANDLE_PTR phKey,
9887         CK_KEY_TYPE keyType,
9888         CK_BBOOL isOnToken,
9889         CK_BBOOL isPrivate)
9890 {
9891         *phKey = CK_INVALID_HANDLE;
9892
9893         if (pMechanism->pParameter == NULL_PTR)
9894         {
9895                 DEBUG_MSG("pParameter must be supplied");
9896                 return CKR_MECHANISM_PARAM_INVALID;
9897         }
9898
9899         ByteString data;
9900
9901         if ((pMechanism->mechanism == CKM_DES_ECB_ENCRYPT_DATA ||
9902             pMechanism->mechanism == CKM_DES3_ECB_ENCRYPT_DATA) &&
9903             pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9904         {
9905                 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9906                 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9907                 if (ulLen == 0 || pData == NULL_PTR)
9908                 {
9909                         DEBUG_MSG("There must be data in the parameter");
9910                         return CKR_MECHANISM_PARAM_INVALID;
9911                 }
9912                 if (ulLen % 8 != 0)
9913                 {
9914                         DEBUG_MSG("The data must be a multiple of 8 bytes long");
9915                         return CKR_MECHANISM_PARAM_INVALID;
9916                 }
9917                 data.resize(ulLen);
9918                 memcpy(&data[0],
9919                        pData,
9920                        ulLen);
9921         }
9922         else if ((pMechanism->mechanism == CKM_DES_CBC_ENCRYPT_DATA ||
9923                  pMechanism->mechanism == CKM_DES3_CBC_ENCRYPT_DATA) &&
9924                  pMechanism->ulParameterLen == sizeof(CK_DES_CBC_ENCRYPT_DATA_PARAMS))
9925         {
9926                 CK_BYTE_PTR pData = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9927                 CK_ULONG length = CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9928                 if (length == 0 || pData == NULL_PTR)
9929                 {
9930                         DEBUG_MSG("There must be data in the parameter");
9931                         return CKR_MECHANISM_PARAM_INVALID;
9932                 }
9933                 if (length % 8 != 0)
9934                 {
9935                         DEBUG_MSG("The data must be a multiple of 8 bytes long");
9936                         return CKR_MECHANISM_PARAM_INVALID;
9937                 }
9938                 data.resize(length);
9939                 memcpy(&data[0],
9940                        pData,
9941                        length);
9942         }
9943         else if (pMechanism->mechanism == CKM_AES_ECB_ENCRYPT_DATA &&
9944                  pMechanism->ulParameterLen == sizeof(CK_KEY_DERIVATION_STRING_DATA))
9945         {
9946                 CK_BYTE_PTR pData = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->pData;
9947                 CK_ULONG ulLen = CK_KEY_DERIVATION_STRING_DATA_PTR(pMechanism->pParameter)->ulLen;
9948                 if (ulLen == 0 || pData == NULL_PTR)
9949                 {
9950                         DEBUG_MSG("There must be data in the parameter");
9951                         return CKR_MECHANISM_PARAM_INVALID;
9952                 }
9953                 if (ulLen % 16 != 0)
9954                 {
9955                         DEBUG_MSG("The data must be a multiple of 16 bytes long");
9956                         return CKR_MECHANISM_PARAM_INVALID;
9957                 }
9958                 data.resize(ulLen);
9959                 memcpy(&data[0],
9960                        pData,
9961                        ulLen);
9962         }
9963         else if ((pMechanism->mechanism == CKM_AES_CBC_ENCRYPT_DATA) &&
9964                  pMechanism->ulParameterLen == sizeof(CK_AES_CBC_ENCRYPT_DATA_PARAMS))
9965         {
9966                 CK_BYTE_PTR pData = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->pData;
9967                 CK_ULONG length = CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->length;
9968                 if (length == 0 || pData == NULL_PTR)
9969                 {
9970                         DEBUG_MSG("There must be data in the parameter");
9971                         return CKR_MECHANISM_PARAM_INVALID;
9972                 }
9973                 if (length % 16 != 0)
9974                 {
9975                         DEBUG_MSG("The data must be a multiple of 16 bytes long");
9976                         return CKR_MECHANISM_PARAM_INVALID;
9977                 }
9978                 data.resize(length);
9979                 memcpy(&data[0],
9980                        pData,
9981                        length);
9982         }
9983         else
9984         {
9985                 DEBUG_MSG("pParameter is invalid");
9986                 return CKR_MECHANISM_PARAM_INVALID;
9987         }
9988
9989         // Get the session
9990         Session* session = (Session*)handleManager->getSession(hSession);
9991         if (session == NULL)
9992                 return CKR_SESSION_HANDLE_INVALID;
9993
9994         // Get the token
9995         Token* token = session->getToken();
9996         if (token == NULL)
9997                 return CKR_GENERAL_ERROR;
9998
9999         // Extract desired parameter information
10000         size_t byteLen = 0;
10001         bool checkValue = true;
10002         for (CK_ULONG i = 0; i < ulCount; i++)
10003         {
10004                 switch (pTemplate[i].type)
10005                 {
10006                         case CKA_VALUE:
10007                                 INFO_MSG("CKA_VALUE must not be included");
10008                                 return CKR_ATTRIBUTE_READ_ONLY;
10009                         case CKA_VALUE_LEN:
10010                                 if (pTemplate[i].ulValueLen != sizeof(CK_ULONG))
10011                                 {
10012                                         INFO_MSG("CKA_VALUE_LEN does not have the size of CK_ULONG");
10013                                         return CKR_ATTRIBUTE_VALUE_INVALID;
10014                                 }
10015                                 byteLen = *(CK_ULONG*)pTemplate[i].pValue;
10016                                 break;
10017                         case CKA_CHECK_VALUE:
10018                                 if (pTemplate[i].ulValueLen > 0)
10019                                 {
10020                                         INFO_MSG("CKA_CHECK_VALUE must be a no-value (0 length) entry");
10021                                         return CKR_ATTRIBUTE_VALUE_INVALID;
10022                                 }
10023                                 checkValue = false;
10024                                 break;
10025                         default:
10026                                 break;
10027                 }
10028         }
10029
10030         // Check the length
10031         switch (keyType)
10032         {
10033                 case CKK_GENERIC_SECRET:
10034                         if (byteLen == 0)
10035                         {
10036                                 INFO_MSG("CKA_VALUE_LEN must be set");
10037                                 return CKR_TEMPLATE_INCOMPLETE;
10038                         }
10039                         break;
10040 #ifndef WITH_FIPS
10041                 case CKK_DES:
10042                         if (byteLen != 0)
10043                         {
10044                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10045                                 return CKR_ATTRIBUTE_READ_ONLY;
10046                         }
10047                         byteLen = 8;
10048                         break;
10049 #endif
10050                 case CKK_DES2:
10051                         if (byteLen != 0)
10052                         {
10053                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10054                                 return CKR_ATTRIBUTE_READ_ONLY;
10055                         }
10056                         byteLen = 16;
10057                         break;
10058                 case CKK_DES3:
10059                         if (byteLen != 0)
10060                         {
10061                                 INFO_MSG("CKA_VALUE_LEN must not be set");
10062                                 return CKR_ATTRIBUTE_READ_ONLY;
10063                         }
10064                         byteLen = 24;
10065                         break;
10066                 case CKK_AES:
10067                         if (byteLen != 16 && byteLen != 24 && byteLen != 32)
10068                         {
10069                                 INFO_MSG("CKA_VALUE_LEN must be 16, 24, or 32");
10070                                 return CKR_ATTRIBUTE_VALUE_INVALID;
10071                         }
10072                         break;
10073                 default:
10074                         return CKR_ATTRIBUTE_VALUE_INVALID;
10075         }
10076
10077         // Get the symmetric algorithm matching the mechanism
10078         SymAlgo::Type algo = SymAlgo::Unknown;
10079         SymMode::Type mode = SymMode::Unknown;
10080         bool padding = false;
10081         ByteString iv;
10082         size_t bb = 8;
10083         switch(pMechanism->mechanism) {
10084 #ifndef WITH_FIPS
10085                 case CKM_DES_ECB_ENCRYPT_DATA:
10086                         algo = SymAlgo::DES;
10087                         mode = SymMode::ECB;
10088                         bb = 7;
10089                         break;
10090                 case CKM_DES_CBC_ENCRYPT_DATA:
10091                         algo = SymAlgo::DES;
10092                         mode = SymMode::CBC;
10093                         bb = 7;
10094                         iv.resize(8);
10095                         memcpy(&iv[0],
10096                                &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10097                                8);
10098                         break;
10099 #endif
10100                 case CKM_DES3_ECB_ENCRYPT_DATA:
10101                         algo = SymAlgo::DES3;
10102                         mode = SymMode::ECB;
10103                         bb = 7;
10104                         break;
10105                 case CKM_DES3_CBC_ENCRYPT_DATA:
10106                         algo = SymAlgo::DES3;
10107                         mode = SymMode::CBC;
10108                         bb = 7;
10109                         iv.resize(8);
10110                         memcpy(&iv[0],
10111                                &(CK_DES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10112                                8);
10113                         break;
10114                 case CKM_AES_ECB_ENCRYPT_DATA:
10115                         algo = SymAlgo::AES;
10116                         mode = SymMode::ECB;
10117                         break;
10118                 case CKM_AES_CBC_ENCRYPT_DATA:
10119                         algo = SymAlgo::AES;
10120                         mode = SymMode::CBC;
10121                         iv.resize(16);
10122                         memcpy(&iv[0],
10123                                &(CK_AES_CBC_ENCRYPT_DATA_PARAMS_PTR(pMechanism->pParameter)->iv[0]),
10124                                16);
10125                         break;
10126                 default:
10127                         return CKR_MECHANISM_INVALID;
10128         }
10129
10130         // Check the key handle
10131         OSObject *baseKey = (OSObject *)handleManager->getObject(hBaseKey);
10132         if (baseKey == NULL_PTR || !baseKey->isValid()) return CKR_OBJECT_HANDLE_INVALID;
10133
10134         SymmetricAlgorithm* cipher = CryptoFactory::i()->getSymmetricAlgorithm(algo);
10135         if (cipher == NULL) return CKR_MECHANISM_INVALID;
10136
10137         SymmetricKey* secretkey = new SymmetricKey();
10138
10139         if (getSymmetricKey(secretkey, token, baseKey) != CKR_OK)
10140         {
10141                 cipher->recycleKey(secretkey);
10142                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10143                 return CKR_GENERAL_ERROR;
10144         }
10145
10146         // adjust key bit length
10147         secretkey->setBitLen(secretkey->getKeyBits().size() * bb);
10148
10149         // Initialize encryption
10150         if (!cipher->encryptInit(secretkey, mode, iv, padding))
10151         {
10152                 cipher->recycleKey(secretkey);
10153                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10154                 return CKR_MECHANISM_INVALID;
10155         }
10156
10157         // Get the data
10158         ByteString secretValue;
10159
10160         // Encrypt the data
10161         if (!cipher->encryptUpdate(data, secretValue))
10162         {
10163                 cipher->recycleKey(secretkey);
10164                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10165                 return CKR_GENERAL_ERROR;
10166         }
10167
10168         // Finalize encryption
10169         ByteString encryptedFinal;
10170         if (!cipher->encryptFinal(encryptedFinal))
10171         {
10172                 cipher->recycleKey(secretkey);
10173                 CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10174                 return CKR_GENERAL_ERROR;
10175         }
10176         cipher->recycleKey(secretkey);
10177         CryptoFactory::i()->recycleSymmetricAlgorithm(cipher);
10178         secretValue += encryptedFinal;
10179
10180         // Create the secret object using C_CreateObject
10181         const CK_ULONG maxAttribs = 32;
10182         CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
10183         CK_ATTRIBUTE secretAttribs[maxAttribs] = {
10184                 { CKA_CLASS, &objClass, sizeof(objClass) },
10185                 { CKA_TOKEN, &isOnToken, sizeof(isOnToken) },
10186                 { CKA_PRIVATE, &isPrivate, sizeof(isPrivate) },
10187                 { CKA_KEY_TYPE, &keyType, sizeof(keyType) },
10188         };
10189         CK_ULONG secretAttribsCount = 4;
10190
10191         // Add the additional
10192         CK_RV rv = CKR_OK;
10193         if (ulCount > (maxAttribs - secretAttribsCount))
10194                 rv = CKR_TEMPLATE_INCONSISTENT;
10195         for (CK_ULONG i=0; i < ulCount && rv == CKR_OK; ++i)
10196         {
10197                 switch (pTemplate[i].type)
10198                 {
10199                         case CKA_CLASS:
10200                         case CKA_TOKEN:
10201                         case CKA_PRIVATE:
10202                         case CKA_KEY_TYPE:
10203                         case CKA_CHECK_VALUE:
10204                                 continue;
10205                         default:
10206                                 secretAttribs[secretAttribsCount++] = pTemplate[i];
10207                 }
10208         }
10209
10210         if (rv == CKR_OK)
10211                 rv = this->CreateObject(hSession, secretAttribs, secretAttribsCount, phKey, OBJECT_OP_DERIVE);
10212
10213         // Store the attributes that are being supplied
10214         if (rv == CKR_OK)
10215         {
10216                 OSObject* osobject = (OSObject*)handleManager->getObject(*phKey);
10217                 if (osobject == NULL_PTR || !osobject->isValid()) {
10218                         rv = CKR_FUNCTION_FAILED;
10219                 } else if (osobject->startTransaction()) {
10220                         bool bOK = true;
10221
10222                         // Common Attributes
10223                         bOK = bOK && osobject->setAttribute(CKA_LOCAL,false);
10224
10225                         // Common Secret Key Attributes
10226                         if (baseKey->getBooleanValue(CKA_ALWAYS_SENSITIVE, false))
10227                         {
10228                                 bool bAlwaysSensitive = osobject->getBooleanValue(CKA_SENSITIVE, false);
10229                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,bAlwaysSensitive);
10230                         }
10231                         else
10232                         {
10233                                 bOK = bOK && osobject->setAttribute(CKA_ALWAYS_SENSITIVE,false);
10234                         }
10235                         if (baseKey->getBooleanValue(CKA_NEVER_EXTRACTABLE, true))
10236                         {
10237                                 bool bNeverExtractable = osobject->getBooleanValue(CKA_EXTRACTABLE, false) == false;
10238                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,bNeverExtractable);
10239                         }
10240                         else
10241                         {
10242                                 bOK = bOK && osobject->setAttribute(CKA_NEVER_EXTRACTABLE,false);
10243                         }
10244
10245                         ByteString value;
10246                         ByteString plainKCV;
10247                         ByteString kcv;
10248
10249                         if (byteLen > secretValue.size())
10250                         {
10251                                 INFO_MSG("The derived secret is too short");
10252                                 bOK = false;
10253                         }
10254                         else
10255                         {
10256                                 // Truncate value when requested, remove from the trailing end
10257                                 if (byteLen < secretValue.size())
10258                                         secretValue.resize(byteLen);
10259
10260                                 // Fix the odd parity for DES
10261                                 if (keyType == CKK_DES ||
10262                                     keyType == CKK_DES2 ||
10263                                     keyType == CKK_DES3)
10264                                 {
10265                                         for (size_t i = 0; i < secretValue.size(); i++)
10266                                         {
10267                                                 secretValue[i] = odd_parity[secretValue[i]];
10268                                         }
10269                                 }
10270
10271                                 // Get the KCV
10272                                 SymmetricKey* secret = new SymmetricKey();
10273                                 secret->setKeyBits(secretValue);
10274                                 switch (keyType)
10275                                 {
10276                                         case CKK_GENERIC_SECRET:
10277                                                 secret->setBitLen(byteLen * 8);
10278                                                 plainKCV = secret->getKeyCheckValue();
10279                                                 break;
10280                                         case CKK_DES:
10281                                         case CKK_DES2:
10282                                         case CKK_DES3:
10283                                                 secret->setBitLen(byteLen * 7);
10284                                                 plainKCV = ((DESKey*)secret)->getKeyCheckValue();
10285                                                 break;
10286                                         case CKK_AES:
10287                                                 secret->setBitLen(byteLen * 8);
10288                                                 plainKCV = ((AESKey*)secret)->getKeyCheckValue();
10289                                                 break;
10290                                         default:
10291                                                 bOK = false;
10292                                                 break;
10293                                 }
10294                                 delete secret;
10295
10296                                 if (isPrivate)
10297                                 {
10298                                         token->encrypt(secretValue, value);
10299                                         token->encrypt(plainKCV, kcv);
10300                                 }
10301                                 else
10302                                 {
10303                                         value = secretValue;
10304                                         kcv = plainKCV;
10305                                 }
10306                         }
10307                         bOK = bOK && osobject->setAttribute(CKA_VALUE, value);
10308                         if (checkValue)
10309                                 bOK = bOK && osobject->setAttribute(CKA_CHECK_VALUE, kcv);
10310
10311                         if (bOK)
10312                                 bOK = osobject->commitTransaction();
10313                         else
10314                                 osobject->abortTransaction();
10315
10316                         if (!bOK)
10317                                 rv = CKR_FUNCTION_FAILED;
10318                 } else
10319                         rv = CKR_FUNCTION_FAILED;
10320         }
10321
10322         // Remove secret that may have been created already when the function fails.
10323         if (rv != CKR_OK)
10324         {
10325                 if (*phKey != CK_INVALID_HANDLE)
10326                 {
10327                         OSObject* ossecret = (OSObject*)handleManager->getObject(*phKey);
10328                         handleManager->destroyObject(*phKey);
10329                         if (ossecret) ossecret->destroyObject();
10330                         *phKey = CK_INVALID_HANDLE;
10331                 }
10332         }
10333
10334         return rv;
10335 }
10336
10337 CK_RV SoftHSM::CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject, int op)
10338 {
10339         if (!isInitialised) return CKR_CRYPTOKI_NOT_INITIALIZED;
10340
10341         if (pTemplate == NULL_PTR) return CKR_ARGUMENTS_BAD;
10342         if (phObject == NULL_PTR) return CKR_ARGUMENTS_BAD;
10343
10344         // Get the session
10345         Session* session = (Session*)handleManager->getSession(hSession);
10346         if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
10347
10348         // Get the slot
10349         Slot* slot = session->getSlot();
10350         if (slot == NULL_PTR) return CKR_GENERAL_ERROR;
10351
10352         // Get the token
10353         Token* token = session->getToken();
10354         if (token == NULL_PTR) return CKR_GENERAL_ERROR;
10355
10356         // Extract information from the template that is needed to create the object.
10357         CK_OBJECT_CLASS objClass = CKO_DATA;
10358         CK_KEY_TYPE keyType = CKK_RSA;
10359         CK_CERTIFICATE_TYPE certType = CKC_X_509;
10360         CK_BBOOL isOnToken = CK_FALSE;
10361         CK_BBOOL isPrivate = CK_TRUE;
10362         bool isImplicit = false;
10363         CK_RV rv = extractObjectInformation(pTemplate,ulCount,objClass,keyType,certType, isOnToken, isPrivate, isImplicit);
10364         if (rv != CKR_OK)
10365         {
10366                 ERROR_MSG("Mandatory attribute not present in template");
10367                 return rv;
10368         }
10369
10370         // Check user credentials
10371         rv = haveWrite(session->getState(), isOnToken, isPrivate);
10372         if (rv != CKR_OK)
10373         {
10374                 if (rv == CKR_USER_NOT_LOGGED_IN)
10375                         INFO_MSG("User is not authorized");
10376                 if (rv == CKR_SESSION_READ_ONLY)
10377                         INFO_MSG("Session is read-only");
10378
10379                 return rv;
10380         }
10381
10382         // Change order of attributes
10383         const CK_ULONG maxAttribs = 32;
10384         CK_ATTRIBUTE attribs[maxAttribs];
10385         CK_ATTRIBUTE saveAttribs[maxAttribs];
10386         CK_ULONG attribsCount = 0;
10387         CK_ULONG saveAttribsCount = 0;
10388         if (ulCount > maxAttribs)
10389         {
10390                 return CKR_TEMPLATE_INCONSISTENT;
10391         }
10392         for (CK_ULONG i=0; i < ulCount; i++)
10393         {
10394                 switch (pTemplate[i].type)
10395                 {
10396                         case CKA_CHECK_VALUE:
10397                                 saveAttribs[saveAttribsCount++] = pTemplate[i];
10398                                 break;
10399                         default:
10400                                 attribs[attribsCount++] = pTemplate[i];
10401                 }
10402         }
10403         for (CK_ULONG i=0; i < saveAttribsCount; i++)
10404         {
10405                 attribs[attribsCount++] = saveAttribs[i];
10406         }
10407
10408         P11Object* p11object = NULL;
10409         rv = newP11Object(objClass,keyType,certType,&p11object);
10410         if (rv != CKR_OK)
10411                 return rv;
10412
10413         // Create the object in session or on the token
10414         OSObject *object = NULL_PTR;
10415         if (isOnToken)
10416         {
10417                 object = (OSObject*) token->createObject();
10418         }
10419         else
10420         {
10421                 object = sessionObjectStore->createObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE);
10422         }
10423
10424         if (object == NULL || !p11object->init(object))
10425         {
10426                 delete p11object;
10427                 return CKR_GENERAL_ERROR;
10428         }
10429
10430         rv = p11object->saveTemplate(token, isPrivate != CK_FALSE, attribs,attribsCount,op);
10431         delete p11object;
10432         if (rv != CKR_OK)
10433                 return rv;
10434
10435         if (op == OBJECT_OP_CREATE)
10436         {
10437                 if (objClass == CKO_PUBLIC_KEY &&
10438                     (!object->startTransaction() ||
10439                     !object->setAttribute(CKA_LOCAL, false) ||
10440                     !object->commitTransaction()))
10441                 {
10442                         return CKR_GENERAL_ERROR;
10443                 }
10444
10445                 if ((objClass == CKO_SECRET_KEY || objClass == CKO_PRIVATE_KEY) &&
10446                     (!object->startTransaction() ||
10447                     !object->setAttribute(CKA_LOCAL, false) ||
10448                     !object->setAttribute(CKA_ALWAYS_SENSITIVE, false) ||
10449                     !object->setAttribute(CKA_NEVER_EXTRACTABLE, false) ||
10450                     !object->commitTransaction()))
10451                 {
10452                         return CKR_GENERAL_ERROR;
10453                 }
10454         }
10455
10456         if (isOnToken)
10457         {
10458                 *phObject = handleManager->addTokenObject(slot->getSlotID(), isPrivate != CK_FALSE, object);
10459         } else {
10460                 *phObject = handleManager->addSessionObject(slot->getSlotID(), hSession, isPrivate != CK_FALSE, object);
10461         }
10462
10463         return CKR_OK;
10464 }
10465
10466 CK_RV SoftHSM::getRSAPrivateKey(RSAPrivateKey* privateKey, Token* token, OSObject* key)
10467 {
10468         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10469         if (token == NULL) return CKR_ARGUMENTS_BAD;
10470         if (key == NULL) return CKR_ARGUMENTS_BAD;
10471
10472         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10473         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10474
10475         // RSA Private Key Attributes
10476         ByteString modulus;
10477         ByteString publicExponent;
10478         ByteString privateExponent;
10479         ByteString prime1;
10480         ByteString prime2;
10481         ByteString exponent1;
10482         ByteString exponent2;
10483         ByteString coefficient;
10484         if (isKeyPrivate)
10485         {
10486                 bool bOK = true;
10487                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10488                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10489                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIVATE_EXPONENT), privateExponent);
10490                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_1), prime1);
10491                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME_2), prime2);
10492                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_1), exponent1);
10493                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EXPONENT_2), exponent2);
10494                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_COEFFICIENT), coefficient);
10495                 if (!bOK)
10496                         return CKR_GENERAL_ERROR;
10497         }
10498         else
10499         {
10500                 modulus = key->getByteStringValue(CKA_MODULUS);
10501                 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10502                 privateExponent = key->getByteStringValue(CKA_PRIVATE_EXPONENT);
10503                 prime1 = key->getByteStringValue(CKA_PRIME_1);
10504                 prime2 = key->getByteStringValue(CKA_PRIME_2);
10505                 exponent1 =  key->getByteStringValue(CKA_EXPONENT_1);
10506                 exponent2 = key->getByteStringValue(CKA_EXPONENT_2);
10507                 coefficient = key->getByteStringValue(CKA_COEFFICIENT);
10508         }
10509
10510         privateKey->setN(modulus);
10511         privateKey->setE(publicExponent);
10512         privateKey->setD(privateExponent);
10513         privateKey->setP(prime1);
10514         privateKey->setQ(prime2);
10515         privateKey->setDP1(exponent1);
10516         privateKey->setDQ1(exponent2);
10517         privateKey->setPQ(coefficient);
10518
10519         return CKR_OK;
10520 }
10521
10522 CK_RV SoftHSM::getRSAPublicKey(RSAPublicKey* publicKey, Token* token, OSObject* key)
10523 {
10524         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10525         if (token == NULL) return CKR_ARGUMENTS_BAD;
10526         if (key == NULL) return CKR_ARGUMENTS_BAD;
10527
10528         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10529         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10530
10531         // RSA Public Key Attributes
10532         ByteString modulus;
10533         ByteString publicExponent;
10534         if (isKeyPrivate)
10535         {
10536                 bool bOK = true;
10537                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_MODULUS), modulus);
10538                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PUBLIC_EXPONENT), publicExponent);
10539                 if (!bOK)
10540                         return CKR_GENERAL_ERROR;
10541         }
10542         else
10543         {
10544                 modulus = key->getByteStringValue(CKA_MODULUS);
10545                 publicExponent = key->getByteStringValue(CKA_PUBLIC_EXPONENT);
10546         }
10547
10548         publicKey->setN(modulus);
10549         publicKey->setE(publicExponent);
10550
10551         return CKR_OK;
10552 }
10553
10554 CK_RV SoftHSM::getDSAPrivateKey(DSAPrivateKey* privateKey, Token* token, OSObject* key)
10555 {
10556         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10557         if (token == NULL) return CKR_ARGUMENTS_BAD;
10558         if (key == NULL) return CKR_ARGUMENTS_BAD;
10559
10560         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10561         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10562
10563         // DSA Private Key Attributes
10564         ByteString prime;
10565         ByteString subprime;
10566         ByteString generator;
10567         ByteString value;
10568         if (isKeyPrivate)
10569         {
10570                 bool bOK = true;
10571                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10572                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10573                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10574                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10575                 if (!bOK)
10576                         return CKR_GENERAL_ERROR;
10577         }
10578         else
10579         {
10580                 prime = key->getByteStringValue(CKA_PRIME);
10581                 subprime = key->getByteStringValue(CKA_SUBPRIME);
10582                 generator = key->getByteStringValue(CKA_BASE);
10583                 value = key->getByteStringValue(CKA_VALUE);
10584         }
10585
10586         privateKey->setP(prime);
10587         privateKey->setQ(subprime);
10588         privateKey->setG(generator);
10589         privateKey->setX(value);
10590
10591         return CKR_OK;
10592 }
10593
10594 CK_RV SoftHSM::getDSAPublicKey(DSAPublicKey* publicKey, Token* token, OSObject* key)
10595 {
10596         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10597         if (token == NULL) return CKR_ARGUMENTS_BAD;
10598         if (key == NULL) return CKR_ARGUMENTS_BAD;
10599
10600         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10601         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10602
10603         // DSA Public Key Attributes
10604         ByteString prime;
10605         ByteString subprime;
10606         ByteString generator;
10607         ByteString value;
10608         if (isKeyPrivate)
10609         {
10610                 bool bOK = true;
10611                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10612                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_SUBPRIME), subprime);
10613                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10614                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10615                 if (!bOK)
10616                         return CKR_GENERAL_ERROR;
10617         }
10618         else
10619         {
10620                 prime = key->getByteStringValue(CKA_PRIME);
10621                 subprime = key->getByteStringValue(CKA_SUBPRIME);
10622                 generator = key->getByteStringValue(CKA_BASE);
10623                 value = key->getByteStringValue(CKA_VALUE);
10624         }
10625
10626         publicKey->setP(prime);
10627         publicKey->setQ(subprime);
10628         publicKey->setG(generator);
10629         publicKey->setY(value);
10630
10631         return CKR_OK;
10632 }
10633
10634 CK_RV SoftHSM::getECPrivateKey(ECPrivateKey* privateKey, Token* token, OSObject* key)
10635 {
10636         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10637         if (token == NULL) return CKR_ARGUMENTS_BAD;
10638         if (key == NULL) return CKR_ARGUMENTS_BAD;
10639
10640         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10641         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10642
10643         // EC Private Key Attributes
10644         ByteString group;
10645         ByteString value;
10646         if (isKeyPrivate)
10647         {
10648                 bool bOK = true;
10649                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10650                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10651                 if (!bOK)
10652                         return CKR_GENERAL_ERROR;
10653         }
10654         else
10655         {
10656                 group = key->getByteStringValue(CKA_EC_PARAMS);
10657                 value = key->getByteStringValue(CKA_VALUE);
10658         }
10659
10660         privateKey->setEC(group);
10661         privateKey->setD(value);
10662
10663         return CKR_OK;
10664 }
10665
10666 CK_RV SoftHSM::getECPublicKey(ECPublicKey* publicKey, Token* token, OSObject* key)
10667 {
10668         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10669         if (token == NULL) return CKR_ARGUMENTS_BAD;
10670         if (key == NULL) return CKR_ARGUMENTS_BAD;
10671
10672         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10673         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10674
10675         // EC Public Key Attributes
10676         ByteString group;
10677         ByteString point;
10678         if (isKeyPrivate)
10679         {
10680                 bool bOK = true;
10681                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_PARAMS), group);
10682                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_EC_POINT), point);
10683                 if (!bOK)
10684                         return CKR_GENERAL_ERROR;
10685         }
10686         else
10687         {
10688                 group = key->getByteStringValue(CKA_EC_PARAMS);
10689                 point = key->getByteStringValue(CKA_EC_POINT);
10690         }
10691
10692         publicKey->setEC(group);
10693         publicKey->setQ(point);
10694
10695         return CKR_OK;
10696 }
10697
10698 CK_RV SoftHSM::getDHPrivateKey(DHPrivateKey* privateKey, Token* token, OSObject* key)
10699 {
10700         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10701         if (token == NULL) return CKR_ARGUMENTS_BAD;
10702         if (key == NULL) return CKR_ARGUMENTS_BAD;
10703
10704         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10705         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10706
10707         // DH Private Key Attributes
10708         ByteString prime;
10709         ByteString generator;
10710         ByteString value;
10711         if (isKeyPrivate)
10712         {
10713                 bool bOK = true;
10714                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_PRIME), prime);
10715                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_BASE), generator);
10716                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10717                 if (!bOK)
10718                         return CKR_GENERAL_ERROR;
10719         }
10720         else
10721         {
10722                 prime = key->getByteStringValue(CKA_PRIME);
10723                 generator = key->getByteStringValue(CKA_BASE);
10724                 value = key->getByteStringValue(CKA_VALUE);
10725         }
10726
10727         privateKey->setP(prime);
10728         privateKey->setG(generator);
10729         privateKey->setX(value);
10730
10731         return CKR_OK;
10732 }
10733
10734 CK_RV SoftHSM::getDHPublicKey(DHPublicKey* publicKey, DHPrivateKey* privateKey, ByteString& pubParams)
10735 {
10736         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10737         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10738
10739         // Copy Domain Parameters from Private Key
10740         publicKey->setP(privateKey->getP());
10741         publicKey->setG(privateKey->getG());
10742
10743         // Set value
10744         publicKey->setY(pubParams);
10745
10746         return CKR_OK;
10747 }
10748
10749 CK_RV SoftHSM::getECDHPublicKey(ECPublicKey* publicKey, ECPrivateKey* privateKey, ByteString& pubData)
10750 {
10751         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10752         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10753
10754         // Copy Domain Parameters from Private Key
10755         publicKey->setEC(privateKey->getEC());
10756
10757         // Set value
10758         ByteString data = getECDHPubData(pubData);
10759         publicKey->setQ(data);
10760
10761         return CKR_OK;
10762 }
10763
10764 // ECDH pubData can be in RAW or DER format.
10765 // Need to convert RAW as SoftHSM uses DER.
10766 ByteString SoftHSM::getECDHPubData(ByteString& pubData)
10767 {
10768         size_t len = pubData.size();
10769         size_t controlOctets = 2;
10770         if (len == 65 || len == 97 || len == 133)
10771         {
10772                 // Raw: Length matches the public key size of P-256, P-384, or P-521
10773                 controlOctets = 0;
10774         }
10775         else if (len < controlOctets || pubData[0] != 0x04)
10776         {
10777                 // Raw: Too short or does not start with 0x04
10778                 controlOctets = 0;
10779         }
10780         else if (pubData[1] < 0x80)
10781         {
10782                 // Raw: Length octet does not match remaining data length
10783                 if (pubData[1] != (len - controlOctets)) controlOctets = 0;
10784         }
10785         else
10786         {
10787                 size_t lengthOctets = pubData[1] & 0x7F;
10788                 controlOctets += lengthOctets;
10789
10790                 if (controlOctets >= len)
10791                 {
10792                         // Raw: Too short
10793                         controlOctets = 0;
10794                 }
10795                 else
10796                 {
10797                         ByteString length(&pubData[2], lengthOctets);
10798
10799                         if (length.long_val() != (len - controlOctets))
10800                         {
10801                                 // Raw: Length octets does not match remaining data length
10802                                 controlOctets = 0;
10803                         }
10804                 }
10805         }
10806
10807         // DER format
10808         if (controlOctets != 0) return pubData;
10809
10810         // RAW format
10811         ByteString header;
10812         if (len < 0x80)
10813         {
10814                 header.resize(2);
10815                 header[0] = (unsigned char)0x04;
10816                 header[1] = (unsigned char)(len & 0x7F);
10817         }
10818         else
10819         {
10820                 // Count significate bytes
10821                 size_t bytes = sizeof(size_t);
10822                 for(; bytes > 0; bytes--)
10823                 {
10824                         size_t value = len >> ((bytes - 1) * 8);
10825                         if (value & 0xFF) break;
10826                 }
10827
10828                 // Set header data
10829                 header.resize(2 + bytes);
10830                 header[0] = (unsigned char)0x04;
10831                 header[1] = (unsigned char)(0x80 | bytes);
10832                 for (size_t i = 1; i <= bytes; i++)
10833                 {
10834                         header[2+bytes-i] = (unsigned char) (len & 0xFF);
10835                         len >>= 8;
10836                 }
10837         }
10838
10839         return header + pubData;
10840 }
10841
10842 CK_RV SoftHSM::getGOSTPrivateKey(GOSTPrivateKey* privateKey, Token* token, OSObject* key)
10843 {
10844         if (privateKey == NULL) return CKR_ARGUMENTS_BAD;
10845         if (token == NULL) return CKR_ARGUMENTS_BAD;
10846         if (key == NULL) return CKR_ARGUMENTS_BAD;
10847
10848         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10849         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10850
10851         // GOST Private Key Attributes
10852         ByteString value;
10853         ByteString param;
10854         if (isKeyPrivate)
10855         {
10856                 bool bOK = true;
10857                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), value);
10858                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10859                 if (!bOK)
10860                         return CKR_GENERAL_ERROR;
10861         }
10862         else
10863         {
10864                 value = key->getByteStringValue(CKA_VALUE);
10865                 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10866         }
10867
10868         privateKey->setD(value);
10869         privateKey->setEC(param);
10870
10871         return CKR_OK;
10872 }
10873
10874 CK_RV SoftHSM::getGOSTPublicKey(GOSTPublicKey* publicKey, Token* token, OSObject* key)
10875 {
10876         if (publicKey == NULL) return CKR_ARGUMENTS_BAD;
10877         if (token == NULL) return CKR_ARGUMENTS_BAD;
10878         if (key == NULL) return CKR_ARGUMENTS_BAD;
10879
10880         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10881         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10882
10883         // GOST Public Key Attributes
10884         ByteString point;
10885         ByteString param;
10886         if (isKeyPrivate)
10887         {
10888                 bool bOK = true;
10889                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_VALUE), point);
10890                 bOK = bOK && token->decrypt(key->getByteStringValue(CKA_GOSTR3410_PARAMS), param);
10891                 if (!bOK)
10892                         return CKR_GENERAL_ERROR;
10893         }
10894         else
10895         {
10896                 point = key->getByteStringValue(CKA_VALUE);
10897                 param = key->getByteStringValue(CKA_GOSTR3410_PARAMS);
10898         }
10899
10900         publicKey->setQ(point);
10901         publicKey->setEC(param);
10902
10903         return CKR_OK;
10904 }
10905
10906 CK_RV SoftHSM::getSymmetricKey(SymmetricKey* skey, Token* token, OSObject* key)
10907 {
10908         if (skey == NULL) return CKR_ARGUMENTS_BAD;
10909         if (token == NULL) return CKR_ARGUMENTS_BAD;
10910         if (key == NULL) return CKR_ARGUMENTS_BAD;
10911
10912         // Get the CKA_PRIVATE attribute, when the attribute is not present use default false
10913         bool isKeyPrivate = key->getBooleanValue(CKA_PRIVATE, false);
10914
10915         ByteString keybits;
10916         if (isKeyPrivate)
10917         {
10918                 if (!token->decrypt(key->getByteStringValue(CKA_VALUE), keybits))
10919                         return CKR_GENERAL_ERROR;
10920         }
10921         else
10922         {
10923                 keybits = key->getByteStringValue(CKA_VALUE);
10924         }
10925
10926         skey->setKeyBits(keybits);
10927
10928         return CKR_OK;
10929 }
10930
10931 bool SoftHSM::setRSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
10932 {
10933         AsymmetricAlgorithm* rsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::RSA);
10934         if (rsa == NULL)
10935                 return false;
10936         PrivateKey* priv = rsa->newPrivateKey();
10937         if (priv == NULL)
10938         {
10939                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10940                 return false;
10941         }
10942         if (!priv->PKCS8Decode(ber))
10943         {
10944                 rsa->recyclePrivateKey(priv);
10945                 CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10946                 return false;
10947         }
10948         // RSA Private Key Attributes
10949         ByteString modulus;
10950         ByteString publicExponent;
10951         ByteString privateExponent;
10952         ByteString prime1;
10953         ByteString prime2;
10954         ByteString exponent1;
10955         ByteString exponent2;
10956         ByteString coefficient;
10957         if (isPrivate)
10958         {
10959                 token->encrypt(((RSAPrivateKey*)priv)->getN(), modulus);
10960                 token->encrypt(((RSAPrivateKey*)priv)->getE(), publicExponent);
10961                 token->encrypt(((RSAPrivateKey*)priv)->getD(), privateExponent);
10962                 token->encrypt(((RSAPrivateKey*)priv)->getP(), prime1);
10963                 token->encrypt(((RSAPrivateKey*)priv)->getQ(), prime2);
10964                 token->encrypt(((RSAPrivateKey*)priv)->getDP1(), exponent1);
10965                 token->encrypt(((RSAPrivateKey*)priv)->getDQ1(), exponent2);
10966                 token->encrypt(((RSAPrivateKey*)priv)->getPQ(), coefficient);
10967         }
10968         else
10969         {
10970                 modulus = ((RSAPrivateKey*)priv)->getN();
10971                 publicExponent = ((RSAPrivateKey*)priv)->getE();
10972                 privateExponent = ((RSAPrivateKey*)priv)->getD();
10973                 prime1 = ((RSAPrivateKey*)priv)->getP();
10974                 prime2 = ((RSAPrivateKey*)priv)->getQ();
10975                 exponent1 =  ((RSAPrivateKey*)priv)->getDP1();
10976                 exponent2 = ((RSAPrivateKey*)priv)->getDQ1();
10977                 coefficient = ((RSAPrivateKey*)priv)->getPQ();
10978         }
10979         bool bOK = true;
10980         bOK = bOK && key->setAttribute(CKA_MODULUS, modulus);
10981         bOK = bOK && key->setAttribute(CKA_PUBLIC_EXPONENT, publicExponent);
10982         bOK = bOK && key->setAttribute(CKA_PRIVATE_EXPONENT, privateExponent);
10983         bOK = bOK && key->setAttribute(CKA_PRIME_1, prime1);
10984         bOK = bOK && key->setAttribute(CKA_PRIME_2, prime2);
10985         bOK = bOK && key->setAttribute(CKA_EXPONENT_1,exponent1);
10986         bOK = bOK && key->setAttribute(CKA_EXPONENT_2, exponent2);
10987         bOK = bOK && key->setAttribute(CKA_COEFFICIENT, coefficient);
10988
10989         rsa->recyclePrivateKey(priv);
10990         CryptoFactory::i()->recycleAsymmetricAlgorithm(rsa);
10991
10992         return bOK;
10993 }
10994
10995 bool SoftHSM::setDSAPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
10996 {
10997         AsymmetricAlgorithm* dsa = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DSA);
10998         if (dsa == NULL)
10999                 return false;
11000         PrivateKey* priv = dsa->newPrivateKey();
11001         if (priv == NULL)
11002         {
11003                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11004                 return false;
11005         }
11006         if (!priv->PKCS8Decode(ber))
11007         {
11008                 dsa->recyclePrivateKey(priv);
11009                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11010                 return false;
11011         }
11012         // DSA Private Key Attributes
11013         ByteString prime;
11014         ByteString subprime;
11015         ByteString generator;
11016         ByteString value;
11017         if (isPrivate)
11018         {
11019                 token->encrypt(((DSAPrivateKey*)priv)->getP(), prime);
11020                 token->encrypt(((DSAPrivateKey*)priv)->getQ(), subprime);
11021                 token->encrypt(((DSAPrivateKey*)priv)->getG(), generator);
11022                 token->encrypt(((DSAPrivateKey*)priv)->getX(), value);
11023         }
11024         else
11025         {
11026                 prime = ((DSAPrivateKey*)priv)->getP();
11027                 subprime = ((DSAPrivateKey*)priv)->getQ();
11028                 generator = ((DSAPrivateKey*)priv)->getG();
11029                 value = ((DSAPrivateKey*)priv)->getX();
11030         }
11031         bool bOK = true;
11032         bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11033         bOK = bOK && key->setAttribute(CKA_SUBPRIME, subprime);
11034         bOK = bOK && key->setAttribute(CKA_BASE, generator);
11035         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11036
11037         dsa->recyclePrivateKey(priv);
11038         CryptoFactory::i()->recycleAsymmetricAlgorithm(dsa);
11039
11040         return bOK;
11041 }
11042
11043 bool SoftHSM::setDHPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11044 {
11045         AsymmetricAlgorithm* dh = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::DH);
11046         if (dh == NULL)
11047                 return false;
11048         PrivateKey* priv = dh->newPrivateKey();
11049         if (priv == NULL)
11050         {
11051                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11052                 return false;
11053         }
11054         if (!priv->PKCS8Decode(ber))
11055         {
11056                 dh->recyclePrivateKey(priv);
11057                 CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11058                 return false;
11059         }
11060         // DH Private Key Attributes
11061         ByteString prime;
11062         ByteString generator;
11063         ByteString value;
11064         if (isPrivate)
11065         {
11066                 token->encrypt(((DHPrivateKey*)priv)->getP(), prime);
11067                 token->encrypt(((DHPrivateKey*)priv)->getG(), generator);
11068                 token->encrypt(((DHPrivateKey*)priv)->getX(), value);
11069         }
11070         else
11071         {
11072                 prime = ((DHPrivateKey*)priv)->getP();
11073                 generator = ((DHPrivateKey*)priv)->getG();
11074                 value = ((DHPrivateKey*)priv)->getX();
11075         }
11076         bool bOK = true;
11077         bOK = bOK && key->setAttribute(CKA_PRIME, prime);
11078         bOK = bOK && key->setAttribute(CKA_BASE, generator);
11079         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11080
11081         dh->recyclePrivateKey(priv);
11082         CryptoFactory::i()->recycleAsymmetricAlgorithm(dh);
11083
11084         return bOK;
11085 }
11086 bool SoftHSM::setECPrivateKey(OSObject* key, const ByteString &ber, Token* token, bool isPrivate) const
11087 {
11088         AsymmetricAlgorithm* ecc = CryptoFactory::i()->getAsymmetricAlgorithm(AsymAlgo::ECDSA);
11089         if (ecc == NULL)
11090                 return false;
11091         PrivateKey* priv = ecc->newPrivateKey();
11092         if (priv == NULL)
11093         {
11094                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11095                 return false;
11096         }
11097         if (!priv->PKCS8Decode(ber))
11098         {
11099                 ecc->recyclePrivateKey(priv);
11100                 CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11101                 return false;
11102         }
11103         // EC Private Key Attributes
11104         ByteString group;
11105         ByteString value;
11106         if (isPrivate)
11107         {
11108                 token->encrypt(((ECPrivateKey*)priv)->getEC(), group);
11109                 token->encrypt(((ECPrivateKey*)priv)->getD(), value);
11110         }
11111         else
11112         {
11113                 group = ((ECPrivateKey*)priv)->getEC();
11114                 value = ((ECPrivateKey*)priv)->getD();
11115         }
11116         bool bOK = true;
11117         bOK = bOK && key->setAttribute(CKA_EC_PARAMS, group);
11118         bOK = bOK && key->setAttribute(CKA_VALUE, value);
11119
11120         ecc->recyclePrivateKey(priv);
11121         CryptoFactory::i()->recycleAsymmetricAlgorithm(ecc);
11122
11123         return bOK;
11124 }
11125
11126 CK_RV SoftHSM::MechParamCheckRSAPKCSOAEP(CK_MECHANISM_PTR pMechanism)
11127 {
11128         // This is a programming error
11129         if (pMechanism->mechanism != CKM_RSA_PKCS_OAEP) {
11130                 ERROR_MSG("MechParamCheckRSAPKCSOAEP called on wrong mechanism");
11131                 return CKR_GENERAL_ERROR;
11132         }
11133
11134         if (pMechanism->pParameter == NULL_PTR ||
11135             pMechanism->ulParameterLen != sizeof(CK_RSA_PKCS_OAEP_PARAMS))
11136         {
11137                 ERROR_MSG("pParameter must be of type CK_RSA_PKCS_OAEP_PARAMS");
11138                 return CKR_ARGUMENTS_BAD;
11139         }
11140
11141         CK_RSA_PKCS_OAEP_PARAMS_PTR params = (CK_RSA_PKCS_OAEP_PARAMS_PTR)pMechanism->pParameter;
11142         if (params->hashAlg != CKM_SHA_1)
11143         {
11144                 ERROR_MSG("hashAlg must be CKM_SHA_1");
11145                 return CKR_ARGUMENTS_BAD;
11146         }
11147         if (params->mgf != CKG_MGF1_SHA1)
11148         {
11149                 ERROR_MSG("mgf must be CKG_MGF1_SHA1");
11150                 return CKR_ARGUMENTS_BAD;
11151         }
11152         if (params->source != CKZ_DATA_SPECIFIED)
11153         {
11154                 ERROR_MSG("source must be CKZ_DATA_SPECIFIED");
11155                 return CKR_ARGUMENTS_BAD;
11156         }
11157         if (params->pSourceData != NULL)
11158         {
11159                 ERROR_MSG("pSourceData must be NULL");
11160                 return CKR_ARGUMENTS_BAD;
11161         }
11162         if (params->ulSourceDataLen != 0)
11163         {
11164                 ERROR_MSG("ulSourceDataLen must be 0");
11165                 return CKR_ARGUMENTS_BAD;
11166         }
11167         return CKR_OK;
11168 }
11169
11170 bool SoftHSM::isMechanismPermitted(OSObject* key, CK_MECHANISM_PTR pMechanism) {
11171         OSAttribute attribute = key->getAttribute(CKA_ALLOWED_MECHANISMS);
11172         std::set<CK_MECHANISM_TYPE> allowed = attribute.getMechanismTypeSetValue();
11173         if (allowed.empty()) {
11174                 return true;
11175         }
11176
11177         return allowed.find(pMechanism->mechanism) != allowed.end();
11178 }