From 6787d29f11d876330f76c86f28dfc37d81f1c79c Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Wed, 28 Mar 2018 11:41:50 +0100 Subject: [PATCH] Add a flag to indicate whether outgoing keys are active. --- .../bramble/api/crypto/TransportCrypto.java | 3 +- .../bramble/api/db/DatabaseComponent.java | 6 ++ .../bramble/api/transport/KeyManager.java | 10 +++ .../bramble/api/transport/OutgoingKeys.java | 12 +++- .../bramble/crypto/TransportCryptoImpl.java | 8 ++- .../org/briarproject/bramble/db/Database.java | 6 ++ .../bramble/db/DatabaseComponentImpl.java | 10 +++ .../briarproject/bramble/db/JdbcDatabase.java | 28 ++++++-- .../bramble/transport/KeyManagerImpl.java | 14 ++++ .../transport/MutableOutgoingKeys.java | 12 +++- .../transport/TransportKeyManager.java | 2 + .../transport/TransportKeyManagerImpl.java | 43 ++++++++--- .../bramble/crypto/KeyDerivationTest.java | 22 +++--- .../bramble/db/DatabaseComponentImplTest.java | 19 ++--- .../bramble/db/JdbcDatabaseTest.java | 3 +- .../TransportKeyManagerImplTest.java | 72 +++++++++++-------- 16 files changed, 201 insertions(+), 69 deletions(-) diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java index 6385d1f015..cbd6449b48 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/crypto/TransportCrypto.java @@ -14,9 +14,10 @@ public interface TransportCrypto { * rotation period from the given master secret. * * @param alice whether the keys are for use by Alice or Bob. + * @param active whether the keys are usable for outgoing streams. */ TransportKeys deriveTransportKeys(TransportId t, SecretKey master, - long rotationPeriod, boolean alice); + long rotationPeriod, boolean alice, boolean active); /** * Rotates the given transport keys to the given rotation period. If the diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java index fcf5efe46c..27e379571e 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/db/DatabaseComponent.java @@ -528,6 +528,12 @@ public interface DatabaseComponent { void setReorderingWindow(Transaction txn, KeySetId k, TransportId t, long rotationPeriod, long base, byte[] bitmap) throws DbException; + /** + * Marks the given transport keys as usable for outgoing streams. + */ + void setTransportKeysActive(Transaction txn, TransportId t, KeySetId k) + throws DbException; + /** * Stores the given transport keys, deleting any keys they have replaced. */ diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java index 06b2f47258..a3f0f6d600 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/KeyManager.java @@ -30,6 +30,9 @@ public interface KeyManager { /** * Derives and stores a set of unbound transport keys for each transport * and returns the key set IDs. + * <p/> + * The keys must be bound before they can be used for incoming streams, + * and also activated before they can be used for outgoing streams. */ Map<TransportId, KeySetId> addUnboundKeys(Transaction txn, SecretKey master, long timestamp, boolean alice) throws DbException; @@ -40,6 +43,13 @@ public interface KeyManager { void bindKeys(Transaction txn, ContactId c, Map<TransportId, KeySetId> keys) throws DbException; + /** + * Marks the given transport keys as usable for outgoing streams. Keys must + * be bound before they are activated. + */ + void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys) + throws DbException; + /** * Removes the given transport keys, which must not have been bound, from * the manager and the database. diff --git a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java index 202c46e6a0..4214ffd914 100644 --- a/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java +++ b/bramble-api/src/main/java/org/briarproject/bramble/api/transport/OutgoingKeys.java @@ -10,18 +10,20 @@ public class OutgoingKeys { private final SecretKey tagKey, headerKey; private final long rotationPeriod, streamCounter; + private final boolean active; public OutgoingKeys(SecretKey tagKey, SecretKey headerKey, - long rotationPeriod) { - this(tagKey, headerKey, rotationPeriod, 0); + long rotationPeriod, boolean active) { + this(tagKey, headerKey, rotationPeriod, 0, active); } public OutgoingKeys(SecretKey tagKey, SecretKey headerKey, - long rotationPeriod, long streamCounter) { + long rotationPeriod, long streamCounter, boolean active) { this.tagKey = tagKey; this.headerKey = headerKey; this.rotationPeriod = rotationPeriod; this.streamCounter = streamCounter; + this.active = active; } public SecretKey getTagKey() { @@ -39,4 +41,8 @@ public class OutgoingKeys { public long getStreamCounter() { return streamCounter; } + + public boolean isActive() { + return active; + } } \ No newline at end of file diff --git a/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java index db35c9d5e3..2d4ffb7d31 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/crypto/TransportCryptoImpl.java @@ -36,7 +36,8 @@ class TransportCryptoImpl implements TransportCrypto { @Override public TransportKeys deriveTransportKeys(TransportId t, - SecretKey master, long rotationPeriod, boolean alice) { + SecretKey master, long rotationPeriod, boolean alice, + boolean active) { // Keys for the previous period are derived from the master secret SecretKey inTagPrev = deriveTagKey(master, t, !alice); SecretKey inHeaderPrev = deriveHeaderKey(master, t, !alice); @@ -57,7 +58,7 @@ class TransportCryptoImpl implements TransportCrypto { IncomingKeys inNext = new IncomingKeys(inTagNext, inHeaderNext, rotationPeriod + 1); OutgoingKeys outCurr = new OutgoingKeys(outTagCurr, outHeaderCurr, - rotationPeriod); + rotationPeriod, active); // Collect and return the keys return new TransportKeys(t, inPrev, inCurr, inNext, outCurr); } @@ -71,6 +72,7 @@ class TransportCryptoImpl implements TransportCrypto { IncomingKeys inNext = k.getNextIncomingKeys(); OutgoingKeys outCurr = k.getCurrentOutgoingKeys(); long startPeriod = outCurr.getRotationPeriod(); + boolean active = outCurr.isActive(); // Rotate the keys for (long p = startPeriod + 1; p <= rotationPeriod; p++) { inPrev = inCurr; @@ -80,7 +82,7 @@ class TransportCryptoImpl implements TransportCrypto { inNext = new IncomingKeys(inNextTag, inNextHeader, p + 1); SecretKey outCurrTag = rotateKey(outCurr.getTagKey(), p); SecretKey outCurrHeader = rotateKey(outCurr.getHeaderKey(), p); - outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p); + outCurr = new OutgoingKeys(outCurrTag, outCurrHeader, p, active); } // Collect and return the keys return new TransportKeys(k.getTransportId(), inPrev, inCurr, inNext, diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java index 6ee996b2b8..ddd4860c2c 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/Database.java @@ -640,6 +640,12 @@ interface Database<T> { void setReorderingWindow(T txn, KeySetId k, TransportId t, long rotationPeriod, long base, byte[] bitmap) throws DbException; + /** + * Marks the given transport keys as usable for outgoing streams. + */ + void setTransportKeysActive(T txn, TransportId t, KeySetId k) + throws DbException; + /** * Updates the transmission count and expiry time of the given message * with respect to the given contact, using the latency of the transport diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java index 697bcdd3d6..a974802005 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/DatabaseComponentImpl.java @@ -890,6 +890,16 @@ class DatabaseComponentImpl<T> implements DatabaseComponent { db.setReorderingWindow(txn, k, t, rotationPeriod, base, bitmap); } + @Override + public void setTransportKeysActive(Transaction transaction, TransportId t, + KeySetId k) throws DbException { + if (transaction.isReadOnly()) throw new IllegalArgumentException(); + T txn = unbox(transaction); + if (!db.containsTransport(txn, t)) + throw new NoSuchTransportException(); + db.setTransportKeysActive(txn, t, k); + } + @Override public void updateTransportKeys(Transaction transaction, Collection<KeySet> keys) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java index 25cfb4d5aa..953a0f1604 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/db/JdbcDatabase.java @@ -234,6 +234,7 @@ abstract class JdbcDatabase implements Database<Connection> { + " tagKey _SECRET NOT NULL," + " headerKey _SECRET NOT NULL," + " stream BIGINT NOT NULL," + + " active BOOLEAN NOT NULL," + " PRIMARY KEY (transportId, keySetId)," + " FOREIGN KEY (transportId)" + " REFERENCES transports (transportId)" @@ -880,8 +881,8 @@ abstract class JdbcDatabase implements Database<Connection> { try { // Store the outgoing keys String sql = "INSERT INTO outgoingKeys (contactId, transportId," - + " rotationPeriod, tagKey, headerKey, stream)" - + " VALUES (?, ?, ?, ?, ?, ?)"; + + " rotationPeriod, tagKey, headerKey, stream, active)" + + " VALUES (?, ?, ?, ?, ?, ?, ?)"; ps = txn.prepareStatement(sql); if (c == null) ps.setNull(1, INTEGER); else ps.setInt(1, c.getInt()); @@ -891,6 +892,7 @@ abstract class JdbcDatabase implements Database<Connection> { ps.setBytes(4, outCurr.getTagKey().getBytes()); ps.setBytes(5, outCurr.getHeaderKey().getBytes()); ps.setLong(6, outCurr.getStreamCounter()); + ps.setBoolean(7, outCurr.isActive()); int affected = ps.executeUpdate(); if (affected != 1) throw new DbStateException(); ps.close(); @@ -2157,7 +2159,7 @@ abstract class JdbcDatabase implements Database<Connection> { ps.close(); // Retrieve the outgoing keys in the same order sql = "SELECT keySetId, contactId, rotationPeriod," - + " tagKey, headerKey, stream" + + " tagKey, headerKey, stream, active" + " FROM outgoingKeys" + " WHERE transportId = ?" + " ORDER BY keySetId"; @@ -2175,8 +2177,9 @@ abstract class JdbcDatabase implements Database<Connection> { SecretKey tagKey = new SecretKey(rs.getBytes(4)); SecretKey headerKey = new SecretKey(rs.getBytes(5)); long streamCounter = rs.getLong(6); + boolean active = rs.getBoolean(7); OutgoingKeys outCurr = new OutgoingKeys(tagKey, headerKey, - rotationPeriod, streamCounter); + rotationPeriod, streamCounter, active); IncomingKeys inPrev = inKeys.get(i * 3); IncomingKeys inCurr = inKeys.get(i * 3 + 1); IncomingKeys inNext = inKeys.get(i * 3 + 2); @@ -2889,6 +2892,23 @@ abstract class JdbcDatabase implements Database<Connection> { } } + @Override + public void setTransportKeysActive(Connection txn, TransportId t, + KeySetId k) throws DbException { + PreparedStatement ps = null; + try { + String sql = "UPDATE outgoingKeys SET active = true" + + " WHERE transportId = ? AND keySetId = ?"; + ps = txn.prepareStatement(sql); + int affected = ps.executeUpdate(); + if (affected < 0 || affected > 1) throw new DbStateException(); + ps.close(); + } catch (SQLException e) { + tryToClose(ps); + throw new DbException(e); + } + } + @Override public void updateExpiryTime(Connection txn, ContactId c, MessageId m, int maxLatency) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java index 1a06ef4a65..860e0e4029 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/KeyManagerImpl.java @@ -132,6 +132,20 @@ class KeyManagerImpl implements KeyManager, Service, EventListener { } } + @Override + public void activateKeys(Transaction txn, Map<TransportId, KeySetId> keys) + throws DbException { + for (Entry<TransportId, KeySetId> e : keys.entrySet()) { + TransportId t = e.getKey(); + TransportKeyManager m = managers.get(t); + if (m == null) { + if (LOG.isLoggable(INFO)) LOG.info("No key manager for " + t); + } else { + m.activateKeys(txn, e.getValue()); + } + } + } + @Override public void removeKeys(Transaction txn, Map<TransportId, KeySetId> keys) throws DbException { diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java index aaafec13bd..c195f445cd 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/MutableOutgoingKeys.java @@ -13,17 +13,19 @@ class MutableOutgoingKeys { private final SecretKey tagKey, headerKey; private final long rotationPeriod; private long streamCounter; + private boolean active; MutableOutgoingKeys(OutgoingKeys out) { tagKey = out.getTagKey(); headerKey = out.getHeaderKey(); rotationPeriod = out.getRotationPeriod(); streamCounter = out.getStreamCounter(); + active = out.isActive(); } OutgoingKeys snapshot() { return new OutgoingKeys(tagKey, headerKey, rotationPeriod, - streamCounter); + streamCounter, active); } SecretKey getTagKey() { @@ -45,4 +47,12 @@ class MutableOutgoingKeys { void incrementStreamCounter() { streamCounter++; } + + boolean isActive() { + return active; + } + + void activate() { + active = true; + } } diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java index 4eff0b289d..2af01fa4a6 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManager.java @@ -23,6 +23,8 @@ interface TransportKeyManager { void bindKeys(Transaction txn, ContactId c, KeySetId k) throws DbException; + void activateKeys(Transaction txn, KeySetId k) throws DbException; + void removeKeys(Transaction txn, KeySetId k) throws DbException; void removeContact(ContactId c); diff --git a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java index 889485d0dc..d7ccb49c26 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/transport/TransportKeyManagerImpl.java @@ -127,10 +127,7 @@ class TransportKeyManagerImpl implements TransportKeyManager { encodeTags(keySetId, contactId, m.getPreviousIncomingKeys()); encodeTags(keySetId, contactId, m.getCurrentIncomingKeys()); encodeTags(keySetId, contactId, m.getNextIncomingKeys()); - // Use the outgoing keys with the highest key set ID - MutableKeySet old = outContexts.get(contactId); - if (old == null || old.getKeySetId().getInt() < keySetId.getInt()) - outContexts.put(contactId, ks); + considerReplacingOutgoingKeys(ks); } } @@ -147,6 +144,17 @@ class TransportKeyManagerImpl implements TransportKeyManager { } } + // Locking: lock + private void considerReplacingOutgoingKeys(MutableKeySet ks) { + // Use the active outgoing keys with the highest key set ID + if (ks.getTransportKeys().getCurrentOutgoingKeys().isActive()) { + MutableKeySet old = outContexts.get(ks.getContactId()); + if (old == null || + old.getKeySetId().getInt() < ks.getKeySetId().getInt()) + outContexts.put(ks.getContactId(), ks); + } + } + private void scheduleKeyRotation(long now) { long delay = rotationPeriodLength - now % rotationPeriodLength; scheduler.schedule((Runnable) this::rotateKeys, delay, MILLISECONDS); @@ -171,17 +179,17 @@ class TransportKeyManagerImpl implements TransportKeyManager { @Override public void addContact(Transaction txn, ContactId c, SecretKey master, long timestamp, boolean alice) throws DbException { - deriveAndAddKeys(txn, c, master, timestamp, alice); + deriveAndAddKeys(txn, c, master, timestamp, alice, true); } @Override public KeySetId addUnboundKeys(Transaction txn, SecretKey master, long timestamp, boolean alice) throws DbException { - return deriveAndAddKeys(txn, null, master, timestamp, alice); + return deriveAndAddKeys(txn, null, master, timestamp, alice, false); } private KeySetId deriveAndAddKeys(Transaction txn, @Nullable ContactId c, - SecretKey master, long timestamp, boolean alice) + SecretKey master, long timestamp, boolean alice, boolean active) throws DbException { lock.lock(); try { @@ -189,7 +197,7 @@ class TransportKeyManagerImpl implements TransportKeyManager { long rotationPeriod = timestamp / rotationPeriodLength; // Derive the transport keys TransportKeys k = transportCrypto.deriveTransportKeys(transportId, - master, rotationPeriod, alice); + master, rotationPeriod, alice, active); // Rotate the keys to the current rotation period if necessary rotationPeriod = clock.currentTimeMillis() / rotationPeriodLength; k = transportCrypto.rotateTransportKeys(k, rotationPeriod); @@ -210,6 +218,7 @@ class TransportKeyManagerImpl implements TransportKeyManager { try { MutableKeySet ks = keys.get(k); if (ks == null) throw new IllegalArgumentException(); + // Check that the keys haven't already been bound if (ks.getContactId() != null) throw new IllegalArgumentException(); MutableTransportKeys m = ks.getTransportKeys(); addKeys(k, c, m); @@ -219,12 +228,30 @@ class TransportKeyManagerImpl implements TransportKeyManager { } } + @Override + public void activateKeys(Transaction txn, KeySetId k) throws DbException { + lock.lock(); + try { + MutableKeySet ks = keys.get(k); + if (ks == null) throw new IllegalArgumentException(); + // Check that the keys have been bound + if (ks.getContactId() == null) throw new IllegalArgumentException(); + MutableTransportKeys m = ks.getTransportKeys(); + m.getCurrentOutgoingKeys().activate(); + considerReplacingOutgoingKeys(ks); + db.setTransportKeysActive(txn, m.getTransportId(), k); + } finally { + lock.unlock(); + } + } + @Override public void removeKeys(Transaction txn, KeySetId k) throws DbException { lock.lock(); try { MutableKeySet ks = keys.remove(k); if (ks == null) throw new IllegalArgumentException(); + // Check that the keys haven't been bound if (ks.getContactId() != null) throw new IllegalArgumentException(); TransportId t = ks.getTransportKeys().getTransportId(); db.removeTransportKeys(txn, t, k); diff --git a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java index 81f73f8d28..dc51966ffb 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/crypto/KeyDerivationTest.java @@ -33,7 +33,7 @@ public class KeyDerivationTest extends BrambleTestCase { @Test public void testKeysAreDistinct() { TransportKeys k = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); assertAllDifferent(k); } @@ -41,9 +41,9 @@ public class KeyDerivationTest extends BrambleTestCase { public void testCurrentKeysMatchCurrentKeysOfContact() { // Start in rotation period 123 TransportKeys kA = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); TransportKeys kB = transportCrypto.deriveTransportKeys(transportId, - master, 123, false); + master, 123, false, true); // Alice's incoming keys should equal Bob's outgoing keys assertArrayEquals(kA.getCurrentIncomingKeys().getTagKey().getBytes(), kB.getCurrentOutgoingKeys().getTagKey().getBytes()); @@ -73,9 +73,9 @@ public class KeyDerivationTest extends BrambleTestCase { public void testPreviousKeysMatchPreviousKeysOfContact() { // Start in rotation period 123 TransportKeys kA = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); TransportKeys kB = transportCrypto.deriveTransportKeys(transportId, - master, 123, false); + master, 123, false, true); // Compare Alice's previous keys in period 456 with Bob's current keys // in period 455 kA = transportCrypto.rotateTransportKeys(kA, 456); @@ -100,9 +100,9 @@ public class KeyDerivationTest extends BrambleTestCase { public void testNextKeysMatchNextKeysOfContact() { // Start in rotation period 123 TransportKeys kA = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); TransportKeys kB = transportCrypto.deriveTransportKeys(transportId, - master, 123, false); + master, 123, false, true); // Compare Alice's current keys in period 456 with Bob's next keys in // period 455 kA = transportCrypto.rotateTransportKeys(kA, 456); @@ -127,9 +127,9 @@ public class KeyDerivationTest extends BrambleTestCase { SecretKey master1 = getSecretKey(); assertFalse(Arrays.equals(master.getBytes(), master1.getBytes())); TransportKeys k = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); TransportKeys k1 = transportCrypto.deriveTransportKeys(transportId, - master1, 123, true); + master1, 123, true, true); assertAllDifferent(k, k1); } @@ -138,9 +138,9 @@ public class KeyDerivationTest extends BrambleTestCase { TransportId transportId1 = new TransportId("id1"); assertFalse(transportId.getString().equals(transportId1.getString())); TransportKeys k = transportCrypto.deriveTransportKeys(transportId, - master, 123, true); + master, 123, true, true); TransportKeys k1 = transportCrypto.deriveTransportKeys(transportId1, - master, 123, true); + master, 123, true, true); assertAllDifferent(k, k1); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java index 61a4991628..d8f1f59fbf 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/DatabaseComponentImplTest.java @@ -71,6 +71,7 @@ import static org.briarproject.bramble.api.transport.TransportConstants.REORDERI import static org.briarproject.bramble.db.DatabaseConstants.MAX_OFFERED_MESSAGES; import static org.briarproject.bramble.test.TestUtils.getAuthor; import static org.briarproject.bramble.test.TestUtils.getLocalAuthor; +import static org.briarproject.bramble.test.TestUtils.getSecretKey; import static org.briarproject.bramble.util.StringUtils.getRandomString; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -1356,22 +1357,22 @@ public class DatabaseComponentImplTest extends BrambleMockTestCase { } private TransportKeys createTransportKeys() { - SecretKey inPrevTagKey = TestUtils.getSecretKey(); - SecretKey inPrevHeaderKey = TestUtils.getSecretKey(); + SecretKey inPrevTagKey = getSecretKey(); + SecretKey inPrevHeaderKey = getSecretKey(); IncomingKeys inPrev = new IncomingKeys(inPrevTagKey, inPrevHeaderKey, 1, 123, new byte[4]); - SecretKey inCurrTagKey = TestUtils.getSecretKey(); - SecretKey inCurrHeaderKey = TestUtils.getSecretKey(); + SecretKey inCurrTagKey = getSecretKey(); + SecretKey inCurrHeaderKey = getSecretKey(); IncomingKeys inCurr = new IncomingKeys(inCurrTagKey, inCurrHeaderKey, 2, 234, new byte[4]); - SecretKey inNextTagKey = TestUtils.getSecretKey(); - SecretKey inNextHeaderKey = TestUtils.getSecretKey(); + SecretKey inNextTagKey = getSecretKey(); + SecretKey inNextHeaderKey = getSecretKey(); IncomingKeys inNext = new IncomingKeys(inNextTagKey, inNextHeaderKey, 3, 345, new byte[4]); - SecretKey outCurrTagKey = TestUtils.getSecretKey(); - SecretKey outCurrHeaderKey = TestUtils.getSecretKey(); + SecretKey outCurrTagKey = getSecretKey(); + SecretKey outCurrHeaderKey = getSecretKey(); OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey, - 2, 456); + 2, 456, true); return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java index 6babc64594..9e4047982d 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/db/JdbcDatabaseTest.java @@ -804,6 +804,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { actual.getHeaderKey().getBytes()); assertEquals(expected.getRotationPeriod(), actual.getRotationPeriod()); assertEquals(expected.getStreamCounter(), actual.getStreamCounter()); + assertEquals(expected.isActive(), actual.isActive()); } @Test @@ -1820,7 +1821,7 @@ public abstract class JdbcDatabaseTest extends BrambleTestCase { SecretKey outCurrTagKey = getSecretKey(); SecretKey outCurrHeaderKey = getSecretKey(); OutgoingKeys outCurr = new OutgoingKeys(outCurrTagKey, outCurrHeaderKey, - 2, 456); + 2, 456, true); return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr); } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java index afc5dfed2d..8da8eefaa4 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/transport/TransportKeyManagerImplTest.java @@ -65,16 +65,16 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { @Test public void testKeysAreRotatedAtStartup() throws Exception { - TransportKeys shouldRotate = createTransportKeys(900, 0); - TransportKeys shouldNotRotate = createTransportKeys(1000, 0); - TransportKeys shouldRotate1 = createTransportKeys(999, 0); + TransportKeys shouldRotate = createTransportKeys(900, 0, true); + TransportKeys shouldNotRotate = createTransportKeys(1000, 0, true); + TransportKeys shouldRotate1 = createTransportKeys(999, 0, false); Collection<KeySet> loaded = asList( new KeySet(keySetId, contactId, shouldRotate), new KeySet(keySetId1, contactId1, shouldNotRotate), new KeySet(keySetId2, null, shouldRotate1) ); - TransportKeys rotated = createTransportKeys(1000, 0); - TransportKeys rotated1 = createTransportKeys(1000, 0); + TransportKeys rotated = createTransportKeys(1000, 0, true); + TransportKeys rotated1 = createTransportKeys(1000, 0, false); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ @@ -117,13 +117,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { @Test public void testKeysAreRotatedWhenAddingContact() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(999, 0); - TransportKeys rotated = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(999, 0, true); + TransportKeys rotated = createTransportKeys(1000, 0, true); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 999, alice); + 999, alice, true); will(returnValue(transportKeys)); // Get the current time (1 ms after start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -155,13 +155,13 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { @Test public void testKeysAreRotatedWhenAddingUnboundKeys() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(999, 0); - TransportKeys rotated = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(999, 0, false); + TransportKeys rotated = createTransportKeys(1000, 0, false); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 999, alice); + 999, alice, false); will(returnValue(transportKeys)); // Get the current time (1 ms after start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -200,7 +200,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { boolean alice = random.nextBoolean(); // The stream counter has been exhausted TransportKeys transportKeys = createTransportKeys(1000, - MAX_32_BIT_UNSIGNED + 1); + MAX_32_BIT_UNSIGNED + 1, true); Transaction txn = new Transaction(null, false); expectAddContactNoRotation(alice, transportKeys, txn); @@ -220,7 +220,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { boolean alice = random.nextBoolean(); // The stream counter can be used one more time before being exhausted TransportKeys transportKeys = createTransportKeys(1000, - MAX_32_BIT_UNSIGNED); + MAX_32_BIT_UNSIGNED, true); Transaction txn = new Transaction(null, false); expectAddContactNoRotation(alice, transportKeys, txn); @@ -254,7 +254,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { public void testIncomingStreamContextIsNullIfTagIsNotFound() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(1000, 0, true); Transaction txn = new Transaction(null, false); expectAddContactNoRotation(alice, transportKeys, txn); @@ -274,14 +274,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { @Test public void testTagIsNotRecognisedTwice() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(1000, 0, true); // Keep a copy of the tags List<byte[]> tags = new ArrayList<>(); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 1000, alice); + 1000, alice, true); will(returnValue(transportKeys)); // Get the current time (the start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -335,14 +335,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { @Test public void testKeysAreRotatedToCurrentPeriod() throws Exception { - TransportKeys transportKeys = createTransportKeys(1000, 0); - TransportKeys transportKeys1 = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(1000, 0, true); + TransportKeys transportKeys1 = createTransportKeys(1000, 0, false); Collection<KeySet> loaded = asList( new KeySet(keySetId, contactId, transportKeys), new KeySet(keySetId1, null, transportKeys1) ); - TransportKeys rotated = createTransportKeys(1001, 0); - TransportKeys rotated1 = createTransportKeys(1001, 0); + TransportKeys rotated = createTransportKeys(1001, 0, true); + TransportKeys rotated1 = createTransportKeys(1001, 0, false); Transaction txn = new Transaction(null, false); Transaction txn1 = new Transaction(null, false); @@ -411,14 +411,14 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { } @Test - public void testTagsAreEncodedWhenKeysAreBound() throws Exception { + public void testBindingAndActivatingKeys() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(1000, 0, false); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 1000, alice); + 1000, alice, false); will(returnValue(transportKeys)); // Get the current time (the start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -438,6 +438,10 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { } // Save the key binding oneOf(db).bindTransportKeys(txn, contactId, transportId, keySetId); + // Activate the keys + oneOf(db).setTransportKeysActive(txn, transportId, keySetId); + // Increment the stream counter + oneOf(db).incrementStreamCounter(txn, contactId, transportId, 1000); }}); TransportKeyManager transportKeyManager = new TransportKeyManagerImpl( @@ -448,17 +452,29 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { assertEquals(keySetId, transportKeyManager.addUnboundKeys(txn, masterKey, timestamp, alice)); transportKeyManager.bindKeys(txn, contactId, keySetId); + // The keys are inactive so no stream context should be returned + assertNull(transportKeyManager.getStreamContext(txn, contactId)); + transportKeyManager.activateKeys(txn, keySetId); + // The keys are active so a stream context should be returned + StreamContext ctx = transportKeyManager.getStreamContext(txn, + contactId); + assertNotNull(ctx); + assertEquals(contactId, ctx.getContactId()); + assertEquals(transportId, ctx.getTransportId()); + assertEquals(tagKey, ctx.getTagKey()); + assertEquals(headerKey, ctx.getHeaderKey()); + assertEquals(0, ctx.getStreamNumber()); } @Test public void testRemovingUnboundKeys() throws Exception { boolean alice = random.nextBoolean(); - TransportKeys transportKeys = createTransportKeys(1000, 0); + TransportKeys transportKeys = createTransportKeys(1000, 0, false); Transaction txn = new Transaction(null, false); context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 1000, alice); + 1000, alice, false); will(returnValue(transportKeys)); // Get the current time (the start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -487,7 +503,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { TransportKeys transportKeys, Transaction txn) throws Exception { context.checking(new Expectations() {{ oneOf(transportCrypto).deriveTransportKeys(transportId, masterKey, - 1000, alice); + 1000, alice, true); will(returnValue(transportKeys)); // Get the current time (the start of rotation period 1000) oneOf(clock).currentTimeMillis(); @@ -509,7 +525,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { } private TransportKeys createTransportKeys(long rotationPeriod, - long streamCounter) { + long streamCounter, boolean active) { IncomingKeys inPrev = new IncomingKeys(tagKey, headerKey, rotationPeriod - 1); IncomingKeys inCurr = new IncomingKeys(tagKey, headerKey, @@ -517,7 +533,7 @@ public class TransportKeyManagerImplTest extends BrambleMockTestCase { IncomingKeys inNext = new IncomingKeys(tagKey, headerKey, rotationPeriod + 1); OutgoingKeys outCurr = new OutgoingKeys(tagKey, headerKey, - rotationPeriod, streamCounter); + rotationPeriod, streamCounter, active); return new TransportKeys(transportId, inPrev, inCurr, inNext, outCurr); } -- GitLab