Skip to content

Support for ECDSA with hashing #683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: develop
Choose a base branch
from
Draft
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
60 changes: 60 additions & 0 deletions src/lib/SoftHSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,11 @@ void SoftHSM::prepareSupportedMecahnisms(std::map<std::string, CK_MECHANISM_TYPE
#ifdef WITH_ECC
t["CKM_EC_KEY_PAIR_GEN"] = CKM_EC_KEY_PAIR_GEN;
t["CKM_ECDSA"] = CKM_ECDSA;
t["CKM_ECDSA_SHA1"] = CKM_ECDSA_SHA1;
t["CKM_ECDSA_SHA224"] = CKM_ECDSA_SHA224;
t["CKM_ECDSA_SHA256"] = CKM_ECDSA_SHA256;
t["CKM_ECDSA_SHA384"] = CKM_ECDSA_SHA384;
t["CKM_ECDSA_SHA512"] = CKM_ECDSA_SHA512;
#endif
#if defined(WITH_ECC) || defined(WITH_EDDSA)
t["CKM_ECDH1_DERIVE"] = CKM_ECDH1_DERIVE;
Expand Down Expand Up @@ -1240,6 +1245,11 @@ CK_RV SoftHSM::C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_
pInfo->flags = CKF_GENERATE_KEY_PAIR | CKF_EC_COMMOM;
break;
case CKM_ECDSA:
case CKM_ECDSA_SHA1:
case CKM_ECDSA_SHA224:
case CKM_ECDSA_SHA256:
case CKM_ECDSA_SHA384:
case CKM_ECDSA_SHA512:
pInfo->ulMinKeySize = ecdsaMinSize;
pInfo->ulMaxKeySize = ecdsaMaxSize;
pInfo->flags = CKF_SIGN | CKF_VERIFY | CKF_EC_COMMOM;
Expand Down Expand Up @@ -4358,6 +4368,31 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA1:
mechanism = AsymMech::ECDSA_SHA1;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA224:
mechanism = AsymMech::ECDSA_SHA224;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA256:
mechanism = AsymMech::ECDSA_SHA256;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA384:
mechanism = AsymMech::ECDSA_SHA384;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA512:
mechanism = AsymMech::ECDSA_SHA512;
bAllowMultiPartOp = false;
isECDSA = true;
break;
#endif
#ifdef WITH_GOST
case CKM_GOSTR3410:
Expand Down Expand Up @@ -5334,6 +5369,31 @@ CK_RV SoftHSM::AsymVerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMech
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA1:
mechanism = AsymMech::ECDSA_SHA1;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA224:
mechanism = AsymMech::ECDSA_SHA224;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA256:
mechanism = AsymMech::ECDSA_SHA256;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA384:
mechanism = AsymMech::ECDSA_SHA384;
bAllowMultiPartOp = false;
isECDSA = true;
break;
case CKM_ECDSA_SHA512:
mechanism = AsymMech::ECDSA_SHA512;
bAllowMultiPartOp = false;
isECDSA = true;
break;
#endif
#ifdef WITH_GOST
case CKM_GOSTR3410:
Expand Down
5 changes: 5 additions & 0 deletions src/lib/crypto/AsymmetricAlgorithm.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@ struct AsymMech
DSA_SHA384,
DSA_SHA512,
ECDSA,
ECDSA_SHA1,
ECDSA_SHA224,
ECDSA_SHA256,
ECDSA_SHA384,
ECDSA_SHA512,
GOST,
GOST_GOST,
EDDSA
Expand Down
109 changes: 88 additions & 21 deletions src/lib/crypto/BotanECDSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,33 @@ bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
ByteString& signature, const AsymMech::Type mechanism,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{
std::string emsa;
std::string emsa = "Raw";

if (mechanism == AsymMech::ECDSA)
HashAlgo::Type hash = HashAlgo::Unknown;
if (mechanism != AsymMech::ECDSA)
{
emsa = "Raw";
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);
return false;
}
}
else
{
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
return false;
}

// Check if the private key is the right type
if (!privateKey->isOfType(BotanECDSAPrivateKey::type))
Expand Down Expand Up @@ -107,12 +123,30 @@ bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
return false;
}

// Pre-hash the data if necessary
ByteString prepDataToSign;

if (hash == HashAlgo::Unknown) {
prepDataToSign = dataToSign;
} else {
HashAlgorithm* digest = BotanCryptoFactory::i()->getHashAlgorithm(hash);

if (!digest->hashInit()
|| !digest->hashUpdate(dataToSign)
|| !digest->hashFinal(prepDataToSign))
{
delete digest;
return false;
}
delete digest;
}

