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 - } - var ( - counter uint64 - block [aes.BlockSize]byte - ) - inc := func() { - counter++ - if counter == 0 { - panic("crypto/rand counter wrapped") - } - byteorder.LePutUint64(block[:], counter) - } - blockCipher.Encrypt(key[:aes.BlockSize], block[:]) - inc() - blockCipher.Encrypt(key[aes.BlockSize:], block[:]) - inc() - mu.Unlock() + defer mu.Unlock() - for len(b) >= aes.BlockSize { - blockCipher.Encrypt(b[:aes.BlockSize], block[:]) - inc() - b = b[aes.BlockSize:] + for len(b) >= 8 { + if x, ok := state.Next(); ok { + byteorder.BePutUint64(b, x) + b = b[8:] + } else { + state.Refill() + } } - if len(b) > 0 { - blockCipher.Encrypt(block[:], block[:]) - copy(b, block[:]) + 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() + } } + state.Reseed() + return nil }