]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/rand: replace crypto/aes with internal/chacha8rand for plan9
authorFilippo Valsorda <filippo@golang.org>
Mon, 4 Nov 2024 12:05:46 +0000 (13:05 +0100)
committerGopher Robot <gobot@golang.org>
Tue, 19 Nov 2024 00:29:26 +0000 (00:29 +0000)
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 <daniel@binaryparadox.net>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
src/crypto/rand/rand_plan9.go

index 0614d85ba7a9abf36486ec6272c2cc2ba39efcff..a9b0b5857f5b04e4be0432275c153e5f6fba238d 100644 (file)
@@ -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
 }