Skip to content

Commit

Permalink
ACVP ECDSA SHA3 Digest Testing (#1819)
Browse files Browse the repository at this point in the history
By submitting this pull request, I confirm that my contribution is made
under the terms of the Apache 2.0 license and the ISC license.
  • Loading branch information
skmcgrail committed Sep 10, 2024
1 parent d13df48 commit 51d9a8d
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 77 deletions.
108 changes: 33 additions & 75 deletions util/fipstools/acvp/acvptool/subprocess/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ package subprocess

import (
"bytes"
"encoding/hex"
"encoding/json"
"fmt"
)
Expand All @@ -36,30 +35,30 @@ type ecdsaTestGroup struct {
HashAlgo string `json:"hashAlg,omitEmpty"`
ComponentTest bool `json:"componentTest"`
Tests []struct {
ID uint64 `json:"tcId"`
QxHex string `json:"qx,omitempty"`
QyHex string `json:"qy,omitempty"`
RHex string `json:"r,omitempty"`
SHex string `json:"s,omitempty"`
MsgHex string `json:"message,omitempty"`
ID uint64 `json:"tcId"`
Qx hexEncodedByteString `json:"qx,omitempty"`
Qy hexEncodedByteString `json:"qy,omitempty"`
R hexEncodedByteString `json:"r,omitempty"`
S hexEncodedByteString `json:"s,omitempty"`
Msg hexEncodedByteString `json:"message,omitempty"`
} `json:"tests"`
}

type ecdsaTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []ecdsaTestResponse `json:"tests"`
QxHex string `json:"qx,omitempty"`
QyHex string `json:"qy,omitempty"`
ID uint64 `json:"tgId"`
Tests []ecdsaTestResponse `json:"tests"`
Qx hexEncodedByteString `json:"qx,omitempty"`
Qy hexEncodedByteString `json:"qy,omitempty"`
}

type ecdsaTestResponse struct {
ID uint64 `json:"tcId"`
DHex string `json:"d,omitempty"`
QxHex string `json:"qx,omitempty"`
QyHex string `json:"qy,omitempty"`
RHex string `json:"r,omitempty"`
SHex string `json:"s,omitempty"`
Passed *bool `json:"testPassed,omitempty"` // using pointer so value is not omitted when it is false
ID uint64 `json:"tcId"`
D hexEncodedByteString `json:"d,omitempty"`
Qx hexEncodedByteString `json:"qx,omitempty"`
Qy hexEncodedByteString `json:"qy,omitempty"`
R hexEncodedByteString `json:"r,omitempty"`
S hexEncodedByteString `json:"s,omitempty"`
Passed *bool `json:"testPassed,omitempty"` // using pointer so value is not omitted when it is false
}

// ecdsa implements an ACVP algorithm by making requests to the
Expand All @@ -83,22 +82,17 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
// https://pages.nist.gov/ACVP/draft-fussell-acvp-ecdsa.html#name-test-vectors
// for details about the tests.
for _, group := range parsed.Groups {
group := group

if _, ok := e.curves[group.Curve]; !ok {
return nil, fmt.Errorf("curve %q in test group %d not supported", group.Curve, group.ID)
}

response := ecdsaTestGroupResponse{
ID: group.ID,
}

var sigGenPrivateKey []byte
var qxHex []byte
var qyHex []byte

for _, test := range group.Tests {
test := test

var testResp ecdsaTestResponse

switch parsed.Mode {
Expand All @@ -110,20 +104,12 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
if err != nil {
return nil, fmt.Errorf("key generation failed for test case %d/%d: %s", group.ID, test.ID, err)
}
testResp.DHex = hex.EncodeToString(result[0])
testResp.QxHex = hex.EncodeToString(result[1])
testResp.QyHex = hex.EncodeToString(result[2])
testResp.D = result[0]
testResp.Qx = result[1]
testResp.Qy = result[2]

case "keyVer":
qx, err := hex.DecodeString(test.QxHex)
if err != nil {
return nil, fmt.Errorf("failed to decode qx in test case %d/%d: %s", group.ID, test.ID, err)
}
qy, err := hex.DecodeString(test.QyHex)
if err != nil {
return nil, fmt.Errorf("failed to decode qy in test case %d/%d: %s", group.ID, test.ID, err)
}
result, err := m.Transact(e.algo+"/"+"keyVer", 1, []byte(group.Curve), qx, qy)
result, err := m.Transact(e.algo+"/"+"keyVer", 1, []byte(group.Curve), test.Qx, test.Qy)
if err != nil {
return nil, fmt.Errorf("key verification failed for test case %d/%d: %s", group.ID, test.ID, err)
}
Expand Down Expand Up @@ -154,39 +140,31 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
}

sigGenPrivateKey = result[0]
qxHex = result[1]
qyHex = result[2]
response.QxHex = hex.EncodeToString(qxHex)
response.QyHex = hex.EncodeToString(qyHex)
response.Qx = result[1]
response.Qy = result[2]
}

msg, err := hex.DecodeString(test.MsgHex)
if err != nil {
return nil, fmt.Errorf("failed to decode message hex in test case %d/%d: %s", group.ID, test.ID, err)
}
op := e.algo + "/" + "sigGen"
if group.ComponentTest {
if len(msg) != h.size {
return nil, fmt.Errorf("test case %d/%d contains message %q of length %d, but expected length %d", group.ID, test.ID, test.MsgHex, len(msg), h.size)
if len(test.Msg) != h.size {
return nil, fmt.Errorf("test case %d/%d contains message %q of length %d, but expected length %d", group.ID, test.ID, test.Msg, len(test.Msg), h.size)
}
op += "/componentTest"
}
result, err := m.Transact(op, 2, []byte(group.Curve), sigGenPrivateKey, []byte(group.HashAlgo), msg)
result, err := m.Transact(op, 2, []byte(group.Curve), sigGenPrivateKey, []byte(group.HashAlgo), test.Msg)
if err != nil {
return nil, fmt.Errorf("signature generation failed for test case %d/%d: %s", group.ID, test.ID, err)
}
rHex := result[0]
sHex := result[1]
testResp.RHex = hex.EncodeToString(rHex)
testResp.SHex = hex.EncodeToString(sHex)
testResp.R = result[0]
testResp.S = result[1]
// Ask the subprocess to verify the generated signature for this test case.
ver_result, ver_err := m.Transact(e.algo+"/"+"sigVer", 1, []byte(group.Curve), []byte(group.HashAlgo), msg, qxHex, qyHex, rHex, sHex)
ver_result, ver_err := m.Transact(e.algo+"/"+"sigVer", 1, []byte(group.Curve), []byte(group.HashAlgo), test.Msg, response.Qx, response.Qy, testResp.R, testResp.S)
if ver_err != nil {
return nil, fmt.Errorf("After signature generation, signature verification failed for test case %d/%d: %s", group.ID, test.ID, ver_err)
return nil, fmt.Errorf("after signature generation, signature verification failed for test case %d/%d: %s", group.ID, test.ID, ver_err)
}
// ver_result[0] should be a single byte. The value should be one in this case.
if !bytes.Equal(ver_result[0], []byte{01}) {
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)
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)
}

