Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/lib/SoftHSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4440,27 +4440,27 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
break;
case CKM_ECDSA_SHA1:
mechanism = AsymMech::ECDSA_SHA1;
bAllowMultiPartOp = false;
bAllowMultiPartOp = true;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Enable multipart verify for the same hashed ECDSA mechanisms.

This only turns multipart on for signing. C_VerifyUpdate/C_VerifyFinal will still fail for CKM_ECDSA_SHA1/224/256/384/512 because SoftHSM::AsymVerifyInit still leaves bAllowMultiPartOp = false (see Line 5541 and the matching SHA224/256/384/512 cases below).

Suggested fix
 		case CKM_ECDSA_SHA1:
 			mechanism = AsymMech::ECDSA_SHA1;
-			bAllowMultiPartOp = false;
+			bAllowMultiPartOp = true;
 			isECDSA = true;
 			break;
 		case CKM_ECDSA_SHA224:
 			mechanism = AsymMech::ECDSA_SHA224;
-			bAllowMultiPartOp = false;
+			bAllowMultiPartOp = true;
 			isECDSA = true;
 			break;
 		case CKM_ECDSA_SHA256:
 			mechanism = AsymMech::ECDSA_SHA256;
-			bAllowMultiPartOp = false;
+			bAllowMultiPartOp = true;
 			isECDSA = true;
 			break;
 		case CKM_ECDSA_SHA384:
 			mechanism = AsymMech::ECDSA_SHA384;
-			bAllowMultiPartOp = false;
+			bAllowMultiPartOp = true;
 			isECDSA = true;
 			break;
 		case CKM_ECDSA_SHA512:
 			mechanism = AsymMech::ECDSA_SHA512;
-			bAllowMultiPartOp = false;
+			bAllowMultiPartOp = true;
 			isECDSA = true;
 			break;

