Introduction Client: Add MAC and signature to ACK message

The MAC and signature are not yet generated and verified.
This will happen in a later commit.
This commit is contained in:
Torsten Grote
2016-08-26 13:07:25 -03:00
parent eb3da2aac9
commit 7db0e4472a
9 changed files with 103 additions and 60 deletions

View File

@@ -34,7 +34,6 @@ import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.MessageId;
import org.briarproject.api.sync.SyncSession;
import org.briarproject.api.sync.SyncSessionFactory;
import org.briarproject.api.sync.ValidationManager;
import org.briarproject.api.sync.ValidationManager.State;
import org.briarproject.api.system.Clock;
import org.briarproject.contact.ContactModule;
@@ -81,12 +80,12 @@ import static org.junit.Assert.assertTrue;
public class IntroductionIntegrationTest extends BriarTestCase {
LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
SyncSessionFactory sync0, sync1, sync2;
ContactManager contactManager0, contactManager1, contactManager2;
ContactId contactId0, contactId1, contactId2;
IdentityManager identityManager0, identityManager1, identityManager2;
LocalAuthor author0, author1, author2;
private LifecycleManager lifecycleManager0, lifecycleManager1, lifecycleManager2;
private SyncSessionFactory sync0, sync1, sync2;
private ContactManager contactManager0, contactManager1, contactManager2;
private ContactId contactId0, contactId1, contactId2;
private IdentityManager identityManager0, identityManager1, identityManager2;
private LocalAuthor author0, author1, author2;
@Inject
Clock clock;
@@ -1050,14 +1049,14 @@ public class IntroductionIntegrationTest extends BriarTestCase {
private class IntroduceeListener implements EventListener {
public volatile boolean requestReceived = false;
public volatile boolean succeeded = false;
public volatile boolean aborted = false;
private volatile boolean requestReceived = false;
private volatile boolean succeeded = false;
private volatile boolean aborted = false;
private final int introducee;
private final boolean accept;
IntroduceeListener(int introducee, boolean accept) {
private IntroduceeListener(int introducee, boolean accept) {
this.introducee = introducee;
this.accept = accept;
}
@@ -1126,9 +1125,9 @@ public class IntroductionIntegrationTest extends BriarTestCase {
private class IntroducerListener implements EventListener {
public volatile boolean response1Received = false;
public volatile boolean response2Received = false;
public volatile boolean aborted = false;
private volatile boolean response1Received = false;
private volatile boolean response2Received = false;
private volatile boolean aborted = false;
@Override
public void eventOccurred(Event e) {

View File

@@ -32,6 +32,7 @@ public enum IntroduceeAction {
public static IntroduceeAction getLocal(int type, boolean accept) {
if (type == TYPE_RESPONSE && accept) return LOCAL_ACCEPT;
if (type == TYPE_RESPONSE) return LOCAL_DECLINE;
if (type == TYPE_ACK) return ACK;
if (type == TYPE_ABORT) return LOCAL_ABORT;
return null;
}

View File

@@ -26,6 +26,8 @@ public interface IntroductionConstants {
String TRANSPORT = "transport";
String MESSAGE_ID = "messageId";
String MESSAGE_TIME = "timestamp";
String MAC = "mac";
String SIGNATURE = "signature";
/* Introducer Local State Metadata */
String STATE = "state";

View File

@@ -22,6 +22,7 @@ import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.introduction.IntroduceeAction.ACK;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ABORT;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_ACCEPT;
import static org.briarproject.api.introduction.IntroduceeAction.LOCAL_DECLINE;
@@ -39,6 +40,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.EXISTS;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
@@ -51,6 +53,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUT
import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.STATE;
import static org.briarproject.api.introduction.IntroductionConstants.TASK;
import static org.briarproject.api.introduction.IntroductionConstants.TASK_ABORT;
@@ -97,10 +100,10 @@ public class IntroduceeEngine
else return abortSession(currentState, localState);
}
List<BdfDictionary> messages = new ArrayList<BdfDictionary>(1);
if (action == LOCAL_ACCEPT || action == LOCAL_DECLINE) {
localState.put(STATE, nextState.getValue());
localState.put(ANSWERED, true);
List<BdfDictionary> messages = new ArrayList<BdfDictionary>(1);
// create the introduction response message
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_RESPONSE);
@@ -118,17 +121,18 @@ public class IntroduceeEngine
if (nextState == AWAIT_ACK) {
localState.put(TASK, TASK_ADD_CONTACT);
// also send ACK, because we already have the other response
BdfDictionary ack = getAckMessage(localState);
messages.add(ack);
}
List<Event> events = Collections.emptyList();
return new StateUpdate<BdfDictionary, BdfDictionary>(false,
false,
localState, messages, events);
} else if (action == ACK) {
// just send ACK, don't update local state again
BdfDictionary ack = getAckMessage(localState);
messages.add(ack);
} else {
throw new IllegalArgumentException();
}
List<Event> events = Collections.emptyList();
return new StateUpdate<BdfDictionary, BdfDictionary>(false,
false,
localState, messages, events);
} catch (FormatException e) {
throw new IllegalArgumentException(e);
}
@@ -181,11 +185,8 @@ public class IntroduceeEngine
addResponseData(localState, msg);
if (nextState == AWAIT_ACK) {
localState.put(TASK, TASK_ADD_CONTACT);
messages = Collections
.singletonList(getAckMessage(localState));
} else {
messages = Collections.emptyList();
}
messages = Collections.emptyList();
events = Collections.emptyList();
}
// we already sent our ACK and now received the other one
@@ -247,6 +248,8 @@ public class IntroduceeEngine
m.put(TYPE, TYPE_ACK);
m.put(GROUP_ID, localState.getRaw(GROUP_ID));
m.put(SESSION_ID, localState.getRaw(SESSION_ID));
m.put(MAC, localState.getRaw(MAC));
m.put(SIGNATURE, localState.getRaw(SIGNATURE));
if (LOG.isLoggable(INFO)) {
LOG.info("Sending ACK " + " to " +

View File

@@ -40,6 +40,7 @@ import javax.inject.Inject;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.api.data.BdfDictionary.NULL_VALUE;
import static org.briarproject.api.introduction.IntroduceeProtocolState.AWAIT_REQUEST;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.ADDED_CONTACT_ID;
@@ -51,6 +52,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_K
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.INTRODUCER;
import static org.briarproject.api.introduction.IntroductionConstants.LOCAL_AUTHOR_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
@@ -63,6 +65,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUT
import static org.briarproject.api.introduction.IntroductionConstants.REMOTE_AUTHOR_IS_US;
import static org.briarproject.api.introduction.IntroductionConstants.ROLE;
import static org.briarproject.api.introduction.IntroductionConstants.ROLE_INTRODUCEE;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.STATE;
import static org.briarproject.api.introduction.IntroductionConstants.STORAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.TASK;
@@ -73,6 +76,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TIME;
import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ABORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
class IntroduceeManager {
@@ -258,11 +262,12 @@ class IntroduceeManager {
private void performTasks(Transaction txn, BdfDictionary localState)
throws FormatException, DbException {
if (!localState.containsKey(TASK)) return;
if (!localState.containsKey(TASK) || localState.get(TASK) == NULL_VALUE)
return;
// remember task and remove it from localState
long task = localState.getLong(TASK);
localState.put(TASK, BdfDictionary.NULL_VALUE);
localState.put(TASK, NULL_VALUE);
if (task == TASK_ADD_CONTACT) {
if (localState.getBoolean(EXISTS)) {
@@ -312,6 +317,10 @@ class IntroduceeManager {
throw new FormatException();
}
// TODO MAC and signature
localState.put(MAC, new byte[42]);
localState.put(SIGNATURE, new byte[42]);
// The agreed timestamp is the minimum of the peers' timestamps
long ourTime = localState.getLong(OUR_TIME);
long theirTime = localState.getLong(TIME);
@@ -339,7 +348,16 @@ class IntroduceeManager {
// delete the ephemeral private key by overwriting with NULL value
// this ensures future ephemeral keys can not be recovered when
// this device should gets compromised
localState.put(OUR_PRIVATE_KEY, BdfDictionary.NULL_VALUE);
localState.put(OUR_PRIVATE_KEY, NULL_VALUE);
// define next action: Send ACK
BdfDictionary localAction = new BdfDictionary();
localAction.put(TYPE, TYPE_ACK);
// start engine and process its state update
IntroduceeEngine engine = new IntroduceeEngine();
processStateUpdate(txn, null,
engine.onLocalAction(localState, localAction));
}
// we sent and received an ACK, so activate contact

View File

@@ -1,9 +1,9 @@
package org.briarproject.introduction;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.clients.BdfMessageContext;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
@@ -15,15 +15,18 @@ import org.briarproject.clients.BdfMessageValidator;
import static org.briarproject.api.TransportId.MAX_TRANSPORT_ID_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.TIME;
import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
@@ -150,13 +153,20 @@ class IntroductionValidator extends BdfMessageValidator {
return d;
}
private BdfDictionary validateAck(BdfList message)
throws FormatException {
private BdfDictionary validateAck(BdfList message) throws FormatException {
checkSize(message, 4);
checkSize(message, 2);
byte[] mac = message.getRaw(2);
// TODO length check?
byte[] sig = message.getRaw(3);
checkLength(sig, 1, MAX_SIGNATURE_LENGTH);
// Return the metadata
return new BdfDictionary();
BdfDictionary d = new BdfDictionary();
d.put(MAC, mac);
d.put(SIGNATURE, sig);
return d;
}
private BdfDictionary validateAbort(BdfList message)

View File

@@ -19,11 +19,13 @@ import javax.inject.Inject;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.MESSAGE_TIME;
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.TIME;
import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
@@ -108,12 +110,12 @@ public class MessageSender {
list.add(d.getRaw(E_PUBLIC_KEY));
list.add(d.getDictionary(TRANSPORT));
}
// TODO Sign the response, see #256
return list;
}
private BdfList encodeAck(BdfDictionary d) throws FormatException {
return BdfList.of(TYPE_ACK, d.getRaw(SESSION_ID));
return BdfList.of(TYPE_ACK, d.getRaw(SESSION_ID),
d.getRaw(MAC), d.getRaw(SIGNATURE));
}
private BdfList encodeAbort(BdfDictionary d) throws FormatException {

View File

@@ -5,11 +5,11 @@ import org.briarproject.TestUtils;
import org.briarproject.api.FormatException;
import org.briarproject.api.TransportId;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList;
import org.briarproject.api.data.MetadataEncoder;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
@@ -24,13 +24,16 @@ import java.io.IOException;
import static org.briarproject.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_PUBLIC_KEY_LENGTH;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.api.introduction.IntroductionConstants.ACCEPT;
import static org.briarproject.api.introduction.IntroductionConstants.E_PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.MSG;
import static org.briarproject.api.introduction.IntroductionConstants.NAME;
import static org.briarproject.api.introduction.IntroductionConstants.PUBLIC_KEY;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.TIME;
import static org.briarproject.api.introduction.IntroductionConstants.TRANSPORT;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
@@ -40,6 +43,7 @@ import static org.briarproject.api.introduction.IntroductionConstants.TYPE_REQUE
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_RESPONSE;
import static org.briarproject.api.properties.TransportPropertyConstants.MAX_PROPERTY_LENGTH;
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -281,19 +285,18 @@ public class IntroductionValidatorTest extends BriarTestCase {
@Test
public void testValidateProperIntroductionAck() throws IOException {
final byte[] sessionId = TestUtils.getRandomId();
BdfDictionary msg = new BdfDictionary();
msg.put(TYPE, TYPE_ACK);
msg.put(SESSION_ID, sessionId);
BdfList body = BdfList.of(msg.getLong(TYPE), msg.getRaw(SESSION_ID));
byte[] sessionId = TestUtils.getRandomId();
byte[] mac = TestUtils.getRandomBytes(42);
byte[] sig = TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
BdfList body = BdfList.of(TYPE_ACK, sessionId, mac, sig);
BdfDictionary result =
validator.validateMessage(message, group, body).getDictionary();
assertEquals(Long.valueOf(TYPE_ACK), result.getLong(TYPE));
assertEquals(sessionId, result.getRaw(SESSION_ID));
assertArrayEquals(sessionId, result.getRaw(SESSION_ID));
assertArrayEquals(mac, result.getRaw(MAC));
assertArrayEquals(sig, result.getRaw(SIGNATURE));
context.assertIsSatisfied();
}

View File

@@ -5,7 +5,7 @@ import org.briarproject.TestUtils;
import org.briarproject.api.FormatException;
import org.briarproject.api.clients.ClientHelper;
import org.briarproject.api.clients.MessageQueueManager;
import org.briarproject.api.clients.PrivateGroupFactory;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.data.BdfDictionary;
import org.briarproject.api.data.BdfEntry;
import org.briarproject.api.data.BdfList;
@@ -14,7 +14,6 @@ import org.briarproject.api.db.DatabaseComponent;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.Metadata;
import org.briarproject.api.db.Transaction;
import org.briarproject.api.clients.SessionId;
import org.briarproject.api.sync.ClientId;
import org.briarproject.api.sync.Group;
import org.briarproject.api.sync.GroupId;
@@ -24,26 +23,27 @@ import org.jmock.Mockery;
import org.junit.Test;
import static junit.framework.Assert.assertFalse;
import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH;
import static org.briarproject.api.introduction.IntroductionConstants.GROUP_ID;
import static org.briarproject.api.introduction.IntroductionConstants.MAC;
import static org.briarproject.api.introduction.IntroductionConstants.SESSION_ID;
import static org.briarproject.api.introduction.IntroductionConstants.SIGNATURE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE;
import static org.briarproject.api.introduction.IntroductionConstants.TYPE_ACK;
public class MessageSenderTest extends BriarTestCase {
final Mockery context;
final MessageSender messageSender;
final DatabaseComponent db;
final PrivateGroupFactory privateGroupFactory;
final ClientHelper clientHelper;
final MetadataEncoder metadataEncoder;
final MessageQueueManager messageQueueManager;
final Clock clock;
private final Mockery context;
private final MessageSender messageSender;
private final DatabaseComponent db;
private final ClientHelper clientHelper;
private final MetadataEncoder metadataEncoder;
private final MessageQueueManager messageQueueManager;
private final Clock clock;
public MessageSenderTest() {
context = new Mockery();
db = context.mock(DatabaseComponent.class);
privateGroupFactory = context.mock(PrivateGroupFactory.class);
clientHelper = context.mock(ClientHelper.class);
metadataEncoder =
context.mock(MetadataEncoder.class);
@@ -59,17 +59,22 @@ public class MessageSenderTest extends BriarTestCase {
@Test
public void testSendMessage() throws DbException, FormatException {
final Transaction txn = new Transaction(null, false);
final Group privateGroup = new Group(new GroupId(TestUtils.getRandomId()),
new ClientId(TestUtils.getRandomId()), new byte[0]);
final Group privateGroup =
new Group(new GroupId(TestUtils.getRandomId()),
new ClientId(TestUtils.getRandomId()), new byte[0]);
final SessionId sessionId = new SessionId(TestUtils.getRandomId());
byte[] mac = TestUtils.getRandomBytes(42);
byte[] sig = TestUtils.getRandomBytes(MAX_SIGNATURE_LENGTH);
final long time = 42L;
final BdfDictionary msg = BdfDictionary.of(
new BdfEntry(TYPE, TYPE_ACK),
new BdfEntry(GROUP_ID, privateGroup.getId()),
new BdfEntry(SESSION_ID, sessionId)
new BdfEntry(SESSION_ID, sessionId),
new BdfEntry(MAC, mac),
new BdfEntry(SIGNATURE, sig)
);
final BdfList bodyList =
BdfList.of(TYPE_ACK, msg.getRaw(SESSION_ID));
BdfList.of(TYPE_ACK, sessionId.getBytes(), mac, sig);
final byte[] body = TestUtils.getRandomBytes(8);
final Metadata metadata = new Metadata();