Hack SshDaemon to not use SecureRandom during tests

We previously needed 8 bytes of data from a SecureRandom in order to
start an SSH daemon. Unfortunately, sometimes machines run out of
entropy, for example when running the Gerrit test suite several times
in a row.

Add an undocumented configuration option to use a different Random
factory for Apache SSHD that uses a hard-coded seed instead of
depending on SecureRandom. Unfortunately, because SshDaemon is
constructed using Daemon's injector stack, we can't easily modify its
modules to swap out the provider, so a configuration option is the
easiest solution.

Change-Id: I539b8e3d39d2da9908962fdb8d9633adf935fb4c
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
index 3e8f0b2..644a4bb 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/GerritServer.java
@@ -131,6 +131,7 @@
     cfg.setString("gerrit", null, "canonicalWebUrl", url);
     cfg.setString("httpd", null, "listenUrl", url);
     cfg.setString("sshd", null, "listenAddress", forceEphemeralPort);
+    cfg.setBoolean("sshd", null, "testUseInsecureRandom", true);
     cfg.setString("cache", null, "directory", null);
     cfg.setString("gerrit", null, "basePath", "git");
     cfg.setBoolean("sendemail", null, "enable", false);
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
index 3306592..cdaf20e 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
@@ -45,6 +45,7 @@
 import org.apache.sshd.common.KeyExchange;
 import org.apache.sshd.common.KeyPairProvider;
 import org.apache.sshd.common.NamedFactory;
+import org.apache.sshd.common.Random;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.Signature;
 import org.apache.sshd.common.SshdSocketAddress;
@@ -94,6 +95,8 @@
 import org.apache.sshd.server.kex.DHG1;
 import org.apache.sshd.server.kex.DHG14;
 import org.apache.sshd.server.session.SessionFactory;
+import org.bouncycastle.crypto.prng.RandomGenerator;
+import org.bouncycastle.crypto.prng.VMPCRandomGenerator;
 import org.eclipse.jgit.lib.Config;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -197,7 +200,7 @@
         MinaServiceFactory.class.getName());
 
     if (SecurityUtils.isBouncyCastleRegistered()) {
-      initProviderBouncyCastle();
+      initProviderBouncyCastle(cfg);
     } else {
       initProviderJce();
     }
@@ -366,11 +369,42 @@
     return r.toString();
   }
 
-  private void initProviderBouncyCastle() {
+  private void initProviderBouncyCastle(Config cfg) {
     setKeyExchangeFactories(Arrays.<NamedFactory<KeyExchange>> asList(
         new DHG14.Factory(), new DHG1.Factory()));
-    setRandomFactory(new SingletonRandomFactory(
-        new BouncyCastleRandom.Factory()));
+    NamedFactory<Random> factory;
+    if (cfg.getBoolean("sshd", null, "testUseInsecureRandom", false)) {
+      factory = new InsecureBouncyCastleRandom.Factory();
+    } else {
+      factory = new BouncyCastleRandom.Factory();
+    }
+    setRandomFactory(new SingletonRandomFactory(factory));
+  }
+
+  private static class InsecureBouncyCastleRandom implements Random {
+    private static class Factory implements NamedFactory<Random> {
+      @Override
+      public String getName() {
+        return "INSECURE_bouncycastle";
+      }
+
+      @Override
+      public Random create() {
+        return new InsecureBouncyCastleRandom();
+      }
+    }
+
+    private final RandomGenerator random;
+
+    private InsecureBouncyCastleRandom() {
+      random = new VMPCRandomGenerator();
+      random.addSeedMaterial(1234);
+    }
+
+    @Override
+    public void fill(byte[] bytes, int start, int len) {
+      random.nextBytes(bytes, start, len);
+    }
   }
 
   private void initProviderJce() {