| // 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. |
| |
| // Entropy generation in FIPS 140-3 mode 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-3 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-3 mode, but as the BSS variable doesn't cost |
| // much, don't bother.) |
| // |
| //go:build !wasm |
| |
| package drbg |
| |
| import entropy "crypto/internal/entropy/v1.0.0" |
| |
| // 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.ScratchBuffer |
| |
| func getEntropy() *[SeedSize]byte { |
| var retries int |
| seed, err := entropy.Seed(&memory) |
| for err != 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 retries++; retries > 100 { |
| panic("fips140/drbg: failed to obtain initial entropy") |
| } |
| seed, err = entropy.Seed(&memory) |
| } |
| return &seed |
| } |