Add a deterministic PRNG for runner.

It's useful, when combined with patching crypto/rand/deterministic.c in, for
debugging things. Also if we want to record fuzzer transcripts again, this
probably should be on.

Change-Id: I109cf27ebab64f01a13466f0d960def3257d8750
Reviewed-on: https://boringssl-review.googlesource.com/8192
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/ssl/test/runner/deterministic.go b/ssl/test/runner/deterministic.go
new file mode 100644
index 0000000..4a61ee0
--- /dev/null
+++ b/ssl/test/runner/deterministic.go
@@ -0,0 +1,37 @@
+// Copyright (c) 2016, Google Inc.
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+package runner
+
+import (
+	"encoding/binary"
+)
+
+// Use a different key from crypto/rand/deterministic.c.
+var deterministicRandKey = []byte("runner deterministic key 0123456")
+
+type deterministicRand struct {
+	numCalls uint64
+}
+
+func (d *deterministicRand) Read(buf []byte) (int, error) {
+	for i := range buf {
+		buf[i] = 0
+	}
+	var nonce [12]byte
+	binary.LittleEndian.PutUint64(nonce[:8], d.numCalls)
+	chaCha20(buf, buf, deterministicRandKey, nonce[:], 0)
+	d.numCalls++
+	return len(buf), nil
+}
diff --git a/ssl/test/runner/runner.go b/ssl/test/runner/runner.go
index f70999b..962ac01 100644
--- a/ssl/test/runner/runner.go
+++ b/ssl/test/runner/runner.go
@@ -54,6 +54,7 @@
 	fuzzer          = flag.Bool("fuzzer", false, "If true, tests against a BoringSSL built in fuzzer mode.")
 	transcriptDir   = flag.String("transcript-dir", "", "The directory in which to write transcripts.")
 	idleTimeout     = flag.Duration("idle-timeout", 15*time.Second, "The number of seconds to wait for a read or write to bssl_shim.")
+	deterministic   = flag.Bool("deterministic", false, "If true, uses a deterministic PRNG in the runner.")
 )
 
 const (
@@ -765,6 +766,9 @@
 	if *fuzzer {
 		config.Bugs.NullAllCiphers = true
 	}
+	if *deterministic {
+		config.Rand = &deterministicRand{}
+	}
 
 	conn, err := acceptOrWait(listener, waitChan)
 	if err == nil {
@@ -795,6 +799,7 @@
 			if *fuzzer {
 				resumeConfig.Bugs.NullAllCiphers = true
 			}
+			resumeConfig.Rand = config.Rand
 		} else {
 			resumeConfig = config
 		}