case "sigVer":
Expand All @@ -196,27 +174,7 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
return nil, fmt.Errorf("unsupported hash algorithm %q in test group %d", group.HashAlgo, group.ID)
}

msg, err := hex.DecodeString(test.MsgHex)
if err != nil {
return nil, fmt.Errorf("failed to decode message hex in test case %d/%d: %s", group.ID, test.ID, err)
}
qx, err := hex.DecodeString(test.QxHex)
if err != nil {
return nil, fmt.Errorf("failed to decode qx in test case %d/%d: %s", group.ID, test.ID, err)
}
qy, err := hex.DecodeString(test.QyHex)
if err != nil {
return nil, fmt.Errorf("failed to decode qy in test case %d/%d: %s", group.ID, test.ID, err)
}
r, err := hex.DecodeString(test.RHex)
if err != nil {
return nil, fmt.Errorf("failed to decode R in test case %d/%d: %s", group.ID, test.ID, err)
}
s, err := hex.DecodeString(test.SHex)
if err != nil {
return nil, fmt.Errorf("failed to decode S in test case %d/%d: %s", group.ID, test.ID, err)
}
result, err := m.Transact(e.algo+"/"+"sigVer", 1, []byte(group.Curve), []byte(group.HashAlgo), msg, qx, qy, r, s)
result, err := m.Transact(e.algo+"/"+"sigVer", 1, []byte(group.Curve), []byte(group.HashAlgo), test.Msg, test.Qx, test.Qy, test.R, test.S)
if err != nil {
return nil, fmt.Errorf("signature verification failed for test case %d/%d: %s", group.ID, test.ID, err)
}
Expand Down
Binary file modified util/fipstools/acvp/acvptool/test/expected/ECDSA.bz2
Binary file not shown.
1 change: 1 addition & 0 deletions util/fipstools/acvp/acvptool/test/tests.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
{"Wrapper": "modulewrapper", "In": "vectors/CMAC-AES.bz2", "Out": "expected/CMAC-AES.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ctrDRBG.bz2", "Out": "expected/ctrDRBG.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA.bz2", "Out": "expected/ECDSA.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA-KeyGen.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/ECDSA-SigGen.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA-1.bz2", "Out": "expected/HMAC-SHA-1.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-224.bz2", "Out": "expected/HMAC-SHA2-224.bz2"},
Expand Down
Binary file not shown.
Binary file modified util/fipstools/acvp/acvptool/test/vectors/ECDSA-SigGen.bz2
Binary file not shown.
Binary file modified util/fipstools/acvp/acvptool/test/vectors/ECDSA.bz2
Binary file not shown.
20 changes: 18 additions & 2 deletions util/fipstools/acvp/modulewrapper/modulewrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,11 @@ static bool GetConfig(const Span<const uint8_t> args[],
"SHA2-384",
"SHA2-512",
"SHA2-512/224",
"SHA2-512/256"
"SHA2-512/256",
"SHA3-224",
"SHA3-256",
"SHA3-384",
"SHA3-512"
]
}]
},
Expand All @@ -613,7 +617,11 @@ static bool GetConfig(const Span<const uint8_t> args[],
"SHA2-384",
"SHA2-512",
"SHA2-512/224",
"SHA2-512/256"
"SHA2-512/256",
"SHA3-224",
"SHA3-256",
"SHA3-384",
"SHA3-512"
]
}]
},)"
Expand Down Expand Up @@ -2287,6 +2295,14 @@ static const EVP_MD *HashFromName(Span<const uint8_t> name) {
return EVP_sha512_224();
} else if (StringEq(name, "SHA2-512/256")) {
return EVP_sha512_256();
} else if (StringEq(name, "SHA3-224")) {
return EVP_sha3_224();
} else if (StringEq(name, "SHA3-256")) {
return EVP_sha3_256();
} else if (StringEq(name, "SHA3-384")) {
return EVP_sha3_384();
} else if (StringEq(name, "SHA3-512")) {
return EVP_sha3_512();
} else if (StringEq(name, "SHAKE-128")) {
return EVP_shake128();
} else if (StringEq(name, "SHAKE-256")) {
Expand Down

0 comments on commit 51d9a8d

Please sign in to comment.