rand_unix.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. // Copyright 2010 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. //go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || plan9 || solaris
  5. // Unix cryptographically secure pseudorandom number
  6. // generator.
  7. package rand
  8. import (
  9. "bufio"
  10. "crypto/aes"
  11. "crypto/cipher"
  12. "encoding/binary"
  13. "io"
  14. "os"
  15. "runtime"
  16. "sync"
  17. "sync/atomic"
  18. "time"
  19. )
  20. const urandomDevice = "/dev/urandom"
  21. // Easy implementation: read from /dev/urandom.
  22. // This is sufficient on Linux, OS X, and FreeBSD.
  23. func init() {
  24. if runtime.GOOS == "plan9" {
  25. Reader = newReader(nil)
  26. } else {
  27. Reader = &devReader{name: urandomDevice}
  28. }
  29. }
  30. // A devReader satisfies reads by reading the file named name.
  31. type devReader struct {
  32. name string
  33. f io.Reader
  34. mu sync.Mutex
  35. used int32 // atomic; whether this devReader has been used
  36. }
  37. // altGetRandom if non-nil specifies an OS-specific function to get
  38. // urandom-style randomness.
  39. var altGetRandom func([]byte) (ok bool)
  40. func warnBlocked() {
  41. println("crypto/rand: blocked for 60 seconds waiting to read random data from the kernel")
  42. }
  43. func (r *devReader) Read(b []byte) (n int, err error) {
  44. if atomic.CompareAndSwapInt32(&r.used, 0, 1) {
  45. // First use of randomness. Start timer to warn about
  46. // being blocked on entropy not being available.
  47. t := time.AfterFunc(60*time.Second, warnBlocked)
  48. defer t.Stop()
  49. }
  50. if altGetRandom != nil && r.name == urandomDevice && altGetRandom(b) {
  51. return len(b), nil
  52. }
  53. r.mu.Lock()
  54. defer r.mu.Unlock()
  55. if r.f == nil {
  56. f, err := os.Open(r.name)
  57. if f == nil {
  58. return 0, err
  59. }
  60. if runtime.GOOS == "plan9" {
  61. r.f = f
  62. } else {
  63. r.f = bufio.NewReader(hideAgainReader{f})
  64. }
  65. }
  66. return r.f.Read(b)
  67. }
  68. var isEAGAIN func(error) bool // set by eagain.go on unix systems
  69. // hideAgainReader masks EAGAIN reads from /dev/urandom.
  70. // See golang.org/issue/9205
  71. type hideAgainReader struct {
  72. r io.Reader
  73. }
  74. func (hr hideAgainReader) Read(p []byte) (n int, err error) {
  75. n, err = hr.r.Read(p)
  76. if err != nil && isEAGAIN != nil && isEAGAIN(err) {
  77. err = nil
  78. }
  79. return
  80. }
  81. // Alternate pseudo-random implementation for use on
  82. // systems without a reliable /dev/urandom.
  83. // newReader returns a new pseudorandom generator that
  84. // seeds itself by reading from entropy. If entropy == nil,
  85. // the generator seeds itself by reading from the system's
  86. // random number generator, typically /dev/random.
  87. // The Read method on the returned reader always returns
  88. // the full amount asked for, or else it returns an error.
  89. //
  90. // The generator uses the X9.31 algorithm with AES-128,
  91. // reseeding after every 1 MB of generated data.
  92. func newReader(entropy io.Reader) io.Reader {
  93. if entropy == nil {
  94. entropy = &devReader{name: "/dev/random"}
  95. }
  96. return &reader{entropy: entropy}
  97. }
  98. type reader struct {
  99. mu sync.Mutex
  100. budget int // number of bytes that can be generated
  101. cipher cipher.Block
  102. entropy io.Reader
  103. time, seed, dst, key [aes.BlockSize]byte
  104. }
  105. func (r *reader) Read(b []byte) (n int, err error) {
  106. r.mu.Lock()
  107. defer r.mu.Unlock()
  108. n = len(b)
  109. for len(b) > 0 {
  110. if r.budget == 0 {
  111. _, err := io.ReadFull(r.entropy, r.seed[0:])
  112. if err != nil {
  113. return n - len(b), err
  114. }
  115. _, err = io.ReadFull(r.entropy, r.key[0:])
  116. if err != nil {
  117. return n - len(b), err
  118. }
  119. r.cipher, err = aes.NewCipher(r.key[0:])
  120. if err != nil {
  121. return n - len(b), err
  122. }
  123. r.budget = 1 << 20 // reseed after generating 1MB
  124. }
  125. r.budget -= aes.BlockSize
  126. // ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
  127. //
  128. // single block:
  129. // t = encrypt(time)
  130. // dst = encrypt(t^seed)
  131. // seed = encrypt(t^dst)
  132. ns := time.Now().UnixNano()
  133. binary.BigEndian.PutUint64(r.time[:], uint64(ns))
  134. r.cipher.Encrypt(r.time[0:], r.time[0:])
  135. for i := 0; i < aes.BlockSize; i++ {
  136. r.dst[i] = r.time[i] ^ r.seed[i]
  137. }
  138. r.cipher.Encrypt(r.dst[0:], r.dst[0:])
  139. for i := 0; i < aes.BlockSize; i++ {
  140. r.seed[i] = r.time[i] ^ r.dst[i]
  141. }
  142. r.cipher.Encrypt(r.seed[0:], r.seed[0:])
  143. m := copy(b, r.dst[0:])
  144. b = b[m:]
  145. }
  146. return n, nil
  147. }