Skip to content

Commit 7e7f06c

Browse files
Replace RSA/ECDSA_Sign/Verify with EVP_DigestSign/Verify APIs in ACVP tests. (#264)
* Replace RSA/ECDSA_Sign/Verify APIs with EVP_DigestSign/Verify APIs in ACVP tests * Fix memory leak. * Rename key to rsa. * Apply suggestions from code review Co-authored-by: torben-hansen <[email protected]> Co-authored-by: torben-hansen <[email protected]>
1 parent c81510d commit 7e7f06c

File tree

6 files changed

+131
-73
lines changed

6 files changed

+131
-73
lines changed

util/fipstools/acvp/acvptool/subprocess/ecdsa.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
9191
ID: group.ID,
9292
}
9393
var sigGenPrivateKey []byte
94+
var qxHex []byte
95+
var qyHex []byte
9496

9597
for _, test := range group.Tests {
9698
var testResp ecdsaTestResponse
@@ -148,8 +150,10 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
148150
}
149151

150152
sigGenPrivateKey = result[0]
151-
response.QxHex = hex.EncodeToString(result[1])
152-
response.QyHex = hex.EncodeToString(result[2])
153+
qxHex = result[1]
154+
qyHex = result[2]
155+
response.QxHex = hex.EncodeToString(qxHex)
156+
response.QyHex = hex.EncodeToString(qyHex)
153157
}
154158

155159
msg, err := hex.DecodeString(test.MsgHex)
@@ -167,8 +171,19 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
167171
if err != nil {
168172
return nil, fmt.Errorf("signature generation failed for test case %d/%d: %s", group.ID, test.ID, err)
169173
}
170-
testResp.RHex = hex.EncodeToString(result[0])
171-
testResp.SHex = hex.EncodeToString(result[1])
174+
rHex := result[0]
175+
sHex := result[1]
176+
testResp.RHex = hex.EncodeToString(rHex)
177+
testResp.SHex = hex.EncodeToString(sHex)
178+
// Ask the subprocess to verify the generated signature for this test case.
179+
ver_result, ver_err := m.Transact(e.algo+"/"+"sigVer", 1, []byte(group.Curve), []byte(group.HashAlgo), msg, qxHex, qyHex, rHex, sHex)
180+
if ver_err != nil {
181+
return nil, fmt.Errorf("After signature generation, signature verification failed for test case %d/%d: %s", group.ID, test.ID, ver_err)
182+
}
183+
// ver_result[0] should be a single byte. The value should be one in this case.
184+
if !bytes.Equal(ver_result[0], []byte{01}) {
185+
return nil, fmt.Errorf("After signature generation, signature verification returned unexpected result: %q for test case %d/%d.", ver_result[0], group.ID, test.ID)
186+
}
172187

173188
case "sigVer":
174189
p := e.primitives[group.HashAlgo]

util/fipstools/acvp/acvptool/subprocess/rsa.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ func processSigGen(vectorSet []byte, m Transactable) (interface{}, error) {
178178
}
179179

180180
operation := "RSA/sigGen/" + group.Hash + "/" + group.SigType
181+
ver_operation := "RSA/sigVer/" + group.Hash + "/" + group.SigType
181182

