Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

crypto: obtain a FIPS 140-3 validation #69536

Open
FiloSottile opened this issue Sep 19, 2024 · 96 comments
Open

crypto: obtain a FIPS 140-3 validation #69536

FiloSottile opened this issue Sep 19, 2024 · 96 comments
Assignees
Labels
Milestone

Comments

@FiloSottile
Copy link
Contributor

Background

FIPS 140 is a set of U.S. Government requirements for cryptographic modules. A number of companies must comply with them, for example as part of a broader FedRAMP compliance posture. (If that's not you, you can ignore this. Run!)

Current solutions for Go program compliance are based on cgo, and replace some of the crypto packages internals with FIPS 140 validated non-memory safe modules. These solutions come with varying levels of support (for example the Go+BoringCrypto solution is not officially supported and its compliance profile is left to the user to assess), introduce memory unsafe code, sometimes delay Go version updates, can have performance issues, affect the developer experience (for example inhibiting cross-compilation), and their compliance profile is debatable. As Go is adopted more and more in regulated settings, this is going to affect Go's adoption and developer experience.

The Go FIPS module

We plan to pursue a FIPS 140-3 validation for the NIST approved components of the Go standard library. The resulting module will be distributed as part of the standard library under the same license as the rest of the Go project, and will be transparently used by the relevant standard library packages with no API changes (wherever possible).

Users will be able to select the module to use at build time, for example choosing between a certified version, a version in the In Process list, or the latest unvalidated update. Moreover, we'll provide some mechanism for applications to disable the use of non-approved algorithms and modes at runtime.

Further planning details

The goal is shipping the module as part of Go 1.24, assuming our validation strategy is successful. This is the first time as far as we know that a Go library (or any non-Java memory safe library) is validated.

Unless completely unavoidable, we'll not compromise on security to achieve compliance. For example, we will inject random bytes from the kernel as additional input per SP 800-90Ar1, Section 8.7.2, every time we use the mandatory DRBG, and we'll use a dedicated DRBG for ECDSA to implement a "hedged" nonce generation equivalent to what crypto/ecdsa does now (safer than both NIST options of fully random and deterministic). Also, we'll try to add minimal complexity to regular non-FIPS builds.

NIST approved packages will be prioritized in being moved to the standard library (#65269) to get validated along the rest.

We'll test at least on Linux on amd64 and arm64. Further details will be available later in the process. (If you have specific requirements, please inquire about becoming a sponsor, see below.)

We aim to deprecate and hopefully remove Go+BoringCrypto once the module lands.

After the initial validation, we plan to revalidate at least every year, and every time a CVE affects the module with no standard library-side mitigation.

All work will be done on Gerrit, tracked in the issue tracker, and the testing harnesses will be committed in the tree.

This is an umbrella issue to track related issues and CLs, and to provide updates to the community. We'll file separate proposals for the exact build-time settings, for the FIPS-only policy mechanism, for any new APIs, and for any behavior changes.

We have started working with a CMVP testing laboratory, and contracted @cpu to help. This is an industry-sponsored effort that I (@FiloSottile) am leading as an independent maintainer, not a Google or Go team project (although it is coordinated with the Go team and @golang/security). We're funded by a few major stakeholders, and we're available to accept sponsorships and offer commercial support (reach out to [email protected] if interested).

@FiloSottile FiloSottile added this to the Go1.24 milestone Sep 19, 2024
@FiloSottile FiloSottile self-assigned this Sep 19, 2024
@gabyhelp
Copy link

Related Issues and Documentation

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

@DejeroDaniel
Copy link

I was just about to ask a question regarding Ed25519 usage in the other ticket when this was posted. Exciting news!
Is Ed25519 support planned to be certified in this new native implementation?

@FiloSottile
Copy link
Contributor Author

Is Ed25519 support planned to be certified in this new native implementation?

Yes, we'll post a full list of algorithms once we are close to finalizing it, but it approximates to "everything that's NIST approved and not frozen, deprecated, or legacy-use".

@mateusz834
Copy link
Member

Users will be able to select the module to use at build time, for example choosing between a certified version, a version in the In Process list, or the latest unvalidated update.

How this is going to be achieved? Build tags?
The default is going to be non-FIPS validated?

@FiloSottile
Copy link
Contributor Author

How this is going to be achieved? Build tags?

Probably something more explicit, such as a go build flag. I suspect build tags won't be flexible enough, but I might be wrong! We'll bring up a dedicated proposal to discuss that.

The default is going to be non-FIPS validated?

Yes.

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/614495 mentions this issue: crypto/sha256,crypto/sha512: make assembly structure consistent

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/614656 mentions this issue: crypto/sha256,crypto/sha512: test fallback implementations

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/615235 mentions this issue: crypto/sha256,crypto/sha512: move implementation to crypto/internal/fips

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/615816 mentions this issue: crypto/internal: add FIPS module test wrapper

@manistal
Copy link

Out of curiosity, how will Go natively handle the key zeroization requirements of FIPS?

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/616636 mentions this issue: crypto/hmac: move implementation to crypto/internal/fips

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/616717 mentions this issue: crypto/internal/fips/sha3: import x/crypto/sha3

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/616716 mentions this issue: crypto/internal/fips/subtle: provide XORBytes

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/616715 mentions this issue: internal/cpu: add ARM64.HasSHA3

cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
Ensure separate implementations are implemented in different functions
called from Go, and that they can be turned off from a GODEBUG.

This will be necessary to test implementations separately for golang#69536.

Change-Id: I3e081deb7abb01b0665265e39c72fd4037dd48b3
Cq-Include-Trybots: luci.golang.try:gotip-linux-arm64-longtest,gotip-linux-amd64-longtest,gotip-linux-ppc64le_power8,gotip-linux-ppc64_power8
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
This will be required for golang#69536 but is also good hygiene and required
by go.dev/wiki/AssemblyPolicy.

> The code must be tested in our CI. This means there need to be
> builders that support the instructions, and if there are multiple (or
> fallback) paths they must be tested separately.

The new crypto/internal/impl registry lets us select alternative
implementations from both the same package and importers (such as
crypto/sha256 tests once we have crypto/internal/fips/sha256, or
crypto/hmac).

Updates golang#69592
Updates golang#69593

Change-Id: Ifea22a9fc9ccffcaf4924ff6bd08da7c9bd39e99
Cq-Include-Trybots: luci.golang.try:gotip-linux-arm64-longtest,gotip-linux-amd64-longtest,gotip-linux-ppc64le_power8,gotip-linux-ppc64_power8
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
For golang#69536

Change-Id: I1efa916e6e9fcddeffa52bc3d23286e6465dae54
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
For golang#69536

Change-Id: I38508a8de4ac321554a2c12ac70bcf9e25fad1aa
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
For golang#69536

Change-Id: If237226ba03e282443b4fc90484968c903198cb1
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
This is needed from inside the module, and we generally don't want to
import the crypto tree from it.

For golang#69536

Change-Id: I69e91e4df89ecac0016c671ccd28e733a7131533
cpu pushed a commit to cpu/go that referenced this issue Oct 1, 2024
For now just internally, pending a dedicated proposal for the exposed
package API.

In this CL the code is copied verbatim, for ease of review. Only the
imports were replaced with the corresponding internal ones, and
crypto.RegisterHash calls were disabled.

DO NOT SUBMIT until CL 616635 is submitted, and this CL is synced, then
specify here what commit was imported.

Updates golang#65269
For golang#69536

Change-Id: Ia4735b50c99b9573a5c4889733c4a119930fe658
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/636558 mentions this issue: crypto/internal/fips140: add Name and Version

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/636775 mentions this issue: crypto/internal/fips140/aes: mark AES-ECB as not approved

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/636795 mentions this issue: crypto/cipher: block non-AES CTR and CBC in fips140=only mode

gopherbot pushed a commit that referenced this issue Dec 17, 2024
NIST SP 800-131Ar3 ipd, scheduled for publication in 2025Q1, marks
AES-ECB as disallowed for encryption, and legacy use for decryption.

There are apparently no details on how the transition is going to work,
so to avoid surprises we just mark direct use of the Block as
non-approved.

We need to use Encrypt from higher level modes without tripping the
service indicator. Within the aes package, we just use the internal
function. For the gcm package we could do something more clever, but
this deep into the freeze, just make an exported function that we commit
to use nowhere else.

I could not figure out a decent way to block ECB on GODEBUG=fips140=only.

For #69536

Change-Id: I972a4b5da8efd0a0ab68d7dd509bec73aa2d6b68
Reviewed-on: https://go-review.googlesource.com/c/go/+/636775
Reviewed-by: David Chase <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
gopherbot pushed a commit that referenced this issue Dec 17, 2024
Somehow I had missed these.

For #69536

Change-Id: I5e60b6f052bbfb707742ad15f663517c6c5f68d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/636795
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: David Chase <[email protected]>
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/637175 mentions this issue: crypto/internal/fips140/aes/gcm: use aes.EncryptBlockInternal on ppc64x and s390x

@gopherbot
Copy link
Contributor

Change https://go.dev/cl/637177 mentions this issue: cmd/go,crypto: reject using Go+BoringCrypto and fips140 together

gopherbot pushed a commit that referenced this issue Dec 17, 2024
Per ISO/IEC 19790:2012, Section 7.4.3.1.

> A cryptographic module shall [04.12] provide the following services to
> operators.
>
> a) Show module’s versioning information. The cryptographic module
> shall [04.13] output the name or module identifier and the versioning
> information that can be correlated with a validation record (e.g.
> hardware, software and/or firmware versioning information)."

For #69536

Change-Id: I8061f64e4ae60a4666f6abd892cb1301d6bf2452
Reviewed-on: https://go-review.googlesource.com/c/go/+/636558
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Reviewed-by: David Chase <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
gopherbot pushed a commit that referenced this issue Dec 17, 2024
…4x and s390x

Left them out of CL 636775 because I did a search by reference, which
does not span architectures.

Fixes crypto/cipher.TestFIPSServiceIndicator failure on ppc64x and s390x.

For #69536

Change-Id: I34b49705a7099066e8c3871a7a34b394a9298e98
Reviewed-on: https://go-review.googlesource.com/c/go/+/637175
Reviewed-by: David Chase <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
@kojiatdell
Copy link

kojiatdell commented Dec 18, 2024

Hi @FiloSottile
I like to know how the Go Crypto code will be validated. Is it going to be FIPS140-3 validated as source code?

gopherbot pushed a commit that referenced this issue Dec 18, 2024
The combination is untested and nonsensical. Both are solutions to the
same problem.

For #69536

Change-Id: I95cc3baaf03b64ce08096e304e311a29e9577385
Reviewed-on: https://go-review.googlesource.com/c/go/+/637177
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Russ Cox <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: David Chase <[email protected]>
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/638855 mentions this issue: crypto/internal/fips140/check: remove Enabled

gopherbot pushed a commit that referenced this issue Jan 3, 2025
check.Enabled, internal/fips140.Enabled, and crypto/fips140.Enabled were
redundant. Package check can just use internal/fips140.Enabled.

check.Verified is still there for the tests and belt-and-suspenders
assurance in crypto/fips140.Enabled, although it's implied by Enabled.

For #69536

Change-Id: I83921cc925da841aba4da79a9a5e9ac526a3f2bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/638855
Reviewed-by: Roland Shoemaker <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
@gopherbot
Copy link
Contributor

Change https://go.dev/cl/640597 mentions this issue: crypto/internal/fips140/drbg: add package comment

wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
NIST SP 800-131Ar3 ipd, scheduled for publication in 2025Q1, marks
AES-ECB as disallowed for encryption, and legacy use for decryption.

There are apparently no details on how the transition is going to work,
so to avoid surprises we just mark direct use of the Block as
non-approved.

We need to use Encrypt from higher level modes without tripping the
service indicator. Within the aes package, we just use the internal
function. For the gcm package we could do something more clever, but
this deep into the freeze, just make an exported function that we commit
to use nowhere else.

I could not figure out a decent way to block ECB on GODEBUG=fips140=only.

For golang#69536

Change-Id: I972a4b5da8efd0a0ab68d7dd509bec73aa2d6b68
Reviewed-on: https://go-review.googlesource.com/c/go/+/636775
Reviewed-by: David Chase <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
Somehow I had missed these.

For golang#69536

Change-Id: I5e60b6f052bbfb707742ad15f663517c6c5f68d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/636795
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: David Chase <[email protected]>
wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
Per ISO/IEC 19790:2012, Section 7.4.3.1.

> A cryptographic module shall [04.12] provide the following services to
> operators.
>
> a) Show module’s versioning information. The cryptographic module
> shall [04.13] output the name or module identifier and the versioning
> information that can be correlated with a validation record (e.g.
> hardware, software and/or firmware versioning information)."

