From 5ff7adcebfd2cd6124a22a179763219a7f235264 Mon Sep 17 00:00:00 2001
From: str4d <str4d@mail.i2p>
Date: Wed, 16 Mar 2016 08:35:23 +0000
Subject: [PATCH] Test BQP implementation

---
 briar-tests/build.gradle                      |   4 +
 .../KeyAgreementProtocolTest.java             | 394 ++++++++++++++++++
 2 files changed, 398 insertions(+)
 create mode 100644 briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java

diff --git a/briar-tests/build.gradle b/briar-tests/build.gradle
index c5ae112372..b3c2af66e1 100644
--- a/briar-tests/build.gradle
+++ b/briar-tests/build.gradle
@@ -15,6 +15,8 @@ dependencies {
 	compile project(':briar-desktop')
 	compile "junit:junit:4.12"
 	compile "org.jmock:jmock:2.8.1"
+	compile "org.jmock:jmock-junit4:2.8.1"
+	compile "org.jmock:jmock-legacy:2.8.1"
 	compile "org.hamcrest:hamcrest-library:1.3"
 	compile "org.hamcrest:hamcrest-core:1.3"
 }
@@ -23,6 +25,8 @@ dependencyVerification {
 	verify = [
 			'junit:junit:59721f0805e223d84b90677887d9ff567dc534d7c502ca903c0c2b17f05c116a',
 			'org.jmock:jmock:75d4bdaf636879f0215830c5e6ab99407069a625eaffde5d57b32d887b75dc14',
+			'org.jmock:jmock-junit4:81e3fff46ed56738a6f3f5147525d1d85cda591ce5df007cc193e735cee31113',
+			'org.jmock:jmock-legacy:19c76059eb254775ba884fc8039bc5c7d1700dc68cc55ad3be5b405a2a8a1819',
 			'org.hamcrest:hamcrest-library:711d64522f9ec410983bd310934296da134be4254a125080a0416ec178dfad1c',
 			'org.hamcrest:hamcrest-core:66fdef91e9739348df7a096aa384a5685f4e875584cce89386a7a47251c4d8e9',
 	]
diff --git a/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java b/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java
new file mode 100644
index 0000000000..e404c547f4
--- /dev/null
+++ b/briar-tests/src/org/briarproject/keyagreement/KeyAgreementProtocolTest.java
@@ -0,0 +1,394 @@
+package org.briarproject.keyagreement;
+
+import org.briarproject.BriarTestCase;
+import org.briarproject.TestUtils;
+import org.briarproject.api.crypto.CryptoComponent;
+import org.briarproject.api.crypto.KeyPair;
+import org.briarproject.api.crypto.PublicKey;
+import org.briarproject.api.crypto.SecretKey;
+import org.briarproject.api.keyagreement.Payload;
+import org.briarproject.api.keyagreement.PayloadEncoder;
+import org.briarproject.util.StringUtils;
+import org.jmock.Expectations;
+import org.jmock.auto.Mock;
+import org.jmock.integration.junit4.JUnitRuleMockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.briarproject.api.keyagreement.KeyAgreementConstants.COMMIT_LENGTH;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class KeyAgreementProtocolTest extends BriarTestCase {
+
+	@Rule
+	public JUnitRuleMockery context = new JUnitRuleMockery() {{
+		// So we can mock concrete classes like KeyAgreementTransport
+		setImposteriser(ClassImposteriser.INSTANCE);
+	}};
+
+	private static final byte[] ALICE_PUBKEY = TestUtils.getRandomBytes(32);
+	private static final byte[] ALICE_COMMIT =
+			TestUtils.getRandomBytes(COMMIT_LENGTH);
+	private static final byte[] ALICE_PAYLOAD =
+			TestUtils.getRandomBytes(COMMIT_LENGTH + 8);
+
+	private static final byte[] BOB_PUBKEY = TestUtils.getRandomBytes(32);
+	private static final byte[] BOB_COMMIT =
+			TestUtils.getRandomBytes(COMMIT_LENGTH);
+	private static final byte[] BOB_PAYLOAD =
+			TestUtils.getRandomBytes(COMMIT_LENGTH + 19);
+
+	private static final byte[] ALICE_CONFIRM =
+			TestUtils.getRandomBytes(SecretKey.LENGTH);
+	private static final byte[] BOB_CONFIRM =
+			TestUtils.getRandomBytes(SecretKey.LENGTH);
+
+	private static final byte[] BAD_PUBKEY = TestUtils.getRandomBytes(32);
+	private static final byte[] BAD_COMMIT =
+			TestUtils.getRandomBytes(COMMIT_LENGTH);
+	private static final byte[] BAD_CONFIRM =
+			TestUtils.getRandomBytes(SecretKey.LENGTH);
+
+	@Mock
+	KeyAgreementProtocol.Callbacks callbacks;
+	@Mock
+	CryptoComponent crypto;
+	@Mock
+	PayloadEncoder payloadEncoder;
+	@Mock
+	KeyAgreementTransport transport;
+	@Mock
+	PublicKey ourPubKey;
+
+	@Test
+	public void testAliceProtocol() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(BOB_COMMIT, null);
+		final Payload ourPayload = new Payload(ALICE_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+		final SecretKey sharedSecret = TestUtils.createSecretKey();
+		final SecretKey masterSecret = TestUtils.createSecretKey();
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, true);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(payloadEncoder).encode(ourPayload);
+			will(returnValue(ALICE_PAYLOAD));
+			allowing(payloadEncoder).encode(theirPayload);
+			will(returnValue(BOB_PAYLOAD));
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(ALICE_PUBKEY));
+
+			// Alice sends her public key
+			oneOf(transport).sendKey(ALICE_PUBKEY);
+
+			// Alice receives Bob's public key
+			oneOf(callbacks).connectionWaiting();
+			oneOf(transport).receiveKey();
+			will(returnValue(BOB_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Alice verifies Bob's public key
+			oneOf(crypto).deriveKeyCommitment(BOB_PUBKEY);
+			will(returnValue(BOB_COMMIT));
+
+			// Alice computes shared secret
+			oneOf(crypto).deriveSharedSecret(BOB_PUBKEY, ourKeyPair, true);
+			will(returnValue(sharedSecret));
+
+			// Alice sends her confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD,
+					ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, true);
+			will(returnValue(ALICE_CONFIRM));
+			oneOf(transport).sendConfirm(ALICE_CONFIRM);
+
+			// Alice receives Bob's confirmation record
+			oneOf(transport).receiveConfirm();
+			will(returnValue(BOB_CONFIRM));
+
+			// Alice verifies Bob's confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD,
+					ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, false);
+			will(returnValue(BOB_CONFIRM));
+
+			// Alice computes master secret
+			oneOf(crypto).deriveMasterSecret(sharedSecret);
+			will(returnValue(masterSecret));
+		}});
+
+		// execute
+		assertThat(masterSecret, is(equalTo(protocol.perform())));
+	}
+
+	@Test
+	public void testBobProtocol() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(ALICE_COMMIT, null);
+		final Payload ourPayload = new Payload(BOB_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+		final SecretKey sharedSecret = TestUtils.createSecretKey();
+		final SecretKey masterSecret = TestUtils.createSecretKey();
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, false);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(payloadEncoder).encode(ourPayload);
+			will(returnValue(BOB_PAYLOAD));
+			allowing(payloadEncoder).encode(theirPayload);
+			will(returnValue(ALICE_PAYLOAD));
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(BOB_PUBKEY));
+
+			// Bob receives Alice's public key
+			oneOf(transport).receiveKey();
+			will(returnValue(ALICE_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Bob verifies Alice's public key
+			oneOf(crypto).deriveKeyCommitment(ALICE_PUBKEY);
+			will(returnValue(ALICE_COMMIT));
+
+			// Bob sends his public key
+			oneOf(transport).sendKey(BOB_PUBKEY);
+
+			// Bob computes shared secret
+			oneOf(crypto).deriveSharedSecret(ALICE_PUBKEY, ourKeyPair, false);
+			will(returnValue(sharedSecret));
+
+			// Bob receives Alices's confirmation record
+			oneOf(transport).receiveConfirm();
+			will(returnValue(ALICE_CONFIRM));
+
+			// Bob verifies Alice's confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD,
+					BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, true);
+			will(returnValue(ALICE_CONFIRM));
+
+			// Bob sends his confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD,
+					BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, false);
+			will(returnValue(BOB_CONFIRM));
+			oneOf(transport).sendConfirm(BOB_CONFIRM);
+
+			// Bob computes master secret
+			oneOf(crypto).deriveMasterSecret(sharedSecret);
+			will(returnValue(masterSecret));
+		}});
+
+		// execute
+		assertThat(masterSecret, is(equalTo(protocol.perform())));
+	}
+
+	@Test(expected = AbortException.class)
+	public void testAliceProtocolAbortOnBadKey() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(BOB_COMMIT, null);
+		final Payload ourPayload = new Payload(ALICE_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, true);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(ALICE_PUBKEY));
+
+			// Alice sends her public key
+			oneOf(transport).sendKey(ALICE_PUBKEY);
+
+			// Alice receives a bad public key
+			oneOf(callbacks).connectionWaiting();
+			oneOf(transport).receiveKey();
+			will(returnValue(BAD_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Alice verifies Bob's public key
+			oneOf(crypto).deriveKeyCommitment(BAD_PUBKEY);
+			will(returnValue(BAD_COMMIT));
+
+			// Alice aborts
+			oneOf(transport).sendAbort(false);
+
+			// Alice never computes shared secret
+			never(crypto).deriveSharedSecret(BAD_PUBKEY, ourKeyPair, true);
+		}});
+
+		// execute
+		protocol.perform();
+	}
+
+	@Test(expected = AbortException.class)
+	public void testBobProtocolAbortOnBadKey() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(ALICE_COMMIT, null);
+		final Payload ourPayload = new Payload(BOB_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, false);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(BOB_PUBKEY));
+
+			// Bob receives a bad public key
+			oneOf(transport).receiveKey();
+			will(returnValue(BAD_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Bob verifies Alice's public key
+			oneOf(crypto).deriveKeyCommitment(BAD_PUBKEY);
+			will(returnValue(BAD_COMMIT));
+
+			// Bob aborts
+			oneOf(transport).sendAbort(false);
+
+			// Bob never sends his public key
+			never(transport).sendKey(BOB_PUBKEY);
+		}});
+
+		// execute
+		protocol.perform();
+	}
+
+	@Test(expected = AbortException.class)
+	public void testAliceProtocolAbortOnBadConfirm() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(BOB_COMMIT, null);
+		final Payload ourPayload = new Payload(ALICE_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+		final SecretKey sharedSecret = TestUtils.createSecretKey();
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, true);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(payloadEncoder).encode(ourPayload);
+			will(returnValue(ALICE_PAYLOAD));
+			allowing(payloadEncoder).encode(theirPayload);
+			will(returnValue(BOB_PAYLOAD));
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(ALICE_PUBKEY));
+
+			// Alice sends her public key
+			oneOf(transport).sendKey(ALICE_PUBKEY);
+
+			// Alice receives Bob's public key
+			oneOf(callbacks).connectionWaiting();
+			oneOf(transport).receiveKey();
+			will(returnValue(BOB_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Alice verifies Bob's public key
+			oneOf(crypto).deriveKeyCommitment(BOB_PUBKEY);
+			will(returnValue(BOB_COMMIT));
+
+			// Alice computes shared secret
+			oneOf(crypto).deriveSharedSecret(BOB_PUBKEY, ourKeyPair, true);
+			will(returnValue(sharedSecret));
+
+			// Alice sends her confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD,
+					ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, true);
+			will(returnValue(ALICE_CONFIRM));
+			oneOf(transport).sendConfirm(ALICE_CONFIRM);
+
+			// Alice receives a bad confirmation record
+			oneOf(transport).receiveConfirm();
+			will(returnValue(BAD_CONFIRM));
+
+			// Alice verifies Bob's confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, BOB_PAYLOAD,
+					ALICE_PAYLOAD, BOB_PUBKEY, ourKeyPair, true, false);
+			will(returnValue(BOB_CONFIRM));
+
+			// Alice aborts
+			oneOf(transport).sendAbort(false);
+
+			// Alice never computes master secret
+			never(crypto).deriveMasterSecret(sharedSecret);
+		}});
+
+		// execute
+		protocol.perform();
+	}
+
+	@Test(expected = AbortException.class)
+	public void testBobProtocolAbortOnBadConfirm() throws Exception {
+		// set up
+		final Payload theirPayload = new Payload(ALICE_COMMIT, null);
+		final Payload ourPayload = new Payload(BOB_COMMIT, null);
+		final KeyPair ourKeyPair = new KeyPair(ourPubKey, null);
+		final SecretKey sharedSecret = TestUtils.createSecretKey();
+
+		KeyAgreementProtocol protocol =
+				new KeyAgreementProtocol(callbacks, crypto, payloadEncoder,
+						transport, theirPayload, ourPayload, ourKeyPair, false);
+
+		// expectations
+		context.checking(new Expectations() {{
+			// Helpers
+			allowing(payloadEncoder).encode(ourPayload);
+			will(returnValue(BOB_PAYLOAD));
+			allowing(payloadEncoder).encode(theirPayload);
+			will(returnValue(ALICE_PAYLOAD));
+			allowing(ourPubKey).getEncoded();
+			will(returnValue(BOB_PUBKEY));
+
+			// Bob receives Alice's public key
+			oneOf(transport).receiveKey();
+			will(returnValue(ALICE_PUBKEY));
+			oneOf(callbacks).initialPacketReceived();
+
+			// Bob verifies Alice's public key
+			oneOf(crypto).deriveKeyCommitment(ALICE_PUBKEY);
+			will(returnValue(ALICE_COMMIT));
+
+			// Bob sends his public key
+			oneOf(transport).sendKey(BOB_PUBKEY);
+
+			// Bob computes shared secret
+			oneOf(crypto).deriveSharedSecret(ALICE_PUBKEY, ourKeyPair, false);
+			will(returnValue(sharedSecret));
+
+			// Bob receives a bad confirmation record
+			oneOf(transport).receiveConfirm();
+			will(returnValue(BAD_CONFIRM));
+
+			// Bob verifies Alice's confirmation record
+			oneOf(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD,
+					BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, true);
+			will(returnValue(ALICE_CONFIRM));
+
+			// Bob aborts
+			oneOf(transport).sendAbort(false);
+
+			// Bob never sends his confirmation record
+			never(crypto).deriveConfirmationRecord(sharedSecret, ALICE_PAYLOAD,
+					BOB_PAYLOAD, ALICE_PUBKEY, ourKeyPair, false, false);
+		}});
+
+		// execute
+		protocol.perform();
+	}
+}
\ No newline at end of file
-- 
GitLab