mirror of https://github.com/golang/go.git
crypto/internal/fips/drbg: implement FIPS-mode randomness generation
For #69536 Change-Id: I5bc83360fcd9114cc76314c3570977e9811fd1c6 Reviewed-on: https://go-review.googlesource.com/c/go/+/624978 Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Daniel McCarney <daniel@binaryparadox.net> Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
e67037fb27
commit
0d8b96de05
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2024 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.
|
||||
|
||||
// Package entropy provides the passive entropy source for the FIPS 140-3
|
||||
// module. It is only used in FIPS mode by [crypto/internal/fips/drbg.Read].
|
||||
//
|
||||
// This complies with IG 9.3.A, Additional Comment 12, which until January 1,
|
||||
// 2026 allows new modules to meet an [earlier version] of Resolution 2(b):
|
||||
// "A software module that contains an approved DRBG that receives a LOAD
|
||||
// command (or its logical equivalent) with entropy obtained from [...] inside
|
||||
// the physical perimeter of the operational environment of the module [...]."
|
||||
//
|
||||
// Distributions that have their own SP 800-90B entropy source should replace
|
||||
// this package with their own implementation.
|
||||
//
|
||||
// [earlier version]: https://csrc.nist.gov/CSRC/media/Projects/cryptographic-module-validation-program/documents/IG%209.3.A%20Resolution%202b%5BMarch%2026%202024%5D.pdf
|
||||
package entropy
|
||||
|
||||
import "crypto/internal/sysrand"
|
||||
|
||||
// Depleted notifies the entropy source that the entropy in the module is
|
||||
// "depleted" and provides the callback for the LOAD command.
|
||||
func Depleted(LOAD func(*[48]byte)) {
|
||||
var entropy [48]byte
|
||||
sysrand.Read(entropy[:])
|
||||
LOAD(&entropy)
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright 2024 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.
|
||||
|
||||
package drbg
|
||||
|
||||
import (
|
||||
"crypto/internal/entropy"
|
||||
"crypto/internal/fips"
|
||||
"crypto/internal/sysrand"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var mu sync.Mutex
|
||||
var drbg *Counter
|
||||
|
||||
// Read fills b with cryptographically secure random bytes. In FIPS mode, it
|
||||
// uses an SP 800-90A Rev. 1 Deterministic Random Bit Generator (DRBG).
|
||||
// Otherwise, it uses the operating system's random number generator.
|
||||
func Read(b []byte) {
|
||||
if !fips.Enabled {
|
||||
sysrand.Read(b)
|
||||
return
|
||||
}
|
||||
|
||||
// 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".
|
||||
additionalInput := new([SeedSize]byte)
|
||||
sysrand.Read(additionalInput[:16])
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
if drbg == nil {
|
||||
entropy.Depleted(func(seed *[48]byte) {
|
||||
drbg = NewCounter(seed)
|
||||
})
|
||||
}
|
||||
|
||||
for len(b) > 0 {
|
||||
size := min(len(b), maxRequestSize)
|
||||
if reseedRequired := drbg.Generate(b[:size], additionalInput); reseedRequired {
|
||||
// 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.
|
||||
entropy.Depleted(func(seed *[48]byte) {
|
||||
drbg.Reseed(seed, additionalInput)
|
||||
})
|
||||
additionalInput = nil
|
||||
continue
|
||||
}
|
||||
b = b[size:]
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
// Copyright 2024 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.
|
||||
|
||||
package fips
|
||||
|
||||
import "internal/godebug"
|
||||
|
||||
var Enabled = godebug.New("#fips140").Value() == "on"
|
||||
|
|
@ -8,6 +8,8 @@ package rand
|
|||
|
||||
import (
|
||||
"crypto/internal/boring"
|
||||
"crypto/internal/fips"
|
||||
"crypto/internal/fips/drbg"
|
||||
"crypto/internal/sysrand"
|
||||
"io"
|
||||
_ "unsafe"
|
||||
|
|
@ -23,6 +25,9 @@ import (
|
|||
// - On Windows, Reader uses the ProcessPrng API.
|
||||
// - On js/wasm, Reader uses the Web Crypto API.
|
||||
// - On wasip1/wasm, Reader uses random_get.
|
||||
//
|
||||
// In FIPS 140-3 mode, the output passes through an SP 800-90A Rev. 1
|
||||
// Deterministric Random Bit Generator (DRBG).
|
||||
var Reader io.Reader
|
||||
|
||||
func init() {
|
||||
|
|
@ -37,7 +42,11 @@ type reader struct{}
|
|||
|
||||
func (r *reader) Read(b []byte) (n int, err error) {
|
||||
boring.Unreachable()
|
||||
sysrand.Read(b)
|
||||
if fips.Enabled {
|
||||
drbg.Read(b)
|
||||
} else {
|
||||
sysrand.Read(b)
|
||||
}
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -441,13 +441,15 @@ var depsRules = `
|
|||
< net/mail;
|
||||
|
||||
STR < crypto/internal/impl;
|
||||
OS < crypto/internal/sysrand;
|
||||
|
||||
OS < crypto/internal/sysrand
|
||||
< crypto/internal/entropy;
|
||||
|
||||
# FIPS is the FIPS 140 module.
|
||||
# It must not depend on external crypto packages.
|
||||
# Internal packages imported by FIPS might need to retain
|
||||
# backwards compatibility with older versions of the module.
|
||||
STR, crypto/internal/impl, crypto/internal/sysrand
|
||||
STR, crypto/internal/impl, crypto/internal/entropy
|
||||
< crypto/internal/fips
|
||||
< crypto/internal/fips/alias
|
||||
< crypto/internal/fips/subtle
|
||||
|
|
|
|||
Loading…
Reference in New Issue