Source File
entropy_fips140.go
Belonging Package
crypto/internal/fips140/drbg
// Copyright 2026 The Go Authors. All rights reserved.// Use of this source code is governed by a BSD-style// license that can be found in the LICENSE file.//go:build !wasm// This file contains reading from from entropy sources in FIPS-140// mode. It uses a scratch buffer in the BSS section (see below),// which usually doesn't cost much, except on Wasm, due to the way// the linear memory works. FIPS-140 mode is not supported on Wasm,// so we just use a build tag to exclude it. (Could also exclude other// platforms that does not support FIPS-140 mode, but as the BSS// variable doesn't cost much, don't bother.)package drbgimport (entropy)// memory is a scratch buffer that is accessed between samples by the entropy// source to expose it to memory access timings.//// We reuse it and share it between Seed calls to avoid the significant (~500µs)// cost of zeroing a new allocation every time. The entropy source accesses it// using atomics (and doesn't care about its contents).//// It should end up in the .noptrbss section, and become backed by physical pages// at first use. This ensures that programs that do not use the FIPS 140-3 module// do not incur any memory use or initialization penalties.var memory entropy.ScratchBufferfunc () *[SeedSize]byte {var int, := entropy.Seed(&memory)for != nil {// The CPU jitter-based SP 800-90B entropy source has a non-negligible// chance of failing the startup health tests.//// Each time it does, it enters a permanent failure state, and we// restart it anew. This is not expected to happen more than a few times// in a row.if ++; > 100 {panic("fips140/drbg: failed to obtain initial entropy")}, = entropy.Seed(&memory)}return &}// getEntropy is very slow (~500µs), so we don't want it on the hot path.// We keep both a persistent DRBG instance and a pool of additional instances.// Occasional uses will use drbgInstance, even if the pool was emptied since the// last use. Frequent concurrent uses will fill the pool and use it.var drbgInstance atomic.Pointer[Counter]var drbgPool = sync.Pool{New: func() any {return NewCounter(getEntropy())},}func ( []byte) {// At every read, 128 random bits from the operating system are mixed as// additional input, to make the output as strong as non-FIPS randomness.// This is not credited as entropy for FIPS purposes, as allowed by Section// 8.7.2: "Note that a DRBG does not rely on additional input to provide// entropy, even though entropy could be provided in the additional input".:= new([SeedSize]byte)sysrand.Read([:16]):= drbgInstance.Swap(nil)if == nil {= drbgPool.Get().(*Counter)}defer func() {if !drbgInstance.CompareAndSwap(nil, ) {drbgPool.Put()}}()for len() > 0 {:= min(len(), maxRequestSize)if := .Generate([:], ); {// See SP 800-90A Rev. 1, Section 9.3.1, Steps 6-8, as explained in// Section 9.3.2: if Generate reports a reseed is required, the// additional input is passed to Reseed along with the entropy and// then nulled before the next Generate call..Reseed(getEntropy(), )= nilcontinue}= [:]}}
![]() |
The pages are generated with Golds v0.8.4. (GOOS=linux GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds. |