@@ -10343,29 +10343,52 @@ CK_RV SoftHSM::deriveECDH
1034310343 CK_BBOOL isPrivate)
1034410344{
1034510345 *phKey = CK_INVALID_HANDLE;
10346+ HashAlgorithm* kdfAlgorithm = NULL ;
1034610347
1034710348 if ((pMechanism->pParameter == NULL_PTR) ||
1034810349 (pMechanism->ulParameterLen != sizeof (CK_ECDH1_DERIVE_PARAMS)))
1034910350 {
1035010351 DEBUG_MSG (" pParameter must be of type CK_ECDH1_DERIVE_PARAMS" );
1035110352 return CKR_MECHANISM_PARAM_INVALID;
1035210353 }
10353- if (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->kdf != CKD_NULL)
10354- {
10355- DEBUG_MSG (" kdf must be CKD_NULL" );
10356- return CKR_MECHANISM_PARAM_INVALID;
10357- }
10358- if ((CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulSharedDataLen != 0 ) ||
10359- (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pSharedData != NULL_PTR))
10354+
10355+ CK_ECDH1_DERIVE_PARAMS_PTR ecdhParams = CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter );
10356+
10357+ if ((ecdhParams->ulPublicDataLen == 0 ) ||
10358+ (ecdhParams->pPublicData == NULL_PTR))
1036010359 {
10361- DEBUG_MSG (" there must be no shared data" );
10360+ DEBUG_MSG (" there must be a public data" );
1036210361 return CKR_MECHANISM_PARAM_INVALID;
1036310362 }
10364- if (( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> ulPublicDataLen == 0 ) ||
10365- ( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> pPublicData == NULL_PTR) )
10363+
10364+ switch (ecdhParams-> kdf )
1036610365 {
10367- DEBUG_MSG (" there must be a public data" );
10368- return CKR_MECHANISM_PARAM_INVALID;
10366+ case CKD_NULL:
10367+ if ((ecdhParams->ulSharedDataLen != 0 ) ||
10368+ (ecdhParams->pSharedData != NULL_PTR))
10369+ {
10370+ DEBUG_MSG (" there must be no shared data when KDF is CKD_NULL" );
10371+ return CKR_MECHANISM_PARAM_INVALID;
10372+ }
10373+ break ;
10374+ case CKD_SHA1_KDF:
10375+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA1);
10376+ break ;
10377+ case CKD_SHA224_KDF:
10378+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA224);
10379+ break ;
10380+ case CKD_SHA256_KDF:
10381+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA256);
10382+ break ;
10383+ case CKD_SHA384_KDF:
10384+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA384);
10385+ break ;
10386+ case CKD_SHA512_KDF:
10387+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA512);
10388+ break ;
10389+ default :
10390+ DEBUG_MSG (" Unknown KDF" );
10391+ return CKR_MECHANISM_PARAM_INVALID;
1036910392 }
1037010393
1037110394 // Get the session
@@ -10414,6 +10437,14 @@ CK_RV SoftHSM::deriveECDH
1041410437 switch (keyType)
1041510438 {
1041610439 case CKK_GENERIC_SECRET:
10440+ if (kdfAlgorithm != NULL ) {
10441+ const size_t maxLen = kdfAlgorithm->getHashSize () * (1UL << 32 );
10442+ if (byteLen > maxLen)
10443+ {
10444+ INFO_MSG (" CKA_VALUE_LEN must be at most %zu" , maxLen);
10445+ return CKR_ATTRIBUTE_VALUE_INVALID;
10446+ }
10447+ }
1041710448 break ;
1041810449#ifndef WITH_FIPS
1041910450 case CKK_DES:
@@ -10477,10 +10508,8 @@ CK_RV SoftHSM::deriveECDH
1047710508 }
1047810509
1047910510 ByteString publicData;
10480- publicData.resize (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10481- memcpy (&publicData[0 ],
10482- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pPublicData ,
10483- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10511+ publicData.resize (ecdhParams->ulPublicDataLen );
10512+ memcpy (&publicData[0 ], ecdhParams->pPublicData , ecdhParams->ulPublicDataLen );
1048410513 PublicKey* publicKey = ecdh->newPublicKey ();
1048510514 if (publicKey == NULL )
1048610515 {
@@ -10504,6 +10533,44 @@ CK_RV SoftHSM::deriveECDH
1050410533 ecdh->recyclePrivateKey (privateKey);
1050510534 ecdh->recyclePublicKey (publicKey);
1050610535
10536+ // Apply key derivation function (ANSI X9.63)
10537+ if (rv == CKR_OK && kdfAlgorithm != NULL ) {
10538+ const ByteString& secretBits = secret->getKeyBits ();
10539+ const size_t counterOffset = secretBits.size ();
10540+ unsigned long counter = 1 ;
10541+
10542+ ByteString hashInput;
10543+ hashInput.resize (secretBits.size () + 4 + ecdhParams->ulSharedDataLen );
10544+
10545+ // Prepare hash input content - derived secret, 4 bytes for counter, shared data
10546+ memcpy (&hashInput[0 ], secretBits.const_byte_str (), secretBits.size ());
10547+ memcpy (&hashInput[secretBits.size () + 4 ], ecdhParams->pSharedData , ecdhParams->ulSharedDataLen );
10548+
10549+ ByteString hashOutput;
10550+ ByteString derivedOutput;
10551+
10552+ while (derivedOutput.size () < byteLen) {
10553+ hashInput[counterOffset + 0 ] = (counter >> 48 ) & 0xFF ;
10554+ hashInput[counterOffset + 1 ] = (counter >> 32 ) & 0xFF ;
10555+ hashInput[counterOffset + 2 ] = (counter >> 16 ) & 0xFF ;
10556+ hashInput[counterOffset + 3 ] = (counter >> 0 ) & 0xFF ;
10557+
10558+ kdfAlgorithm->hashInit ();
10559+ kdfAlgorithm->hashUpdate (hashInput);
10560+ kdfAlgorithm->hashFinal (hashOutput);
10561+
10562+ derivedOutput += hashOutput;
10563+ counter++;
10564+ }
10565+
10566+ // Trim to desired length
10567+ derivedOutput.resize (byteLen);
10568+
10569+ secret->setBitLen (byteLen * 8 );
10570+ if (!secret->setKeyBits (derivedOutput))
10571+ rv = CKR_FUNCTION_FAILED;
10572+ }
10573+
1050710574 // Create the secret object using C_CreateObject
1050810575 const CK_ULONG maxAttribs = 32 ;
1050910576 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
@@ -10697,29 +10764,52 @@ CK_RV SoftHSM::deriveEDDSA
1069710764 CK_BBOOL isPrivate)
1069810765{
1069910766 *phKey = CK_INVALID_HANDLE;
10767+ HashAlgorithm* kdfAlgorithm = NULL ;
1070010768
1070110769 if ((pMechanism->pParameter == NULL_PTR) ||
1070210770 (pMechanism->ulParameterLen != sizeof (CK_ECDH1_DERIVE_PARAMS)))
1070310771 {
1070410772 DEBUG_MSG (" pParameter must be of type CK_ECDH1_DERIVE_PARAMS" );
1070510773 return CKR_MECHANISM_PARAM_INVALID;
1070610774 }
10707- if (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->kdf != CKD_NULL)
10708- {
10709- DEBUG_MSG (" kdf must be CKD_NULL" );
10710- return CKR_MECHANISM_PARAM_INVALID;
10711- }
10712- if ((CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulSharedDataLen != 0 ) ||
10713- (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pSharedData != NULL_PTR))
10775+
10776+ CK_ECDH1_DERIVE_PARAMS_PTR ecdhParams = CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter );
10777+
10778+ if ((ecdhParams->ulPublicDataLen == 0 ) ||
10779+ (ecdhParams->pPublicData == NULL_PTR))
1071410780 {
10715- DEBUG_MSG (" there must be no shared data" );
10781+ DEBUG_MSG (" there must be a public data" );
1071610782 return CKR_MECHANISM_PARAM_INVALID;
1071710783 }
10718- if (( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> ulPublicDataLen == 0 ) ||
10719- ( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> pPublicData == NULL_PTR) )
10784+
10785+ switch (ecdhParams-> kdf )
1072010786 {
10721- DEBUG_MSG (" there must be a public data" );
10722- return CKR_MECHANISM_PARAM_INVALID;
10787+ case CKD_NULL:
10788+ if ((ecdhParams->ulSharedDataLen != 0 ) ||
10789+ (ecdhParams->pSharedData != NULL_PTR))
10790+ {
10791+ DEBUG_MSG (" there must be no shared data when KDF is CKD_NULL" );
10792+ return CKR_MECHANISM_PARAM_INVALID;
10793+ }
10794+ break ;
10795+ case CKD_SHA1_KDF:
10796+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA1);
10797+ break ;
10798+ case CKD_SHA224_KDF:
10799+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA224);
10800+ break ;
10801+ case CKD_SHA256_KDF:
10802+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA256);
10803+ break ;
10804+ case CKD_SHA384_KDF:
10805+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA384);
10806+ break ;
10807+ case CKD_SHA512_KDF:
10808+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA512);
10809+ break ;
10810+ default :
10811+ DEBUG_MSG (" Unknown KDF" );
10812+ return CKR_MECHANISM_PARAM_INVALID;
1072310813 }
1072410814
1072510815 // Get the session
@@ -10768,6 +10858,14 @@ CK_RV SoftHSM::deriveEDDSA
1076810858 switch (keyType)
1076910859 {
1077010860 case CKK_GENERIC_SECRET:
10861+ if (kdfAlgorithm != NULL ) {
10862+ const size_t maxLen = kdfAlgorithm->getHashSize () * (1UL << 32 );
10863+ if (byteLen > maxLen)
10864+ {
10865+ INFO_MSG (" CKA_VALUE_LEN must be at most %zu" , maxLen);
10866+ return CKR_ATTRIBUTE_VALUE_INVALID;
10867+ }
10868+ }
1077110869 break ;
1077210870#ifndef WITH_FIPS
1077310871 case CKK_DES:
@@ -10831,10 +10929,8 @@ CK_RV SoftHSM::deriveEDDSA
1083110929 }
1083210930
1083310931 ByteString publicData;
10834- publicData.resize (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10835- memcpy (&publicData[0 ],
10836- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pPublicData ,
10837- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10932+ publicData.resize (ecdhParams->ulPublicDataLen );
10933+ memcpy (&publicData[0 ], ecdhParams->pPublicData , ecdhParams->ulPublicDataLen );
1083810934 PublicKey* publicKey = eddsa->newPublicKey ();
1083910935 if (publicKey == NULL )
1084010936 {
@@ -10858,6 +10954,44 @@ CK_RV SoftHSM::deriveEDDSA
1085810954 eddsa->recyclePrivateKey (privateKey);
1085910955 eddsa->recyclePublicKey (publicKey);
1086010956
10957+ // Apply key derivation function (ANSI X9.63)
10958+ if (rv == CKR_OK && kdfAlgorithm != NULL ) {
10959+ const ByteString& secretBits = secret->getKeyBits ();
10960+ const size_t counterOffset = secretBits.size ();
10961+ unsigned long counter = 1 ;
10962+
10963+ ByteString hashInput;
10964+ hashInput.resize (secretBits.size () + 4 + ecdhParams->ulSharedDataLen );
10965+
10966+ // Prepare hash input content - derived secret, 4 bytes for counter, shared data
10967+ memcpy (&hashInput[0 ], secretBits.const_byte_str (), secretBits.size ());
10968+ memcpy (&hashInput[secretBits.size () + 4 ], ecdhParams->pSharedData , ecdhParams->ulSharedDataLen );
10969+
10970+ ByteString hashOutput;
10971+ ByteString derivedOutput;
10972+
10973+ while (derivedOutput.size () < byteLen) {
10974+ hashInput[counterOffset + 0 ] = (counter >> 48 ) & 0xFF ;
10975+ hashInput[counterOffset + 1 ] = (counter >> 32 ) & 0xFF ;
10976+ hashInput[counterOffset + 2 ] = (counter >> 16 ) & 0xFF ;
10977+ hashInput[counterOffset + 3 ] = (counter >> 0 ) & 0xFF ;
10978+
10979+ kdfAlgorithm->hashInit ();
10980+ kdfAlgorithm->hashUpdate (hashInput);
10981+ kdfAlgorithm->hashFinal (hashOutput);
10982+
10983+ derivedOutput += hashOutput;
10984+ counter++;
10985+ }
10986+
10987+ // Trim to desired length
10988+ derivedOutput.resize (byteLen);
10989+
10990+ secret->setBitLen (byteLen * 8 );
10991+ if (!secret->setKeyBits (derivedOutput))
10992+ rv = CKR_FUNCTION_FAILED;
10993+ }
10994+
1086110995 // Create the secret object using C_CreateObject
1086210996 const CK_ULONG maxAttribs = 32 ;
1086310997 CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
0 commit comments