For golang#69536

Change-Id: I8061f64e4ae60a4666f6abd892cb1301d6bf2452
Reviewed-on: https://go-review.googlesource.com/c/go/+/636558
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Reviewed-by: David Chase <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
…4x and s390x

Left them out of CL 636775 because I did a search by reference, which
does not span architectures.

Fixes crypto/cipher.TestFIPSServiceIndicator failure on ppc64x and s390x.

For golang#69536

Change-Id: I34b49705a7099066e8c3871a7a34b394a9298e98
Reviewed-on: https://go-review.googlesource.com/c/go/+/637175
Reviewed-by: David Chase <[email protected]>
Reviewed-by: Roland Shoemaker <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
The combination is untested and nonsensical. Both are solutions to the
same problem.

For golang#69536

Change-Id: I95cc3baaf03b64ce08096e304e311a29e9577385
Reviewed-on: https://go-review.googlesource.com/c/go/+/637177
LUCI-TryBot-Result: Go LUCI <[email protected]>
Reviewed-by: Russ Cox <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
Reviewed-by: David Chase <[email protected]>
wyf9661 pushed a commit to wyf9661/go that referenced this issue Jan 21, 2025
check.Enabled, internal/fips140.Enabled, and crypto/fips140.Enabled were
redundant. Package check can just use internal/fips140.Enabled.

