Skip to content

Support native Golang "fips140" mode - #1696

Open
wadey wants to merge 83 commits into
masterfrom
fips140
Open

Support native Golang "fips140" mode#1696
wadey wants to merge 83 commits into
masterfrom
fips140

Conversation

@wadey

@wadey wadey commented Apr 27, 2026

Copy link
Copy Markdown
Member

Add support for the "fips140" mode of Go:

You can build with make fips140, see the README changes for more info.

Some differences from the boringcrypto builds:

  • We switch to using go:linkname crypto/tls.aeadAESGCMTLS13, which gives us the fips implementation for both boringcrypto and fips140 modes. This means we also no longer need -checklinkname=0
  • Go native fips140 doesn't need CGO_ENABLED=1
  • We decide if we should use the fips140 GCM at runtime, if fips140.Enabled() is true. If you use the make release-fips140, we build with build tag fips140enforce which ensures the binary is running with fips140 enabled and that only P256 / AES-GCM is being used. If you don't want this enforce mode, you can build without the build tag.

@wadey wadey added this to the v1.11.0 milestone Apr 27, 2026
Comment thread Makefile Outdated
cd .github/workflows/smoke/ && NAME="smoke-p256" CURVE="P256" ./build.sh
cd .github/workflows/smoke/ && NAME="smoke-p256" ./smoke.sh
cd .github/workflows/smoke/ && $(GOENV) ./build.sh
cd .github/workflows/smoke/ && $(GOENV)./smoke.sh

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a space after $(GOENV)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, fixed

Comment thread noise.go Outdated

type cipherAEADDanger interface {
EncryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error)
DecryptDanger(out, ad, plaintext []byte, n uint64, nb []byte) ([]byte, error)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

plaintext -> ciphertext

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

im confused, when you call this function it is still plaintext

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

err nm lol I see

Comment thread Makefile
@$(MAKE) service ${.DEFAULT_GOAL} --no-print-directory
endif

fips140:

@nbrownus nbrownus Apr 29, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

boringcrypto outputs with a suffix on the folder like: build/linux-amd64-boringcrypto/nebula

fips140 outputs to a colliding path with non fips140: build/linux-amd64/nebula, seems like a good idea to push this into build/linux-amd64-fips140/nebula.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch! let me rework this.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added release-fips140 and bin-fips140 for this

Comment thread noise.go Outdated
out = s.c.Seal(out, nb, plaintext, ad)
//l.Debugf("Encryption: outlen: %d, nonce: %d, ad: %s, plainlen %d", len(out), n, ad, len(plaintext))
return out, nil
switch ce := s.c.(type) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be awesome to swap out the interface and avoid the type check for each packet.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in latest commit

Comment thread Makefile Outdated

fips140:
@echo > $(NULL_FILE)
$(eval GOENV += GOFIPS140=v1.0.0)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will also need to require go 1.26 and include this LDFLAGS: -X runtime.godebugDefault=fips140=only

Otherwise fips is enabled but all non fips crypto just keeps working. Will need to couple this with a change to assert fips140.Enforced() is true.

@wadey wadey Jun 1, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added the default, but not enforcing and instead just logging the state of it. Considering the check.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented with a build tag fips140enforce

Comment thread noiseutil/fips140.go Outdated
// EncryptLockNeeded indicates if calls to Encrypt need a lock
// This is true for fips140 because the Seal function verifies that the
// nonce is strictly increasing.
const EncryptLockNeeded = true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other part of -X runtime.godebugDefault=fips140=only is that we will want an init check to assert fips140.Enforced() here.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Implemented with a build tag fips140enforce.

wadey added 4 commits July 8, 2026 10:41
This is safer because it doesn't clober other defaults that are set by
Go or the environment.
@nbrownus nbrownus mentioned this pull request Jul 8, 2026
56 tasks
Comment thread noiseutil/fips140.go
}

func (c *aeadGCMFIPS140Cipher) Seal(dst, nonce, plaintext, additionalData []byte) []byte {
if !c.ready {

@JackDoan JackDoan Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we do this as part of extractFIPSAEAD? It would avoid a branch & technically also avoids an opportunity to race (thought my understanding is this should always be called under a lock bc of how the fips nonce checker works

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can as long as nothing in our code encrypts with a "0" nonce. I think this is true. Ill test it

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, the first WriteMessage that noise does is with nonce 0, so this is a bit tricky to optimize

JackDoan
JackDoan previously approved these changes Jul 17, 2026
JackDoan
JackDoan previously approved these changes Jul 20, 2026
Comment thread pki.go Outdated
switch curve {
case cert.Curve_CURVE25519:
if fips140.Enforced() {
panic("pki: use of Curve25519 is not allowed in FIPS 140-only mode")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thoughts on returning an error instead of throwing a panic?

@wadey wadey Jul 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We throw a panic for the other algorithms when fips140.Enforced is turned on. Let me check.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy with a panic as long as we can show it's not reachable from UDP

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ill change to return an error, that matches what stdlib does in my research

@nbrownus nbrownus modified the milestones: v1.11.0, v1.12.0 Jul 23, 2026
@JackDoan

Copy link
Copy Markdown
Collaborator

Do we want to check for and respect /proc/sys/crypto/fips_enabled on Linux?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants