From 8886d954d79aac5ea44e264c8c15ad8567958b50 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Tue, 14 Jan 2014 19:33:17 +0000
Subject: [PATCH] Reorganised Guice modules. Contribute entropy to pool on
 Linux/Android.

---
 briar-android/res/values/roboguice.xml        |  3 +-
 .../briarproject/android/AndroidModule.java   | 50 +-----------
 .../plugins/AndroidPluginsModule.java         | 61 +++++++++++++++
 .../droidtooth/DroidtoothPluginFactory.java   |  3 +-
 .../plugins/tcp/DroidLanTcpPluginFactory.java |  3 +-
 .../{android => system}/AndroidFileUtils.java |  2 +-
 .../system/AndroidSeedProvider.java           | 23 ++++++
 .../system/AndroidSystemModule.java           |  8 +-
 .../api/{crypto => system}/SeedProvider.java  |  2 +-
 .../crypto/CryptoComponentImpl.java           |  2 +-
 .../org/briarproject/crypto/CryptoModule.java |  5 --
 .../crypto/LinuxSeedProvider.java             | 23 ------
 .../org/briarproject/db/DatabaseModule.java   |  2 +-
 .../plugins/tcp/LanTcpPluginFactory.java      |  2 +-
 .../ReliabilityLayerFactoryImpl.java          |  2 +-
 .../system/LinuxSeedProvider.java             | 69 +++++++++++++++++
 .../org/briarproject}/system/SystemClock.java |  4 +-
 .../org/briarproject}/system/SystemTimer.java |  4 +-
 .../bluetooth/BluetoothPluginFactory.java     |  2 +-
 .../plugins/modem/ModemFactoryImpl.java       |  2 +-
 .../briarproject/system/DesktopOsModule.java  | 13 ----
 .../system/DesktopSystemModule.java           | 27 +++++++
 .../briarproject/system/FileUtilsImpl.java    | 13 ----
 briar-tests/build.xml                         |  1 +
 .../briarproject/ProtocolIntegrationTest.java |  6 +-
 .../org/briarproject/TestSeedProvider.java    |  2 +-
 .../org/briarproject/TestSystemModule.java    | 18 +++++
 .../src/org/briarproject/TestUtils.java       | 29 -------
 .../briarproject/crypto/KeyAgreementTest.java |  2 +-
 .../db/DatabaseCleanerImplTest.java           |  2 +-
 .../db/DatabaseComponentImplTest.java         |  2 +-
 .../org/briarproject/db/H2DatabaseTest.java   |  2 +-
 .../briarproject/messaging/ConstantsTest.java |  5 +-
 .../OutgoingSimplexConnectionTest.java        |  5 +-
 .../SimplexMessagingIntegrationTest.java      |  5 +-
 .../plugins/PluginManagerImplTest.java        |  2 +-
 .../bluetooth/BluetoothClientTest.java        |  2 +-
 .../bluetooth/BluetoothServerTest.java        |  2 +-
 .../plugins/tcp/LanTcpClientTest.java         |  2 +-
 .../plugins/tcp/LanTcpPluginTest.java         |  2 +-
 .../plugins/tcp/LanTcpServerTest.java         |  2 +-
 .../system/LinuxSeedProviderTest.java         | 77 +++++++++++++++++++
 .../IncomingEncryptionLayerTest.java          |  4 +-
 .../OutgoingEncryptionLayerTest.java          |  4 +-
 .../transport/TransportIntegrationTest.java   |  4 +-
 45 files changed, 327 insertions(+), 178 deletions(-)
 create mode 100644 briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
 rename briar-android/src/org/briarproject/{android => system}/AndroidFileUtils.java (93%)
 create mode 100644 briar-android/src/org/briarproject/system/AndroidSeedProvider.java
 rename briar-core/src/org/briarproject/system/SystemModule.java => briar-android/src/org/briarproject/system/AndroidSystemModule.java (51%)
 rename briar-api/src/org/briarproject/api/{crypto => system}/SeedProvider.java (82%)
 delete mode 100644 briar-core/src/org/briarproject/crypto/LinuxSeedProvider.java
 create mode 100644 briar-core/src/org/briarproject/system/LinuxSeedProvider.java
 rename {briar-api/src/org/briarproject/api => briar-core/src/org/briarproject}/system/SystemClock.java (77%)
 rename {briar-api/src/org/briarproject/api => briar-core/src/org/briarproject}/system/SystemTimer.java (88%)
 delete mode 100644 briar-desktop/src/org/briarproject/system/DesktopOsModule.java
 create mode 100644 briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
 delete mode 100644 briar-desktop/src/org/briarproject/system/FileUtilsImpl.java
 create mode 100644 briar-tests/src/org/briarproject/TestSystemModule.java
 create mode 100644 briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java

diff --git a/briar-android/res/values/roboguice.xml b/briar-android/res/values/roboguice.xml
index e1ccbebbe9..0f6ffcd915 100644
--- a/briar-android/res/values/roboguice.xml
+++ b/briar-android/res/values/roboguice.xml
@@ -9,9 +9,10 @@
 		<item>org.briarproject.messaging.MessagingModule</item>
 		<item>org.briarproject.messaging.duplex.DuplexMessagingModule</item>
 		<item>org.briarproject.messaging.simplex.SimplexMessagingModule</item>
+		<item>org.briarproject.plugins.AndroidPluginsModule</item>
 		<item>org.briarproject.plugins.PluginsModule</item>
 		<item>org.briarproject.serial.SerialModule</item>
-		<item>org.briarproject.system.SystemModule</item>
+		<item>org.briarproject.system.AndroidSystemModule</item>
 		<item>org.briarproject.transport.TransportModule</item>
 	</string-array>
 </resources>
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/AndroidModule.java b/briar-android/src/org/briarproject/android/AndroidModule.java
index df6bfb316c..78c7a3a579 100644
--- a/briar-android/src/org/briarproject/android/AndroidModule.java
+++ b/briar-android/src/org/briarproject/android/AndroidModule.java
@@ -4,9 +4,6 @@ import static android.content.Context.MODE_PRIVATE;
 import static java.util.concurrent.TimeUnit.SECONDS;
 
 import java.io.File;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
 import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.ExecutorService;
@@ -19,23 +16,11 @@ import javax.inject.Singleton;
 import org.briarproject.api.android.AndroidExecutor;
 import org.briarproject.api.android.DatabaseUiExecutor;
 import org.briarproject.api.android.ReferenceManager;
-import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.db.DatabaseConfig;
 import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.plugins.PluginExecutor;
-import org.briarproject.api.plugins.duplex.DuplexPluginConfig;
-import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
-import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
-import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
-import org.briarproject.api.system.FileUtils;
 import org.briarproject.api.ui.UiCallback;
-import org.briarproject.plugins.droidtooth.DroidtoothPluginFactory;
-import org.briarproject.plugins.tcp.DroidLanTcpPluginFactory;
-import org.briarproject.plugins.tcp.WanTcpPluginFactory;
-import org.briarproject.plugins.tor.TorPluginFactory;
+
 import android.app.Application;
-import android.content.Context;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
@@ -75,7 +60,6 @@ public class AndroidModule extends AbstractModule {
 		bind(AndroidExecutor.class).to(AndroidExecutorImpl.class);
 		bind(ReferenceManager.class).to(
 				ReferenceManagerImpl.class).in(Singleton.class);
-		bind(FileUtils.class).to(AndroidFileUtils.class);
 		bind(UiCallback.class).toInstance(uiCallback);
 	}
 
@@ -85,38 +69,6 @@ public class AndroidModule extends AbstractModule {
 		return databaseUiExecutor;
 	}
 
