Documentation ¶
Overview ¶
Package fips implements support for the GOFIPS140 build setting.
The GOFIPS140 build setting controls two aspects of the build:
Whether binaries are built to default to running in FIPS-140 mode, meaning whether they default to GODEBUG=fips140=on or =off.
Which copy of the crypto/internal/fips140 source code to use. The default is obviously GOROOT/src/crypto/internal/fips140, but earlier snapshots that have differing levels of external validation and certification are stored in GOROOT/lib/fips140 and can be substituted into the build instead.
This package provides the logic needed by the rest of the go command to make those decisions and implement the resulting policy.
Init must be called to initialize the FIPS logic. It may fail and call base.Fatalf.
When GOFIPS140=off, Enabled returns false, and the build is unchanged from its usual behaviors.
When GOFIPS140 is anything else, Enabled returns true, and the build sets the default GODEBUG to include fips140=on. This will make binaries change their behavior at runtime to confirm to various FIPS-140 details. cmd/go/internal/load.defaultGODEBUG calls [fips.Enabled] when preparing the default settings.
For all builds, FIPS code and data is laid out in contiguous regions that are conceptually concatenated into a "fips object file" that the linker hashes and then binaries can re-hash at startup to detect corruption of those symbols. When Enabled is true, the link step passes -fipso={a.Objdir}/fips.o to the linker to save a copy of the fips.o file. Since the first build target always uses a.Objdir set to $WORK/b001, a build like
GOFIPS140=latest go build -work my/binary
will leave fips.o behind in $WORK/b001. Auditors like to be able to see that file. Accordingly, when Enabled returns true, cmd/go/internal/work.Builder.useCache arranges never to cache linker output, so that the link step always runs, and fips.o is always left behind in the link step. If this proves too slow, we could always cache fips.o as an extra link output and then restore it when -work is set, but we went a very long time never caching link steps at all, so not caching them in FIPS mode seems perfectly fine.
When GOFIPS140 is set to something besides off and latest, Snapshot returns true, indicating that the build should replace the latest copy of crypto/internal/fips140 with an earlier snapshot. The reason to do this is to use a copy that has been through additional lab validation (an "in-process" module) or NIST certification (a "certified" module). The snapshots are stored in GOROOT/lib/fips140 in module zip form. When a snapshot is being used, Init unpacks it into the module cache and then uses that directory as the source location.
A FIPS snapshot like v1.2.3 is integrated into the build in two different ways.
First, the snapshot's fips140 directory replaces crypto/internal/fips140 using fsys.Bind. The effect is to appear to have deleted crypto/internal/fips140 and everything below it, replacing it with the single subdirectory crypto/internal/fips140/v1.2.3, which now has the FIPS packages. This virtual file system replacement makes patterns like std and crypto... automatically see the snapshot packages instead of the original packages as they walk GOROOT/src/crypto/internal/fips140.
Second, ResolveImport is called to resolve an import like crypto/internal/fips140/sha256. When snapshot v1.2.3 is being used, ResolveImport translates that path to crypto/internal/fips140/v1.2.3/sha256 and returns the actual source directory in the unpacked snapshot. Using the actual directory instead of the virtual directory GOROOT/src/crypto/internal/fips140/v1.2.3 makes sure that other tools using go list -json output can find the sources, as well as making sure builds have a real directory in which to run the assembler, compiler, and so on. The translation of the import path happens in the same code that handles mapping golang.org/x/mod to cmd/vendor/golang.org/x/mod when building commands.
It is not strictly required to include v1.2.3 in the import path when using a snapshot - we could make things work without doing that - but including the v1.2.3 gives a different version of the code a different name, which is always a good general rule. In particular, it will mean that govulncheck need not have any special cases for crypto/internal/fips140 at all. The reports simply need to list the relevant symbols in a given Go version. (For example, if a bug is only in the in-tree copy but not the snapshots, it doesn't list the snapshot symbols; if it's in any snapshots, it has to list the specific snapshot symbols in addition to the “normal” symbol.)
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Dir ¶
func Dir() string
Dir reports the directory containing the crypto/internal/fips140 source code. If Snapshot() is false, Dir returns GOROOT/src/crypto/internal/fips140. Otherwise Dir ensures that the snapshot has been unpacked into the module cache and then returns the directory in the module cache corresponding to the crypto/internal/fips140 directory.
func Enabled ¶
func Enabled() bool
Enabled reports whether FIPS mode is enabled at all. That is, it reports whether GOFIPS140 is set to something besides "off".
func Init ¶
func Init()
Init initializes the FIPS settings. It must be called before using any other functions in this package. If initialization fails, Init calls base.Fatalf.
func ResolveImport ¶
ResolveImport resolves the import path imp. If it is of the form crypto/internal/fips140/foo (not crypto/internal/fips140/v1.2.3/foo) and we are using a snapshot, then LookupImport rewrites the path to crypto/internal/fips140/v1.2.3/foo and returns that path and its location in the unpacked FIPS snapshot.
Types ¶
This section is empty.