check.Verified is still there for the tests and belt-and-suspenders
assurance in crypto/fips140.Enabled, although it's implied by Enabled.

For golang#69536

Change-Id: I83921cc925da841aba4da79a9a5e9ac526a3f2bf
Reviewed-on: https://go-review.googlesource.com/c/go/+/638855
Reviewed-by: Roland Shoemaker <[email protected]>
Reviewed-by: Daniel McCarney <[email protected]>
Reviewed-by: Dmitri Shuralyov <[email protected]>
LUCI-TryBot-Result: Go LUCI <[email protected]>
Auto-Submit: Filippo Valsorda <[email protected]>
@juliens
Copy link
Contributor

juliens commented Jan 21, 2025

Hi Team,

From my understanding, there seems to be a conflict between FIPS
requirements and the QUIC specification defined in RFC 9001. ( I created an issue on the Quic-go repository as well quic-go/quic-go#4894 )

According to Section 5.8 of RFC 9001, QUIC mandates the use of a fixed
nonce for handshake retries. However, FIPS explicitly prohibits the
use of fixed nonces, as this weakens cryptographic security. This
appears to create a direct conflict between the two standards.

What would be the best approach to address this apparent conflict in a
FIPS-compliant context?

Thank you for your insights and guidance!

@neild
Copy link
Contributor

neild commented Jan 21, 2025

Some added detail on QUIC vs. FIPS:

With GODEBUG=fips140-only set, crypto/cipher.NewGCM panics with an error indicating that GCM with arbitrary IVs is not permitted.

QUIC includes a feature called "address validation", in which a server responds to a client's first packet with a demand for proof that the client can receive packets sent to its source IP address. In address validation, the server sends a "Retry" packet to the client containing a token and the client restarts the handshake with the provided token (providing proof that it was able to receive the server's Retry packet).

