Skip to content

Commit c59b86c

Browse files
nhatnghihosgmenda
andauthored
Various Small Additions to ACVP Tool (#3024)
### Issues: Addresses P355857148 ### Description of changes: This PR adds ACVP support for: - `RSA signaturePrimitive` - `RSA decryptionPrimitive` - `KAS-ECC-SSC onePassDh` - `ECDSA sigGen componentTest` ### Call-outs: Due to the random nature of ECDH and ECDSA sigGen, no expected vector was added for these 2. To review, please run the script locally to verify the result. ### Testing: Run `check_expected.go` on the new test vectors. 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. --------- Co-authored-by: sanketh <sgmenda@amazon.com>
1 parent 343be17 commit c59b86c

15 files changed

Lines changed: 496 additions & 63 deletions

File tree

crypto/evp_extra/evp_test.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,22 @@ static void RunWycheproofDecryptTest(
10081008
// BoringSSL does not enforce policies on weak keys and leaves it to the
10091009
// caller.
10101010
bool is_valid = result.IsValid({"SmallModulus"});
1011+
1012+
// AWS-LC enforces FIPS 800-56B Rev. 2 §7.1.2.1 which requires 1 < c < (n-1).
1013+
// But Wycheproof mistakenly marks some vectors with c values outside this range as valid.
1014+
if (is_valid) {
1015+
const RSA *rsa = EVP_PKEY_get0_RSA(key.get());
1016+
const BIGNUM *n = RSA_get0_n(rsa);
1017+
bssl::UniquePtr<BIGNUM> c(BN_bin2bn(ct.data(), ct.size(), nullptr));
1018+
bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(n));
1019+
ASSERT_TRUE(c && n_minus_one);
1020+
ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
1021+
if (BN_is_zero(c.get()) || BN_is_one(c.get()) ||
1022+
BN_cmp(c.get(), n_minus_one.get()) >= 0) {
1023+
is_valid = false;
1024+
}
1025+
}
1026+
10111027
EXPECT_EQ(ret, is_valid ? 1 : 0);
10121028
if (is_valid) {
10131029
out.resize(len);

crypto/fipsmodule/rsa/rsa_impl.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -564,7 +564,14 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
564564

565565
// The input to the RSA private transform may be secret, but padding is
566566
// expected to construct a value within range, so we can leak this comparison.
567-
if (constant_time_declassify_int(BN_ucmp(f, rsa->n) >= 0)) {
567+
BIGNUM *n_minus_one = BN_CTX_get(ctx);
568+
if (n_minus_one == NULL || !BN_copy(n_minus_one, rsa->n) ||
569+
!BN_sub_word(n_minus_one, 1)) {
570+
goto err;
571+
}
572+
if (constant_time_declassify_int(BN_ucmp(f, n_minus_one) >= 0) ||
573+
constant_time_declassify_int(BN_is_zero(f)) ||
574+
constant_time_declassify_int(BN_is_one(f))) {
568575
// Usually the padding functions would catch this.
569576
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
570577
goto err;

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,11 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
158158
testResp.R = result[0]
159159
testResp.S = result[1]
160160
// Ask the subprocess to verify the generated signature for this test case.
161-
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)
161+
op = e.algo+"/"+"sigVer"
162+
if group.ComponentTest {
163+
op += "/componentTest"
164+
}
165+
ver_result, ver_err := m.Transact(op, 1, []byte(group.Curve), []byte(group.HashAlgo), test.Msg, response.Qx, response.Qy, testResp.R, testResp.S)
162166
if ver_err != nil {
163167
return nil, fmt.Errorf("after signature generation, signature verification failed for test case %d/%d: %s", group.ID, test.ID, ver_err)
164168
}

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

Lines changed: 48 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ package subprocess
1616

1717
import (
1818
"bytes"
19-
"encoding/hex"
2019
"encoding/json"
2120
"fmt"
2221
)
@@ -37,15 +36,15 @@ type kasTestGroup struct {
3736
type kasTest struct {
3837
ID uint64 `json:"tcId"`
3938

40-
EphemeralXHex string `json:"ephemeralPublicServerX"`
41-
EphemeralYHex string `json:"ephemeralPublicServerY"`
42-
EphemeralPrivateKeyHex string `json:"ephemeralPrivateIut"`
39+
EphemeralXHex hexEncodedByteString `json:"ephemeralPublicServerX"`
40+
EphemeralYHex hexEncodedByteString `json:"ephemeralPublicServerY"`
41+
EphemeralPrivateKeyHex hexEncodedByteString `json:"ephemeralPrivateIut"`
4342

44-
StaticXHex string `json:"staticPublicServerX"`
45-
StaticYHex string `json:"staticPublicServerY"`
46-
StaticPrivateKeyHex string `json:"staticPrivateIut"`
43+
StaticXHex hexEncodedByteString `json:"staticPublicServerX"`
44+
StaticYHex hexEncodedByteString `json:"staticPublicServerY"`
45+
StaticPrivateKeyHex hexEncodedByteString `json:"staticPrivateIut"`
4746

48-
ResultHex string `json:"z"`
47+
Result hexEncodedByteString `json:"z"`
4948
}
5049

5150
type kasTestGroupResponse struct {
@@ -56,14 +55,14 @@ type kasTestGroupResponse struct {
5655
type kasTestResponse struct {
5756
ID uint64 `json:"tcId"`
5857

59-
EphemeralXHex string `json:"ephemeralPublicIutX,omitempty"`
60-
EphemeralYHex string `json:"ephemeralPublicIutY,omitempty"`
58+
EphemeralXHex hexEncodedByteString `json:"ephemeralPublicIutX,omitempty"`
59+
EphemeralYHex hexEncodedByteString `json:"ephemeralPublicIutY,omitempty"`
6160

62-
StaticXHex string `json:"staticPublicIutX,omitempty"`
63-
StaticYHex string `json:"staticPublicIutY,omitempty"`
61+
StaticXHex hexEncodedByteString `json:"staticPublicIutX,omitempty"`
62+
StaticYHex hexEncodedByteString `json:"staticPublicIutY,omitempty"`
6463

65-
ResultHex string `json:"z,omitempty"`
66-
Passed *bool `json:"testPassed,omitempty"`
64+
Result hexEncodedByteString `json:"z,omitempty"`
65+
Passed *bool `json:"testPassed,omitempty"`
6766
}
6867

6968
type kas struct{}
@@ -94,76 +93,72 @@ func (k *kas) Process(vectorSet []byte, m Transactable) (interface{}, error) {
9493

9594
switch group.Curve {
9695
case "P-224", "P-256", "P-384", "P-521":
97-
break
9896
default:
9997
return nil, fmt.Errorf("unknown curve %q", group.Curve)
10098
}
10199

102100
switch group.Role {
103101
case "initiator", "responder":
104-
break
105102
default:
106103
return nil, fmt.Errorf("unknown role %q", group.Role)
107104
}
108105

109-
var useStaticNamedFields bool
106+
var useEphemeralPeerKeys bool
107+
var useEphemeralPrivateKey bool
110108
switch group.Scheme {
111109
case "ephemeralUnified":
112-
break
110+
useEphemeralPeerKeys = true
111+
useEphemeralPrivateKey = true
113112
case "staticUnified":
114-
useStaticNamedFields = true
115-
break
113+
useEphemeralPeerKeys = false
114+
useEphemeralPrivateKey = false
115+
case "onePassDh":
116+
if group.Role == "initiator" {
117+
useEphemeralPeerKeys = false
118+
useEphemeralPrivateKey = true
119+
} else {
120+
useEphemeralPeerKeys = true
121+
useEphemeralPrivateKey = false
122+
}
116123
default:
117124
return nil, fmt.Errorf("unknown scheme %q", group.Scheme)
118125
}
119126

127+
generateEphemeralKeys := useEphemeralPrivateKey && group.Role != "staticUnified"
128+
120129
method := "ECDH/" + group.Curve
121130

122131
for _, test := range group.Tests {
123132
test := test
124133

125-
var xHex, yHex, privateKeyHex string
126-
if useStaticNamedFields {
127-
xHex, yHex, privateKeyHex = test.StaticXHex, test.StaticYHex, test.StaticPrivateKeyHex
134+
var peerX, peerY, privateKey hexEncodedByteString
135+
if useEphemeralPeerKeys {
136+
peerX, peerY = test.EphemeralXHex, test.EphemeralYHex
128137
} else {
129-
xHex, yHex, privateKeyHex = test.EphemeralXHex, test.EphemeralYHex, test.EphemeralPrivateKeyHex
138+
peerX, peerY = test.StaticXHex, test.StaticYHex
130139
}
131140

132-
if len(xHex) == 0 || len(yHex) == 0 {
133-
return nil, fmt.Errorf("%d/%d is missing peer's point", group.ID, test.ID)
134-
}
135-
136-
peerX, err := hex.DecodeString(xHex)
137-
if err != nil {
138-
return nil, err
141+
if useEphemeralPrivateKey {
142+
privateKey = test.EphemeralPrivateKeyHex
143+
} else {
144+
privateKey = test.StaticPrivateKeyHex
139145
}
140146

141-
peerY, err := hex.DecodeString(yHex)
142-
if err != nil {
143-
return nil, err
147+
if len(peerX) == 0 || len(peerY) == 0 {
148+
return nil, fmt.Errorf("%d/%d is missing peer's point", group.ID, test.ID)
144149
}
145150

146-
if (len(privateKeyHex) != 0) != privateKeyGiven {
151+
if (len(privateKey) != 0) != privateKeyGiven {
147152
return nil, fmt.Errorf("%d/%d incorrect private key presence", group.ID, test.ID)
148153
}
149154

150155
if privateKeyGiven {
151-
privateKey, err := hex.DecodeString(privateKeyHex)
152-
if err != nil {
153-
return nil, err
154-
}
155-
156-
expectedOutput, err := hex.DecodeString(test.ResultHex)
157-
if err != nil {
158-
return nil, err
159-
}
160-
161156
result, err := m.Transact(method, 3, peerX, peerY, privateKey)
162157
if err != nil {
163158
return nil, err
164159
}
165160

166-
ok := bytes.Equal(result[2], expectedOutput)
161+
ok := bytes.Equal(result[2], test.Result)
167162
response.Tests = append(response.Tests, kasTestResponse{
168163
ID: test.ID,
169164
Passed: &ok,
@@ -175,16 +170,16 @@ func (k *kas) Process(vectorSet []byte, m Transactable) (interface{}, error) {
175170
}
176171

177172
testResponse := kasTestResponse{
178-
ID: test.ID,
179-
ResultHex: hex.EncodeToString(result[2]),
173+
ID: test.ID,
174+
Result: result[2],
180175
}
181176

182-
if useStaticNamedFields {
183-
testResponse.StaticXHex = hex.EncodeToString(result[0])
184-
testResponse.StaticYHex = hex.EncodeToString(result[1])
177+
if generateEphemeralKeys {
178+
testResponse.EphemeralXHex = result[0]
179+
testResponse.EphemeralYHex = result[1]
185180
} else {
186-
testResponse.EphemeralXHex = hex.EncodeToString(result[0])
187-
testResponse.EphemeralYHex = hex.EncodeToString(result[1])
181+
testResponse.StaticXHex = result[0]
182+
testResponse.StaticYHex = result[1]
188183
}
189184

190185
response.Tests = append(response.Tests, testResponse)

0 commit comments

Comments
 (0)