Skip to content
HN On Hacker News ↗

proposal: crypto/fips140: do not bloat crypto code unnecessarily

▲ 19 points • 8 comments • by zx2c4 • 2w ago • HN discussion ↗

Pangram verdict · v3.3

We believe that this entire text is human-written.

1 %

AI likelihood · overall

Human
100% human-written 0% AI-generated
SEGMENTS · HUMAN 1 of 1
SEGMENTS · AI 0 of 1
WORD COUNT 583
PEAK AI % 1% · §1
Analyzed
Sep 28
backend: pangram/v3.3
Segments scanned
1 windows
avg 583 words each
Distribution
100 / 0%
human / AI fraction
Verdict
Human
Pangram v3.3

Article text · 583 words · 1 segments analyzed

Human AI-generated
§1 Human · 1%

Abstract The FIPS140 code, especially its RNG, sits unused and bloaty on the overwhelming majority of Go binaries. All but the most specific users actually jump through the hoops of turning on this mostly useless (from a technical perspective) code. So it just sits there, wasting memory (the init functions still trigger) and wasting disk space and filling caches and just being a very unwelcome weight to a formerly clean set of crypto libraries. This proposal is to add a new GOFIPS140=disabled default value to not compile in unused FIPS code. Motivation The new fips140 code adds lots of indirection and gravely bloats the code size of resultant binaries, even when disabled or not in use. Its use is gated by default-off GODEBUG flag. Yet it is always compiled into Go binaries. In addition to indirecting large amounts of crypto through its framework (to then bail out early when it's not been enabled with a GODEBUG flag), it also imports large amounts of additional crypto and complexity. As far as I can tell, in addition to causing lots of indirection through its framework, it adds branchy code paths to: TLS RSA/PKCS1 The random number generator wrapper functions AES/GCM I think adding the additional unused code is a shame in all of these cases, and all of these ought to instead be gated on a compile time constant (the Enabled symbol could go from var to const). But it's the RNG situation that I find especially egregious, so that's what I'll focus on here to illustrate what I mean. I made two test programs: tester1: package main func main() { println("hello") } tester2: package main import "crypto/rand" func main() { var b [1]byte rand.Read(b[:]) println("hello", b[0]) } Let's see which crypto packages tester2 adds. We'd expect that it'd pull in crypto/rand, of course, plus some internal crypto things for dispatching this to the various syscalls or whatever else involved in getting the good random bytes. That's not exactly what happens: $ comm -13 <(go tool objdump tester1 | grep ^TEXT\ crypto | sort) <(go tool objdump tester2 | grep ^TEXT\ crypto | sort) TEXT crypto/fips140.init(SB) <autogenerated> TEXT crypto.init(SB) <autogenerated> TEXT crypto/internal/entropy/v1%2e0%2e0.digestBytes(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/sha384.go TEXT crypto/internal/entropy/v1%2e0%2e0.newSource(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/entropy.go TEXT crypto/internal/entropy/v1%2e0%2e0.Samples(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/entropy.go TEXT crypto/internal/entropy/v1%2e0%2e0.Seed(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/entropy.go TEXT crypto/internal/entropy/v1%2e0%2e0.sha384Block(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/sha384.go TEXT crypto/internal/entropy/v1%2e0%2e0.SHA384(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/sha384.go TEXT crypto/internal/entropy/v1%2e0%2e0.(*source).Sample(SB) /usr/lib/go/src/crypto/internal/entropy/v1.0.0/entropy.go TEXT crypto/internal/fips140/aes.(*Block).BlockSize(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes.go TEXT crypto/internal/fips140/aes.(*CBCDecrypter).CryptBlocks(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cbc.go TEXT crypto/internal/fips140/aes.(*CBCEncrypter).CryptBlocks(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cbc.go TEXT crypto/internal/fips140/aes.cryptBlocksDecGeneric(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cbc.go TEXT crypto/internal/fips140/aes.cryptBlocksEncGeneric(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cbc.go TEXT crypto/internal/fips140/aes.ctrBlocks1Asm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_amd64.s TEXT crypto/internal/fips140/aes.ctrBlocks1(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_asm.go TEXT crypto/internal/fips140/aes.ctrBlocks2Asm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_amd64.s TEXT crypto/internal/fips140/aes.ctrBlocks2(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_asm.go TEXT crypto/internal/fips140/aes.ctrBlocks4Asm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_amd64.s TEXT crypto/internal/fips140/aes.ctrBlocks4(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_asm.go TEXT crypto/internal/fips140/aes.ctrBlocks8Asm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_amd64.s TEXT crypto/internal/fips140/aes.ctrBlocks8(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr_asm.go TEXT crypto/internal/fips140/aes.ctrBlocks(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr.go TEXT crypto/internal/fips140/aes.(*CTR).XORKeyStreamAt(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr.go TEXT crypto/internal/fips140/aes.(*CTR).XORKeyStream(SB) /usr/lib/go/src/crypto/internal/fips140/aes/ctr.go TEXT crypto/internal/fips140/aes.decryptBlockAsm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_amd64.s TEXT crypto/internal/fips140/aes.decryptBlockGeneric(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_generic.go TEXT crypto/internal/fips140/aes.decryptBlock(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_asm.go TEXT crypto/internal/fips140/aes.encryptBlockAsm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_amd64.s TEXT crypto/internal/fips140/aes.encryptBlockGeneric(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_generic.go TEXT crypto/internal/fips140/aes.encryptBlock(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_asm.go TEXT crypto/internal/fips140/aes.expandKeyAsm.abi0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_amd64.s TEXT crypto/internal/fips140/aes.expandKeyGeneric(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_generic.go TEXT crypto/internal/fips140/aes/gcm.(*CMAC).deriveSubkeys(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/cmac.go TEXT crypto/internal/fips140/aes/gcm.(*CMAC).MAC(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/cmac.go TEXT crypto/internal/fips140/aes/gcm.(*CounterKDF).DeriveKey(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/ctrkdf.go TEXT crypto/internal/fips140/aes/gcm.init.0.func1(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/cast.go TEXT crypto/internal/fips140/aes/gcm.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/cast.go TEXT crypto/internal/fips140/aes/gcm.init.1(SB) /usr/lib/go/src/crypto/internal/fips140/aes/gcm/gcm_asm.go TEXT crypto/internal/fips140/aes/gcm.init(SB) <autogenerated> TEXT crypto/internal/fips140/aes.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_asm.go TEXT crypto/internal/fips140/aes.init.1.func1(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cast.go TEXT crypto/internal/fips140/aes.init.1(SB) /usr/lib/go/src/crypto/internal/fips140/aes/cast.go TEXT crypto/internal/fips140/aes.init(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_asm.go TEXT crypto/internal/fips140/aes.(*KeySizeError).Error(SB) <autogenerated> TEXT crypto/internal/fips140/aes.KeySizeError.Error(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes.go TEXT crypto/internal/fips140/aes.newBlock(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes_asm.go TEXT crypto/internal/fips140/aes.newOutlined(SB) /usr/lib/go/src/crypto/internal/fips140/aes/aes.go TEXT crypto/internal/fips140.CAST(SB) /usr/lib/go/src/crypto/internal/fips140/cast.go TEXT crypto/internal/fips140/check.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/check/check.go TEXT crypto/internal/fips140deps/cpu.init(SB) /usr/lib/go/src/crypto/internal/fips140deps/cpu/cpu.go TEXT crypto/internal/fips140deps/time.monoTime(SB) /usr/lib/go/src/runtime/time.go TEXT crypto/internal/fips140/drbg.(*Counter).Generate(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/ctrdrbg.go TEXT crypto/internal/fips140/drbg.(*Counter).Reseed(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/ctrdrbg.go TEXT crypto/internal/fips140/drbg.(*Counter).update(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/ctrdrbg.go TEXT crypto/internal/fips140/drbg.getEntropy(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/entropy_fips140.go TEXT crypto/internal/fips140/drbg.init.0.func1(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/cast.go TEXT crypto/internal/fips140/drbg.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/cast.go TEXT crypto/internal/fips140/drbg.init.func1(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/rand.go TEXT crypto/internal/fips140/drbg.init(SB) <autogenerated> TEXT crypto/internal/fips140/drbg.NewCounter(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/ctrdrbg.go TEXT crypto/internal/fips140/drbg.Read.func1(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/rand.go TEXT crypto/internal/fips140/drbg.Read(SB) /usr/lib/go/src/crypto/internal/fips140/drbg/rand.go TEXT crypto/internal/fips140.fatal(SB) /usr/lib/go/src/runtime/panic.go TEXT crypto/internal/fips140.getIndicator(SB) /usr/lib/go/src/runtime/runtime1.go TEXT crypto/internal/fips140/hmac.(*HMAC).BlockSize(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.(*HMAC).Reset(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.(*HMAC).Sum(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.(*HMAC).Write(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.init.0.func1(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/cast.go TEXT crypto/internal/fips140/hmac.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/cast.go TEXT crypto/internal/fips140/hmac.New[go.shape.*uint8].func1.1(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.New[go.shape.*uint8].func1(SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140/hmac.New[go.shape.*uint8](SB) /usr/lib/go/src/crypto/internal/fips140/hmac/hmac.go TEXT crypto/internal/fips140.init.0(SB) /usr/lib/go/src/crypto/internal/fips140/fips140.go TEXT crypto/internal/fips140.init(SB) <autogenerated> TEXT crypto/internal/fips140.RecordApproved(SB) /usr/lib/go/src/crypto/internal/fips140/indicator.go