The Retry packet sent by the server contains proof that the sender observed the client's Initial packet, preventing an off-path attacker from sending spoofed retries.

This proof (the Retry Integrity Tag) comes in the form of the output of AEAD_AES_128_GCM used with a fixed secret key, fixed nonce, empty plaintext, and associated data containing certain fields from the client's Initial packet.

It doesn't appear to be possible to generate the Retry Integrity Tag in FIPS-140 mode.

See:
https://www.rfc-editor.org/rfc/rfc9000#section-8.1.2
https://www.rfc-editor.org/rfc/rfc9001.html#section-5.8

@FiloSottile
Copy link
Contributor Author

I believe at the very least we'd have to explicitly test the use of the FIPS module's AES-GCM with QUIC, and claim support in the Security Policy. It's too late for that in v1.0, but we can keep it in mind for v2.0.

@neild
Copy link
Contributor

neild commented Jan 21, 2025

Presumably too late for v1.0, but perhaps a no-plaintext GCM variant would be acceptable to FIPS? (Returns an AEAD that accepts key, nonce, and additional data only, panics if the plaintext is non-empty.)

@marten-seemann
Copy link
Contributor

I'm not sure what v1.0 and v2.0 refer to here (it's the first time these version numbers are mentioned in this thread, as far as I can tell), but it sounds like resolving this problem won't happen before the Go 1.24 release? Is that correct?

If that's the case, it simply won't be possible to run QUIC when using fips-only mode, as Retry is a non-optional part of the RFC. quic-go currently panics on initialization, since we call cipher.NewGCM in init, but we could change this to returning an error when the user tries to dial / listen for QUIC connections.

@bwesterb
Copy link

I think the use of AES GCM here is a red herring. When using TLS over TCP, there is plenty of stuff that's not encrypted (packet headers), which FIPS doesn't care about. I don't think FIPS cares about the retry packet.

@chr-bell
Copy link

chr-bell commented Jan 22, 2025 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests