From 777e1ff3b1443788c5fdb982b3b822aac5448d9e Mon Sep 17 00:00:00 2001 From: Adam Langley Date: Thu, 22 Oct 2020 16:57:56 -0700 Subject: [PATCH] acvp: RSA signature verification tests. Change-Id: I8697230d4feb3bc5308905aa8981087b0f080555 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/43626 Commit-Queue: Adam Langley Reviewed-by: David Benjamin --- .../fipstools/acvp/acvptool/subprocess/rsa.go | 89 +++++++++ .../acvp/modulewrapper/modulewrapper.cc | 182 ++++++++++++++++++ 2 files changed, 271 insertions(+) diff --git a/util/fipstools/acvp/acvptool/subprocess/rsa.go b/util/fipstools/acvp/acvptool/subprocess/rsa.go index 0825c04b4..d2de73d63 100644 --- a/util/fipstools/acvp/acvptool/subprocess/rsa.go +++ b/util/fipstools/acvp/acvptool/subprocess/rsa.go @@ -87,6 +87,36 @@ type rsaSigGenTestResponse struct { Sig string `json:"signature"` } +type rsaSigVerTestVectorSet struct { + Groups []rsaSigVerGroup `json:"testGroups"` +} + +type rsaSigVerGroup struct { + ID uint64 `json:"tgId"` + Type string `json:"testType"` + SigType string `json:"sigType"` + Hash string `json:"hashAlg"` + N string `json:"n"` + E string `json:"e"` + Tests []rsaSigVerTest `json:"tests"` +} + +type rsaSigVerTest struct { + ID uint64 `json:"tcId"` + MessageHex string `json:"message"` + SignatureHex string `json:"signature"` +} + +type rsaSigVerTestGroupResponse struct { + ID uint64 `json:"tgId"` + Tests []rsaSigVerTestResponse `json:"tests"` +} + +type rsaSigVerTestResponse struct { + ID uint64 `json:"tcId"` + Passed bool `json:"testPassed"` +} + func processKeyGen(vectorSet []byte, m Transactable) (interface{}, error) { var parsed rsaKeyGenTestVectorSet if err := json.Unmarshal(vectorSet, &parsed); err != nil { @@ -179,6 +209,63 @@ func processSigGen(vectorSet []byte, m Transactable) (interface{}, error) { return ret, nil } +func processSigVer(vectorSet []byte, m Transactable) (interface{}, error) { + var parsed rsaSigVerTestVectorSet + if err := json.Unmarshal(vectorSet, &parsed); err != nil { + return nil, err + } + + var ret []rsaSigVerTestGroupResponse + + for _, group := range parsed.Groups { + // GDT means "Generated data test", which makes no sense in this context. + const expectedType = "GDT" + if group.Type != expectedType { + return nil, fmt.Errorf("RSA SigVer test group has type %q, but only 'generation' tests (%q) are supported", group.Type, expectedType) + } + + n, err := hex.DecodeString(group.N) + if err != nil { + return nil, fmt.Errorf("test group %d contains invalid hex: %s", group.ID, err) + } + e, err := hex.DecodeString(group.E) + if err != nil { + return nil, fmt.Errorf("test group %d contains invalid hex: %s", group.ID, err) + } + + response := rsaSigVerTestGroupResponse{ + ID: group.ID, + } + + operation := "RSA/sigVer/" + group.Hash + "/" + group.SigType + + for _, test := range group.Tests { + msg, err := hex.DecodeString(test.MessageHex) + if err != nil { + return nil, fmt.Errorf("test case %d/%d contains invalid hex: %s", group.ID, test.ID, err) + } + sig, err := hex.DecodeString(test.SignatureHex) + if err != nil { + return nil, fmt.Errorf("test case %d/%d contains invalid hex: %s", group.ID, test.ID, err) + } + + results, err := m.Transact(operation, 1, n, e, msg, sig) + if err != nil { + return nil, err + } + + response.Tests = append(response.Tests, rsaSigVerTestResponse{ + ID: test.ID, + Passed: len(results[0]) == 1 && results[0][0] == 1, + }) + } + + ret = append(ret, response) + } + + return ret, nil +} + type rsa struct{} func (*rsa) Process(vectorSet []byte, m Transactable) (interface{}, error) { @@ -192,6 +279,8 @@ func (*rsa) Process(vectorSet []byte, m Transactable) (interface{}, error) { return processKeyGen(vectorSet, m) case "sigGen": return processSigGen(vectorSet, m) + case "sigVer": + return processSigVer(vectorSet, m) default: return nil, fmt.Errorf("Unknown RSA mode %q", parsed.Mode) } diff --git a/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/util/fipstools/acvp/modulewrapper/modulewrapper.cc index aad2a3cd6..804349709 100644 --- a/util/fipstools/acvp/modulewrapper/modulewrapper.cc +++ b/util/fipstools/acvp/modulewrapper/modulewrapper.cc @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -542,6 +543,141 @@ static bool GetConfig(const Span args[]) { }] }] }, + { + "algorithm": "RSA", + "mode": "sigVer", + "revision": "FIPS186-4", + "pubExpMode": "fixed", + "fixedPubExp": "010001", + "capabilities": [{ + "sigType": "pkcs1v1.5", + "properties": [{ + "modulo": 1024, + "hashPair": [{ + "hashAlg": "SHA2-224" + }, { + "hashAlg": "SHA2-256" + }, { + "hashAlg": "SHA2-384" + }, { + "hashAlg": "SHA2-512" + }, { + "hashAlg": "SHA-1" + }] + }] + },{ + "sigType": "pkcs1v1.5", + "properties": [{ + "modulo": 2048, + "hashPair": [{ + "hashAlg": "SHA2-224" + }, { + "hashAlg": "SHA2-256" + }, { + "hashAlg": "SHA2-384" + }, { + "hashAlg": "SHA2-512" + }, { + "hashAlg": "SHA-1" + }] + }] + },{ + "sigType": "pkcs1v1.5", + "properties": [{ + "modulo": 3072, + "hashPair": [{ + "hashAlg": "SHA2-224" + }, { + "hashAlg": "SHA2-256" + }, { + "hashAlg": "SHA2-384" + }, { + "hashAlg": "SHA2-512" + }, { + "hashAlg": "SHA-1" + }] + }] + },{ + "sigType": "pkcs1v1.5", + "properties": [{ + "modulo": 4096, + "hashPair": [{ + "hashAlg": "SHA2-224" + }, { + "hashAlg": "SHA2-256" + }, { + "hashAlg": "SHA2-384" + }, { + "hashAlg": "SHA2-512" + }, { + "hashAlg": "SHA-1" + }] + }] + },{ + "sigType": "pss", + "properties": [{ + "modulo": 2048, + "hashPair": [{ + "hashAlg": "SHA2-224", + "saltLen": 28 + }, { + "hashAlg": "SHA2-256", + "saltLen": 32 + }, { + "hashAlg": "SHA2-384", + "saltLen": 48 + }, { + "hashAlg": "SHA2-512", + "saltLen": 64 + }, { + "hashAlg": "SHA-1", + "saltLen": 20 + }] + }] + },{ + "sigType": "pss", + "properties": [{ + "modulo": 3072, + "hashPair": [{ + "hashAlg": "SHA2-224", + "saltLen": 28 + }, { + "hashAlg": "SHA2-256", + "saltLen": 32 + }, { + "hashAlg": "SHA2-384", + "saltLen": 48 + }, { + "hashAlg": "SHA2-512", + "saltLen": 64 + }, { + "hashAlg": "SHA-1", + "saltLen": 20 + }] + }] + },{ + "sigType": "pss", + "properties": [{ + "modulo": 4096, + "hashPair": [{ + "hashAlg": "SHA2-224", + "saltLen": 28 + }, { + "hashAlg": "SHA2-256", + "saltLen": 32 + }, { + "hashAlg": "SHA2-384", + "saltLen": 48 + }, { + "hashAlg": "SHA2-512", + "saltLen": 64 + }, { + "hashAlg": "SHA-1", + "saltLen": 20 + }] + }] + }] + }, { "algorithm": "CMAC-AES", "revision": "1.0", @@ -1238,6 +1374,42 @@ static bool RSASigGen(const Span args[]) { BIGNUMBytes(RSA_get0_e(key)), sig); } +template +static bool RSASigVer(const Span args[]) { + const Span n_bytes = args[0]; + const Span e_bytes = args[1]; + const Span msg = args[2]; + const Span sig = args[3]; + + BIGNUM *n = BN_new(); + BIGNUM *e = BN_new(); + bssl::UniquePtr key(RSA_new()); + if (!BN_bin2bn(n_bytes.data(), n_bytes.size(), n) || + !BN_bin2bn(e_bytes.data(), e_bytes.size(), e) || + !RSA_set0_key(key.get(), n, e, /*d=*/nullptr)) { + return false; + } + + const EVP_MD *const md = MDFunc(); + uint8_t digest_buf[EVP_MAX_MD_SIZE]; + unsigned digest_len; + if (!EVP_Digest(msg.data(), msg.size(), digest_buf, &digest_len, md, NULL)) { + return false; + } + + uint8_t ok; + if (UsePSS) { + ok = RSA_verify_pss_mgf1(key.get(), digest_buf, digest_len, md, md, -1, + sig.data(), sig.size()); + } else { + ok = RSA_verify(EVP_MD_type(md), digest_buf, digest_len, sig.data(), + sig.size(), key.get()); + } + ERR_clear_error(); + + return WriteReply(STDOUT_FILENO, Span(&ok, 1)); +} + static constexpr struct { const char name[kMaxNameLength + 1]; uint8_t expected_args; @@ -1289,6 +1461,16 @@ static constexpr struct { {"RSA/sigGen/SHA2-384/pss", 2, RSASigGen}, {"RSA/sigGen/SHA2-512/pss", 2, RSASigGen}, {"RSA/sigGen/SHA-1/pss", 2, RSASigGen}, + {"RSA/sigVer/SHA2-224/pkcs1v1.5", 4, RSASigVer}, + {"RSA/sigVer/SHA2-256/pkcs1v1.5", 4, RSASigVer}, + {"RSA/sigVer/SHA2-384/pkcs1v1.5", 4, RSASigVer}, + {"RSA/sigVer/SHA2-512/pkcs1v1.5", 4, RSASigVer}, + {"RSA/sigVer/SHA-1/pkcs1v1.5", 4, RSASigVer}, + {"RSA/sigVer/SHA2-224/pss", 4, RSASigVer}, + {"RSA/sigVer/SHA2-256/pss", 4, RSASigVer}, + {"RSA/sigVer/SHA2-384/pss", 4, RSASigVer}, + {"RSA/sigVer/SHA2-512/pss", 4, RSASigVer}, + {"RSA/sigVer/SHA-1/pss", 4, RSASigVer}, }; int main() {