@@ -10607,29 +10607,52 @@ CK_RV SoftHSM::deriveECDH
10607
10607
CK_BBOOL isPrivate)
10608
10608
{
10609
10609
*phKey = CK_INVALID_HANDLE;
10610
+ HashAlgorithm* kdfAlgorithm = NULL ;
10610
10611
10611
10612
if ((pMechanism->pParameter == NULL_PTR) ||
10612
10613
(pMechanism->ulParameterLen != sizeof (CK_ECDH1_DERIVE_PARAMS)))
10613
10614
{
10614
10615
DEBUG_MSG (" pParameter must be of type CK_ECDH1_DERIVE_PARAMS" );
10615
10616
return CKR_MECHANISM_PARAM_INVALID;
10616
10617
}
10617
- if (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->kdf != CKD_NULL)
10618
- {
10619
- DEBUG_MSG (" kdf must be CKD_NULL" );
10620
- return CKR_MECHANISM_PARAM_INVALID;
10621
- }
10622
- if ((CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulSharedDataLen != 0 ) ||
10623
- (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pSharedData != NULL_PTR))
10618
+
10619
+ CK_ECDH1_DERIVE_PARAMS_PTR ecdhParams = CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter );
10620
+
10621
+ if ((ecdhParams->ulPublicDataLen == 0 ) ||
10622
+ (ecdhParams->pPublicData == NULL_PTR))
10624
10623
{
10625
- DEBUG_MSG (" there must be no shared data" );
10624
+ DEBUG_MSG (" there must be a public data" );
10626
10625
return CKR_MECHANISM_PARAM_INVALID;
10627
10626
}
10628
- if (( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> ulPublicDataLen == 0 ) ||
10629
- ( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> pPublicData == NULL_PTR) )
10627
+
10628
+ switch (ecdhParams-> kdf )
10630
10629
{
10631
- DEBUG_MSG (" there must be a public data" );
10632
- return CKR_MECHANISM_PARAM_INVALID;
10630
+ case CKD_NULL:
10631
+ if ((ecdhParams->ulSharedDataLen != 0 ) ||
10632
+ (ecdhParams->pSharedData != NULL_PTR))
10633
+ {
10634
+ DEBUG_MSG (" there must be no shared data when KDF is CKD_NULL" );
10635
+ return CKR_MECHANISM_PARAM_INVALID;
10636
+ }
10637
+ break ;
10638
+ case CKD_SHA1_KDF:
10639
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA1);
10640
+ break ;
10641
+ case CKD_SHA224_KDF:
10642
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA224);
10643
+ break ;
10644
+ case CKD_SHA256_KDF:
10645
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA256);
10646
+ break ;
10647
+ case CKD_SHA384_KDF:
10648
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA384);
10649
+ break ;
10650
+ case CKD_SHA512_KDF:
10651
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA512);
10652
+ break ;
10653
+ default :
10654
+ DEBUG_MSG (" Unknown KDF" );
10655
+ return CKR_MECHANISM_PARAM_INVALID;
10633
10656
}
10634
10657
10635
10658
// Get the session
@@ -10678,6 +10701,14 @@ CK_RV SoftHSM::deriveECDH
10678
10701
switch (keyType)
10679
10702
{
10680
10703
case CKK_GENERIC_SECRET:
10704
+ if (kdfAlgorithm != NULL ) {
10705
+ const size_t maxLen = kdfAlgorithm->getHashSize () * (1UL << 32 );
10706
+ if (byteLen > maxLen)
10707
+ {
10708
+ INFO_MSG (" CKA_VALUE_LEN must be at most %zu" , maxLen);
10709
+ return CKR_ATTRIBUTE_VALUE_INVALID;
10710
+ }
10711
+ }
10681
10712
break ;
10682
10713
#ifndef WITH_FIPS
10683
10714
case CKK_DES:
@@ -10741,10 +10772,8 @@ CK_RV SoftHSM::deriveECDH
10741
10772
}
10742
10773
10743
10774
ByteString publicData;
10744
- publicData.resize (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10745
- memcpy (&publicData[0 ],
10746
- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pPublicData ,
10747
- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
10775
+ publicData.resize (ecdhParams->ulPublicDataLen );
10776
+ memcpy (&publicData[0 ], ecdhParams->pPublicData , ecdhParams->ulPublicDataLen );
10748
10777
PublicKey* publicKey = ecdh->newPublicKey ();
10749
10778
if (publicKey == NULL )
10750
10779
{
@@ -10768,6 +10797,44 @@ CK_RV SoftHSM::deriveECDH
10768
10797
ecdh->recyclePrivateKey (privateKey);
10769
10798
ecdh->recyclePublicKey (publicKey);
10770
10799
10800
+ // Apply key derivation function (ANSI X9.63)
10801
+ if (rv == CKR_OK && kdfAlgorithm != NULL ) {
10802
+ const ByteString& secretBits = secret->getKeyBits ();
10803
+ const size_t counterOffset = secretBits.size ();
10804
+ unsigned long counter = 1 ;
10805
+
10806
+ ByteString hashInput;
10807
+ hashInput.resize (secretBits.size () + 4 + ecdhParams->ulSharedDataLen );
10808
+
10809
+ // Prepare hash input content - derived secret, 4 bytes for counter, shared data
10810
+ memcpy (&hashInput[0 ], secretBits.const_byte_str (), secretBits.size ());
10811
+ memcpy (&hashInput[secretBits.size () + 4 ], ecdhParams->pSharedData , ecdhParams->ulSharedDataLen );
10812
+
10813
+ ByteString hashOutput;
10814
+ ByteString derivedOutput;
10815
+
10816
+ while (derivedOutput.size () < byteLen) {
10817
+ hashInput[counterOffset + 0 ] = (counter >> 48 ) & 0xFF ;
10818
+ hashInput[counterOffset + 1 ] = (counter >> 32 ) & 0xFF ;
10819
+ hashInput[counterOffset + 2 ] = (counter >> 16 ) & 0xFF ;
10820
+ hashInput[counterOffset + 3 ] = (counter >> 0 ) & 0xFF ;
10821
+
10822
+ kdfAlgorithm->hashInit ();
10823
+ kdfAlgorithm->hashUpdate (hashInput);
10824
+ kdfAlgorithm->hashFinal (hashOutput);
10825
+
10826
+ derivedOutput += hashOutput;
10827
+ counter++;
10828
+ }
10829
+
10830
+ // Trim to desired length
10831
+ derivedOutput.resize (byteLen);
10832
+
10833
+ secret->setBitLen (byteLen * 8 );
10834
+ if (!secret->setKeyBits (derivedOutput))
10835
+ rv = CKR_FUNCTION_FAILED;
10836
+ }
10837
+
10771
10838
// Create the secret object using C_CreateObject
10772
10839
const CK_ULONG maxAttribs = 32 ;
10773
10840
CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
@@ -10961,29 +11028,52 @@ CK_RV SoftHSM::deriveEDDSA
10961
11028
CK_BBOOL isPrivate)
10962
11029
{
10963
11030
*phKey = CK_INVALID_HANDLE;
11031
+ HashAlgorithm* kdfAlgorithm = NULL ;
10964
11032
10965
11033
if ((pMechanism->pParameter == NULL_PTR) ||
10966
11034
(pMechanism->ulParameterLen != sizeof (CK_ECDH1_DERIVE_PARAMS)))
10967
11035
{
10968
11036
DEBUG_MSG (" pParameter must be of type CK_ECDH1_DERIVE_PARAMS" );
10969
11037
return CKR_MECHANISM_PARAM_INVALID;
10970
11038
}
10971
- if (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->kdf != CKD_NULL)
10972
- {
10973
- DEBUG_MSG (" kdf must be CKD_NULL" );
10974
- return CKR_MECHANISM_PARAM_INVALID;
10975
- }
10976
- if ((CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulSharedDataLen != 0 ) ||
10977
- (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pSharedData != NULL_PTR))
11039
+
11040
+ CK_ECDH1_DERIVE_PARAMS_PTR ecdhParams = CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter );
11041
+
11042
+ if ((ecdhParams->ulPublicDataLen == 0 ) ||
11043
+ (ecdhParams->pPublicData == NULL_PTR))
10978
11044
{
10979
- DEBUG_MSG (" there must be no shared data" );
11045
+ DEBUG_MSG (" there must be a public data" );
10980
11046
return CKR_MECHANISM_PARAM_INVALID;
10981
11047
}
10982
- if (( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> ulPublicDataLen == 0 ) ||
10983
- ( CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism-> pParameter )-> pPublicData == NULL_PTR) )
11048
+
11049
+ switch (ecdhParams-> kdf )
10984
11050
{
10985
- DEBUG_MSG (" there must be a public data" );
10986
- return CKR_MECHANISM_PARAM_INVALID;
11051
+ case CKD_NULL:
11052
+ if ((ecdhParams->ulSharedDataLen != 0 ) ||
11053
+ (ecdhParams->pSharedData != NULL_PTR))
11054
+ {
11055
+ DEBUG_MSG (" there must be no shared data when KDF is CKD_NULL" );
11056
+ return CKR_MECHANISM_PARAM_INVALID;
11057
+ }
11058
+ break ;
11059
+ case CKD_SHA1_KDF:
11060
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA1);
11061
+ break ;
11062
+ case CKD_SHA224_KDF:
11063
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA224);
11064
+ break ;
11065
+ case CKD_SHA256_KDF:
11066
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA256);
11067
+ break ;
11068
+ case CKD_SHA384_KDF:
11069
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA384);
11070
+ break ;
11071
+ case CKD_SHA512_KDF:
11072
+ kdfAlgorithm = CryptoFactory::i ()->getHashAlgorithm (HashAlgo::SHA512);
11073
+ break ;
11074
+ default :
11075
+ DEBUG_MSG (" Unknown KDF" );
11076
+ return CKR_MECHANISM_PARAM_INVALID;
10987
11077
}
10988
11078
10989
11079
// Get the session
@@ -11032,6 +11122,14 @@ CK_RV SoftHSM::deriveEDDSA
11032
11122
switch (keyType)
11033
11123
{
11034
11124
case CKK_GENERIC_SECRET:
11125
+ if (kdfAlgorithm != NULL ) {
11126
+ const size_t maxLen = kdfAlgorithm->getHashSize () * (1UL << 32 );
11127
+ if (byteLen > maxLen)
11128
+ {
11129
+ INFO_MSG (" CKA_VALUE_LEN must be at most %zu" , maxLen);
11130
+ return CKR_ATTRIBUTE_VALUE_INVALID;
11131
+ }
11132
+ }
11035
11133
break ;
11036
11134
#ifndef WITH_FIPS
11037
11135
case CKK_DES:
@@ -11095,10 +11193,8 @@ CK_RV SoftHSM::deriveEDDSA
11095
11193
}
11096
11194
11097
11195
ByteString publicData;
11098
- publicData.resize (CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
11099
- memcpy (&publicData[0 ],
11100
- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->pPublicData ,
11101
- CK_ECDH1_DERIVE_PARAMS_PTR (pMechanism->pParameter )->ulPublicDataLen );
11196
+ publicData.resize (ecdhParams->ulPublicDataLen );
11197
+ memcpy (&publicData[0 ], ecdhParams->pPublicData , ecdhParams->ulPublicDataLen );
11102
11198
PublicKey* publicKey = eddsa->newPublicKey ();
11103
11199
if (publicKey == NULL )
11104
11200
{
@@ -11122,6 +11218,44 @@ CK_RV SoftHSM::deriveEDDSA
11122
11218
eddsa->recyclePrivateKey (privateKey);
11123
11219
eddsa->recyclePublicKey (publicKey);
11124
11220
11221
+ // Apply key derivation function (ANSI X9.63)
11222
+ if (rv == CKR_OK && kdfAlgorithm != NULL ) {
11223
+ const ByteString& secretBits = secret->getKeyBits ();
11224
+ const size_t counterOffset = secretBits.size ();
11225
+ unsigned long counter = 1 ;
11226
+
11227
+ ByteString hashInput;
11228
+ hashInput.resize (secretBits.size () + 4 + ecdhParams->ulSharedDataLen );
11229
+
11230
+ // Prepare hash input content - derived secret, 4 bytes for counter, shared data
11231
+ memcpy (&hashInput[0 ], secretBits.const_byte_str (), secretBits.size ());
11232
+ memcpy (&hashInput[secretBits.size () + 4 ], ecdhParams->pSharedData , ecdhParams->ulSharedDataLen );
11233
+
11234
+ ByteString hashOutput;
11235
+ ByteString derivedOutput;
11236
+
11237
+ while (derivedOutput.size () < byteLen) {
11238
+ hashInput[counterOffset + 0 ] = (counter >> 48 ) & 0xFF ;
11239
+ hashInput[counterOffset + 1 ] = (counter >> 32 ) & 0xFF ;
11240
+ hashInput[counterOffset + 2 ] = (counter >> 16 ) & 0xFF ;
11241
+ hashInput[counterOffset + 3 ] = (counter >> 0 ) & 0xFF ;
11242
+
11243
+ kdfAlgorithm->hashInit ();
11244
+ kdfAlgorithm->hashUpdate (hashInput);
11245
+ kdfAlgorithm->hashFinal (hashOutput);
11246
+
11247
+ derivedOutput += hashOutput;
11248
+ counter++;
11249
+ }
11250
+
11251
+ // Trim to desired length
11252
+ derivedOutput.resize (byteLen);
11253
+
11254
+ secret->setBitLen (byteLen * 8 );
11255
+ if (!secret->setKeyBits (derivedOutput))
11256
+ rv = CKR_FUNCTION_FAILED;
11257
+ }
11258
+
11125
11259
// Create the secret object using C_CreateObject
11126
11260
const CK_ULONG maxAttribs = 32 ;
11127
11261
CK_OBJECT_CLASS objClass = CKO_SECRET_KEY;
0 commit comments