import (
"crypto/internal/fips140"
"crypto/internal/fips140/check"
- "internal/godebug"
)
-var fips140GODEBUG = godebug.New("fips140")
-
// Enabled reports whether the cryptography libraries are operating in FIPS
// 140-3 mode.
//
//
// This can't be changed after the program has started.
func Enabled() bool {
- godebug := fips140GODEBUG.Value()
- currentlyEnabled := godebug == "on" || godebug == "only" || godebug == "debug"
- if currentlyEnabled != fips140.Enabled {
- panic("crypto/fips140: GODEBUG setting changed after program start")
- }
if fips140.Enabled && !check.Verified {
panic("crypto/fips140: FIPS 140-3 mode enabled, but integrity check didn't pass")
}
--- /dev/null
+// Copyright 2025 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package fips140
+
+import (
+ "internal/godebug"
+ "os"
+ "testing"
+)
+
+func TestImmutableGODEBUG(t *testing.T) {
+ defer func(v string) { os.Setenv("GODEBUG", v) }(os.Getenv("GODEBUG"))
+
+ fips140Enabled := Enabled()
+ fips140Setting := godebug.New("fips140")
+ fips140SettingValue := fips140Setting.Value()
+
+ os.Setenv("GODEBUG", "fips140=off")
+ if Enabled() != fips140Enabled {
+ t.Errorf("Enabled() changed after setting GODEBUG=fips140=off")
+ }
+ if fips140Setting.Value() != fips140SettingValue {
+ t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=off")
+ }
+
+ os.Setenv("GODEBUG", "fips140=on")
+ if Enabled() != fips140Enabled {
+ t.Errorf("Enabled() changed after setting GODEBUG=fips140=on")
+ }
+ if fips140Setting.Value() != fips140SettingValue {
+ t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=on")
+ }
+
+ os.Setenv("GODEBUG", "fips140=")
+ if Enabled() != fips140Enabled {
+ t.Errorf("Enabled() changed after setting GODEBUG=fips140=")
+ }
+ if fips140Setting.Value() != fips140SettingValue {
+ t.Errorf("fips140Setting.Value() changed after setting GODEBUG=fips140=")
+ }
+
+ os.Setenv("GODEBUG", "")
+ if Enabled() != fips140Enabled {
+ t.Errorf("Enabled() changed after setting GODEBUG=")
+ }
+ if fips140Setting.Value() != fips140SettingValue {
+ t.Errorf("fips140Setting.Value() changed after setting GODEBUG=")
+ }
+}
< crypto/internal/fips140/edwards25519
< crypto/internal/fips140/ed25519
< crypto/internal/fips140/rsa
- < FIPS;
-
- FIPS, internal/godebug < crypto/fips140;
+ < FIPS < crypto/fips140;
crypto !< FIPS;
// Update all the cached values, creating new ones as needed.
// We parse the environment variable first, so that any settings it has
// are already locked in place (did[name] = true) before we consider
- // the defaults.
+ // the defaults. Existing immutable settings are always locked.
did := make(map[string]bool)
+ cache.Range(func(name, s any) bool {
+ if info := s.(*setting).info; info != nil && info.Immutable {
+ did[name.(string)] = true
+ }
+ return true
+ })
parse(did, env)
parse(did, def)
}
}
}
+
+func TestImmutable(t *testing.T) {
+ defer func(godebug string) {
+ os.Setenv("GODEBUG", godebug)
+ }(os.Getenv("GODEBUG"))
+
+ setting := New("fips140")
+ value := setting.Value()
+
+ os.Setenv("GODEBUG", "fips140=off")
+ if setting.Value() != value {
+ t.Errorf("Value() changed after setting GODEBUG=fips140=off")
+ }
+
+ os.Setenv("GODEBUG", "fips140=on")
+ if setting.Value() != value {
+ t.Errorf("Value() changed after setting GODEBUG=fips140=on")
+ }
+
+ os.Setenv("GODEBUG", "fips140=")
+ if setting.Value() != value {
+ t.Errorf("Value() changed after setting GODEBUG=fips140=")
+ }
+
+ os.Setenv("GODEBUG", "")
+ if setting.Value() != value {
+ t.Errorf("Value() changed after setting GODEBUG=")
+ }
+}
// An Info describes a single known GODEBUG setting.
type Info struct {
- Name string // name of the setting ("panicnil")
- Package string // package that uses the setting ("runtime")
- Changed int // minor version when default changed, if any; 21 means Go 1.21
- Old string // value that restores behavior prior to Changed
- Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault]
+ Name string // name of the setting ("panicnil")
+ Package string // package that uses the setting ("runtime")
+ Changed int // minor version when default changed, if any; 21 means Go 1.21
+ Old string // value that restores behavior prior to Changed
+ Opaque bool // setting does not export information to runtime/metrics using [internal/godebug.Setting.IncNonDefault]
+ Immutable bool // setting cannot be changed after program start
}
// All is the table of known settings, sorted by Name.
{Name: "decoratemappings", Package: "runtime", Opaque: true, Changed: 25, Old: "0"},
{Name: "embedfollowsymlinks", Package: "cmd/go"},
{Name: "execerrdot", Package: "os/exec"},
- {Name: "fips140", Package: "crypto/fips140", Opaque: true},
+ {Name: "fips140", Package: "crypto/fips140", Opaque: true, Immutable: true},
{Name: "gocachehash", Package: "cmd/go"},
{Name: "gocachetest", Package: "cmd/go"},
{Name: "gocacheverify", Package: "cmd/go"},