From: Filippo Valsorda Date: Mon, 4 Nov 2024 12:05:46 +0000 (+0100) Subject: crypto/rand: replace crypto/aes with internal/chacha8rand for plan9 X-Git-Tag: go1.24rc1~301 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=f705cf8f96bef3f61ba65e62b0b9123d718d0d12;p=gostls13.git crypto/rand: replace crypto/aes with internal/chacha8rand for plan9 We will need to import this functionality from the FIPS module, and we can't import AES from there. Plan 9 is not going to be FIPS validated anyway, so we can use non-approved cryptography. For #69536 Change-Id: I7921ec0829b576de2e80f3a7d0a9a776ff387684 Reviewed-on: https://go-review.googlesource.com/c/go/+/624975 Reviewed-by: Daniel McCarney LUCI-TryBot-Result: Go LUCI Auto-Submit: Filippo Valsorda Reviewed-by: Roland Shoemaker Reviewed-by: Dmitri Shuralyov --- diff --git a/src/crypto/rand/rand_plan9.go b/src/crypto/rand/rand_plan9.go index 0614d85ba7..a9b0b5857f 100644 --- a/src/crypto/rand/rand_plan9.go +++ b/src/crypto/rand/rand_plan9.go @@ -5,76 +5,68 @@ package rand import ( - "crypto/aes" "internal/byteorder" + "internal/chacha8rand" "io" "os" "sync" - "time" ) const randomDevice = "/dev/random" // This is a pseudorandom generator that seeds itself by reading from // /dev/random. The read function always returns the full amount asked for, or -// else it returns an error. The generator is a fast key erasure RNG. +// else it returns an error. var ( mu sync.Mutex seeded sync.Once seedErr error - key [32]byte + state chacha8rand.State ) func read(b []byte) error { seeded.Do(func() { - t := time.AfterFunc(time.Minute, func() { - println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel") - }) - defer t.Stop() entropy, err := os.Open(randomDevice) if err != nil { seedErr = err return } defer entropy.Close() - _, seedErr = io.ReadFull(entropy, key[:]) + var seed [32]byte + _, err = io.ReadFull(entropy, seed[:]) + if err != nil { + seedErr = err + return + } + state.Init(seed) }) if seedErr != nil { return seedErr } mu.Lock() - blockCipher, err := aes.NewCipher(key[:]) - if err != nil { - mu.Unlock() - return err + defer mu.Unlock() + + for len(b) >= 8 { + if x, ok := state.Next(); ok { + byteorder.BePutUint64(b, x) + b = b[8:] + } else { + state.Refill() + } } - var ( - counter uint64 - block [aes.BlockSize]byte - ) - inc := func() { - counter++ - if counter == 0 { - panic("crypto/rand counter wrapped") + for len(b) > 0 { + if x, ok := state.Next(); ok { + var buf [8]byte + byteorder.BePutUint64(buf[:], x) + n := copy(b, buf[:]) + b = b[n:] + } else { + state.Refill() } - byteorder.LePutUint64(block[:], counter) } - blockCipher.Encrypt(key[:aes.BlockSize], block[:]) - inc() - blockCipher.Encrypt(key[aes.BlockSize:], block[:]) - inc() - mu.Unlock() + state.Reseed() - for len(b) >= aes.BlockSize { - blockCipher.Encrypt(b[:aes.BlockSize], block[:]) - inc() - b = b[aes.BlockSize:] - } - if len(b) > 0 { - blockCipher.Encrypt(block[:], block[:]) - copy(b, block[:]) - } return nil }