// Perform the signature operation
std::vector<uint8_t> signResult;
try
{
BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
signResult = signer->sign_message(prepDataToSign.const_byte_str(), prepDataToSign.size(), *rng->getRNG());
}
catch (...)
{
Expand Down Expand Up @@ -162,18 +196,33 @@ bool BotanECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
const ByteString& signature, const AsymMech::Type mechanism,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{
std::string emsa;
std::string emsa = "Raw";

if (mechanism == AsymMech::ECDSA)
{
emsa = "Raw";
}
else
HashAlgo::Type hash = HashAlgo::Unknown;
if (mechanism != AsymMech::ECDSA)
{
switch (mechanism)
{
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);

return false;
}
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);
return false;
}
}

// Check if the public key is the right type
if (!publicKey->isOfType(BotanECDSAPublicKey::type))
Expand Down Expand Up @@ -204,12 +253,30 @@ bool BotanECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
return false;
}

// Pre-hash the data if necessary
ByteString prepDataToSign;

if (hash == HashAlgo::Unknown) {
prepDataToSign = originalData;
} else {
HashAlgorithm* digest = BotanCryptoFactory::i()->getHashAlgorithm(hash);

if (!digest->hashInit()
|| !digest->hashUpdate(originalData)
|| !digest->hashFinal(prepDataToSign))
{
delete digest;
return false;
}
delete digest;
}

// Perform the verify operation
bool verResult;
try
{
verResult = verifier->verify_message(originalData.const_byte_str(),
originalData.size(),
verResult = verifier->verify_message(prepDataToSign.const_byte_str(),
prepDataToSign.size(),
signature.const_byte_str(),
signature.size());
}
Expand Down
96 changes: 88 additions & 8 deletions src/lib/crypto/OSSLECDSA.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,32 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
ByteString& signature, const AsymMech::Type mechanism,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{

HashAlgo::Type hash = HashAlgo::Unknown;

if (mechanism != AsymMech::ECDSA)
{
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
return false;
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);
return false;
}
}

// Check if the private key is the right type
Expand Down Expand Up @@ -93,6 +115,24 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
EC_KEY_set_method(eckey, EC_KEY_OpenSSL());
#endif

// Pre-hash the data if necessary
ByteString prepDataToSign;
if (hash == HashAlgo::Unknown) {
prepDataToSign = dataToSign;
} else {
HashAlgorithm* digest = CryptoFactory::i()->getHashAlgorithm(hash);

if (!digest->hashInit()
|| !digest->hashUpdate(dataToSign)
|| !digest->hashFinal(prepDataToSign))
{
delete digest;
return false;
}
delete digest;
}


// Perform the signature operation
size_t len = pk->getOrderLength();
if (len == 0)
Expand All @@ -102,7 +142,7 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
}
signature.resize(2 * len);
memset(&signature[0], 0, 2 * len);
ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
ECDSA_SIG *sig = ECDSA_do_sign(prepDataToSign.const_byte_str(), prepDataToSign.size(), eckey);
if (sig == NULL)
{
ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error());
Expand Down Expand Up @@ -145,11 +185,33 @@ bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
const ByteString& signature, const AsymMech::Type mechanism,
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
{

HashAlgo::Type hash = HashAlgo::Unknown;

if (mechanism != AsymMech::ECDSA)
{
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
return false;
}
{
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);
return false;
}
}

// Check if the private key is the right type
if (!publicKey->isOfType(OSSLECPublicKey::type))
Expand Down Expand Up @@ -213,7 +275,25 @@ bool OSSLECDSA::verify(PublicKey* publicKey, const ByteString& originalData,
ECDSA_SIG_free(sig);
return false;
}
int ret = ECDSA_do_verify(originalData.const_byte_str(), originalData.size(), sig, eckey);

// Pre-hash the data if necessary
ByteString prepDataToSign;
if (hash == HashAlgo::Unknown) {
prepDataToSign = originalData;
} else {
HashAlgorithm* digest = CryptoFactory::i()->getHashAlgorithm(hash);

if (!digest->hashInit()
|| !digest->hashUpdate(originalData)
|| !digest->hashFinal(prepDataToSign))
{
delete digest;
return false;
}
delete digest;
}

int ret = ECDSA_do_verify(prepDataToSign.const_byte_str(), prepDataToSign.size(), sig, eckey);
if (ret != 1)
{
if (ret < 0)
Expand Down
Loading