182183
for _, test := range group.Tests {
183184
msg, err := hex.DecodeString(test.MessageHex)
@@ -190,16 +191,28 @@ func processSigGen(vectorSet []byte, m Transactable) (interface{}, error) {
190191
return nil, err
191192
}
192193

194+
n := results[0]
195+
e := results[1]
196+
sig := results[2]
197+
193198
if len(response.N) == 0 {
194-
response.N = hex.EncodeToString(results[0])
195-
response.E = hex.EncodeToString(results[1])
196-
} else if response.N != hex.EncodeToString(results[0]) {
199+
response.N = hex.EncodeToString(n)
200+
response.E = hex.EncodeToString(e)
201+
} else if response.N != hex.EncodeToString(n) {
197202
return nil, fmt.Errorf("module wrapper returned different RSA keys for the same SigGen configuration")
198203
}
199204

205+
// Ask the subprocess to verify the generated signature for this test case.
206+
ver_results, ver_err := m.Transact(ver_operation, 1, n, e, msg, sig)
207+
if ver_err != nil {
208+
return nil, ver_err
209+
}
210+
if len(ver_results[0]) != 1 || ver_results[0][0] != 1 {
211+
return nil, fmt.Errorf("module wrapper returned RSA Sig cannot be verified for test case %d/%d.", group.ID, test.ID)
212+
}
200213
response.Tests = append(response.Tests, rsaSigGenTestResponse{
201214
ID: test.ID,
202-
Sig: hex.EncodeToString(results[2]),
215+
Sig: hex.EncodeToString(sig),
203216
})
204217
}
205218

util/fipstools/acvp/acvptool/test/tests.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
{"Wrapper": "modulewrapper", "In": "vectors/CMAC-AES.bz2", "Out": "expected/CMAC-AES.bz2"},
1414
{"Wrapper": "modulewrapper", "In": "vectors/ctrDRBG.bz2", "Out": "expected/ctrDRBG.bz2"},
1515
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA.bz2", "Out": "expected/ECDSA.bz2"},
16+
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA-SigGen.bz2"},
1617
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA-1.bz2", "Out": "expected/HMAC-SHA-1.bz2"},
1718
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-224.bz2", "Out": "expected/HMAC-SHA2-224.bz2"},
1819
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-256.bz2", "Out": "expected/HMAC-SHA2-256.bz2"},
@@ -25,6 +26,7 @@
2526
{"Wrapper": "modulewrapper", "In": "vectors/ACVP-AES-GCM-internal-IV.bz2"},
2627
{"Wrapper": "modulewrapper", "In": "vectors/kdf-components.bz2", "Out": "expected/kdf-components.bz2"},
2728
{"Wrapper": "modulewrapper", "In": "vectors/RSA.bz2", "Out": "expected/RSA.bz2"},
29+
{"Wrapper": "modulewrapper", "In": "vectors/RSA-SigGen.bz2"},
2830
{"Wrapper": "modulewrapper", "In": "vectors/SHA-1.bz2", "Out": "expected/SHA-1.bz2"},
2931
{"Wrapper": "modulewrapper", "In": "vectors/SHA2-224.bz2", "Out": "expected/SHA2-224.bz2"},
3032
{"Wrapper": "modulewrapper", "In": "vectors/SHA2-256.bz2", "Out": "expected/SHA2-256.bz2"},
21.5 KB
Binary file not shown.
14.7 KB
Binary file not shown.

util/fipstools/acvp/modulewrapper/modulewrapper.cc

