diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractIntroduceeSession.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractIntroduceeSession.java new file mode 100644 index 0000000000000000000000000000000000000000..76ece209544803cc1568d07bd7ffd856abd8f565 --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractIntroduceeSession.java @@ -0,0 +1,157 @@ +package org.briarproject.briar.mailbox; + +import org.briarproject.bramble.api.identity.Author; +import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.TransportId; +import org.briarproject.bramble.api.properties.TransportProperties; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.MessageId; +import org.briarproject.bramble.api.transport.KeySetId; +import org.briarproject.briar.api.client.SessionId; + +import java.util.Map; + +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; + +@Immutable +@NotNullByDefault +abstract class AbstractIntroduceeSession extends Session<IntroduceeState> + implements PeerSession { + + final GroupId contactGroupId; + final Author introducer; + final Local local; + final Remote remote; + @Nullable + final byte[] masterKey; + @Nullable + final Map<TransportId, KeySetId> transportKeys; + + AbstractIntroduceeSession(SessionId sessionId, IntroduceeState state, + long requestTimestamp, GroupId contactGroupId, Author introducer, + Local local, Remote remote, @Nullable byte[] masterKey, + @Nullable Map<TransportId, KeySetId> transportKeys, + long sessionCounter) { + super(sessionId, state, requestTimestamp, sessionCounter); + this.contactGroupId = contactGroupId; + this.introducer = introducer; + this.local = local; + this.remote = remote; + this.masterKey = masterKey; + this.transportKeys = transportKeys; + } + + @Override + public GroupId getContactGroupId() { + return contactGroupId; + } + + @Override + public long getLocalTimestamp() { + return local.lastMessageTimestamp; + } + + @Nullable + @Override + public MessageId getLastLocalMessageId() { + return local.lastMessageId; + } + + @Nullable + @Override + public MessageId getLastRemoteMessageId() { + return remote.lastMessageId; + } + + Author getIntroducer() { + return introducer; + } + + public Local getLocal() { + return local; + } + + public Remote getRemote() { + return remote; + } + + @Nullable + byte[] getMasterKey() { + return masterKey; + } + + @Nullable + Map<TransportId, KeySetId> getTransportKeys() { + return transportKeys; + } + + abstract static class Common { + final boolean alice; + @Nullable + final MessageId lastMessageId; + @Nullable + final byte[] ephemeralPublicKey; + + final long acceptTimestamp; + @Nullable + final byte[] macKey; + + private Common(boolean alice, @Nullable MessageId lastMessageId, + @Nullable byte[] ephemeralPublicKey, @Nullable + long acceptTimestamp, @Nullable byte[] macKey) { + this.alice = alice; + this.lastMessageId = lastMessageId; + this.ephemeralPublicKey = ephemeralPublicKey; + this.acceptTimestamp = acceptTimestamp; + this.macKey = macKey; + } + } + + static class Local extends Common { + final long lastMessageTimestamp; + @Nullable + final byte[] ephemeralPrivateKey; + + Local(boolean alice, @Nullable MessageId lastMessageId, + long lastMessageTimestamp, @Nullable byte[] ephemeralPublicKey, + @Nullable byte[] ephemeralPrivateKey, long acceptTimestamp, + @Nullable byte[] macKey) { + super(alice, lastMessageId, ephemeralPublicKey, acceptTimestamp, + macKey); + this.lastMessageTimestamp = lastMessageTimestamp; + this.ephemeralPrivateKey = ephemeralPrivateKey; + } + + Local(Local s, @Nullable MessageId lastMessageId, + long lastMessageTimestamp) { + this(s.alice, lastMessageId, lastMessageTimestamp, + s.ephemeralPublicKey, s.ephemeralPrivateKey, + s.acceptTimestamp, s.macKey); + } + } + + static class Remote extends Common { + final Author author; + @Nullable + final Map<TransportId, TransportProperties> transportProperties; + + Remote(boolean alice, Author author, + @Nullable MessageId lastMessageId, + @Nullable byte[] ephemeralPublicKey, @Nullable + Map<TransportId, TransportProperties> transportProperties, + long acceptTimestamp, @Nullable byte[] macKey) { + super(alice, lastMessageId, ephemeralPublicKey, acceptTimestamp, + macKey); + this.author = author; + this.transportProperties = transportProperties; + } + + Remote(Remote s, @Nullable MessageId lastMessageId) { + this(s.alice, s.author, lastMessageId, s.ephemeralPublicKey, + s.transportProperties, s.acceptTimestamp, s.macKey); + } + + } + +} diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractProtocolEngine.java index 25bc7337151a837067028b2e54cd8e43359019d0..5397d7b7e5e6d21af504c736aff6ebefa2e8f203 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/AbstractProtocolEngine.java @@ -21,8 +21,9 @@ import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; import static org.briarproject.briar.mailbox.MessageType.ABORT; -import static org.briarproject.briar.mailbox.MessageType.CONTACT_REQUEST; import static org.briarproject.briar.mailbox.MessageType.DECLINE; +import static org.briarproject.briar.mailbox.MessageType.INTRODUCEE_ACCEPT; +import static org.briarproject.briar.mailbox.MessageType.INTRODUCEE_REQUEST; import static org.briarproject.briar.mailbox.MessageType.MAILBOX_ACCEPT; import static org.briarproject.briar.mailbox.MessageType.MAILBOX_REQUEST; @@ -73,24 +74,45 @@ abstract class AbstractProtocolEngine<S extends Session> } Message sendMailboxAcceptMessage(Transaction txn, PeerSession s, - long timestamp, byte[] ephemeralPublicKey, long acceptTimestamp, + long timestamp, + byte[] ephemeralPublicKey, long acceptTimestamp, long messageCounter) throws DbException { Message m = messageEncoder - .encodeMailboxAcceptMessage(s.getContactGroupId(), timestamp, - s.getLastLocalMessageId(), s.getSessionId(), - ephemeralPublicKey, acceptTimestamp, messageCounter); - sendMessage(txn, MAILBOX_ACCEPT, s.getSessionId(), m, messageCounter); + .encodeIntroduceeRequestMessage(s.getContactGroupId(), + timestamp, s.getLastLocalMessageId(), s.getSessionId(), + ephemeralPublicKey, + acceptTimestamp, + messageCounter); + sendMessage(txn, MAILBOX_ACCEPT, s.getSessionId(), m, + messageCounter); return m; } - Message sendContactRequestMessage(Transaction txn, PeerSession s, - long timestamp, Author author, Author introduceeAuthor, + Message sendIntroduceeRequestMessage(Transaction txn, PeerSession s, + long timestamp, + byte[] ephemeralPublicKey, long acceptTimestamp, long messageCounter) throws DbException { Message m = messageEncoder - .encodeRequestMessage(s.getContactGroupId(), timestamp, - s.getLastLocalMessageId(), introduceeAuthor, + .encodeIntroduceeRequestMessage(s.getContactGroupId(), + timestamp, s.getLastLocalMessageId(), s.getSessionId(), + ephemeralPublicKey, + acceptTimestamp, messageCounter); - sendMessage(txn, CONTACT_REQUEST, s.getSessionId(), m, 0); + sendMessage(txn, INTRODUCEE_REQUEST, s.getSessionId(), m, + messageCounter); + return m; + } + + Message sendIntroduceeResponseMessage(Transaction txn, PeerSession s, + long timestamp, byte[] ephemeralPublicKey, byte[] mac, + byte[] signature, long messageCounter) throws DbException { + Message m = messageEncoder + .encodeIntroduceeAcceptMessage(s.getContactGroupId(), + timestamp, + s.getLastLocalMessageId(), s.getSessionId(), + ephemeralPublicKey, mac, signature, messageCounter); + sendMessage(txn, INTRODUCEE_ACCEPT, s.getSessionId(), m, + messageCounter); return m; } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeProtocolEngine.java new file mode 100644 index 0000000000000000000000000000000000000000..8ac793092687577d4d87d15ce5f3d57a298e6d50 --- /dev/null +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeProtocolEngine.java @@ -0,0 +1,213 @@ +package org.briarproject.briar.mailbox; + +import org.briarproject.bramble.api.FormatException; +import org.briarproject.bramble.api.client.ClientHelper; +import org.briarproject.bramble.api.client.ContactGroupFactory; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.crypto.KeyPair; +import org.briarproject.bramble.api.crypto.SecretKey; +import org.briarproject.bramble.api.data.BdfDictionary; +import org.briarproject.bramble.api.db.DatabaseComponent; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.Transaction; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.identity.LocalAuthor; +import org.briarproject.bramble.api.sync.Message; +import org.briarproject.bramble.api.sync.MessageId; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.api.client.MessageTracker; +import org.briarproject.briar.api.client.SessionId; +import org.briarproject.briar.api.mailbox.event.MailboxIntroductionRequestReceivedEvent; + +import java.security.GeneralSecurityException; +import java.util.logging.Logger; + +import javax.annotation.Nullable; +import javax.inject.Inject; + +import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.util.LogUtils.logException; +import static org.briarproject.briar.mailbox.IntroduceeState.AWAIT_AUTH; + +class IntroduceeProtocolEngine + extends AbstractProtocolEngine<IntroduceeSession> { + + private final static Logger LOG = + Logger.getLogger(IntroduceeProtocolEngine.class.getName()); + + @Inject + IntroduceeProtocolEngine(DatabaseComponent db, ClientHelper clientHelper, + ContactManager contactManager, + ContactGroupFactory contactGroupFactory, + MessageTracker messageTracker, IdentityManager identityManager, + MailboxMessageParser messageParser, + MailboxMessageEncoder messageEncoder, Clock clock, + MailboxIntroductionCrypto crypto) { + super(db, clientHelper, contactManager, contactGroupFactory, + messageTracker, identityManager, messageParser, messageEncoder, + clock, crypto); + } + + @Override + public IntroduceeSession onRequestAction(Transaction txn, + IntroduceeSession session, long timestamp) throws DbException { + return null; + } + + @Override + public IntroduceeSession onAcceptAction(Transaction txn, + IntroduceeSession session, long timestamp) throws DbException { + return null; + } + + @Override + public IntroduceeSession onDeclineAction(Transaction txn, + IntroduceeSession session, long timestamp) throws DbException { + return null; + } + + @Override + public IntroduceeSession onRequestMessage(Transaction txn, + IntroduceeSession session, RequestMessage m) + throws DbException, FormatException { + throw new UnsupportedOperationException(); + } + + @Override + public IntroduceeSession onMailboxAcceptMessage(Transaction txn, + IntroduceeSession session, IntroduceeRequestMessage m) + throws DbException, FormatException { + throw new UnsupportedOperationException(); + } + + @Override + public IntroduceeSession onIntroduceeRequestMessage(Transaction txn, + IntroduceeSession session, IntroduceeRequestMessage m) + throws DbException, FormatException { + switch (session.getState()) { + case START: + return onRemoteRequest(txn, session, m); + case AWAIT_LOCAL_RESPONSE: + case LOCAL_DECLINED: + case LOCAL_ACCEPTED: + case AWAIT_REMOTE_RESPONSE: + case MAILBOX_ADDED: + return abort(txn, session); + default: + throw new AssertionError(); + } + } + + private IntroduceeSession onRemoteRequest(Transaction txn, + IntroduceeSession s, + IntroduceeRequestMessage m) throws DbException { + // The dependency, if any, must be the last remote message + if (isInvalidDependency(s, m.getPreviousMessageId())) + return abort(txn, s); + + // Add SessionId to message metadata + addSessionId(txn, m.getMessageId(), s.getSessionId()); + + // Broadcast IntroductionRequestReceivedEvent + LocalAuthor localAuthor = identityManager.getLocalAuthor(txn); + txn.attach(new MailboxIntroductionRequestReceivedEvent( + localAuthor.getId())); + + // Create ephemeral key pair and get local transport properties + KeyPair keyPair = crypto.generateKeyPair(); + byte[] publicKey = keyPair.getPublic().getEncoded(); + byte[] privateKey = keyPair.getPrivate().getEncoded(); + long localTimestamp = clock.currentTimeMillis(); + try { + SecretKey secretKey = crypto.deriveMasterKey(publicKey, privateKey, + m.getEphemeralPublicKey()); + SecretKey aliceMacKey = crypto.deriveMacKey(secretKey, false); + SecretKey bobMacKey = crypto.deriveMacKey(secretKey, false); + byte[] mac = crypto.authMac(bobMacKey, s, localAuthor.getId()); + byte[] signature = + crypto.sign(bobMacKey, localAuthor.getPrivateKey()); + // Send ephemeral public key and timestamp back + Message reply = + sendIntroduceeResponseMessage(txn, s, localTimestamp, + publicKey, mac, signature, s.getMessageCounter()); + //TODO: Check for reasons to decline and if any, move to LOCAL_DECLINE + // Move to the AWAIT_REMOTE_RESPONSE state + return IntroduceeSession + .addLocalAuth(s, AWAIT_AUTH, reply, secretKey, aliceMacKey, + bobMacKey, + localTimestamp); + } catch (GeneralSecurityException e) { + logException(LOG, WARNING, e); + return abort(txn, s); + } + } + + private IntroduceeSession abort(Transaction txn, IntroduceeSession s) + throws DbException { + /* + // Mark the request message unavailable to answer + markRequestsUnavailableToAnswer(txn, s); + + // Send an ABORT message + Message sent = sendAbortMessage(txn, s, getLocalTimestamp(s)); + + // Broadcast abort event for testing + txn.attach(new IntroductionAbortedEvent(s.getSessionId())); + + // Reset the session back to initial state + return IntroduceeSession.clear(s, START, sent.getId(), + sent.getTimestamp(), s.getLastRemoteMessageId()); + */ + return null; + } + + @Override + public IntroduceeSession onContactAcceptMessage(Transaction txn, + IntroduceeSession session, IntroduceeRequestMessage m) + throws DbException, FormatException { + return null; + } + + @Override + public IntroduceeSession onDeclineMessage(Transaction txn, + IntroduceeSession session, DeclineMessage m) + throws DbException, FormatException { + return null; + } + + @Override + public IntroduceeSession onAuthMessage(Transaction txn, + IntroduceeSession session, + MailboxAuthMessage m) throws DbException, FormatException { + return null; + } + + @Override + public IntroduceeSession onAbortMessage(Transaction txn, + IntroduceeSession session, AbortMessage m) + throws DbException, FormatException { + return null; + } + + + private boolean isInvalidDependency(AbstractIntroduceeSession s, + @Nullable MessageId dependency) { + return isInvalidDependency(s.getLastRemoteMessageId(), dependency); + } + + private long getLocalTimestamp(AbstractIntroduceeSession s) { + return getLocalTimestamp(s.getLocalTimestamp(), + s.getRequestTimestamp()); + } + + private void addSessionId(Transaction txn, MessageId m, SessionId sessionId) + throws DbException { + BdfDictionary meta = new BdfDictionary(); + messageEncoder.addSessionId(meta, sessionId); + try { + clientHelper.mergeMessageMetadata(txn, m, meta); + } catch (FormatException e) { + throw new AssertionError(e); + } + } +} diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxAcceptMessage.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeRequestMessage.java similarity index 87% rename from briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxAcceptMessage.java rename to briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeRequestMessage.java index 6b740de8282dd027020b6bd5e21b874213c56ed0..88146af1d39b28c0711c338b50450d32104f6d09 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxAcceptMessage.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeRequestMessage.java @@ -10,13 +10,13 @@ import javax.annotation.concurrent.Immutable; @Immutable @NotNullByDefault -class MailboxAcceptMessage extends AbstractMailboxIntroductionMessage { +class IntroduceeRequestMessage extends AbstractMailboxIntroductionMessage { private final SessionId sessionId; private final byte[] ephemeralPublicKey; private final long acceptTimestamp; - protected MailboxAcceptMessage(MessageId messageId, GroupId groupId, + protected IntroduceeRequestMessage(MessageId messageId, GroupId groupId, long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId, byte[] ephemeralPublicKey, long acceptTimestamp) { diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeSession.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeSession.java index 0ae5cf1f1d0edfbedac8d14c4b64c765e40fdfcc..825ada662de4e3aa730271e793c7bde89bf5b63c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeSession.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeSession.java @@ -1,45 +1,108 @@ package org.briarproject.briar.mailbox; +import org.briarproject.bramble.api.crypto.SecretKey; import org.briarproject.bramble.api.identity.Author; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.plugin.TransportId; -import org.briarproject.bramble.api.properties.TransportProperties; import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.sync.Message; import org.briarproject.bramble.api.sync.MessageId; import org.briarproject.bramble.api.transport.KeySetId; import org.briarproject.briar.api.client.SessionId; +import org.briarproject.briar.api.mailbox.Role; import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import static org.briarproject.briar.api.mailbox.Role.INTRODUCEE; +import static org.briarproject.briar.mailbox.IntroduceeState.AWAIT_REMOTE_RESPONSE; +import static org.briarproject.briar.mailbox.IntroduceeState.START; + @Immutable @NotNullByDefault -abstract class IntroduceeSession extends Session<IntroduceeState> - implements PeerSession { +class IntroduceeSession extends AbstractIntroduceeSession { - final GroupId contactGroupId; - final Author introducer; - final Local local; - final Remote remote; - @Nullable - final byte[] masterKey; - @Nullable - final Map<TransportId, KeySetId> transportKeys; IntroduceeSession(SessionId sessionId, IntroduceeState state, long requestTimestamp, GroupId contactGroupId, Author introducer, Local local, Remote remote, @Nullable byte[] masterKey, @Nullable Map<TransportId, KeySetId> transportKeys, long sessionCounter) { - super(sessionId, state, requestTimestamp, sessionCounter); - this.contactGroupId = contactGroupId; - this.introducer = introducer; - this.local = local; - this.remote = remote; - this.masterKey = masterKey; - this.transportKeys = transportKeys; + super(sessionId, state, requestTimestamp, contactGroupId, introducer, + local, remote, masterKey, transportKeys, sessionCounter); + } + + static IntroduceeSession getInitial(GroupId contactGroupId, + SessionId sessionId, Author introducer, boolean localIsAlice, + Author remoteAuthor) { + Local local = new Local(localIsAlice, null, -1, null, null, -1, null); + Remote remote = + new Remote(!localIsAlice, remoteAuthor, null, null, null, -1, + null); + return new IntroduceeSession(sessionId, START, -1, contactGroupId, + introducer, local, remote, null, null, 0); + } + + static IntroduceeSession addLocalAccept(IntroduceeSession s, + IntroduceeState state, Message m, byte[] ephemeralPublicKey, + byte[] ephemeralPrivateKey, long acceptTimestamp) { + Local local = new Local(false, m.getId(), m.getTimestamp(), + ephemeralPublicKey, ephemeralPrivateKey, acceptTimestamp, null); + return new IntroduceeSession(s.getSessionId(), state, m.getTimestamp(), + s.contactGroupId, s.introducer, local, s.remote, s.masterKey, + s.transportKeys, s.getMessageCounter() + 1); + } + + static IntroduceeSession addLocalAuth(IntroduceeSession s, + IntroduceeState state, + Message m, SecretKey masterKey, + SecretKey aliceMacKey, + SecretKey bobMacKey, long acceptTimestamp) { + // add mac key and sent message + Local local = new Local(false, m.getId(), m.getTimestamp(), + null, null, + acceptTimestamp, bobMacKey.getBytes()); + // just add the mac key + Remote remote = new Remote(true, s.remote.author, + s.remote.lastMessageId, null, null, + s.remote.acceptTimestamp, + aliceMacKey.getBytes()); + // add master key + return new IntroduceeSession(s.getSessionId(), state, + s.getRequestTimestamp(), s.contactGroupId, s.introducer, local, + remote, masterKey.getBytes(), s.transportKeys, + s.getMessageCounter() + 1); + } + + static IntroduceeSession awaitAuth(IntroduceeSession s, + MailboxAuthMessage m, + Message sent, @Nullable Map<TransportId, KeySetId> transportKeys) { + Local local = new Local(s.local, sent.getId(), sent.getTimestamp()); + Remote remote = new Remote(s.remote, m.getMessageId()); + return new IntroduceeSession(s.getSessionId(), AWAIT_REMOTE_RESPONSE, + s.getRequestTimestamp(), s.contactGroupId, s.introducer, local, + remote, null, transportKeys, s.getMessageCounter()); + } + + static IntroduceeSession clear(IntroduceeSession s, IntroduceeState state, + @Nullable MessageId lastLocalMessageId, long localTimestamp, + @Nullable MessageId lastRemoteMessageId) { + Local local = + new Local(s.local.alice, lastLocalMessageId, localTimestamp, + null, null, -1, null); + Remote remote = + new Remote(s.remote.alice, s.remote.author, lastRemoteMessageId, + null, null, -1, null); + return new IntroduceeSession(s.getSessionId(), state, + s.getRequestTimestamp(), s.contactGroupId, s.introducer, local, + remote, null, null, s.getMessageCounter()); + } + + @Override + Role getRole() { + return INTRODUCEE; } @Override @@ -86,72 +149,4 @@ abstract class IntroduceeSession extends Session<IntroduceeState> return transportKeys; } - abstract static class Common { - final boolean alice; - @Nullable - final MessageId lastMessageId; - @Nullable - final byte[] ephemeralPublicKey; - - final long acceptTimestamp; - @Nullable - final byte[] macKey; - - private Common(boolean alice, @Nullable MessageId lastMessageId, - @Nullable byte[] ephemeralPublicKey, @Nullable - long acceptTimestamp, @Nullable byte[] macKey) { - this.alice = alice; - this.lastMessageId = lastMessageId; - this.ephemeralPublicKey = ephemeralPublicKey; - this.acceptTimestamp = acceptTimestamp; - this.macKey = macKey; - } - } - - static class Local extends Common { - final long lastMessageTimestamp; - @Nullable - final byte[] ephemeralPrivateKey; - - Local(boolean alice, @Nullable MessageId lastMessageId, - long lastMessageTimestamp, @Nullable byte[] ephemeralPublicKey, - @Nullable byte[] ephemeralPrivateKey, long acceptTimestamp, - @Nullable byte[] macKey) { - super(alice, lastMessageId, ephemeralPublicKey, acceptTimestamp, - macKey); - this.lastMessageTimestamp = lastMessageTimestamp; - this.ephemeralPrivateKey = ephemeralPrivateKey; - } - - Local(Local s, @Nullable MessageId lastMessageId, - long lastMessageTimestamp) { - this(s.alice, lastMessageId, lastMessageTimestamp, - s.ephemeralPublicKey, s.ephemeralPrivateKey, - s.acceptTimestamp, s.macKey); - } - } - - static class Remote extends Common { - final Author author; - @Nullable - final Map<TransportId, TransportProperties> transportProperties; - - Remote(boolean alice, Author author, - @Nullable MessageId lastMessageId, - @Nullable byte[] ephemeralPublicKey, @Nullable - Map<TransportId, TransportProperties> transportProperties, - long acceptTimestamp, @Nullable byte[] macKey) { - super(alice, lastMessageId, ephemeralPublicKey, acceptTimestamp, - macKey); - this.author = author; - this.transportProperties = transportProperties; - } - - Remote(Remote s, @Nullable MessageId lastMessageId) { - this(s.alice, s.author, lastMessageId, s.ephemeralPublicKey, - s.transportProperties, s.acceptTimestamp, s.macKey); - } - - } - } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeState.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeState.java index 1f0aebd2c54c45008c84b8ad8b72d0f0dc47ab16..13b2bc31612d1228122c77e99baf0257d8ae70d8 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeState.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/IntroduceeState.java @@ -14,7 +14,8 @@ enum IntroduceeState implements State { LOCAL_DECLINED(2), LOCAL_ACCEPTED(3), AWAIT_REMOTE_RESPONSE(4), - MAILBOX_ADDED(5); + AWAIT_AUTH(5), + MAILBOX_ADDED(6); private final int value; diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCrypto.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCrypto.java index e4eb75246ef9844fdd538d8d71f9f61ac55f1d18..ea4d38f630bbc728d1392a2ef55091f7ea5252b2 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCrypto.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCrypto.java @@ -35,13 +35,18 @@ interface MailboxIntroductionCrypto { * * @return The secret master key */ - SecretKey deriveMasterKey(IntroduceeSession s) + SecretKey deriveMasterKey(AbstractIntroduceeSession s) + throws GeneralSecurityException; + + @SuppressWarnings("ConstantConditions") + SecretKey deriveMasterKey(byte[] ephemeralPublicKey, + byte[] ephemeralPrivateKey, byte[] remoteEphemeralPublicKey) throws GeneralSecurityException; /** * Derives a MAC key from the session's master key for Alice or Bob. * - * @param masterKey The key returned by {@link #deriveMasterKey(IntroduceeSession)} + * @param masterKey The key returned by {@link #deriveMasterKey(AbstractIntroduceeSession)} * @param alice true for Alice's MAC key, false for Bob's * @return The MAC key */ @@ -51,17 +56,17 @@ interface MailboxIntroductionCrypto { * Generates a MAC that covers both introducee's ephemeral public keys, * transport properties, Author IDs and timestamps of the accept message. */ - byte[] authMac(SecretKey macKey, IntroduceeSession s, + byte[] authMac(SecretKey macKey, AbstractIntroduceeSession s, AuthorId localAuthorId); /** * Verifies a received MAC * * @param mac The MAC to verify - * as returned by {@link #deriveMasterKey(IntroduceeSession)} + * as returned by {@link #deriveMasterKey(AbstractIntroduceeSession)} * @throws GeneralSecurityException if the verification fails */ - void verifyAuthMac(byte[] mac, IntroduceeSession s, + void verifyAuthMac(byte[] mac, AbstractIntroduceeSession s, AuthorId localAuthorId) throws GeneralSecurityException; @@ -82,20 +87,20 @@ interface MailboxIntroductionCrypto { * * @throws GeneralSecurityException if the signature is invalid */ - void verifySignature(byte[] signature, IntroduceeSession s) + void verifySignature(byte[] signature, AbstractIntroduceeSession s) throws GeneralSecurityException; /** * Generates a MAC using the local MAC key. */ - byte[] activateMac(IntroduceeSession s); + byte[] activateMac(AbstractIntroduceeSession s); /** * Verifies a MAC from an ACTIVATE message. * * @throws GeneralSecurityException if the verification fails */ - void verifyActivateMac(byte[] mac, IntroduceeSession s) + void verifyActivateMac(byte[] mac, AbstractIntroduceeSession s) throws GeneralSecurityException; } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCryptoImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCryptoImpl.java index 8e117c9806c64fe3142f92be7f1ac9cf3ee058bb..debe6e83f0d53edc6aa8444bc6036920a7305f3c 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCryptoImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionCryptoImpl.java @@ -28,9 +28,9 @@ import static org.briarproject.briar.api.introduction.IntroductionConstants.LABE import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_MASTER_KEY; import static org.briarproject.briar.api.introduction.IntroductionConstants.LABEL_SESSION_ID; import static org.briarproject.briar.api.introduction.IntroductionManager.MAJOR_VERSION; -import static org.briarproject.briar.mailbox.IntroduceeSession.Common; -import static org.briarproject.briar.mailbox.IntroduceeSession.Local; -import static org.briarproject.briar.mailbox.IntroduceeSession.Remote; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Common; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Local; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Remote; @Immutable @NotNullByDefault @@ -72,7 +72,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { @Override @SuppressWarnings("ConstantConditions") - public SecretKey deriveMasterKey(IntroduceeSession s) + public SecretKey deriveMasterKey(AbstractIntroduceeSession s) throws GeneralSecurityException { return deriveMasterKey( s.getLocal().ephemeralPublicKey, @@ -82,6 +82,19 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { ); } + @Override + @SuppressWarnings("ConstantConditions") + public SecretKey deriveMasterKey(byte[] ephemeralPublicKey, + byte[] ephemeralPrivateKey, byte[] remoteEphemeralPublicKey) + throws GeneralSecurityException { + return deriveMasterKey( + ephemeralPublicKey, + ephemeralPrivateKey, + remoteEphemeralPublicKey, + false + ); + } + SecretKey deriveMasterKey(byte[] publicKey, byte[] privateKey, byte[] remotePublicKey, boolean alice) throws GeneralSecurityException { @@ -110,7 +123,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { @Override @SuppressWarnings("ConstantConditions") - public byte[] authMac(SecretKey macKey, IntroduceeSession s, + public byte[] authMac(SecretKey macKey, AbstractIntroduceeSession s, AuthorId localAuthorId) { // the macKey is not yet available in the session at this point return authMac(macKey, s.getIntroducer().getId(), localAuthorId, @@ -130,7 +143,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { @Override @SuppressWarnings("ConstantConditions") - public void verifyAuthMac(byte[] mac, IntroduceeSession s, + public void verifyAuthMac(byte[] mac, AbstractIntroduceeSession s, AuthorId localAuthorId) throws GeneralSecurityException { verifyAuthMac(mac, new SecretKey(s.getRemote().macKey), s.getIntroducer().getId(), localAuthorId, s.getLocal(), @@ -156,12 +169,12 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { localAuthorId, local.acceptTimestamp, local.ephemeralPublicKey - ); + ); BdfList remoteInfo = BdfList.of( remoteAuthorId, remote.acceptTimestamp, remote.ephemeralPublicKey - ); + ); BdfList macList = BdfList.of( introducerId, localInfo, @@ -186,7 +199,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { @Override @SuppressWarnings("ConstantConditions") - public void verifySignature(byte[] signature, IntroduceeSession s) + public void verifySignature(byte[] signature, AbstractIntroduceeSession s) throws GeneralSecurityException { SecretKey macKey = new SecretKey(s.getRemote().macKey); verifySignature(macKey, s.getRemote().author.getPublicKey(), signature); @@ -206,7 +219,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { } @Override - public byte[] activateMac(IntroduceeSession s) { + public byte[] activateMac(AbstractIntroduceeSession s) { if (s.getLocal().macKey == null) throw new AssertionError("Local MAC key is null"); return activateMac(new SecretKey(s.getLocal().macKey)); @@ -220,7 +233,7 @@ class MailboxIntroductionCryptoImpl implements MailboxIntroductionCrypto { } @Override - public void verifyActivateMac(byte[] mac, IntroduceeSession s) + public void verifyActivateMac(byte[] mac, AbstractIntroduceeSession s) throws GeneralSecurityException { if (s.getRemote().macKey == null) throw new AssertionError("Remote MAC key is null"); diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionManagerImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionManagerImpl.java index 82a802fee7173a9c15674e44380b4f84792c86c4..3a81dd3735993cbd8dd1d3bc9ff5846114997367 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionManagerImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxIntroductionManagerImpl.java @@ -40,6 +40,7 @@ import static org.briarproject.bramble.api.contact.ContactManager.ContactHook; import static org.briarproject.bramble.api.contact.ContactType.MAILBOX_OWNER; import static org.briarproject.bramble.api.contact.ContactType.values; import static org.briarproject.bramble.api.versioning.ClientVersioningManager.ClientVersioningHook; +import static org.briarproject.briar.api.mailbox.Role.INTRODUCEE; import static org.briarproject.briar.api.mailbox.Role.MAILBOX; import static org.briarproject.briar.api.mailbox.Role.OWNER; import static org.briarproject.briar.mailbox.IntroductionConstants.GROUP_KEY_CONTACT_ID; @@ -200,7 +201,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook session = handleMessage(txn, m, body, meta.getMessageType(), sessionParser.parseOwnerSession(ss.bdfSession), ownerProtocolEngine); - } else if (role == MAILBOX) { + } else if (role == INTRODUCEE) { session = handleMessage(txn, m, body, meta.getMessageType(), sessionParser.parseMailboxSession(m.getGroupId(), ss.bdfSession), mailboxProtocolEngine); @@ -251,11 +252,15 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook return engine.onRequestMessage(txn, session, request); } case MAILBOX_ACCEPT: { - MailboxAcceptMessage acceptMessage = + IntroduceeRequestMessage acceptMessage = messageParser.parseMailboxAcceptMessage(m, body); return engine .onMailboxAcceptMessage(txn, session, acceptMessage); } + case INTRODUCEE_REQUEST: + IntroduceeRequestMessage acceptMessage = + messageParser.parseMailboxAcceptMessage(m, body); + return engine.onIntroduceeRequestMessage(txn, session, acceptMessage); case ABORT: { AbortMessage abort = messageParser.parseAbortMessage(m, body); return engine.onAbortMessage(txn, session, abort); @@ -372,7 +377,7 @@ class MailboxIntroductionManagerImpl extends BdfIncomingMessageHook d = sessionEncoder.encodeIntroducerSession((OwnerSession) session); } else if (session.getRole() == MAILBOX) { d = sessionEncoder - .encodeIntroduceeSession((IntroduceeSession) session); + .encodeIntroduceeSession((AbstractIntroduceeSession) session); } else { throw new AssertionError(); } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoder.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoder.java index dc9b032e1d355dc23ac8241fe69efca6c0792cac..ed8414e5c9b5ad58329abc78561b15dee8662c26 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoder.java @@ -27,8 +27,15 @@ interface MailboxMessageEncoder { @Nullable MessageId previousMessageId, Author introduceeAuthor, long messageCounter); - Message encodeMailboxAcceptMessage(GroupId contactGroupId, long timestamp, + Message encodeIntroduceeAcceptMessage(GroupId contactGroupId, + long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId, + byte[] ephemeralPublicKey, byte[] mac, byte[] signature, + long messageCounter); + + Message encodeIntroduceeRequestMessage(GroupId contactGroupId, + long timestamp, @Nullable MessageId previousMessageId, + SessionId sessionId, byte[] ephemeralPublicKey, long acceptTimestamp, long messageCounter); diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoderImpl.java index fc2ddcff754ffb223e706e955e7945bf6cf44870..c1bdc76d8ecdbc005602b6d48e40c2149c0e7d53 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageEncoderImpl.java @@ -83,7 +83,7 @@ class MailboxMessageEncoderImpl implements MailboxMessageEncoder { } @Override - public Message encodeMailboxAcceptMessage(GroupId contactGroupId, + public Message encodeIntroduceeRequestMessage(GroupId contactGroupId, long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId, byte[] ephemeralPublicKey, long acceptTimestamp, long messageCounter) { @@ -93,6 +93,18 @@ class MailboxMessageEncoderImpl implements MailboxMessageEncoder { return createMessage(contactGroupId, timestamp, body); } + @Override + public Message encodeIntroduceeAcceptMessage(GroupId contactGroupId, + long timestamp, @Nullable MessageId previousMessageId, + SessionId sessionId, byte[] ephemeralPublicKey, byte[] mac, + byte[] signature, long messageCounter) { + BdfList body = BdfList.of(MAILBOX_ACCEPT.getValue(), sessionId, + previousMessageId, ephemeralPublicKey, mac, signature, + timestamp, + messageCounter); + return createMessage(contactGroupId, timestamp, body); + } + @Override public Message encodeDeclineMessage(GroupId contactGroupId, long timestamp, @Nullable MessageId previousMessageId, SessionId sessionId) { diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParser.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParser.java index 7370e7bd2ae3a81e064a035bad31f32895b753ad..6ee90e89a70cc1257b8f7355539cd3af14ebd654 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParser.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParser.java @@ -19,7 +19,7 @@ interface MailboxMessageParser { RequestMessage parseRequestMessage(Message m, BdfList body) throws FormatException; - MailboxAcceptMessage parseMailboxAcceptMessage(Message m, BdfList body) + IntroduceeRequestMessage parseMailboxAcceptMessage(Message m, BdfList body) throws FormatException; DeclineMessage parseDeclineMessage(Message m, BdfList body) diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParserImpl.java index 93e72e916f0037cb1d82d4f83d4274df0de1ddc1..944bf0e08628d23b240a1277bcf35f6d476d30c1 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxMessageParserImpl.java @@ -67,7 +67,7 @@ class MailboxMessageParserImpl implements MailboxMessageParser { } @Override - public MailboxAcceptMessage parseMailboxAcceptMessage(Message m, + public IntroduceeRequestMessage parseMailboxAcceptMessage(Message m, BdfList body) throws FormatException { SessionId sessionId = new SessionId(body.getRaw(1)); byte[] previousMsgBytes = body.getOptionalRaw(2); @@ -75,7 +75,7 @@ class MailboxMessageParserImpl implements MailboxMessageParser { new MessageId(previousMsgBytes)); byte[] ephemeralPublicKey = body.getRaw(3); long acceptTimestamp = body.getLong(4); - return new MailboxAcceptMessage(m.getId(), m.getGroupId(), + return new IntroduceeRequestMessage(m.getId(), m.getGroupId(), m.getTimestamp(), previousMessageId, sessionId, ephemeralPublicKey, acceptTimestamp); } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxProtocolEngine.java index 901c6efca8c2fbd07dde4e04a82e860d64ea1eeb..e134fc57ca654d66eca2fb582cb6fc6301466569 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxProtocolEngine.java @@ -126,14 +126,21 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> { @Override public MailboxSession onMailboxAcceptMessage(Transaction txn, - MailboxSession session, MailboxAcceptMessage m) + MailboxSession session, IntroduceeRequestMessage m) throws DbException, FormatException { return null; } + @Override + public MailboxSession onIntroduceeRequestMessage(Transaction txn, + MailboxSession session, IntroduceeRequestMessage m) + throws DbException, FormatException { + throw new UnsupportedOperationException(); + } + @Override public MailboxSession onContactAcceptMessage(Transaction txn, - MailboxSession session, MailboxAcceptMessage m) + MailboxSession session, IntroduceeRequestMessage m) throws DbException, FormatException { return null; } @@ -159,12 +166,12 @@ class MailboxProtocolEngine extends AbstractProtocolEngine<MailboxSession> { } - private boolean isInvalidDependency(IntroduceeSession s, + private boolean isInvalidDependency(AbstractIntroduceeSession s, @Nullable MessageId dependency) { return isInvalidDependency(s.getLastRemoteMessageId(), dependency); } - private long getLocalTimestamp(IntroduceeSession s) { + private long getLocalTimestamp(AbstractIntroduceeSession s) { return getLocalTimestamp(s.getLocalTimestamp(), s.getRequestTimestamp()); } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSession.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSession.java index 54f46c7493ef321186136b2f73d891207e3c2360..c9974ba924b92097ab58fc0b2e70e64178948e25 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSession.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSession.java @@ -16,12 +16,13 @@ import java.util.Map; import javax.annotation.Nullable; import javax.annotation.concurrent.Immutable; +import static org.briarproject.briar.api.mailbox.Role.MAILBOX; import static org.briarproject.briar.mailbox.IntroduceeState.AWAIT_REMOTE_RESPONSE; import static org.briarproject.briar.mailbox.IntroduceeState.START; @Immutable @NotNullByDefault -class MailboxSession extends IntroduceeSession { +class MailboxSession extends AbstractIntroduceeSession { MailboxSession(SessionId sessionId, IntroduceeState state, @@ -99,7 +100,7 @@ class MailboxSession extends IntroduceeSession { @Override Role getRole() { - return Role.MAILBOX; + return MAILBOX; } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoder.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoder.java index 6ac94a2a3dc04ea5cabfa75cccf4eaf07be1c1c2..a20028f41a006f88965097195f5efe6065a5a749 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoder.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoder.java @@ -13,6 +13,6 @@ interface MailboxSessionEncoder { BdfDictionary encodeIntroducerSession(OwnerSession s); - BdfDictionary encodeIntroduceeSession(IntroduceeSession s); + BdfDictionary encodeIntroduceeSession(AbstractIntroduceeSession s); } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoderImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoderImpl.java index d8ef32f1cf0d75fe0155260474074f7f4d4bffe3..af188a7544a826bb0f94cdf908d089d6d459dd2e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoderImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionEncoderImpl.java @@ -17,12 +17,13 @@ import javax.inject.Inject; import static org.briarproject.bramble.api.data.BdfDictionary.NULL_VALUE; import static org.briarproject.briar.api.introduction.Role.INTRODUCEE; import static org.briarproject.briar.api.introduction.Role.INTRODUCER; -import static org.briarproject.briar.mailbox.IntroduceeSession.Common; -import static org.briarproject.briar.mailbox.IntroduceeSession.Local; -import static org.briarproject.briar.mailbox.IntroduceeSession.Remote; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Common; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Local; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Remote; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_ACCEPT_TIMESTAMP; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_ALICE; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_AUTHOR; +import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_COUNTER; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_EPHEMERAL_PRIVATE_KEY; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_EPHEMERAL_PUBLIC_KEY; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_GROUP_ID; @@ -92,7 +93,7 @@ class MailboxSessionEncoderImpl implements } @Override - public BdfDictionary encodeIntroduceeSession(IntroduceeSession s) { + public BdfDictionary encodeIntroduceeSession(AbstractIntroduceeSession s) { BdfDictionary d = encodeSession(s); d.put(SESSION_KEY_INTRODUCER, clientHelper.toList(s.getIntroducer())); d.put(SESSION_KEY_LOCAL, encodeLocal(s.getLocal())); @@ -134,6 +135,7 @@ class MailboxSessionEncoderImpl implements d.put(SESSION_KEY_ROLE, s.getRole().getValue()); d.put(SESSION_KEY_STATE, s.getState().getValue()); d.put(SESSION_KEY_REQUEST_TIMESTAMP, s.getRequestTimestamp()); + d.put(SESSION_KEY_COUNTER, s.getMessageCounter()); return d; } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionParserImpl.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionParserImpl.java index d3f995611fb2e17f78ce7845b30092d92c716242..b7beb49ff33c87e5281b8b6056318c5c0cd0e269 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionParserImpl.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MailboxSessionParserImpl.java @@ -24,9 +24,8 @@ import javax.inject.Inject; import static org.briarproject.briar.api.mailbox.Role.INTRODUCEE; import static org.briarproject.briar.api.mailbox.Role.OWNER; import static org.briarproject.briar.api.mailbox.Role.fromValue; -import static org.briarproject.briar.mailbox.IntroduceeSession.Local; -import static org.briarproject.briar.mailbox.IntroduceeSession.Remote; -import static org.briarproject.briar.mailbox.IntroductionConstants.MSG_KEY_COUNTER; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Local; +import static org.briarproject.briar.mailbox.AbstractIntroduceeSession.Remote; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_ACCEPT_TIMESTAMP; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_ALICE; import static org.briarproject.briar.mailbox.IntroductionConstants.SESSION_KEY_AUTHOR; @@ -75,7 +74,7 @@ class MailboxSessionParserImpl implements MailboxSessionParser { @Override public long getMessageCounter(BdfDictionary d) throws FormatException { - return d.getLong(MSG_KEY_COUNTER); + return d.getLong(SESSION_KEY_COUNTER); } @Override diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/MessageType.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/MessageType.java index 644de22c4b8125d0c5f1f3675dc3a17b4b6a0c52..0b35f7721432489dc09933d971932626e1cb914e 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/MessageType.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/MessageType.java @@ -9,8 +9,8 @@ import javax.annotation.concurrent.Immutable; @NotNullByDefault enum MessageType { - MAILBOX_REQUEST(0), MAILBOX_ACCEPT(1), CONTACT_REQUEST(2), - CONTACT_ACCEPT(3), CONTACT_INFO(4), MAILBOX_AUTH(5), DECLINE(5), ABORT(6); + MAILBOX_REQUEST(0), MAILBOX_ACCEPT(1), INTRODUCEE_REQUEST(2), + INTRODUCEE_ACCEPT(3), CONTACT_INFO(4), MAILBOX_AUTH(5), DECLINE(5), ABORT(6); private final int value; diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/OwnerProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/OwnerProtocolEngine.java index adb82656b86658238d8fc3a2f398f8c952392ca1..0cfd4c22de2c061c467e4f1cc7492036c020ffd5 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/OwnerProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/OwnerProtocolEngine.java @@ -74,11 +74,11 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> { @Override public OwnerSession onMailboxAcceptMessage(Transaction txn, OwnerSession s, - MailboxAcceptMessage m) throws DbException, FormatException { + IntroduceeRequestMessage m) throws DbException, FormatException { switch (s.getState()) { case START: case AWAIT_RESPONSE_M: - onMailboxAccept(txn, s, m); + return onMailboxAccept(txn, s, m); case M_DECLINED: case AWAIT_RESPONSE_B: case B_DECLINED: @@ -90,19 +90,26 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> { } } + @Override + public OwnerSession onIntroduceeRequestMessage(Transaction txn, + OwnerSession session, IntroduceeRequestMessage m) + throws DbException, FormatException { + throw new UnsupportedOperationException(); + } + @Override public OwnerSession onContactAcceptMessage(Transaction txn, - OwnerSession session, MailboxAcceptMessage m) + OwnerSession session, IntroduceeRequestMessage m) throws DbException, FormatException { throw new UnsupportedOperationException(); } private OwnerSession onMailboxAccept(Transaction txn, OwnerSession s, - MailboxAcceptMessage m) throws DbException { + IntroduceeRequestMessage m) throws DbException { // The dependency, if any, must be the last remote message if (isInvalidDependency(s.getMailbox().lastRemoteMessageId, m.getPreviousMessageId())) return abort(txn, s); - Message forward = sendMailboxAcceptMessage(txn, s.getIntroducee(), + Message forward = sendIntroduceeRequestMessage(txn, s.getIntroducee(), clock.currentTimeMillis(), m.getEphemeralPublicKey(), m.getAcceptTimestamp(), s.getMessageCounter()); broadcastMailboxIntroductionResponseReceived(txn, s.getMailbox().author, @@ -162,7 +169,7 @@ class OwnerProtocolEngine extends AbstractProtocolEngine<OwnerSession> { void broadcastMailboxIntroductionResponseReceived(Transaction txn, Author from, Author to) { MailboxIntroductionResponseReceivedEvent e = - new MailboxIntroductionResponseReceivedEvent(to, from); + new MailboxIntroductionResponseReceivedEvent(from, to); txn.attach(e); } diff --git a/briar-core/src/main/java/org/briarproject/briar/mailbox/ProtocolEngine.java b/briar-core/src/main/java/org/briarproject/briar/mailbox/ProtocolEngine.java index 18ffec2e56f79f6dbea9527ce35200cc0563239a..edcd5b63e6152e9d2e4877acea6b8975be9d9670 100644 --- a/briar-core/src/main/java/org/briarproject/briar/mailbox/ProtocolEngine.java +++ b/briar-core/src/main/java/org/briarproject/briar/mailbox/ProtocolEngine.java @@ -20,10 +20,16 @@ interface ProtocolEngine<S extends Session> { S onRequestMessage(Transaction txn, S session, RequestMessage m) throws DbException, FormatException; - S onMailboxAcceptMessage(Transaction txn, S session, MailboxAcceptMessage m) + S onMailboxAcceptMessage(Transaction txn, S session, + IntroduceeRequestMessage m) throws DbException, FormatException; - S onContactAcceptMessage(Transaction txn, S session, MailboxAcceptMessage m) + S onIntroduceeRequestMessage(Transaction txn, + S session, IntroduceeRequestMessage m) + throws DbException, FormatException; + + S onContactAcceptMessage(Transaction txn, S session, + IntroduceeRequestMessage m) throws DbException, FormatException; S onDeclineMessage(Transaction txn, S session, DeclineMessage m) diff --git a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java index a089eb0e06e61af209ae4d22d27d83a7ac650c58..1e6fa46e29546e19e31d3581dbb51609fa5cadea 100644 --- a/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/blog/BlogManagerIntegrationTest.java @@ -86,6 +86,9 @@ public class BlogManagerIntegrationTest c2 = DaggerBriarIntegrationTestComponent.builder() .testDatabaseModule(new TestDatabaseModule(t2Dir)).build(); injectEagerSingletons(c2); + cMailbox = DaggerBriarIntegrationTestComponent.builder() + .testDatabaseModule(new TestDatabaseModule(t3Dir)).build(); + injectEagerSingletons(cMailbox); } @Test diff --git a/briar-core/src/test/java/org/briarproject/briar/mailbox/MailboxIntroductionIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/mailbox/MailboxIntroductionIntegrationTest.java index 3d794f9ebbb4f65b8403c61800bf71653bc96594..403904d211b7ded0a2f8c739b9b11766ab67c0d1 100644 --- a/briar-core/src/test/java/org/briarproject/briar/mailbox/MailboxIntroductionIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/mailbox/MailboxIntroductionIntegrationTest.java @@ -136,12 +136,15 @@ public class MailboxIntroductionIntegrationTest extends eventWaiter.await(TIMEOUT, 1); assertTrue(listenerMailbox.requestReceived); assertEquals(authorMailbox.getId(), listenerMailbox.getRequest()); - // sync first REQUEST message + // sync RESPONSE message syncMailboxTo0(1, true); eventWaiter.await(TIMEOUT, 1); assertTrue(listener0.response1Received); assertEquals(authorMailbox.getId(), listener0.getAuthors()[0]); assertEquals(author1.getId(), listener0.getAuthors()[1]); + // sync/forward RESPONSE message to the contact + sync0To1(1, true); + eventWaiter.await(TIMEOUT, 1); } @@ -249,7 +252,7 @@ public class MailboxIntroductionIntegrationTest extends } finally { eventWaiter.resume(); } - } else if (e instanceof IntroductionResponseReceivedEvent) { + } else if (e instanceof MailboxIntroductionResponseReceivedEvent) { // only broadcast for DECLINE messages in introducee role latestEvent = e; eventWaiter.resume(); diff --git a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java index 394d19204f481d3d3b8f79a6eb09cc8dcb0eb847..7c43ea31a0ed149b7d9e43c6be0ed9dc6de02faa 100644 --- a/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java +++ b/briar-core/src/test/java/org/briarproject/briar/test/BriarIntegrationTest.java @@ -187,7 +187,7 @@ public abstract class BriarIntegrationTest<C extends BriarIntegrationTestCompone component.inject(new GroupInvitationModule.EagerSingletons()); component.inject(new IdentityModule.EagerSingletons()); component.inject(new IntroductionModule.EagerSingletons()); - // component.inject(new MailboxIntroductionModule.EagerSingletons()); + component.inject(new MailboxIntroductionModule.EagerSingletons()); component.inject(new LifecycleModule.EagerSingletons()); component.inject(new MessagingModule.EagerSingletons()); component.inject(new PrivateGroupModule.EagerSingletons());