Skip to content

Commit a5d8b93

Browse files
Support for ECDSA with hashing
Aims to fix #620.
1 parent 557b2fd commit a5d8b93

File tree

4 files changed

+121
-12
lines changed

4 files changed

+121
-12
lines changed

src/lib/SoftHSM.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,11 @@ void SoftHSM::prepareSupportedMechanisms(std::map<std::string, CK_MECHANISM_TYPE
804804
#ifdef WITH_ECC
805805
t["CKM_EC_KEY_PAIR_GEN"] = CKM_EC_KEY_PAIR_GEN;
806806
t["CKM_ECDSA"] = CKM_ECDSA;
807+
t["CKM_ECDSA_SHA1"] = CKM_ECDSA_SHA1;
808+
t["CKM_ECDSA_SHA224"] = CKM_ECDSA_SHA224;
809+
t["CKM_ECDSA_SHA256"] = CKM_ECDSA_SHA256;
810+
t["CKM_ECDSA_SHA384"] = CKM_ECDSA_SHA384;
811+
t["CKM_ECDSA_SHA512"] = CKM_ECDSA_SHA512;
807812
#endif
808813
#if defined(WITH_ECC) || defined(WITH_EDDSA)
809814
t["CKM_ECDH1_DERIVE"] = CKM_ECDH1_DERIVE;
@@ -4360,6 +4365,31 @@ CK_RV SoftHSM::AsymSignInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechan
43604365
bAllowMultiPartOp = false;
43614366
isECDSA = true;
43624367
break;
4368+
case CKM_ECDSA_SHA1:
4369+
mechanism = AsymMech::ECDSA_SHA1;
4370+
bAllowMultiPartOp = false;
4371+
isECDSA = true;
4372+
break;
4373+
case CKM_ECDSA_SHA224:
4374+
mechanism = AsymMech::ECDSA_SHA224;
4375+
bAllowMultiPartOp = false;
4376+
isECDSA = true;
4377+
break;
4378+
case CKM_ECDSA_SHA256:
4379+
mechanism = AsymMech::ECDSA_SHA256;
4380+
bAllowMultiPartOp = false;
4381+
isECDSA = true;
4382+
break;
4383+
case CKM_ECDSA_SHA384:
4384+
mechanism = AsymMech::ECDSA_SHA384;
4385+
bAllowMultiPartOp = false;
4386+
isECDSA = true;
4387+
break;
4388+
case CKM_ECDSA_SHA512:
4389+
mechanism = AsymMech::ECDSA_SHA512;
4390+
bAllowMultiPartOp = false;
4391+
isECDSA = true;
4392+
break;
43634393
#endif
43644394
#ifdef WITH_GOST
43654395
case CKM_GOSTR3410:

src/lib/crypto/AsymmetricAlgorithm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ struct AsymMech
8585
DSA_SHA384,
8686
DSA_SHA512,
8787
ECDSA,
88+
ECDSA_SHA1,
89+
ECDSA_SHA224,
90+
ECDSA_SHA256,
91+
ECDSA_SHA384,
92+
ECDSA_SHA512,
8893
GOST,
8994
GOST_GOST,
9095
EDDSA

src/lib/crypto/BotanECDSA.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -65,17 +65,33 @@ bool BotanECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
6565
ByteString& signature, const AsymMech::Type mechanism,
6666
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
6767
{
68-
std::string emsa;
68+
std::string emsa = "Raw";
6969

70-
if (mechanism == AsymMech::ECDSA)
70+
HashAlgo::Type hash = HashAlgo::Unknown;
71+
if (mechanism != AsymMech::ECDSA)
7172
{
72-
emsa = "Raw";
73+
switch (mechanism)
74+
{
75+
case AsymMech::ECDSA_SHA1:
76+
hash = HashAlgo::SHA1;
77+
break;
78+
case AsymMech::ECDSA_SHA224:
79+
hash = HashAlgo::SHA224;
80+
break;
81+
case AsymMech::ECDSA_SHA256:
82+
hash = HashAlgo::SHA256;
83+
break;
84+
case AsymMech::ECDSA_SHA384:
85+
hash = HashAlgo::SHA384;
86+
break;
87+
case AsymMech::ECDSA_SHA512:
88+
hash = HashAlgo::SHA512;
89+
break;
90+
default:
91+
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
92+
return false;
93+
}
7394
}
74-
else
75-
{
76-
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
77-
return false;
78-
}
7995

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

126+
// Pre-hash the data if necessary
127+
ByteString prepDataToSign;
128+
129+
if (hash == HashAlgo::Unknown) {
130+
prepDataToSign = dataToSign;
131+
} else {
132+
HashAlgorithm* digest = BotanCryptoFactory::i()->getHashAlgorithm(hash);
133+
134+
if (!digest->hashInit()
135+
|| !digest->hashUpdate(dataToSign)
136+
|| !digest->hashFinal(prepDataToSign))
137+
{
138+
delete digest;
139+
return false;
140+
}
141+
delete digest;
142+
}
143+
110144
// Perform the signature operation
111145
std::vector<uint8_t> signResult;
112146
try
113147
{
114148
BotanRNG* rng = (BotanRNG*)BotanCryptoFactory::i()->getRNG();
115-
signResult = signer->sign_message(dataToSign.const_byte_str(), dataToSign.size(), *rng->getRNG());
149+
signResult = signer->sign_message(prepDataToSign.const_byte_str(), prepDataToSign.size(), *rng->getRNG());
116150
}
117151
catch (...)
118152
{

src/lib/crypto/OSSLECDSA.cpp

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,32 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
5353
ByteString& signature, const AsymMech::Type mechanism,
5454
const void* /* param = NULL */, const size_t /* paramLen = 0 */)
5555
{
56+
57+
HashAlgo::Type hash = HashAlgo::Unknown;
58+
5659
if (mechanism != AsymMech::ECDSA)
5760
{
58-
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
59-
return false;
61+
switch (mechanism)
62+
{
63+
case AsymMech::ECDSA_SHA1:
64+
hash = HashAlgo::SHA1;
65+
break;
66+
case AsymMech::ECDSA_SHA224:
67+
hash = HashAlgo::SHA224;
68+
break;
69+
case AsymMech::ECDSA_SHA256:
70+
hash = HashAlgo::SHA256;
71+
break;
72+
case AsymMech::ECDSA_SHA384:
73+
hash = HashAlgo::SHA384;
74+
break;
75+
case AsymMech::ECDSA_SHA512:
76+
hash = HashAlgo::SHA512;
77+
break;
78+
default:
79+
ERROR_MSG("Invalid mechanism supplied (%i)", mechanism);
80+
return false;
81+
}
6082
}
6183

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

118+
// Pre-hash the data if necessary
119+
ByteString prepDataToSign;
120+
if (hash == HashAlgo::Unknown) {
121+
prepDataToSign = dataToSign;
122+
} else {
123+
HashAlgorithm* digest = CryptoFactory::i()->getHashAlgorithm(hash);
124+
125+
if (!digest->hashInit()
126+
|| !digest->hashUpdate(dataToSign)
127+
|| !digest->hashFinal(prepDataToSign))
128+
{
129+
delete digest;
130+
return false;
131+
}
132+
delete digest;
133+
}
134+
135+
96136
// Perform the signature operation
97137
size_t len = pk->getOrderLength();
98138
if (len == 0)
@@ -102,7 +142,7 @@ bool OSSLECDSA::sign(PrivateKey* privateKey, const ByteString& dataToSign,
102142
}
103143
signature.resize(2 * len);
104144
memset(&signature[0], 0, 2 * len);
105-
ECDSA_SIG *sig = ECDSA_do_sign(dataToSign.const_byte_str(), dataToSign.size(), eckey);
145+
ECDSA_SIG *sig = ECDSA_do_sign(prepDataToSign.const_byte_str(), prepDataToSign.size(), eckey);
106146
if (sig == NULL)
107147
{
108148
ERROR_MSG("ECDSA sign failed (0x%08X)", ERR_get_error());

0 commit comments

Comments
 (0)