Lines changed: 93 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <openssl/dh.h>
3333
#include <openssl/digest.h>
3434
#include <openssl/ec.h>
35+
#include <openssl/evp.h>
3536
#include <openssl/ec_key.h>
3637
#include <openssl/ecdh.h>
3738
#include <openssl/ecdsa.h>
@@ -1567,16 +1568,27 @@ static bool ECDSASigGen(const Span<const uint8_t> args[], ReplyCallback write_re
15671568
bssl::UniquePtr<EC_KEY> key = ECKeyFromName(args[0]);
15681569
bssl::UniquePtr<BIGNUM> d = BytesToBIGNUM(args[1]);
15691570
const EVP_MD *hash = HashFromName(args[2]);
1570-
uint8_t digest[EVP_MAX_MD_SIZE];
1571-
unsigned digest_len;
1572-
if (!key || !hash ||
1573-
!EVP_Digest(args[3].data(), args[3].size(), digest, &digest_len, hash,
1574-
/*impl=*/nullptr) ||
1575-
!EC_KEY_set_private_key(key.get(), d.get())) {
1571+
auto msg = args[3];
1572+
if (!key || !hash || !EC_KEY_set_private_key(key.get(), d.get())) {
15761573
return false;
15771574
}
1578-
1579-
bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_do_sign(digest, digest_len, key.get()));
1575+
bssl::ScopedEVP_MD_CTX ctx;
1576+
EVP_PKEY_CTX *pctx;
1577+
bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
1578+
if (!evp_pkey || !EVP_PKEY_set1_EC_KEY(evp_pkey.get(), key.get())) {
1579+
return false;
1580+
}
1581+
std::vector<uint8_t> sig_der;
1582+
size_t len;
1583+
if (!EVP_DigestSignInit(ctx.get(), &pctx, hash, nullptr, evp_pkey.get()) ||
1584+
!EVP_DigestSign(ctx.get(), nullptr, &len, msg.data(), msg.size())) {
1585+
return false;
1586+
}
1587+
sig_der.resize(len);
1588+
if (!EVP_DigestSign(ctx.get(), sig_der.data(), &len, msg.data(), msg.size())) {
1589+
return false;
1590+
}
1591+
bssl::UniquePtr<ECDSA_SIG> sig(ECDSA_SIG_from_bytes(sig_der.data(), len));
15801592
if (!sig) {
15811593
return false;
15821594
}
@@ -1599,27 +1611,35 @@ static bool ECDSASigVer(const Span<const uint8_t> args[], ReplyCallback write_re
15991611
ECDSA_SIG sig;
16001612
sig.r = r.get();
16011613
sig.s = s.get();
1602-
1603-
uint8_t digest[EVP_MAX_MD_SIZE];
1604-
unsigned digest_len;
1605-
if (!key || !hash ||
1606-
!EVP_Digest(msg.data(), msg.size(), digest, &digest_len, hash,
1607-
/*impl=*/nullptr)) {
1614+
uint8_t *der;
1615+
size_t der_len;
1616+
if (!key || !hash || !ECDSA_SIG_to_bytes(&der, &der_len, &sig)) {
16081617
return false;
16091618
}
1610-
1619+
// Let |delete_der| manage the release of |der|.
1620+
bssl::UniquePtr<uint8_t> delete_der(der);
16111621
bssl::UniquePtr<EC_POINT> point(EC_POINT_new(EC_KEY_get0_group(key.get())));
1612-
uint8_t reply[1];
16131622
if (!EC_POINT_set_affine_coordinates_GFp(EC_KEY_get0_group(key.get()),
16141623
point.get(), x.get(), y.get(),
16151624
/*ctx=*/nullptr) ||
16161625
!EC_KEY_set_public_key(key.get(), point.get()) ||
1617-
!EC_KEY_check_fips(key.get()) ||
1618-
!ECDSA_do_verify(digest, digest_len, &sig, key.get())) {
1626+
!EC_KEY_check_fips(key.get())) {
1627+
return false;
1628+
}
1629+
bssl::ScopedEVP_MD_CTX ctx;
1630+
EVP_PKEY_CTX *pctx;
1631+
bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
1632+
if (!evp_pkey || !EVP_PKEY_set1_EC_KEY(evp_pkey.get(), key.get())) {
1633+
return false;
1634+
}
1635+
uint8_t reply[1];
1636+
if (!EVP_DigestVerifyInit(ctx.get(), &pctx, hash, nullptr, evp_pkey.get()) ||
1637+
!EVP_DigestVerify(ctx.get(), der, der_len, msg.data(), msg.size())) {
16191638
reply[0] = 0;
16201639
} else {
16211640
reply[0] = 1;
16221641
}
1642+
ERR_clear_error();
16231643

16241644
return write_reply({Span<const uint8_t>(reply)});
16251645
}
@@ -1657,26 +1677,34 @@ static bool CMAC_AESVerify(const Span<const uint8_t> args[], ReplyCallback write
16571677
return write_reply({Span<const uint8_t>(&ok, sizeof(ok))});
16581678
}
16591679

1660-
static std::map<unsigned, bssl::UniquePtr<RSA>>& CachedRSAKeys() {
1661-
static std::map<unsigned, bssl::UniquePtr<RSA>> keys;
1680+
static std::map<unsigned, bssl::UniquePtr<EVP_PKEY>>& CachedRSAEVPKeys() {
1681+
static std::map<unsigned, bssl::UniquePtr<EVP_PKEY>> keys;
16621682
return keys;
16631683
}
16641684

1665-
static RSA* GetRSAKey(unsigned bits) {
1666-
auto it = CachedRSAKeys().find(bits);
1667-
if (it != CachedRSAKeys().end()) {
1685+
static EVP_PKEY* AddRSAKeyToCache(bssl::UniquePtr<RSA>& rsa, unsigned bits) {
1686+
bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
1687+
if (!evp_pkey || !EVP_PKEY_set1_RSA(evp_pkey.get(), rsa.get())) {
1688+
return nullptr;
1689+
}
1690+
1691+
EVP_PKEY *const ret = evp_pkey.get();
1692+
CachedRSAEVPKeys().emplace(static_cast<unsigned>(bits), std::move(evp_pkey));
1693+
return ret;
1694+
}
1695+
1696+
static EVP_PKEY* GetRSAKey(unsigned bits) {
1697+
auto it = CachedRSAEVPKeys().find(bits);
1698+
if (it != CachedRSAEVPKeys().end()) {
16681699
return it->second.get();
16691700
}
16701701

1671-
bssl::UniquePtr<RSA> key(RSA_new());
1672-
if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
1702+
bssl::UniquePtr<RSA> rsa(RSA_new());
1703+
if (!RSA_generate_key_fips(rsa.get(), bits, nullptr)) {
16731704
abort();
16741705
}
16751706

1676-
RSA *const ret = key.get();
1677-
CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
1678-
1679-
return ret;
1707+
return AddRSAKeyToCache(rsa, bits);
16801708
}
16811709

16821710
static bool RSAKeyGen(const Span<const uint8_t> args[], ReplyCallback write_reply) {
@@ -1686,22 +1714,24 @@ static bool RSAKeyGen(const Span<const uint8_t> args[], ReplyCallback write_repl
16861714
}
16871715
memcpy(&bits, args[0].data(), sizeof(bits));
16881716

1689-
bssl::UniquePtr<RSA> key(RSA_new());
1690-
if (!RSA_generate_key_fips(key.get(), bits, nullptr)) {
1717+
bssl::UniquePtr<RSA> rsa(RSA_new());
1718+
if (!RSA_generate_key_fips(rsa.get(), bits, nullptr)) {
16911719
LOG_ERROR("RSA_generate_key_fips failed for modulus length %u.\n", bits);
16921720
return false;
16931721
}
16941722

16951723
const BIGNUM *n, *e, *d, *p, *q;
1696-
RSA_get0_key(key.get(), &n, &e, &d);
1697-
RSA_get0_factors(key.get(), &p, &q);
1724+
RSA_get0_key(rsa.get(), &n, &e, &d);
1725+
RSA_get0_factors(rsa.get(), &p, &q);
16981726

16991727
if (!write_reply({BIGNUMBytes(e), BIGNUMBytes(p), BIGNUMBytes(q),
17001728
BIGNUMBytes(n), BIGNUMBytes(d)})) {
17011729
return false;
17021730
}
17031731

1704-
CachedRSAKeys().emplace(static_cast<unsigned>(bits), std::move(key));
1732+
if (AddRSAKeyToCache(rsa, bits) == nullptr) {
1733+
return false;
1734+
}
17051735
return true;
17061736
}
17071737

@@ -1713,35 +1743,32 @@ static bool RSASigGen(const Span<const uint8_t> args[], ReplyCallback write_repl
17131743
}
17141744
memcpy(&bits, args[0].data(), sizeof(bits));
17151745
const Span<const uint8_t> msg = args[1];
1716-
1717-
RSA *const key = GetRSAKey(bits);
1718-
const EVP_MD *const md = MDFunc();
1719-
uint8_t digest_buf[EVP_MAX_MD_SIZE];
1720-
unsigned digest_len;
1721-
if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
1746+
EVP_PKEY *const evp_pkey = GetRSAKey(bits);
1747+
if (evp_pkey == nullptr) {
17221748
return false;
17231749
}
1724-
1725-
std::vector<uint8_t> sig(RSA_size(key));
1750+
RSA *const rsa = EVP_PKEY_get0_RSA(evp_pkey);
1751+
if (rsa == nullptr) {
1752+
return false;
1753+
}
1754+
const EVP_MD *const md = MDFunc();
1755+
std::vector<uint8_t> sig;
17261756
size_t sig_len;
1727-
if (UsePSS) {
1728-
if (!RSA_sign_pss_mgf1(key, &sig_len, sig.data(), sig.size(), digest_buf,
1729-
digest_len, md, md, -1)) {
1730-
return false;
1731-
}
1732-
} else {
1733-
unsigned sig_len_u;
1734-
if (!RSA_sign(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
1735-
&sig_len_u, key)) {
1736-
return false;
1737-
}
1738-
sig_len = sig_len_u;
1757+
bssl::ScopedEVP_MD_CTX ctx;
1758+
EVP_PKEY_CTX *pctx;
1759+
int padding = UsePSS ? RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
1760+
if (!EVP_DigestSignInit(ctx.get(), &pctx, md, nullptr, evp_pkey) ||
1761+
!EVP_PKEY_CTX_set_rsa_padding(pctx, padding) ||
1762+
!EVP_DigestSign(ctx.get(), nullptr, &sig_len, msg.data(), msg.size())) {
1763+
return false;
17391764
}
1740-
17411765
sig.resize(sig_len);
1766+
if (!EVP_DigestSign(ctx.get(), sig.data(), &sig_len, msg.data(), msg.size())) {
1767+
return false;
1768+
}
17421769

17431770
return write_reply(
1744-
{BIGNUMBytes(RSA_get0_n(key)), BIGNUMBytes(RSA_get0_e(key)), sig});
1771+
{BIGNUMBytes(RSA_get0_n(rsa)), BIGNUMBytes(RSA_get0_e(rsa)), sig});
17451772
}
17461773

17471774
template <const EVP_MD *(MDFunc)(), bool UsePSS>
@@ -1761,19 +1788,20 @@ static bool RSASigVer(const Span<const uint8_t> args[], ReplyCallback write_repl
17611788
}
17621789

17631790
const EVP_MD *const md = MDFunc();
1764-
uint8_t digest_buf[EVP_MAX_MD_SIZE];
1765-
unsigned digest_len;
1766-
if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) {
1791+
bssl::ScopedEVP_MD_CTX ctx;
1792+
EVP_PKEY_CTX *pctx;
1793+
bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
1794+
if (!evp_pkey || !EVP_PKEY_set1_RSA(evp_pkey.get(), key.get())) {
17671795
return false;
17681796
}
1769-
17701797
uint8_t ok;
1771-
if (UsePSS) {
1772-
ok = RSA_verify_pss_mgf1(key.get(), digest_buf, digest_len, md, md, -1,
1773-
sig.data(), sig.size());
1798+
int padding = UsePSS ? RSA_PKCS1_PSS_PADDING : RSA_PKCS1_PADDING;
1799+
if (!EVP_DigestVerifyInit(ctx.get(), &pctx, md, nullptr, evp_pkey.get()) ||
1800+
!EVP_PKEY_CTX_set_rsa_padding(pctx, padding) ||
1801+
!EVP_DigestVerify(ctx.get(), sig.data(), sig.size(), msg.data(), msg.size())) {
1802+
ok = 0;
17741803
} else {
1775-
ok = RSA_verify(EVP_MD_type(md), digest_buf, digest_len, sig.data(),
1776-
sig.size(), key.get());
1804+
ok = 1;
17771805
}
17781806
ERR_clear_error();
17791807

0 commit comments

Comments
 (0)