Skip to content
16 changes: 16 additions & 0 deletions crypto/evp_extra/evp_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,22 @@ static void RunWycheproofDecryptTest(
// BoringSSL does not enforce policies on weak keys and leaves it to the
// caller.
bool is_valid = result.IsValid({"SmallModulus"});

// AWS-LC enforces FIPS 800-56B Rev. 2 §7.1.2.1 which requires 1 < c < (n-1).
// But Wycheproof mistakenly marks some vectors with c values outside this range as valid.
if (is_valid) {
const RSA *rsa = EVP_PKEY_get0_RSA(key.get());
const BIGNUM *n = RSA_get0_n(rsa);
bssl::UniquePtr<BIGNUM> c(BN_bin2bn(ct.data(), ct.size(), nullptr));
bssl::UniquePtr<BIGNUM> n_minus_one(BN_dup(n));
ASSERT_TRUE(c && n_minus_one);
ASSERT_TRUE(BN_sub_word(n_minus_one.get(), 1));
if (BN_is_zero(c.get()) || BN_is_one(c.get()) ||
BN_cmp(c.get(), n_minus_one.get()) >= 0) {
is_valid = false;
}
}

EXPECT_EQ(ret, is_valid ? 1 : 0);
if (is_valid) {
out.resize(len);
Expand Down
9 changes: 8 additions & 1 deletion crypto/fipsmodule/rsa/rsa_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,14 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,

// The input to the RSA private transform may be secret, but padding is
// expected to construct a value within range, so we can leak this comparison.
if (constant_time_declassify_int(BN_ucmp(f, rsa->n) >= 0)) {
BIGNUM *n_minus_one = BN_CTX_get(ctx);
if (n_minus_one == NULL || !BN_copy(n_minus_one, rsa->n) ||
!BN_sub_word(n_minus_one, 1)) {
goto err;
}
if (constant_time_declassify_int(BN_ucmp(f, n_minus_one) >= 0) ||
constant_time_declassify_int(BN_is_zero(f)) ||
constant_time_declassify_int(BN_is_one(f))) {
// Usually the padding functions would catch this.
OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
Expand Down
6 changes: 5 additions & 1 deletion util/fipstools/acvp/acvptool/subprocess/ecdsa.go
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ func (e *ecdsa) Process(vectorSet []byte, m Transactable) (interface{}, error) {
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), test.Msg, response.Qx, response.Qy, testResp.R, testResp.S)
op = e.algo+"/"+"sigVer"
if group.ComponentTest {
op += "/componentTest"
}
ver_result, ver_err := m.Transact(op, 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)
}
Expand Down
101 changes: 48 additions & 53 deletions util/fipstools/acvp/acvptool/subprocess/kas.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 @@ -37,15 +36,15 @@ type kasTestGroup struct {
type kasTest struct {
ID uint64 `json:"tcId"`

EphemeralXHex string `json:"ephemeralPublicServerX"`
EphemeralYHex string `json:"ephemeralPublicServerY"`
EphemeralPrivateKeyHex string `json:"ephemeralPrivateIut"`
EphemeralXHex hexEncodedByteString `json:"ephemeralPublicServerX"`
EphemeralYHex hexEncodedByteString `json:"ephemeralPublicServerY"`
EphemeralPrivateKeyHex hexEncodedByteString `json:"ephemeralPrivateIut"`

StaticXHex string `json:"staticPublicServerX"`
StaticYHex string `json:"staticPublicServerY"`
StaticPrivateKeyHex string `json:"staticPrivateIut"`
StaticXHex hexEncodedByteString `json:"staticPublicServerX"`
StaticYHex hexEncodedByteString `json:"staticPublicServerY"`
StaticPrivateKeyHex hexEncodedByteString `json:"staticPrivateIut"`

ResultHex string `json:"z"`
Result hexEncodedByteString `json:"z"`
}

type kasTestGroupResponse struct {
Expand All @@ -56,14 +55,14 @@ type kasTestGroupResponse struct {
type kasTestResponse struct {
ID uint64 `json:"tcId"`

EphemeralXHex string `json:"ephemeralPublicIutX,omitempty"`
EphemeralYHex string `json:"ephemeralPublicIutY,omitempty"`
EphemeralXHex hexEncodedByteString `json:"ephemeralPublicIutX,omitempty"`
EphemeralYHex hexEncodedByteString `json:"ephemeralPublicIutY,omitempty"`

StaticXHex string `json:"staticPublicIutX,omitempty"`
StaticYHex string `json:"staticPublicIutY,omitempty"`
StaticXHex hexEncodedByteString `json:"staticPublicIutX,omitempty"`
StaticYHex hexEncodedByteString `json:"staticPublicIutY,omitempty"`

ResultHex string `json:"z,omitempty"`
Passed *bool `json:"testPassed,omitempty"`
Result hexEncodedByteString `json:"z,omitempty"`
Passed *bool `json:"testPassed,omitempty"`
}

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

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

switch group.Role {
case "initiator", "responder":
break
default:
return nil, fmt.Errorf("unknown role %q", group.Role)
}

var useStaticNamedFields bool
var useEphemeralPeerKeys bool
var useEphemeralPrivateKey bool
switch group.Scheme {
case "ephemeralUnified":
break
useEphemeralPeerKeys = true
useEphemeralPrivateKey = true
case "staticUnified":
useStaticNamedFields = true
break
useEphemeralPeerKeys = false
useEphemeralPrivateKey = false
case "onePassDh":
if group.Role == "initiator" {
useEphemeralPeerKeys = false
useEphemeralPrivateKey = true
} else {
useEphemeralPeerKeys = true
useEphemeralPrivateKey = false
}
default:
return nil, fmt.Errorf("unknown scheme %q", group.Scheme)
}

generateEphemeralKeys := useEphemeralPrivateKey && group.Role != "staticUnified"

method := "ECDH/" + group.Curve

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

var xHex, yHex, privateKeyHex string
if useStaticNamedFields {
xHex, yHex, privateKeyHex = test.StaticXHex, test.StaticYHex, test.StaticPrivateKeyHex
var peerX, peerY, privateKey hexEncodedByteString
if useEphemeralPeerKeys {
peerX, peerY = test.EphemeralXHex, test.EphemeralYHex
} else {
xHex, yHex, privateKeyHex = test.EphemeralXHex, test.EphemeralYHex, test.EphemeralPrivateKeyHex
peerX, peerY = test.StaticXHex, test.StaticYHex
}

if len(xHex) == 0 || len(yHex) == 0 {
return nil, fmt.Errorf("%d/%d is missing peer's point", group.ID, test.ID)
}

peerX, err := hex.DecodeString(xHex)
if err != nil {
return nil, err
if useEphemeralPrivateKey {
privateKey = test.EphemeralPrivateKeyHex
} else {
privateKey = test.StaticPrivateKeyHex
}

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

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

if privateKeyGiven {
privateKey, err := hex.DecodeString(privateKeyHex)
if err != nil {
return nil, err
}

expectedOutput, err := hex.DecodeString(test.ResultHex)
if err != nil {
return nil, err
}

result, err := m.Transact(method, 3, peerX, peerY, privateKey)
if err != nil {
return nil, err
}

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

testResponse := kasTestResponse{
ID: test.ID,
ResultHex: hex.EncodeToString(result[2]),
ID: test.ID,
Result: result[2],
}

if useStaticNamedFields {
testResponse.StaticXHex = hex.EncodeToString(result[0])
testResponse.StaticYHex = hex.EncodeToString(result[1])
if generateEphemeralKeys {
testResponse.EphemeralXHex = result[0]
testResponse.EphemeralYHex = result[1]
} else {
testResponse.EphemeralXHex = hex.EncodeToString(result[0])
testResponse.EphemeralYHex = hex.EncodeToString(result[1])
testResponse.StaticXHex = result[0]
testResponse.StaticYHex = result[1]
}

response.Tests = append(response.Tests, testResponse)
Expand Down
Loading
Loading