Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions ct/x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -781,8 +781,10 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
}

pub := &rsa.PublicKey{
E: p.E,
N: p.N,
// Defensively copy E so callers cannot mutate it through the
// parsed wire structure.
E: new(big.Int).Set(p.E),
N: new(big.Int).Set(p.N),
}
return pub, nil
case DSA:
Expand Down
8 changes: 4 additions & 4 deletions internal/testenv/testenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func Builder() string {
return os.Getenv("GO_BUILDER_NAME")
}

// HasGoBuild reports whether the current system can build programs with ``go build''
// HasGoBuild reports whether the current system can build programs with go build
// and then run them with os.StartProcess or exec.Command.
func HasGoBuild() bool {
if os.Getenv("GO_GCFLAGS") != "" {
Expand All @@ -50,7 +50,7 @@ func HasGoBuild() bool {
return true
}

// MustHaveGoBuild checks that the current system can build programs with ``go build''
// MustHaveGoBuild checks that the current system can build programs with go build
// and then run them with os.StartProcess or exec.Command.
// If not, MustHaveGoBuild calls t.Skip with an explanation.
func MustHaveGoBuild(t testing.TB) {
Expand All @@ -62,13 +62,13 @@ func MustHaveGoBuild(t testing.TB) {
}
}

// HasGoRun reports whether the current system can run programs with ``go run.''
// HasGoRun reports whether the current system can run programs with go run.
func HasGoRun() bool {
// For now, having go run and having go build are the same.
return HasGoBuild()
}

// MustHaveGoRun checks that the current system can run programs with ``go run.''
// MustHaveGoRun checks that the current system can run programs with go run.
// If not, MustHaveGoRun calls t.Skip with an explanation.
func MustHaveGoRun(t testing.TB) {
if !HasGoRun() {
Expand Down
29 changes: 29 additions & 0 deletions rsa/rsa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -895,3 +895,32 @@ var testEncryptOAEPData = []testEncryptOAEPStruct{
},
},
}

// TestPublicKeyDefensiveCopy verifies that mutating the caller's PublicKey
// after performing an operation does not affect subsequent operations on the
// same key via the precomputed FIPS state.
func TestPublicKeyDefensiveCopy(t *testing.T) {
priv, err := GenerateKey(rand.Reader, 2048)
if err != nil {
t.Fatal(err)
}
msg := []byte("hello")
ct, err := EncryptPKCS1v15(rand.Reader, &priv.PublicKey, msg)
if err != nil {
t.Fatal(err)
}
pt, err := DecryptPKCS1v15(rand.Reader, priv, ct)
if err != nil || !bytes.Equal(pt, msg) {
t.Fatalf("decrypt mismatch: %v / %x", err, pt)
}
// Mutate the caller's E in place. A correctly defensively-copied internal
// state must continue to function.
originalE := new(big.Int).Set(priv.PublicKey.E)
priv.PublicKey.E.SetInt64(7)
pt2, err := DecryptPKCS1v15(rand.Reader, priv, ct)
// Restore E so subsequent tests aren't affected.
priv.PublicKey.E.Set(originalE)
if err != nil || !bytes.Equal(pt2, msg) {
t.Fatalf("decrypt after caller-side E mutation failed (defensive copy missing?): %v / %x", err, pt2)
}
}
6 changes: 4 additions & 2 deletions x509/pkcs1.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,10 @@ func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) {
//}

return &rsa.PublicKey{
E: pub.E,
N: pub.N,
// Defensively copy E so callers cannot mutate it through the
// parsed wire structure.
E: new(big.Int).Set(pub.E),
N: new(big.Int).Set(pub.N),
}, nil
}

Expand Down
6 changes: 4 additions & 2 deletions x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -1346,8 +1346,10 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{
}

return &rsa.PublicKey{
E: p.E,
N: p.N,
// Defensively copy E so callers cannot mutate it through the
// parsed wire structure.
E: new(big.Int).Set(p.E),
N: new(big.Int).Set(p.N),
}, nil
case DSA:
var p *big.Int
Expand Down
Loading