-	@Provides
-	SimplexPluginConfig getSimplexPluginConfig() {
-		return new SimplexPluginConfig() {
-			public Collection<SimplexPluginFactory> getFactories() {
-				return Collections.emptyList();
-			}
-		};
-	}
-
-	@Provides
-	DuplexPluginConfig getDuplexPluginConfig(
-			@PluginExecutor Executor pluginExecutor,
-			AndroidExecutor androidExecutor, Context appContext,
-			CryptoComponent crypto, ShutdownManager shutdownManager) {
-		DuplexPluginFactory droidtooth = new DroidtoothPluginFactory(
-				pluginExecutor, androidExecutor, appContext,
-				crypto.getSecureRandom());
-		DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor,
-				appContext, shutdownManager);
-		DuplexPluginFactory lan = new DroidLanTcpPluginFactory(pluginExecutor,
-				appContext);
-		DuplexPluginFactory wan = new WanTcpPluginFactory(pluginExecutor,
-				shutdownManager);
-		final Collection<DuplexPluginFactory> factories =
-				Arrays.asList(droidtooth, tor, lan, wan);
-		return new DuplexPluginConfig() {
-			public Collection<DuplexPluginFactory> getFactories() {
-				return factories;
-			}
-		};
-	}
-
 	@Provides @Singleton
 	DatabaseConfig getDatabaseConfig(final Application app) {
 		final File dir = app.getApplicationContext().getDir("db", MODE_PRIVATE);
diff --git a/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
new file mode 100644
index 0000000000..d778a70901
--- /dev/null
+++ b/briar-android/src/org/briarproject/plugins/AndroidPluginsModule.java
@@ -0,0 +1,61 @@
+package org.briarproject.plugins;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.concurrent.Executor;
+
+import org.briarproject.api.android.AndroidExecutor;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.lifecycle.ShutdownManager;
+import org.briarproject.api.plugins.PluginExecutor;
+import org.briarproject.api.plugins.duplex.DuplexPluginConfig;
+import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
+import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
+import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
+import org.briarproject.plugins.droidtooth.DroidtoothPluginFactory;
+import org.briarproject.plugins.tcp.DroidLanTcpPluginFactory;
+import org.briarproject.plugins.tcp.WanTcpPluginFactory;
+import org.briarproject.plugins.tor.TorPluginFactory;
+
+import android.content.Context;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Provides;
+
+public class AndroidPluginsModule extends AbstractModule {
+
+	protected void configure() {}
+
+	@Provides
+	SimplexPluginConfig getSimplexPluginConfig() {
+		return new SimplexPluginConfig() {
+			public Collection<SimplexPluginFactory> getFactories() {
+				return Collections.emptyList();
+			}
+		};
+	}
+
+	@Provides
+	DuplexPluginConfig getDuplexPluginConfig(
+			@PluginExecutor Executor pluginExecutor,
+			AndroidExecutor androidExecutor, Context appContext,
+			CryptoComponent crypto, ShutdownManager shutdownManager) {
+		DuplexPluginFactory droidtooth = new DroidtoothPluginFactory(
+				pluginExecutor, androidExecutor, appContext,
+				crypto.getSecureRandom());
+		DuplexPluginFactory tor = new TorPluginFactory(pluginExecutor,
+				appContext, shutdownManager);
+		DuplexPluginFactory lan = new DroidLanTcpPluginFactory(pluginExecutor,
+				appContext);
+		DuplexPluginFactory wan = new WanTcpPluginFactory(pluginExecutor,
+				shutdownManager);
+		final Collection<DuplexPluginFactory> factories =
+				Arrays.asList(droidtooth, tor, lan, wan);
+		return new DuplexPluginConfig() {
+			public Collection<DuplexPluginFactory> getFactories() {
+				return factories;
+			}
+		};
+	}
+}
diff --git a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java
index 08a44b8207..4015185fa3 100644
--- a/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java
+++ b/briar-android/src/org/briarproject/plugins/droidtooth/DroidtoothPluginFactory.java
@@ -9,7 +9,8 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
+
 import android.content.Context;
 
 public class DroidtoothPluginFactory implements DuplexPluginFactory {
diff --git a/briar-android/src/org/briarproject/plugins/tcp/DroidLanTcpPluginFactory.java b/briar-android/src/org/briarproject/plugins/tcp/DroidLanTcpPluginFactory.java
index b9d870fc4a..70ce255bcf 100644
--- a/briar-android/src/org/briarproject/plugins/tcp/DroidLanTcpPluginFactory.java
+++ b/briar-android/src/org/briarproject/plugins/tcp/DroidLanTcpPluginFactory.java
@@ -7,7 +7,8 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
+
 import android.content.Context;
 
 public class DroidLanTcpPluginFactory implements DuplexPluginFactory {
diff --git a/briar-android/src/org/briarproject/android/AndroidFileUtils.java b/briar-android/src/org/briarproject/system/AndroidFileUtils.java
similarity index 93%
rename from briar-android/src/org/briarproject/android/AndroidFileUtils.java
rename to briar-android/src/org/briarproject/system/AndroidFileUtils.java
index 6c1f98a8a1..80efdc2a47 100644
--- a/briar-android/src/org/briarproject/android/AndroidFileUtils.java
+++ b/briar-android/src/org/briarproject/system/AndroidFileUtils.java
@@ -1,4 +1,4 @@
-package org.briarproject.android;
+package org.briarproject.system;
 
 import java.io.File;
 import java.io.IOException;
diff --git a/briar-android/src/org/briarproject/system/AndroidSeedProvider.java b/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
new file mode 100644
index 0000000000..3d20ee25fc
--- /dev/null
+++ b/briar-android/src/org/briarproject/system/AndroidSeedProvider.java
@@ -0,0 +1,23 @@
+package org.briarproject.system;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+import android.os.Build;
+
+class AndroidSeedProvider extends LinuxSeedProvider {
+
+	@Override
+	void writeToEntropyPool(DataOutputStream out) throws IOException {
+		out.writeInt(android.os.Process.myPid());
+		out.writeInt(android.os.Process.myTid());
+		out.writeInt(android.os.Process.myUid());
+		String fingerprint = Build.FINGERPRINT;
+		if(fingerprint != null) out.writeUTF(fingerprint);
+		if(Build.VERSION.SDK_INT >= 9) {
+			String serial = Build.SERIAL;
+			if(serial != null) out.writeUTF(serial);
+		}
+		super.writeToEntropyPool(out);
+	}
+}
diff --git a/briar-core/src/org/briarproject/system/SystemModule.java b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
similarity index 51%
rename from briar-core/src/org/briarproject/system/SystemModule.java
rename to briar-android/src/org/briarproject/system/AndroidSystemModule.java
index db0b92cb54..570d4fbbc7 100644
--- a/briar-core/src/org/briarproject/system/SystemModule.java
+++ b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
@@ -1,16 +1,18 @@
 package org.briarproject.system;
 
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
-import org.briarproject.api.system.SystemTimer;
+import org.briarproject.api.system.FileUtils;
+import org.briarproject.api.system.SeedProvider;
 import org.briarproject.api.system.Timer;
 
 import com.google.inject.AbstractModule;
 
-public class SystemModule extends AbstractModule {
+public class AndroidSystemModule extends AbstractModule {
 
 	protected void configure() {
 		bind(Clock.class).to(SystemClock.class);
 		bind(Timer.class).to(SystemTimer.class);
+		bind(SeedProvider.class).to(AndroidSeedProvider.class);
+		bind(FileUtils.class).to(AndroidFileUtils.class);
 	}
 }
diff --git a/briar-api/src/org/briarproject/api/crypto/SeedProvider.java b/briar-api/src/org/briarproject/api/system/SeedProvider.java
similarity index 82%
rename from briar-api/src/org/briarproject/api/crypto/SeedProvider.java
rename to briar-api/src/org/briarproject/api/system/SeedProvider.java
index 56cc9092a2..886fa2df3c 100644
--- a/briar-api/src/org/briarproject/api/crypto/SeedProvider.java
+++ b/briar-api/src/org/briarproject/api/system/SeedProvider.java
@@ -1,4 +1,4 @@
-package org.briarproject.api.crypto;
+package org.briarproject.api.system;
 
 /**
  * Uses a platform-specific source to provide a seed for a pseudo-random
diff --git a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
index e6d7c3cdbf..49e362b67a 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoComponentImpl.java
@@ -30,8 +30,8 @@ import org.briarproject.api.crypto.PrivateKey;
 import org.briarproject.api.crypto.PseudoRandom;
 import org.briarproject.api.crypto.PublicKey;
 import org.briarproject.api.crypto.SecretKey;
-import org.briarproject.api.crypto.SeedProvider;
 import org.briarproject.api.crypto.Signature;
+import org.briarproject.api.system.SeedProvider;
 import org.briarproject.util.ByteUtils;
 import org.spongycastle.crypto.AsymmetricCipherKeyPair;
 import org.spongycastle.crypto.BlockCipher;
diff --git a/briar-core/src/org/briarproject/crypto/CryptoModule.java b/briar-core/src/org/briarproject/crypto/CryptoModule.java
index 9d097e7e82..f0eb56f05d 100644
--- a/briar-core/src/org/briarproject/crypto/CryptoModule.java
+++ b/briar-core/src/org/briarproject/crypto/CryptoModule.java
@@ -14,9 +14,7 @@ import javax.inject.Singleton;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.CryptoExecutor;
 import org.briarproject.api.crypto.PasswordStrengthEstimator;
-import org.briarproject.api.crypto.SeedProvider;
 import org.briarproject.api.lifecycle.LifecycleManager;
-import org.briarproject.util.OsUtils;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
@@ -41,9 +39,6 @@ public class CryptoModule extends AbstractModule {
 	}
 
 	protected void configure() {
-		if(OsUtils.isAndroid() || OsUtils.isLinux()) {
-			bind(SeedProvider.class).to(LinuxSeedProvider.class);
-		}
 		bind(CryptoComponent.class).to(
 				CryptoComponentImpl.class).in(Singleton.class);
 		bind(PasswordStrengthEstimator.class).to(
diff --git a/briar-core/src/org/briarproject/crypto/LinuxSeedProvider.java b/briar-core/src/org/briarproject/crypto/LinuxSeedProvider.java
deleted file mode 100644
index 3db1cd87f5..0000000000
--- a/briar-core/src/org/briarproject/crypto/LinuxSeedProvider.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.briarproject.crypto;
-
-import java.io.DataInputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-import org.briarproject.api.crypto.SeedProvider;
-
-class LinuxSeedProvider implements SeedProvider {
-
-	public byte[] getSeed() {
-		byte[] seed = new byte[SEED_BYTES];
-		try {
-			DataInputStream in =  new DataInputStream(
-					new FileInputStream("/dev/urandom"));
-			in.readFully(seed);
-			in.close();
-		} catch(IOException e) {
-			throw new RuntimeException(e);
-		}
-		return seed;
-	}
-}
diff --git a/briar-core/src/org/briarproject/db/DatabaseModule.java b/briar-core/src/org/briarproject/db/DatabaseModule.java
index 3457fc6962..d8916a591b 100644
--- a/briar-core/src/org/briarproject/db/DatabaseModule.java
+++ b/briar-core/src/org/briarproject/db/DatabaseModule.java
@@ -19,7 +19,7 @@ import org.briarproject.api.lifecycle.LifecycleManager;
 import org.briarproject.api.lifecycle.ShutdownManager;
 import org.briarproject.api.system.Clock;
 import org.briarproject.api.system.FileUtils;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 import com.google.inject.AbstractModule;
 import com.google.inject.Provides;
diff --git a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java
index 502418457e..3ce4e4af56 100644
--- a/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java
+++ b/briar-core/src/org/briarproject/plugins/tcp/LanTcpPluginFactory.java
@@ -7,7 +7,7 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 public class LanTcpPluginFactory implements DuplexPluginFactory {
 
diff --git a/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java b/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
index a71e42672f..0cb3716cbf 100644
--- a/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
+++ b/briar-core/src/org/briarproject/reliability/ReliabilityLayerFactoryImpl.java
@@ -9,7 +9,7 @@ import org.briarproject.api.reliability.ReliabilityLayer;
 import org.briarproject.api.reliability.ReliabilityLayerFactory;
 import org.briarproject.api.reliability.WriteHandler;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 class ReliabilityLayerFactoryImpl implements ReliabilityLayerFactory {
 
diff --git a/briar-core/src/org/briarproject/system/LinuxSeedProvider.java b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
new file mode 100644
index 0000000000..49645a776b
--- /dev/null
+++ b/briar-core/src/org/briarproject/system/LinuxSeedProvider.java
@@ -0,0 +1,69 @@
+package org.briarproject.system;
+
+import static java.util.logging.Level.WARNING;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.Collections;
+import java.util.List;
+import java.util.logging.Logger;
+
+import org.briarproject.api.system.SeedProvider;
+
+class LinuxSeedProvider implements SeedProvider {
+
+	private static final Logger LOG =
+			Logger.getLogger(LinuxSeedProvider.class.getName());
+
+	private final String outputFile, inputFile;
+
+	LinuxSeedProvider() {
+		this("/dev/urandom", "/dev/urandom");
+	}
+
+	LinuxSeedProvider(String outputFile, String inputFile) {
+		this.outputFile = outputFile;
+		this.inputFile = inputFile;
+	}
+
+	public byte[] getSeed() {
+		byte[] seed = new byte[SEED_BYTES];
+		// Contribute whatever slightly unpredictable info we have to the pool
+		try {
+			DataOutputStream out = new DataOutputStream(
+					new FileOutputStream(outputFile));
+			writeToEntropyPool(out);
+			out.flush();
+			out.close();
+		} catch(IOException e) {
+			// On some devices /dev/urandom isn't writable - this isn't fatal
+			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
+		}
+		// Read the seed from the pool
+		try {
+			DataInputStream in =  new DataInputStream(
+					new FileInputStream(inputFile));
+			in.readFully(seed);
+			in.close();
+		} catch(IOException e) {
+			throw new RuntimeException(e);
+		}
+		return seed;
+	}
+
+	void writeToEntropyPool(DataOutputStream out) throws IOException {
+		out.writeLong(System.currentTimeMillis());
+		out.writeLong(System.nanoTime());
+		List<NetworkInterface> ifaces =
+				Collections.list(NetworkInterface.getNetworkInterfaces());
+		for(NetworkInterface i : ifaces) {
+			List<InetAddress> addrs = Collections.list(i.getInetAddresses());
+			for(InetAddress a : addrs) out.write(a.getAddress());
+		}
+	}
+}
diff --git a/briar-api/src/org/briarproject/api/system/SystemClock.java b/briar-core/src/org/briarproject/system/SystemClock.java
similarity index 77%
rename from briar-api/src/org/briarproject/api/system/SystemClock.java
rename to briar-core/src/org/briarproject/system/SystemClock.java
index bf8c148724..3117b0a503 100644
--- a/briar-api/src/org/briarproject/api/system/SystemClock.java
+++ b/briar-core/src/org/briarproject/system/SystemClock.java
@@ -1,4 +1,6 @@
-package org.briarproject.api.system;
+package org.briarproject.system;
+
+import org.briarproject.api.system.Clock;
 
 /** Default clock implementation. */
 public class SystemClock implements Clock {
diff --git a/briar-api/src/org/briarproject/api/system/SystemTimer.java b/briar-core/src/org/briarproject/system/SystemTimer.java
similarity index 88%
rename from briar-api/src/org/briarproject/api/system/SystemTimer.java
rename to briar-core/src/org/briarproject/system/SystemTimer.java
index bbdf596741..d1bd00735c 100644
--- a/briar-api/src/org/briarproject/api/system/SystemTimer.java
+++ b/briar-core/src/org/briarproject/system/SystemTimer.java
@@ -1,7 +1,9 @@
-package org.briarproject.api.system;
+package org.briarproject.system;
 
 import java.util.TimerTask;
 
+import org.briarproject.api.system.Timer;
+
 /** Default timer implementation. */
 public class SystemTimer implements Timer {
 
diff --git a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java
index ad744d766b..8e4963f790 100644
--- a/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java
+++ b/briar-desktop/src/org/briarproject/plugins/bluetooth/BluetoothPluginFactory.java
@@ -8,7 +8,7 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexPluginFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 public class BluetoothPluginFactory implements DuplexPluginFactory {
 
diff --git a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java b/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java
index 2dc8375221..892f8f541f 100644
--- a/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java
+++ b/briar-desktop/src/org/briarproject/plugins/modem/ModemFactoryImpl.java
@@ -4,7 +4,7 @@ import java.util.concurrent.Executor;
 
 import org.briarproject.api.reliability.ReliabilityLayerFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 class ModemFactoryImpl implements ModemFactory {
 
diff --git a/briar-desktop/src/org/briarproject/system/DesktopOsModule.java b/briar-desktop/src/org/briarproject/system/DesktopOsModule.java
deleted file mode 100644
index 7b3c73dc28..0000000000
--- a/briar-desktop/src/org/briarproject/system/DesktopOsModule.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.system;
-
-import org.briarproject.api.system.FileUtils;
-
-import com.google.inject.AbstractModule;
-
-public class DesktopOsModule extends AbstractModule {
-
-	@Override
-	protected void configure() {
-		bind(FileUtils.class).to(FileUtilsImpl.class);
-	}
-}
diff --git a/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
new file mode 100644
index 0000000000..5a3badb9fa
--- /dev/null
+++ b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
@@ -0,0 +1,27 @@
+package org.briarproject.system;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.briarproject.api.system.Clock;
+import org.briarproject.api.system.FileUtils;
+import org.briarproject.api.system.SeedProvider;
+import org.briarproject.api.system.Timer;
+import org.briarproject.util.OsUtils;
+
+import com.google.inject.AbstractModule;
+
+public class DesktopSystemModule extends AbstractModule {
+
+	protected void configure() {
+		bind(Clock.class).to(SystemClock.class);
+		bind(Timer.class).to(SystemTimer.class);
+		if(OsUtils.isLinux())
+			bind(SeedProvider.class).to(LinuxSeedProvider.class);
+		bind(FileUtils.class).toInstance(new FileUtils() {
+			public long getFreeSpace(File f) throws IOException {
+				return f.getFreeSpace();
+			}
+		});
+	}
+}
diff --git a/briar-desktop/src/org/briarproject/system/FileUtilsImpl.java b/briar-desktop/src/org/briarproject/system/FileUtilsImpl.java
deleted file mode 100644
index b22a6034fe..0000000000
--- a/briar-desktop/src/org/briarproject/system/FileUtilsImpl.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.briarproject.system;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.briarproject.api.system.FileUtils;
-
-class FileUtilsImpl implements FileUtils {
-
-	public long getFreeSpace(File f) throws IOException {
-		return f.getFreeSpace();
-	}
-}
diff --git a/briar-tests/build.xml b/briar-tests/build.xml
index 01eca558d3..06a023d918 100644
--- a/briar-tests/build.xml
+++ b/briar-tests/build.xml
@@ -123,6 +123,7 @@
 			<test name='org.briarproject.plugins.tcp.LanTcpPluginTest'/>
 			<test name='org.briarproject.serial.ReaderImplTest'/>
 			<test name='org.briarproject.serial.WriterImplTest'/>
+			<test name='org.briarproject.system.LinuxSeedProviderTest'/>
 			<test name='org.briarproject.transport.ConnectionReaderImplTest'/>
 			<test name='org.briarproject.transport.ConnectionRegistryImplTest'/>
 			<test name='org.briarproject.transport.ConnectionWindowTest'/>
diff --git a/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java b/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java
index 6676679b5b..1fff6b50c0 100644
--- a/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java
+++ b/briar-tests/src/org/briarproject/ProtocolIntegrationTest.java
@@ -48,9 +48,7 @@ import org.briarproject.messaging.duplex.DuplexMessagingModule;
 import org.briarproject.messaging.simplex.SimplexMessagingModule;
 import org.briarproject.reliability.ReliabilityModule;
 import org.briarproject.serial.SerialModule;
-import org.briarproject.system.SystemModule;
 import org.briarproject.transport.TransportModule;
-
 import org.junit.Test;
 
 import com.google.inject.Guice;
@@ -79,8 +77,8 @@ public class ProtocolIntegrationTest extends BriarTestCase {
 
 	public ProtocolIntegrationTest() throws Exception {
 		Injector i = Guice.createInjector(new TestDatabaseModule(),
-				new TestLifecycleModule(), new TestUiModule(),
-				new SystemModule(), new CryptoModule(), new DatabaseModule(),
+				new TestLifecycleModule(), new TestSystemModule(),
+				new TestUiModule(), new CryptoModule(), new DatabaseModule(),
 				new MessagingModule(), new DuplexMessagingModule(),
 				new SimplexMessagingModule(), new ReliabilityModule(),
 				new SerialModule(), new TransportModule());
diff --git a/briar-tests/src/org/briarproject/TestSeedProvider.java b/briar-tests/src/org/briarproject/TestSeedProvider.java
index 6a6ef90d91..aefeeda5c9 100644
--- a/briar-tests/src/org/briarproject/TestSeedProvider.java
+++ b/briar-tests/src/org/briarproject/TestSeedProvider.java
@@ -2,7 +2,7 @@ package org.briarproject;
 
 import java.util.Random;
 
-import org.briarproject.api.crypto.SeedProvider;
+import org.briarproject.api.system.SeedProvider;
 
 public class TestSeedProvider implements SeedProvider {
 
diff --git a/briar-tests/src/org/briarproject/TestSystemModule.java b/briar-tests/src/org/briarproject/TestSystemModule.java
new file mode 100644
index 0000000000..1015deb9ec
--- /dev/null
+++ b/briar-tests/src/org/briarproject/TestSystemModule.java
@@ -0,0 +1,18 @@
+package org.briarproject;
+
+import org.briarproject.api.system.Clock;
+import org.briarproject.api.system.SeedProvider;
+import org.briarproject.api.system.Timer;
+import org.briarproject.system.SystemClock;
+import org.briarproject.system.SystemTimer;
+
+import com.google.inject.AbstractModule;
+
+public class TestSystemModule extends AbstractModule {
+
+	protected void configure() {
+		bind(Clock.class).to(SystemClock.class);
+		bind(Timer.class).to(SystemTimer.class);
+		bind(SeedProvider.class).to(TestSeedProvider.class);
+	}
+}
diff --git a/briar-tests/src/org/briarproject/TestUtils.java b/briar-tests/src/org/briarproject/TestUtils.java
index de09fc35b5..4c39dec2a2 100644
--- a/briar-tests/src/org/briarproject/TestUtils.java
+++ b/briar-tests/src/org/briarproject/TestUtils.java
@@ -1,15 +1,12 @@
 package org.briarproject;
 
-
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.io.PrintStream;
 import java.util.Random;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import junit.framework.TestCase;
 import org.briarproject.api.UniqueId;
 
 public class TestUtils {
@@ -42,38 +39,12 @@ public class TestUtils {
 		testDir.getParentFile().delete(); // Delete if empty
 	}
 
-	public static File getBuildDirectory() {
-		File build = new File("build"); // Ant
-		if(build.exists() && build.isDirectory()) return build;
-		File bin = new File("bin"); // Eclipse
-		if(bin.exists() && bin.isDirectory()) return bin;
-		throw new RuntimeException("Could not find build directory");
-	}
-
-	public static File getFontDirectory() {
-		File f = new File("i18n");
-		if(f.exists() && f.isDirectory()) return f;
-		f = new File("../i18n");
-		if(f.exists() && f.isDirectory()) return f;
-		throw new RuntimeException("Could not find font directory");
-	}
-
 	public static byte[] getRandomId() {
 		byte[] b = new byte[UniqueId.LENGTH];
 		random.nextBytes(b);
 		return b;
 	}
 
-	public static void readFully(InputStream in, byte[] b) throws IOException {
-		int offset = 0;
-		while(offset < b.length) {
-			int read = in.read(b, offset, b.length - offset);
-			if(read == -1) break;
-			offset += read;
-		}
-		TestCase.assertEquals(b.length, offset);
-	}
-
 	public static String createRandomString(int length) throws Exception {
 		StringBuilder s = new StringBuilder(length);
 		for(int i = 0; i < length; i++)
diff --git a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java b/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java
index 1193e60d95..ae8860b687 100644
--- a/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java
+++ b/briar-tests/src/org/briarproject/crypto/KeyAgreementTest.java
@@ -6,7 +6,7 @@ import org.briarproject.BriarTestCase;
 import org.briarproject.TestSeedProvider;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.KeyPair;
-import org.briarproject.api.crypto.SeedProvider;
+import org.briarproject.api.system.SeedProvider;
 import org.junit.Test;
 
 public class KeyAgreementTest extends BriarTestCase {
diff --git a/briar-tests/src/org/briarproject/db/DatabaseCleanerImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseCleanerImplTest.java
index 2442aed79f..28b35b54bc 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseCleanerImplTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseCleanerImplTest.java
@@ -6,9 +6,9 @@ import java.util.concurrent.CountDownLatch;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.api.db.DbException;
-import org.briarproject.api.system.SystemTimer;
 import org.briarproject.api.system.Timer;
 import org.briarproject.db.DatabaseCleaner.Callback;
+import org.briarproject.system.SystemTimer;
 
 import org.junit.Test;
 
diff --git a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
index 7f68c99e7f..d531116c51 100644
--- a/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
+++ b/briar-tests/src/org/briarproject/db/DatabaseComponentImplTest.java
@@ -8,8 +8,8 @@ import java.util.Collections;
 import org.briarproject.api.db.DatabaseComponent;
 import org.briarproject.api.db.DbException;
 import org.briarproject.api.lifecycle.ShutdownManager;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.db.DatabaseCleaner.Callback;
+import org.briarproject.system.SystemClock;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
index dc93ac9889..77ee034057 100644
--- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
+++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
@@ -38,9 +38,9 @@ import org.briarproject.api.messaging.GroupId;
 import org.briarproject.api.messaging.GroupStatus;
 import org.briarproject.api.messaging.Message;
 import org.briarproject.api.messaging.MessageId;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.api.transport.Endpoint;
 import org.briarproject.api.transport.TemporarySecret;
+import org.briarproject.system.SystemClock;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/briar-tests/src/org/briarproject/messaging/ConstantsTest.java b/briar-tests/src/org/briarproject/messaging/ConstantsTest.java
index 2f457f690c..52c40b056a 100644
--- a/briar-tests/src/org/briarproject/messaging/ConstantsTest.java
+++ b/briar-tests/src/org/briarproject/messaging/ConstantsTest.java
@@ -19,6 +19,7 @@ import java.util.Random;
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestDatabaseModule;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.Author;
 import org.briarproject.api.AuthorFactory;
@@ -45,9 +46,7 @@ import org.briarproject.db.DatabaseModule;
 import org.briarproject.messaging.duplex.DuplexMessagingModule;
 import org.briarproject.messaging.simplex.SimplexMessagingModule;
 import org.briarproject.serial.SerialModule;
-import org.briarproject.system.SystemModule;
 import org.briarproject.transport.TransportModule;
-
 import org.junit.Test;
 
 import com.google.inject.Guice;
@@ -63,7 +62,7 @@ public class ConstantsTest extends BriarTestCase {
 
 	public ConstantsTest() throws Exception {
 		Injector i = Guice.createInjector(new TestDatabaseModule(),
-				new TestLifecycleModule(), new SystemModule(),
+				new TestLifecycleModule(), new TestSystemModule(),
 				new CryptoModule(), new DatabaseModule(), new MessagingModule(),
 				new DuplexMessagingModule(), new SimplexMessagingModule(),
 				new SerialModule(), new TransportModule());
diff --git a/briar-tests/src/org/briarproject/messaging/simplex/OutgoingSimplexConnectionTest.java b/briar-tests/src/org/briarproject/messaging/simplex/OutgoingSimplexConnectionTest.java
index f3b9d6c012..c01501c927 100644
--- a/briar-tests/src/org/briarproject/messaging/simplex/OutgoingSimplexConnectionTest.java
+++ b/briar-tests/src/org/briarproject/messaging/simplex/OutgoingSimplexConnectionTest.java
@@ -14,6 +14,7 @@ import java.util.concurrent.Executors;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
@@ -30,9 +31,7 @@ import org.briarproject.crypto.CryptoModule;
 import org.briarproject.messaging.MessagingModule;
 import org.briarproject.messaging.duplex.DuplexMessagingModule;
 import org.briarproject.serial.SerialModule;
-import org.briarproject.system.SystemModule;
 import org.briarproject.transport.TransportModule;
-
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
@@ -68,7 +67,7 @@ public class OutgoingSimplexConnectionTest extends BriarTestCase {
 			}
 		};
 		Injector i = Guice.createInjector(testModule,
-				new TestLifecycleModule(), new SystemModule(),
+				new TestLifecycleModule(), new TestSystemModule(),
 				new CryptoModule(), new MessagingModule(),
 				new DuplexMessagingModule(), new SimplexMessagingModule(),
 				new SerialModule(), new TransportModule());
diff --git a/briar-tests/src/org/briarproject/messaging/simplex/SimplexMessagingIntegrationTest.java b/briar-tests/src/org/briarproject/messaging/simplex/SimplexMessagingIntegrationTest.java
index 1c522d458d..9fa7f371b3 100644
--- a/briar-tests/src/org/briarproject/messaging/simplex/SimplexMessagingIntegrationTest.java
+++ b/briar-tests/src/org/briarproject/messaging/simplex/SimplexMessagingIntegrationTest.java
@@ -12,6 +12,7 @@ import java.util.Random;
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestDatabaseModule;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.Author;
 import org.briarproject.api.AuthorId;
@@ -42,9 +43,7 @@ import org.briarproject.messaging.MessagingModule;
 import org.briarproject.messaging.duplex.DuplexMessagingModule;
 import org.briarproject.plugins.ImmediateExecutor;
 import org.briarproject.serial.SerialModule;
-import org.briarproject.system.SystemModule;
 import org.briarproject.transport.TransportModule;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -87,7 +86,7 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase {
 
 	private Injector createInjector(File dir) {
 		return Guice.createInjector(new TestDatabaseModule(dir),
-				new TestLifecycleModule(), new SystemModule(),
+				new TestLifecycleModule(), new TestSystemModule(),
 				new CryptoModule(), new DatabaseModule(), new MessagingModule(),
 				new DuplexMessagingModule(), new SimplexMessagingModule(), 
 				new SerialModule(), new TransportModule());
diff --git a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
index 78ddfb5e84..3d832c4728 100644
--- a/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
+++ b/briar-tests/src/org/briarproject/plugins/PluginManagerImplTest.java
@@ -17,9 +17,9 @@ import org.briarproject.api.plugins.simplex.SimplexPluginCallback;
 import org.briarproject.api.plugins.simplex.SimplexPluginConfig;
 import org.briarproject.api.plugins.simplex.SimplexPluginFactory;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.api.transport.ConnectionDispatcher;
 import org.briarproject.api.ui.UiCallback;
+import org.briarproject.system.SystemClock;
 import org.jmock.Expectations;
 import org.jmock.Mockery;
 import org.junit.Test;
diff --git a/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothClientTest.java b/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothClientTest.java
index 28eef667e1..3b86da8a1b 100644
--- a/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothClientTest.java
+++ b/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothClientTest.java
@@ -10,8 +10,8 @@ import java.util.concurrent.Executors;
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportConfig;
 import org.briarproject.api.TransportProperties;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.plugins.DuplexClientTest;
+import org.briarproject.system.SystemClock;
 
 // This is not a JUnit test - it has to be run manually while the server test
 // is running on another machine
diff --git a/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothServerTest.java b/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothServerTest.java
index 99b77e3f24..1dfbf841dc 100644
--- a/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothServerTest.java
+++ b/briar-tests/src/org/briarproject/plugins/bluetooth/BluetoothServerTest.java
@@ -8,8 +8,8 @@ import java.util.concurrent.Executors;
 
 import org.briarproject.api.TransportConfig;
 import org.briarproject.api.TransportProperties;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.plugins.DuplexServerTest;
+import org.briarproject.system.SystemClock;
 
 // This is not a JUnit test - it has to be run manually while the client test
 // is running on another machine
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpClientTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpClientTest.java
index 1c7c7b83a7..9e9fb77d59 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpClientTest.java
+++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpClientTest.java
@@ -10,8 +10,8 @@ import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportConfig;
 import org.briarproject.api.TransportProperties;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.plugins.DuplexClientTest;
+import org.briarproject.system.SystemClock;
 
 // This is not a JUnit test - it has to be run manually while the server test
 // is running on another machine
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
index 38ba8b6a4e..832107d521 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
+++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpPluginTest.java
@@ -21,7 +21,7 @@ import org.briarproject.api.plugins.duplex.DuplexPlugin;
 import org.briarproject.api.plugins.duplex.DuplexPluginCallback;
 import org.briarproject.api.plugins.duplex.DuplexTransportConnection;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
+import org.briarproject.system.SystemClock;
 
 import org.junit.Test;
 
diff --git a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpServerTest.java b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpServerTest.java
index d53f77b488..3506de7f71 100644
--- a/briar-tests/src/org/briarproject/plugins/tcp/LanTcpServerTest.java
+++ b/briar-tests/src/org/briarproject/plugins/tcp/LanTcpServerTest.java
@@ -8,8 +8,8 @@ import java.util.concurrent.Executors;
 import org.briarproject.api.TransportConfig;
 import org.briarproject.api.TransportProperties;
 import org.briarproject.api.system.Clock;
-import org.briarproject.api.system.SystemClock;
 import org.briarproject.plugins.DuplexServerTest;
+import org.briarproject.system.SystemClock;
 
 // This is not a JUnit test - it has to be run manually while the client test
 // is running on another machine
diff --git a/briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java b/briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java
new file mode 100644
index 0000000000..e7ddccf352
--- /dev/null
+++ b/briar-tests/src/org/briarproject/system/LinuxSeedProviderTest.java
@@ -0,0 +1,77 @@
+package org.briarproject.system;
+
+import static org.briarproject.api.system.SeedProvider.SEED_BYTES;
+import static org.junit.Assert.assertArrayEquals;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.util.HashSet;
+import java.util.Random;
+import java.util.Set;
+
+import org.briarproject.BriarTestCase;
+import org.briarproject.TestUtils;
+import org.briarproject.api.Bytes;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LinuxSeedProviderTest extends BriarTestCase {
+
+	private final File testDir = TestUtils.getTestDirectory();
+
+	@Before
+	public void setUp() {
+		testDir.mkdirs();
+	}
+
+	@Test
+	public void testSeedAppearsSane() {
+		Set<Bytes> seeds = new HashSet<Bytes>();
+		LinuxSeedProvider p = new LinuxSeedProvider();
+		for(int i = 0; i < 1000; i++) {
+			byte[] seed = p.getSeed();
+			assertEquals(SEED_BYTES, seed.length);
+			assertTrue(seeds.add(new Bytes(seed)));
+		}
+	}
+
+	@Test
+	public void testEntropyIsWrittenToPool() throws Exception {
+		// Redirect the provider's entropy to a file
+		File urandom = new File(testDir, "urandom");
+		urandom.delete();
+		assertTrue(urandom.createNewFile());
+		assertEquals(0, urandom.length());
+		String path = urandom.getAbsolutePath();
+		LinuxSeedProvider p = new LinuxSeedProvider(path, "/dev/urandom");
+		p.getSeed();
+		// There should be 16 bytes from the clock, plus network interfaces
+		assertTrue(urandom.length() > 20);
+	}
+
+	@Test
+	public void testSeedIsReadFromPool() throws Exception {
+		// Generate a seed
+		byte[] seed = new byte[SEED_BYTES];
+		new Random().nextBytes(seed);
+		// Write the seed to a file
+		File urandom = new File(testDir, "urandom");
+		urandom.delete();
+		FileOutputStream out = new FileOutputStream(urandom);
+		out.write(seed);
+		out.flush();
+		out.close();
+		assertTrue(urandom.exists());
+		assertEquals(SEED_BYTES, urandom.length());
+		// Check that the provider reads the seed from the file
+		String path = urandom.getAbsolutePath();
+		LinuxSeedProvider p = new LinuxSeedProvider("/dev/urandom", path);
+		assertArrayEquals(seed, p.getSeed());
+	}
+
+	@After
+	public void tearDown() {
+		TestUtils.deleteTestDirectory(testDir);
+	}
+}
diff --git a/briar-tests/src/org/briarproject/transport/IncomingEncryptionLayerTest.java b/briar-tests/src/org/briarproject/transport/IncomingEncryptionLayerTest.java
index 631c33faca..cc1a38e1c0 100644
--- a/briar-tests/src/org/briarproject/transport/IncomingEncryptionLayerTest.java
+++ b/briar-tests/src/org/briarproject/transport/IncomingEncryptionLayerTest.java
@@ -10,12 +10,12 @@ import java.io.ByteArrayInputStream;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.api.FormatException;
 import org.briarproject.api.crypto.AuthenticatedCipher;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.SecretKey;
 import org.briarproject.crypto.CryptoModule;
-
 import org.junit.Test;
 
 import com.google.inject.Guice;
@@ -35,7 +35,7 @@ public class IncomingEncryptionLayerTest extends BriarTestCase {
 
 	public IncomingEncryptionLayerTest() {
 		Injector i = Guice.createInjector(new CryptoModule(),
-				new TestLifecycleModule());
+				new TestLifecycleModule(), new TestSystemModule());
 		crypto = i.getInstance(CryptoComponent.class);
 		frameCipher = crypto.getFrameCipher();
 		frameKey = crypto.generateSecretKey();
diff --git a/briar-tests/src/org/briarproject/transport/OutgoingEncryptionLayerTest.java b/briar-tests/src/org/briarproject/transport/OutgoingEncryptionLayerTest.java
index bf9a12c1b3..8a35ce732c 100644
--- a/briar-tests/src/org/briarproject/transport/OutgoingEncryptionLayerTest.java
+++ b/briar-tests/src/org/briarproject/transport/OutgoingEncryptionLayerTest.java
@@ -11,11 +11,11 @@ import java.io.ByteArrayOutputStream;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.api.crypto.AuthenticatedCipher;
 import org.briarproject.api.crypto.CryptoComponent;
 import org.briarproject.api.crypto.SecretKey;
 import org.briarproject.crypto.CryptoModule;
-
 import org.junit.Test;
 
 import com.google.inject.Guice;
@@ -35,7 +35,7 @@ public class OutgoingEncryptionLayerTest extends BriarTestCase {
 
 	public OutgoingEncryptionLayerTest() {
 		Injector i = Guice.createInjector(new CryptoModule(),
-				new TestLifecycleModule());
+				new TestLifecycleModule(), new TestSystemModule());
 		crypto = i.getInstance(CryptoComponent.class);
 		frameCipher = crypto.getFrameCipher();
 		tag = new byte[TAG_LENGTH];
diff --git a/briar-tests/src/org/briarproject/transport/TransportIntegrationTest.java b/briar-tests/src/org/briarproject/transport/TransportIntegrationTest.java
index 99f4ff4529..857bfdb6ed 100644
--- a/briar-tests/src/org/briarproject/transport/TransportIntegrationTest.java
+++ b/briar-tests/src/org/briarproject/transport/TransportIntegrationTest.java
@@ -13,6 +13,7 @@ import java.util.Random;
 
 import org.briarproject.BriarTestCase;
 import org.briarproject.TestLifecycleModule;
+import org.briarproject.TestSystemModule;
 import org.briarproject.TestUtils;
 import org.briarproject.api.ContactId;
 import org.briarproject.api.TransportId;
@@ -23,7 +24,6 @@ import org.briarproject.api.transport.ConnectionContext;
 import org.briarproject.api.transport.ConnectionWriter;
 import org.briarproject.api.transport.ConnectionWriterFactory;
 import org.briarproject.crypto.CryptoModule;
-
 import org.junit.Test;
 
 import com.google.inject.AbstractModule;
@@ -52,7 +52,7 @@ public class TransportIntegrationTest extends BriarTestCase {
 			}
 		};
 		Injector i = Guice.createInjector(testModule, new CryptoModule(),
-				new TestLifecycleModule());
+				new TestLifecycleModule(), new TestSystemModule());
 		crypto = i.getInstance(CryptoComponent.class);
 		connectionWriterFactory = i.getInstance(ConnectionWriterFactory.class);
 		contactId = new ContactId(234);
-- 
GitLab