From 501c2dab315688ffe007d7419de33b74904ba34e Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Wed, 9 Nov 2016 15:55:31 +0000
Subject: [PATCH] Preserve the order of descriptors in QR code payloads.

---
 .../api/keyagreement/Payload.java             | 10 ++-
 .../api/keyagreement/TransportDescriptor.java | 28 ++++++++
 .../keyagreement/KeyAgreementConnector.java   | 19 +++--
 .../keyagreement/KeyAgreementProtocol.java    | 70 ++++++++++---------
 .../keyagreement/PayloadEncoderImpl.java      |  9 +--
 .../keyagreement/PayloadParserImpl.java       | 15 ++--
 6 files changed, 88 insertions(+), 63 deletions(-)
 create mode 100644 briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java

diff --git a/briar-api/src/org/briarproject/api/keyagreement/Payload.java b/briar-api/src/org/briarproject/api/keyagreement/Payload.java
index 60cbb45a36..14cb82421f 100644
--- a/briar-api/src/org/briarproject/api/keyagreement/Payload.java
+++ b/briar-api/src/org/briarproject/api/keyagreement/Payload.java
@@ -1,11 +1,9 @@
 package org.briarproject.api.keyagreement;
 
 import org.briarproject.api.Bytes;
-import org.briarproject.api.TransportId;
-import org.briarproject.api.data.BdfList;
 import org.briarproject.api.nullsafety.NotNullByDefault;
 
-import java.util.Map;
+import java.util.List;
 
 import javax.annotation.concurrent.Immutable;
 
@@ -17,9 +15,9 @@ import javax.annotation.concurrent.Immutable;
 public class Payload implements Comparable<Payload> {
 
 	private final Bytes commitment;
-	private final Map<TransportId, BdfList> descriptors;
+	private final List<TransportDescriptor> descriptors;
 
-	public Payload(byte[] commitment, Map<TransportId, BdfList> descriptors) {
+	public Payload(byte[] commitment, List<TransportDescriptor> descriptors) {
 		this.commitment = new Bytes(commitment);
 		this.descriptors = descriptors;
 	}
@@ -34,7 +32,7 @@ public class Payload implements Comparable<Payload> {
 	/**
 	 * Returns the transport descriptors contained in this payload.
 	 */
-	public Map<TransportId, BdfList> getTransportDescriptors() {
+	public List<TransportDescriptor> getTransportDescriptors() {
 		return descriptors;
 	}
 
diff --git a/briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java b/briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java
new file mode 100644
index 0000000000..7b61d74ffd
--- /dev/null
+++ b/briar-api/src/org/briarproject/api/keyagreement/TransportDescriptor.java
@@ -0,0 +1,28 @@
+package org.briarproject.api.keyagreement;
+
+import org.briarproject.api.TransportId;
+import org.briarproject.api.data.BdfList;
+import org.briarproject.api.nullsafety.NotNullByDefault;
+
+import javax.annotation.concurrent.Immutable;
+
+@Immutable
+@NotNullByDefault
+public class TransportDescriptor {
+
+	private final TransportId id;
+	private final BdfList descriptor;
+
+	public TransportDescriptor(TransportId id, BdfList descriptor) {
+		this.id = id;
+		this.descriptor = descriptor;
+	}
+
+	public TransportId getId() {
+		return id;
+	}
+
+	public BdfList getDescriptor() {
+		return descriptor;
+	}
+}
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java b/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java
index 44636b31d6..ee5c0e10dd 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java
+++ b/briar-core/src/org/briarproject/keyagreement/KeyAgreementConnector.java
@@ -7,6 +7,7 @@ import org.briarproject.api.data.BdfList;
 import org.briarproject.api.keyagreement.KeyAgreementConnection;
 import org.briarproject.api.keyagreement.KeyAgreementListener;
 import org.briarproject.api.keyagreement.Payload;
+import org.briarproject.api.keyagreement.TransportDescriptor;
 import org.briarproject.api.plugins.Plugin;
 import org.briarproject.api.plugins.PluginManager;
 import org.briarproject.api.plugins.duplex.DuplexPlugin;
@@ -16,10 +17,7 @@ import org.briarproject.api.system.Clock;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionService;
 import java.util.concurrent.ExecutionException;
@@ -73,13 +71,14 @@ class KeyAgreementConnector {
 		byte[] commitment = crypto.deriveKeyCommitment(
 				localKeyPair.getPublic().getEncoded());
 		// Start all listeners and collect their descriptors
-		Map<TransportId, BdfList> descriptors =
-				new HashMap<TransportId, BdfList>();
+		List<TransportDescriptor> descriptors =
+				new ArrayList<TransportDescriptor>();
 		for (DuplexPlugin plugin : pluginManager.getKeyAgreementPlugins()) {
 			KeyAgreementListener l =
 					plugin.createKeyAgreementListener(commitment);
 			if (l != null) {
-				descriptors.put(plugin.getId(), l.getDescriptor());
+				TransportId id = plugin.getId();
+				descriptors.add(new TransportDescriptor(id, l.getDescriptor()));
 				pending.add(connect.submit(new ReadableTask(l.listen())));
 				listeners.add(l);
 			}
@@ -104,15 +103,13 @@ class KeyAgreementConnector {
 
 		// Start connecting over supported transports
 		LOG.info("Starting outgoing BQP connections");
-		Map<TransportId, BdfList> descriptors =
-				remotePayload.getTransportDescriptors();
-		for (Entry<TransportId, BdfList> e : descriptors.entrySet()) {
-			Plugin p = pluginManager.getPlugin(e.getKey());
+		for (TransportDescriptor d : remotePayload.getTransportDescriptors()) {
+			Plugin p = pluginManager.getPlugin(d.getId());
 			if (p instanceof DuplexPlugin) {
 				DuplexPlugin plugin = (DuplexPlugin) p;
 				pending.add(connect.submit(new ReadableTask(
 						new ConnectorTask(plugin, remotePayload.getCommitment(),
-								e.getValue(), end))));
+								d.getDescriptor(), end))));
 			}
 		}
 
diff --git a/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java b/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java
index c832edd092..f67a85ecd6 100644
--- a/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java
+++ b/briar-core/src/org/briarproject/keyagreement/KeyAgreementProtocol.java
@@ -15,51 +15,53 @@ import java.util.Arrays;
  * <p/>
  * Alice:
  * <ul>
- *     <li>Send A_KEY</li>
- *     <li>Receive B_KEY
- *     <ul>
- *         <li>Check B_KEY matches B_COMMIT</li>
- *     </ul></li>
- *     <li>Calculate s</li>
- *     <li>Send A_CONFIRM</li>
- *     <li>Receive B_CONFIRM
- *     <ul>
- *         <li>Check B_CONFIRM matches expected</li>
- *     </ul></li>
- *     <li>Derive master</li>
+ * <li>Send A_KEY</li>
+ * <li>Receive B_KEY
+ * <ul>
+ * <li>Check B_KEY matches B_COMMIT</li>
+ * </ul></li>
+ * <li>Calculate s</li>
+ * <li>Send A_CONFIRM</li>
+ * <li>Receive B_CONFIRM
+ * <ul>
+ * <li>Check B_CONFIRM matches expected</li>
+ * </ul></li>
+ * <li>Derive master</li>
  * </ul><p/>
  * Bob:
  * <ul>
- *     <li>Receive A_KEY
- *     <ul>
- *         <li>Check A_KEY matches A_COMMIT</li>
- *     </ul></li>
- *     <li>Send B_KEY</li>
- *     <li>Calculate s</li>
- *     <li>Receive A_CONFIRM
- *     <ul>
- *         <li>Check A_CONFIRM matches expected</li>
- *     </ul></li>
- *     <li>Send B_CONFIRM</li>
- *     <li>Derive master</li>
+ * <li>Receive A_KEY
+ * <ul>
+ * <li>Check A_KEY matches A_COMMIT</li>
+ * </ul></li>
+ * <li>Send B_KEY</li>
+ * <li>Calculate s</li>
+ * <li>Receive A_CONFIRM
+ * <ul>
+ * <li>Check A_CONFIRM matches expected</li>
+ * </ul></li>
+ * <li>Send B_CONFIRM</li>
+ * <li>Derive master</li>
  * </ul>
  */
 class KeyAgreementProtocol {
 
 	interface Callbacks {
+
 		void connectionWaiting();
+
 		void initialPacketReceived();
 	}
 
-	private Callbacks callbacks;
-	private CryptoComponent crypto;
-	private PayloadEncoder payloadEncoder;
-	private KeyAgreementTransport transport;
-	private Payload theirPayload, ourPayload;
-	private KeyPair ourKeyPair;
-	private boolean alice;
+	private final Callbacks callbacks;
+	private final CryptoComponent crypto;
+	private final PayloadEncoder payloadEncoder;
+	private final KeyAgreementTransport transport;
+	private final Payload theirPayload, ourPayload;
+	private final KeyPair ourKeyPair;
+	private final boolean alice;
 
-	public KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto,
+	KeyAgreementProtocol(Callbacks callbacks, CryptoComponent crypto,
 			PayloadEncoder payloadEncoder, KeyAgreementTransport transport,
 			Payload theirPayload, Payload ourPayload, KeyPair ourKeyPair,
 			boolean alice) {
@@ -78,9 +80,9 @@ class KeyAgreementProtocol {
 	 *
 	 * @return the negotiated master secret.
 	 * @throws AbortException when the protocol may have been tampered with.
-	 * @throws IOException for all other other connection errors.
+	 * @throws IOException    for all other other connection errors.
 	 */
-	public SecretKey perform() throws AbortException, IOException {
+	SecretKey perform() throws AbortException, IOException {
 		try {
 			byte[] theirPublicKey;
 			if (alice) {
diff --git a/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java b/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java
index 32342993c1..ac1a647d13 100644
--- a/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java
+++ b/briar-core/src/org/briarproject/keyagreement/PayloadEncoderImpl.java
@@ -1,16 +1,14 @@
 package org.briarproject.keyagreement;
 
-import org.briarproject.api.TransportId;
-import org.briarproject.api.data.BdfList;
 import org.briarproject.api.data.BdfWriter;
 import org.briarproject.api.data.BdfWriterFactory;
 import org.briarproject.api.keyagreement.Payload;
 import org.briarproject.api.keyagreement.PayloadEncoder;
+import org.briarproject.api.keyagreement.TransportDescriptor;
 import org.briarproject.api.nullsafety.NotNullByDefault;
 
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
-import java.util.Map;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
@@ -36,9 +34,8 @@ class PayloadEncoderImpl implements PayloadEncoder {
 			w.writeListStart(); // Payload start
 			w.writeLong(PROTOCOL_VERSION);
 			w.writeRaw(p.getCommitment());
-			Map<TransportId, BdfList> descriptors = p.getTransportDescriptors();
-			for (BdfList descriptor : descriptors.values())
-				w.writeList(descriptor);
+			for (TransportDescriptor d : p.getTransportDescriptors())
+				w.writeList(d.getDescriptor());
 			w.writeListEnd(); // Payload end
 		} catch (IOException e) {
 			// Shouldn't happen with ByteArrayOutputStream
diff --git a/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java b/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java
index 105311811b..1f9b656357 100644
--- a/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java
+++ b/briar-core/src/org/briarproject/keyagreement/PayloadParserImpl.java
@@ -7,12 +7,13 @@ import org.briarproject.api.data.BdfReader;
 import org.briarproject.api.data.BdfReaderFactory;
 import org.briarproject.api.keyagreement.Payload;
 import org.briarproject.api.keyagreement.PayloadParser;
+import org.briarproject.api.keyagreement.TransportDescriptor;
 import org.briarproject.api.nullsafety.NotNullByDefault;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
+import java.util.ArrayList;
+import java.util.List;
 
 import javax.annotation.concurrent.Immutable;
 import javax.inject.Inject;
@@ -48,15 +49,17 @@ class PayloadParserImpl implements PayloadParser {
 		byte[] commitment = payload.getRaw(1);
 		if (commitment.length != COMMIT_LENGTH) throw new FormatException();
 		// Remaining elements: transport descriptors
-		Map<TransportId, BdfList> recognised =
-				new HashMap<TransportId, BdfList>();
+		List<TransportDescriptor> recognised =
+				new ArrayList<TransportDescriptor>();
 		for (int i = 2; i < payload.size(); i++) {
 			BdfList descriptor = payload.getList(i);
 			long transportId = descriptor.getLong(0);
 			if (transportId == TRANSPORT_ID_BLUETOOTH) {
-				recognised.put(new TransportId("bt"), descriptor);
+				TransportId id = new TransportId("bt");
+				recognised.add(new TransportDescriptor(id, descriptor));
 			} else if (transportId == TRANSPORT_ID_LAN) {
-				recognised.put(new TransportId("lan"), descriptor);
+				TransportId id = new TransportId("lan");
+				recognised.add(new TransportDescriptor(id, descriptor));
 			}
 		}
 		return new Payload(commitment, recognised);
-- 
GitLab