blob: b06efc2c46dd5924540858d35b373ae89f145ff3 [file] [log] [blame]
NingSun0c89b3c2018-02-08 08:34:03 -08001/*
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
82std::unique_ptr<MutexFactory> MutexFactory::instance(nullptr);
83std::unique_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(nullptr);
84#if defined(WITH_OPENSSL)
85std::unique_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(nullptr);
86#else
87std::unique_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(nullptr);
88#endif
89std::unique_ptr<SoftHSM> SoftHSM::instance(nullptr);
90
91#else
92
93std::auto_ptr<MutexFactory> MutexFactory::instance(NULL);
94std::auto_ptr<SecureMemoryRegistry> SecureMemoryRegistry::instance(NULL);
95#if defined(WITH_OPENSSL)
96std::auto_ptr<OSSLCryptoFactory> OSSLCryptoFactory::instance(NULL);
97#else
98std::auto_ptr<BotanCryptoFactory> BotanCryptoFactory::instance(NULL);
99#endif
100std::auto_ptr<SoftHSM> SoftHSM::instance(NULL);
101
102#endif
103
104static 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
193static 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
289static 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
307static 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
319SoftHSM* SoftHSM::i()
320{
321 if (!instance.get())
322 {
323 instance.reset(new SoftHSM());
324 }
325
326 return instance.get();
327}
328
329void SoftHSM::reset()
330{
331 if (instance.get())
332 instance.reset();
333}
334
335// Constructor
336SoftHSM::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
348SoftHSM::~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
362CK_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
525CK_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
552CK_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
575CK_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
583CK_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
607CK_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
627CK_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
780CK_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
1129CK_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
1155CK_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
1180CK_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
1219CK_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
1238CK_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
1258CK_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
1284CK_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
1296CK_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
1308CK_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
1320CK_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
1367CK_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
1396CK_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
1402CK_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
1579CK_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
1625CK_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
1649CK_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
1696CK_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
1747CK_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
1896CK_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
1923CK_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
1939static 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
1962CK_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
2186CK_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
2285CK_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
2294static 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
2372static 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
2432CK_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
2456static 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
2528CK_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
2551static 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
2624CK_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
2642CK_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
2867CK_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
2989CK_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
2998static 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
3068static 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
3131CK_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
3155static 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
3231CK_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
3253static 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
3326CK_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
3344CK_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
3406CK_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
3469CK_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
3496CK_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
3570CK_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
3622static 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
3645CK_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
3797CK_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
4197CK_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
4206static 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
4263static 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
4340CK_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
4364static 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
4388static 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
4419CK_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
4440static 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
4487static 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
4542CK_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
4563CK_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
4578CK_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
4590CK_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
4742CK_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
5134CK_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
5143static 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
5188static 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
5244CK_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
5268static 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
5293static 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
5318CK_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
5339static 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
5374static 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
5410CK_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
5431CK_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
5446CK_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
5458CK_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
5470CK_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
5482CK_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
5494CK_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
5506CK_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
5634CK_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
5792CK_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
5866CK_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
5955CK_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
6198CK_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
6252CK_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
6313CK_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
6607CK_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
6777CK_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
6799CK_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
6827CK_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
6839CK_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
6851CK_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
6857CK_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
7047CK_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
7214CK_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
7381CK_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
7548CK_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
7835CK_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
8099CK_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
8273CK_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
8519CK_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
8794CK_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
8948CK_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
9210CK_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
9524CK_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
9880CK_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
10337CK_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
10466CK_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
10522CK_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
10554CK_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
10594CK_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
10634CK_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
10666CK_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
10698CK_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
10734CK_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
10749CK_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.
10766ByteString 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
10842CK_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
10874CK_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
10906CK_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
10931bool 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
10995bool 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
11043bool 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}
11086bool 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
11126CK_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
11170bool 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}