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
(unless the build result is cached, of course).
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.)