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