Source file src/crypto/internal/sysrand/rand_plan9.go

     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  
     5  package sysrand
     6  
     7  import (
     8  	"internal/byteorder"
     9  	"internal/chacha8rand"
    10  	"io"
    11  	"os"
    12  	"sync"
    13  )
    14  
    15  const randomDevice = "/dev/random"
    16  
    17  // This is a pseudorandom generator that seeds itself by reading from
    18  // /dev/random. The read function always returns the full amount asked for, or
    19  // else it returns an error.
    20  
    21  var (
    22  	mu      sync.Mutex
    23  	seeded  sync.Once
    24  	seedErr error
    25  	state   chacha8rand.State
    26  )
    27  
    28  func read(b []byte) error {
    29  	seeded.Do(func() {
    30  		entropy, err := os.Open(randomDevice)
    31  		if err != nil {
    32  			seedErr = err
    33  			return
    34  		}
    35  		defer entropy.Close()
    36  		var seed [32]byte
    37  		_, err = io.ReadFull(entropy, seed[:])
    38  		if err != nil {
    39  			seedErr = err
    40  			return
    41  		}
    42  		state.Init(seed)
    43  	})
    44  	if seedErr != nil {
    45  		return seedErr
    46  	}
    47  
    48  	mu.Lock()
    49  	defer mu.Unlock()
    50  
    51  	for len(b) >= 8 {
    52  		if x, ok := state.Next(); ok {
    53  			byteorder.BEPutUint64(b, x)
    54  			b = b[8:]
    55  		} else {
    56  			state.Refill()
    57  		}
    58  	}
    59  	for len(b) > 0 {
    60  		if x, ok := state.Next(); ok {
    61  			var buf [8]byte
    62  			byteorder.BEPutUint64(buf[:], x)
    63  			n := copy(b, buf[:])
    64  			b = b[n:]
    65  		} else {
    66  			state.Refill()
    67  		}
    68  	}
    69  	state.Reseed()
    70  
    71  	return nil
    72  }
    73  

View as plain text