Also applies to: 4448-4448, 4453-4453, 4458-4458, 4463-4463

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lib/SoftHSM.cpp` at line 4443, AsymVerifyInit currently leaves multipart
disabled for hashed ECDSA mechanisms; update the CKM_ECDSA_SHA1 /
CKM_ECDSA_SHA224 / CKM_ECDSA_SHA256 / CKM_ECDSA_SHA384 / CKM_ECDSA_SHA512
branches in SoftHSM::AsymVerifyInit to set bAllowMultiPartOp = true (same as the
signing side), so C_VerifyUpdate/C_VerifyFinal will be allowed for these
mechanisms; modify the branches handling those mechanism constants to enable
multipart by assigning bAllowMultiPartOp = true.

isECDSA = true;
break;
case CKM_ECDSA_SHA224:
mechanism = AsymMech::ECDSA_SHA224;
bAllowMultiPartOp = false;
bAllowMultiPartOp = true;
isECDSA = true;
break;
case CKM_ECDSA_SHA256:
mechanism = AsymMech::ECDSA_SHA256;
bAllowMultiPartOp = false;
bAllowMultiPartOp = true;
isECDSA = true;
break;
case CKM_ECDSA_SHA384:
mechanism = AsymMech::ECDSA_SHA384;
bAllowMultiPartOp = false;
bAllowMultiPartOp = true;
isECDSA = true;
break;
case CKM_ECDSA_SHA512:
mechanism = AsymMech::ECDSA_SHA512;
bAllowMultiPartOp = false;
bAllowMultiPartOp = true;
isECDSA = true;
break;
#endif
Expand Down
317 changes: 295 additions & 22 deletions src/lib/crypto/BotanECDSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,19 @@ BotanECDSA::BotanECDSA()
{
signer = NULL;
verifier = NULL;
pCurrentHash = NULL;
}

// Destructor
BotanECDSA::~BotanECDSA()
{
delete signer;
delete verifier;

if (pCurrentHash != NULL)
{
delete pCurrentHash;
}
}

// Signing functions
Expand Down Expand Up @@ -169,27 +175,162 @@ bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
return true;
}

// Signing functions
bool BotanECDSA::signInit(PrivateKey* /*privateKey*/, const AsymMech::Type /*mechanism*/,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
bool BotanECDSA::signInit(PrivateKey* privateKey, const AsymMech::Type mechanism,
const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
ERROR_MSG("ECDSA does not support multi part signing");
if (!AsymmetricAlgorithm::signInit(privateKey, mechanism, param, paramLen))
{
return false;
}

return false;
// Check if the private key is the right type
if (!privateKey->isOfType(BotanECDSAPrivateKey::type))
{
ERROR_MSG("Invalid key type supplied");

ByteString dummy;
AsymmetricAlgorithm::signFinal(dummy);

return false;
}

HashAlgo::Type hash = HashAlgo::Unknown;

switch (mechanism)
{
case AsymMech::ECDSA_SHA1:
hash = HashAlgo::SHA1;
break;
case AsymMech::ECDSA_SHA224:
hash = HashAlgo::SHA224;
break;
case AsymMech::ECDSA_SHA256:
hash = HashAlgo::SHA256;
break;
case AsymMech::ECDSA_SHA384:
hash = HashAlgo::SHA384;
break;
case AsymMech::ECDSA_SHA512:
hash = HashAlgo::SHA512;
break;
default:
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);

ByteString dummy;
AsymmetricAlgorithm::signFinal(dummy);

return false;
}

pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash);

if (pCurrentHash == NULL || !pCurrentHash->hashInit())
{
if (pCurrentHash != NULL)
{
delete pCurrentHash;
pCurrentHash = NULL;
}

ByteString dummy;
AsymmetricAlgorithm::signFinal(dummy);

return false;
}

return true;
}

bool BotanECDSA::signUpdate(const ByteString& /*dataToSign*/)
bool BotanECDSA::signUpdate(const ByteString& dataToSign)
{
ERROR_MSG("ECDSA does not support multi part signing");
if (!AsymmetricAlgorithm::signUpdate(dataToSign))
{
return false;
}

return false;
if (!pCurrentHash->hashUpdate(dataToSign))
{
delete pCurrentHash;
pCurrentHash = NULL;

ByteString dummy;
AsymmetricAlgorithm::signFinal(dummy);

return false;
}

return true;
}

bool BotanECDSA::signFinal(ByteString& /*signature*/)
bool BotanECDSA::signFinal(ByteString& signature)
{
ERROR_MSG("ECDSA does not support multi part signing");
// Save necessary state before calling super class signFinal
BotanECDSAPrivateKey* pk = (BotanECDSAPrivateKey*) currentPrivateKey;

return false;
if (!AsymmetricAlgorithm::signFinal(signature))
{
return false;
}

ByteString hash;

bool bResult = pCurrentHash->hashFinal(hash);

delete pCurrentHash;
pCurrentHash = NULL;

if (!bResult)
{
return false;
}

// Get the Botan key
Botan::ECDSA_PrivateKey* botanKey = pk->getBotanKey();

if (botanKey == NULL)
{
ERROR_MSG("Could not get the Botan private key");

return false;
}

try
{
BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
signer = new Botan::PK_Signer(*botanKey, *rng->getRNG(), "Raw");
}
catch (...)
{
ERROR_MSG("Could not create the signer token");

return false;
}

// Perform the signature operation
std::vector<uint8_t> signResult;
try
{
BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
signResult = signer->sign_message(hash.const_byte_str(), hash.size(), *rng->getRNG());
}
catch (...)
{
ERROR_MSG("Could not sign the data");

delete signer;
signer = NULL;

return false;
}

// Return the result
signature.resize(signResult.size());
memcpy(&signature[0], signResult.data(), signResult.size());

delete signer;
signer = NULL;

return true;
}

// Verification functions
Expand Down Expand Up @@ -298,27 +439,159 @@ bool BotanECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
return verResult;
}

// Verification functions
bool BotanECDSA::verifyInit(PublicKey* /*publicKey*/, const AsymMech::Type /*mechanism*/,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
bool BotanECDSA::verifyInit(PublicKey* publicKey, const AsymMech::Type mechanism,
const void* param /* = NULL */, const size_t paramLen /* = 0 */)
{
ERROR_MSG("ECDSA does not support multi part verifying");
if (!AsymmetricAlgorithm::verifyInit(publicKey, mechanism, param, paramLen))
{
return false;
}

return false;
// Check if the public key is the right type
if (!publicKey->isOfType(BotanECDSAPublicKey::type))
{
ERROR_MSG("Invalid key type supplied");

ByteString dummy;
AsymmetricAlgorithm::verifyFinal(dummy);

return false;
}

HashAlgo::Type hash = HashAlgo::Unknown;

switch (mechanism)
{
case AsymMech::ECDSA_SHA1:
hash = HashAlgo::SHA1;
break;
case AsymMech::ECDSA_SHA224:
hash = HashAlgo::SHA224;
break;
case AsymMech::ECDSA_SHA256:
hash = HashAlgo::SHA256;
break;
case AsymMech::ECDSA_SHA384:
hash = HashAlgo::SHA384;
break;
case AsymMech::ECDSA_SHA512:
hash = HashAlgo::SHA512;
break;
default:
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);

ByteString dummy;
AsymmetricAlgorithm::verifyFinal(dummy);

return false;
}

pCurrentHash = CryptoFactory::i()->getHashAlgorithm(hash);

if (pCurrentHash == NULL || !pCurrentHash->hashInit())
{
if (pCurrentHash != NULL)
{
delete pCurrentHash;
pCurrentHash = NULL;
}

ByteString dummy;
AsymmetricAlgorithm::verifyFinal(dummy);

return false;
}

return true;
}

bool BotanECDSA::verifyUpdate(const ByteString& /*originalData*/)
bool BotanECDSA::verifyUpdate(const ByteString& originalData)
{
ERROR_MSG("ECDSA does not support multi part verifying");
if (!AsymmetricAlgorithm::verifyUpdate(originalData))
{
return false;
}

return false;
if (!pCurrentHash->hashUpdate(originalData))
{
delete pCurrentHash;
pCurrentHash = NULL;

ByteString dummy;
AsymmetricAlgorithm::verifyFinal(dummy);

return false;
}

return true;
}

bool BotanECDSA::verifyFinal(const ByteString& /*signature*/)
bool BotanECDSA::verifyFinal(const ByteString& signature)
{
ERROR_MSG("ECDSA does not support multi part verifying");
// Save necessary state before calling super class verifyFinal
BotanECDSAPublicKey* pk = (BotanECDSAPublicKey*) currentPublicKey;

return false;
if (!AsymmetricAlgorithm::verifyFinal(signature))
{
return false;
}

ByteString hash;

bool bResult = pCurrentHash->hashFinal(hash);

delete pCurrentHash;
pCurrentHash = NULL;

if (!bResult)
{
return false;
}

// Get the Botan key
Botan::ECDSA_PublicKey* botanKey = pk->getBotanKey();

if (botanKey == NULL)
{
ERROR_MSG("Could not get the Botan public key");

return false;
}

try
{
verifier = new Botan::PK_Verifier(*botanKey, "Raw");
}
catch (...)
{
ERROR_MSG("Could not create the verifier token");

return false;
}

// Perform the verify operation
bool verResult;
try
{
verResult = verifier->verify_message(hash.const_byte_str(),
hash.size(),
signature.const_byte_str(),
signature.size());
}
catch (...)
{
ERROR_MSG("Could not check the signature");

delete verifier;
verifier = NULL;

return false;
}

delete verifier;
verifier = NULL;

return verResult;
}

// Encryption functions
Expand Down
Loading
Loading