Commit 7439e557 authored by akwizgran's avatar akwizgran

Let plugins know if we're Alice or Bob.

parent 4452dacc
Pipeline #3452 passed with stage
in 7 minutes and 50 seconds
...@@ -57,5 +57,5 @@ public interface DuplexPlugin extends Plugin { ...@@ -57,5 +57,5 @@ public interface DuplexPlugin extends Plugin {
*/ */
@Nullable @Nullable
RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
ConnectionHandler incoming); boolean alice, ConnectionHandler incoming);
} }
...@@ -399,7 +399,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener { ...@@ -399,7 +399,7 @@ abstract class BluetoothPlugin<SS> implements DuplexPlugin, EventListener {
@Override @Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
ConnectionHandler incoming) { boolean alice, ConnectionHandler incoming) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
...@@ -310,7 +310,7 @@ abstract class TcpPlugin implements DuplexPlugin { ...@@ -310,7 +310,7 @@ abstract class TcpPlugin implements DuplexPlugin {
@Override @Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
ConnectionHandler incoming) { boolean alice, ConnectionHandler incoming) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
...@@ -614,7 +614,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener { ...@@ -614,7 +614,7 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
@Override @Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
ConnectionHandler incoming) { boolean alice, ConnectionHandler incoming) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
...@@ -83,7 +83,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -83,7 +83,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
private final Executor worker; private final Executor worker;
// The following fields are only accessed on the worker // The following fields are only accessed on the worker
private final Map<TransportId, PluginState> pluginStates = new HashMap<>(); private final Map<TransportId, PluginState> pluginStates = new HashMap<>();
private final Map<PendingContactId, SecretKey> rendezvousKeys = private final Map<PendingContactId, CryptoState> cryptoStates =
new HashMap<>(); new HashMap<>();
@Nullable @Nullable
private KeyPair handshakeKeyPair = null; private KeyPair handshakeKeyPair = null;
...@@ -153,12 +153,15 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -153,12 +153,15 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
.deriveStaticMasterKey(p.getPublicKey(), handshakeKeyPair); .deriveStaticMasterKey(p.getPublicKey(), handshakeKeyPair);
SecretKey rendezvousKey = rendezvousCrypto SecretKey rendezvousKey = rendezvousCrypto
.deriveRendezvousKey(staticMasterKey); .deriveRendezvousKey(staticMasterKey);
requireNull(rendezvousKeys.put(p.getId(), rendezvousKey)); boolean alice = transportCrypto
for (PluginState state : pluginStates.values()) { .isAlice(p.getPublicKey(), handshakeKeyPair);
CryptoState cs = new CryptoState(rendezvousKey, alice);
requireNull(cryptoStates.put(p.getId(), cs));
for (PluginState ps : pluginStates.values()) {
RendezvousEndpoint endpoint = RendezvousEndpoint endpoint =
createEndpoint(state.plugin, p.getId(), rendezvousKey); createEndpoint(ps.plugin, p.getId(), cs);
if (endpoint != null) if (endpoint != null)
requireNull(state.endpoints.put(p.getId(), endpoint)); requireNull(ps.endpoints.put(p.getId(), endpoint));
} }
} catch (DbException | GeneralSecurityException e) { } catch (DbException | GeneralSecurityException e) {
logException(LOG, WARNING, e); logException(LOG, WARNING, e);
...@@ -179,9 +182,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -179,9 +182,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
// Worker // Worker
private boolean removePendingContact(PendingContactId p) { private boolean removePendingContact(PendingContactId p) {
// We can come here twice if a pending contact fails and is then removed // We can come here twice if a pending contact fails and is then removed
if (rendezvousKeys.remove(p) == null) return false; if (cryptoStates.remove(p) == null) return false;
for (PluginState state : pluginStates.values()) { for (PluginState ps : pluginStates.values()) {
RendezvousEndpoint endpoint = state.endpoints.remove(p); RendezvousEndpoint endpoint = ps.endpoints.remove(p);
if (endpoint != null) tryToClose(endpoint, LOG, INFO); if (endpoint != null) tryToClose(endpoint, LOG, INFO);
} }
return true; return true;
...@@ -189,33 +192,33 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -189,33 +192,33 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
@Nullable @Nullable
private RendezvousEndpoint createEndpoint(DuplexPlugin plugin, private RendezvousEndpoint createEndpoint(DuplexPlugin plugin,
PendingContactId p, SecretKey rendezvousKey) { PendingContactId p, CryptoState cs) {
TransportId t = plugin.getId(); TransportId t = plugin.getId();
KeyMaterialSource k = KeyMaterialSource k =
rendezvousCrypto.createKeyMaterialSource(rendezvousKey, t); rendezvousCrypto.createKeyMaterialSource(cs.rendezvousKey, t);
Handler h = new Handler(p, t, true); Handler h = new Handler(p, t, true);
return plugin.createRendezvousEndpoint(k, h); return plugin.createRendezvousEndpoint(k, cs.alice, h);
} }
@Scheduler @Scheduler
private void poll() { private void poll() {
worker.execute(() -> { worker.execute(() -> {
for (PluginState state : pluginStates.values()) poll(state); for (PluginState ps : pluginStates.values()) poll(ps);
}); });
} }
// Worker // Worker
private void poll(PluginState state) { private void poll(PluginState ps) {
List<Pair<TransportProperties, ConnectionHandler>> properties = List<Pair<TransportProperties, ConnectionHandler>> properties =
new ArrayList<>(); new ArrayList<>();
for (Entry<PendingContactId, RendezvousEndpoint> e : for (Entry<PendingContactId, RendezvousEndpoint> e :
state.endpoints.entrySet()) { ps.endpoints.entrySet()) {
TransportProperties props = TransportProperties props =
e.getValue().getRemoteTransportProperties(); e.getValue().getRemoteTransportProperties();
Handler h = new Handler(e.getKey(), state.plugin.getId(), false); Handler h = new Handler(e.getKey(), ps.plugin.getId(), false);
properties.add(new Pair<>(props, h)); properties.add(new Pair<>(props, h));
} }
state.plugin.poll(properties); ps.plugin.poll(properties);
} }
@Override @Override
...@@ -249,13 +252,13 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -249,13 +252,13 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
// Worker // Worker
private void poll(PendingContactId p) { private void poll(PendingContactId p) {
for (PluginState state : pluginStates.values()) { for (PluginState ps : pluginStates.values()) {
RendezvousEndpoint endpoint = state.endpoints.get(p); RendezvousEndpoint endpoint = ps.endpoints.get(p);
if (endpoint != null) { if (endpoint != null) {
TransportProperties props = TransportProperties props =
endpoint.getRemoteTransportProperties(); endpoint.getRemoteTransportProperties();
Handler h = new Handler(p, state.plugin.getId(), false); Handler h = new Handler(p, ps.plugin.getId(), false);
state.plugin.poll(singletonList(new Pair<>(props, h))); ps.plugin.poll(singletonList(new Pair<>(props, h)));
} }
} }
} }
...@@ -279,7 +282,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -279,7 +282,7 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
private void addTransport(DuplexPlugin plugin) { private void addTransport(DuplexPlugin plugin) {
TransportId t = plugin.getId(); TransportId t = plugin.getId();
Map<PendingContactId, RendezvousEndpoint> endpoints = new HashMap<>(); Map<PendingContactId, RendezvousEndpoint> endpoints = new HashMap<>();
for (Entry<PendingContactId, SecretKey> e : rendezvousKeys.entrySet()) { for (Entry<PendingContactId, CryptoState> e : cryptoStates.entrySet()) {
RendezvousEndpoint endpoint = RendezvousEndpoint endpoint =
createEndpoint(plugin, e.getKey(), e.getValue()); createEndpoint(plugin, e.getKey(), e.getValue());
if (endpoint != null) endpoints.put(e.getKey(), endpoint); if (endpoint != null) endpoints.put(e.getKey(), endpoint);
...@@ -294,9 +297,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -294,9 +297,9 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
// Worker // Worker
private void removeTransport(TransportId t) { private void removeTransport(TransportId t) {
PluginState state = pluginStates.remove(t); PluginState ps = pluginStates.remove(t);
if (state != null) { if (ps != null) {
for (RendezvousEndpoint endpoint : state.endpoints.values()) { for (RendezvousEndpoint endpoint : ps.endpoints.values()) {
tryToClose(endpoint, LOG, INFO); tryToClose(endpoint, LOG, INFO);
} }
} }
...@@ -314,6 +317,17 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener { ...@@ -314,6 +317,17 @@ class RendezvousPollerImpl implements RendezvousPoller, Service, EventListener {
} }
} }
private static class CryptoState {
private final SecretKey rendezvousKey;
private final boolean alice;
private CryptoState(SecretKey rendezvousKey, boolean alice) {
this.rendezvousKey = rendezvousKey;
this.alice = alice;
}
}
private class Handler implements ConnectionHandler { private class Handler implements ConnectionHandler {
private final PendingContactId pendingContactId; private final PendingContactId pendingContactId;
......
...@@ -30,6 +30,7 @@ import org.jmock.Expectations; ...@@ -30,6 +30,7 @@ import org.jmock.Expectations;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import java.util.Random;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
...@@ -79,6 +80,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -79,6 +80,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
private final TransportId transportId = getTransportId(); private final TransportId transportId = getTransportId();
private final TransportProperties transportProperties = private final TransportProperties transportProperties =
getTransportProperties(3); getTransportProperties(3);
private final boolean alice = new Random().nextBoolean();
private RendezvousPollerImpl rendezvousPoller; private RendezvousPollerImpl rendezvousPoller;
...@@ -122,6 +124,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -122,6 +124,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
will(returnValue(staticMasterKey)); will(returnValue(staticMasterKey));
oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey);
will(returnValue(rendezvousKey)); will(returnValue(rendezvousKey));
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
handshakeKeyPair);
will(returnValue(alice));
}}); }});
rendezvousPoller.startService(); rendezvousPoller.startService();
...@@ -182,11 +187,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -182,11 +187,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
will(returnValue(staticMasterKey)); will(returnValue(staticMasterKey));
oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey);
will(returnValue(rendezvousKey)); will(returnValue(rendezvousKey));
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
handshakeKeyPair);
will(returnValue(alice));
oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey, oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey,
transportId); transportId);
will(returnValue(keyMaterialSource)); will(returnValue(keyMaterialSource));
oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource),
with(any(ConnectionHandler.class))); with(alice), with(any(ConnectionHandler.class)));
will(returnValue(rendezvousEndpoint)); will(returnValue(rendezvousEndpoint));
// Poll newly added pending contact // Poll newly added pending contact
oneOf(rendezvousEndpoint).getRemoteTransportProperties(); oneOf(rendezvousEndpoint).getRemoteTransportProperties();
...@@ -250,11 +258,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -250,11 +258,14 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
will(returnValue(staticMasterKey)); will(returnValue(staticMasterKey));
oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey);
will(returnValue(rendezvousKey)); will(returnValue(rendezvousKey));
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
handshakeKeyPair);
will(returnValue(alice));
oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey, oneOf(rendezvousCrypto).createKeyMaterialSource(rendezvousKey,
transportId); transportId);
will(returnValue(keyMaterialSource)); will(returnValue(keyMaterialSource));
oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource),
with(any(ConnectionHandler.class))); with(alice), with(any(ConnectionHandler.class)));
will(returnValue(rendezvousEndpoint)); will(returnValue(rendezvousEndpoint));
// Poll newly added pending contact // Poll newly added pending contact
oneOf(rendezvousEndpoint).getRemoteTransportProperties(); oneOf(rendezvousEndpoint).getRemoteTransportProperties();
...@@ -305,6 +316,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -305,6 +316,9 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
will(returnValue(staticMasterKey)); will(returnValue(staticMasterKey));
oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey); oneOf(rendezvousCrypto).deriveRendezvousKey(staticMasterKey);
will(returnValue(rendezvousKey)); will(returnValue(rendezvousKey));
oneOf(transportCrypto).isAlice(pendingContact.getPublicKey(),
handshakeKeyPair);
will(returnValue(alice));
}}); }});
rendezvousPoller.eventOccurred( rendezvousPoller.eventOccurred(
...@@ -323,7 +337,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase { ...@@ -323,7 +337,7 @@ public class RendezvousPollerImplTest extends BrambleMockTestCase {
transportId); transportId);
will(returnValue(keyMaterialSource)); will(returnValue(keyMaterialSource));
oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource), oneOf(plugin).createRendezvousEndpoint(with(keyMaterialSource),
with(any(ConnectionHandler.class))); with(alice), with(any(ConnectionHandler.class)));
will(returnValue(rendezvousEndpoint)); will(returnValue(rendezvousEndpoint));
}}); }});
......
...@@ -193,7 +193,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback { ...@@ -193,7 +193,7 @@ class ModemPlugin implements DuplexPlugin, Modem.Callback {
@Override @Override
public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k, public RendezvousEndpoint createRendezvousEndpoint(KeyMaterialSource k,
ConnectionHandler incoming) { boolean alice, ConnectionHandler incoming) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment