// 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 (
	
	
	
	
	
	
)

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 ( []byte) {
	if !fips140.Enabled {
		sysrand.Read()
		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".
	 := new([SeedSize]byte)
	sysrand.Read([:16])

	mu.Lock()
	defer mu.Unlock()

	if drbg == nil {
		entropy.Depleted(func( *[48]byte) {
			drbg = NewCounter()
		})
	}

	for len() > 0 {
		 := min(len(), maxRequestSize)
		if  := drbg.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.
			entropy.Depleted(func( *[48]byte) {
				drbg.Reseed(, )
			})
			 = nil
			continue
		}
		 = [:]
	}
}

// DefaultReader is a sentinel type, embedded in the default
// [crypto/rand.Reader], used to recognize it when passed to
// APIs that accept a rand io.Reader.
type DefaultReader interface{ defaultReader() }

// ReadWithReader uses Reader to fill b with cryptographically secure random
// bytes. It is intended for use in APIs that expose a rand io.Reader.
//
// If Reader is not the default Reader from crypto/rand,
// [randutil.MaybeReadByte] and [fips140.RecordNonApproved] are called.
func ( io.Reader,  []byte) error {
	if ,  := .(DefaultReader);  {
		Read()
		return nil
	}

	fips140.RecordNonApproved()
	randutil.MaybeReadByte()
	,  := io.ReadFull(, )
	return 
}

// ReadWithReaderDeterministic is like ReadWithReader, but it doesn't call
// [randutil.MaybeReadByte] on non-default Readers.
func ( io.Reader,  []byte) error {
	if ,  := .(DefaultReader);  {
		Read()
		return nil
	}

	fips140.RecordNonApproved()
	,  := io.ReadFull(, )
	return 
}