mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-23 08:09:54 +01:00
Compare commits
14 Commits
remote-wip
...
social-bac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d564fc8713 | ||
|
|
41443db817 | ||
|
|
274722d695 | ||
|
|
275c7d261f | ||
|
|
667f8db4f0 | ||
|
|
8398ecdeae | ||
|
|
8437aa1b10 | ||
|
|
9cf00efa9c | ||
|
|
2a45fd3c91 | ||
|
|
f1f16f8474 | ||
|
|
873675d68f | ||
|
|
1ffa8ee024 | ||
|
|
a425a33209 | ||
|
|
5adbf18851 |
@@ -116,4 +116,8 @@ public interface KeyManager {
|
|||||||
@Nullable
|
@Nullable
|
||||||
StreamContext getStreamContext(TransportId t, byte[] tag)
|
StreamContext getStreamContext(TransportId t, byte[] tag)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
StreamContext getStreamContextInHandshakeMode(ContactId c, TransportId t)
|
||||||
|
throws DbException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,9 @@ abstract class Connection {
|
|||||||
TransportId transportId) {
|
TransportId transportId) {
|
||||||
StreamContext ctx;
|
StreamContext ctx;
|
||||||
try {
|
try {
|
||||||
|
LOG.info("Reading tag...");
|
||||||
byte[] tag = readTag(reader.getInputStream());
|
byte[] tag = readTag(reader.getInputStream());
|
||||||
|
LOG.info("Read tag!");
|
||||||
return keyManager.getStreamContext(transportId, tag);
|
return keyManager.getStreamContext(transportId, tag);
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
|
|||||||
@@ -130,13 +130,17 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
private boolean performHandshake(StreamContext ctxIn, ContactId contactId) {
|
private boolean performHandshake(StreamContext ctxIn, ContactId contactId) {
|
||||||
LOG.info("Performing handshake (Incoming)");
|
LOG.info("Performing handshake (Incoming)");
|
||||||
// Allocate the outgoing stream context
|
// Allocate the outgoing stream context
|
||||||
StreamContext ctxOut =
|
StreamContext ctxOut;
|
||||||
allocateStreamContext(contactId, transportId);
|
|
||||||
if (ctxOut == null) {
|
try {
|
||||||
|
ctxOut = keyManager.getStreamContextInHandshakeMode(contactId, transportId);
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
LOG.warning("Could not allocate stream context");
|
LOG.warning("Could not allocate stream context");
|
||||||
onReadError(true);
|
onReadError(true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
InputStream in = streamReaderFactory.createStreamReader(
|
InputStream in = streamReaderFactory.createStreamReader(
|
||||||
reader.getInputStream(), ctxIn);
|
reader.getInputStream(), ctxIn);
|
||||||
@@ -148,7 +152,7 @@ class IncomingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
handshakeManager.handshake(contactId, in, out);
|
handshakeManager.handshake(contactId, in, out);
|
||||||
keyManager.addRotationKeys(contactId, result.getMasterKey(),
|
keyManager.addRotationKeys(contactId, result.getMasterKey(),
|
||||||
TIMESTAMP, result.isAlice(), true);
|
TIMESTAMP, result.isAlice(), true);
|
||||||
LOG.info("Rotation keys added");
|
LOG.info("Rotation keys added - IncomingDuplexSyncConnection");
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
LOG.info("Running OutgoingDuplexSyncConnection on transport " +
|
LOG.info("Running OutgoingDuplexSyncConnection on transport " +
|
||||||
transportId.getString());
|
transportId.getString());
|
||||||
// Allocate a stream context
|
// Allocate a stream context
|
||||||
|
|
||||||
StreamContext ctx = allocateStreamContext(contactId, transportId);
|
StreamContext ctx = allocateStreamContext(contactId, transportId);
|
||||||
if (ctx == null) {
|
if (ctx == null) {
|
||||||
LOG.warning("Could not allocate stream context");
|
LOG.warning("Could not allocate stream context");
|
||||||
@@ -71,6 +72,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ctx.isHandshakeMode()) {
|
if (ctx.isHandshakeMode()) {
|
||||||
|
LOG.info("OutgoingDuplexSyncConnection - context is in handshake mode, performing handshake");
|
||||||
if (!performHandshake(ctx)) {
|
if (!performHandshake(ctx)) {
|
||||||
LOG.warning("Handshake failed");
|
LOG.warning("Handshake failed");
|
||||||
return;
|
return;
|
||||||
@@ -155,7 +157,8 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean performHandshake(StreamContext ctxOut) {
|
private boolean performHandshake(StreamContext ctxOut) {
|
||||||
LOG.info("Performing handshake (Outgoing)");
|
LOG.info("Performing handshake (Outgoing) for transport " +
|
||||||
|
ctxOut.getTransportId().getString());
|
||||||
// Flush the output stream to send the outgoing stream header
|
// Flush the output stream to send the outgoing stream header
|
||||||
StreamWriter out;
|
StreamWriter out;
|
||||||
try {
|
try {
|
||||||
@@ -177,7 +180,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
}
|
}
|
||||||
// Check that the stream comes from the expected contact
|
// Check that the stream comes from the expected contact
|
||||||
ContactId inContactId = ctxIn.getContactId();
|
ContactId inContactId = ctxIn.getContactId();
|
||||||
if (contactId == null) {
|
if (inContactId == null) {
|
||||||
LOG.warning("Expected contact tag, got rendezvous tag");
|
LOG.warning("Expected contact tag, got rendezvous tag");
|
||||||
onReadError();
|
onReadError();
|
||||||
return false;
|
return false;
|
||||||
@@ -196,7 +199,7 @@ class OutgoingDuplexSyncConnection extends DuplexSyncConnection
|
|||||||
handshakeManager.handshake(contactId, in, out);
|
handshakeManager.handshake(contactId, in, out);
|
||||||
keyManager.addRotationKeys(contactId, result.getMasterKey(),
|
keyManager.addRotationKeys(contactId, result.getMasterKey(),
|
||||||
TIMESTAMP, result.isAlice(), true);
|
TIMESTAMP, result.isAlice(), true);
|
||||||
LOG.info("Rotation keys added");
|
LOG.info("Rotation keys added - OutgoingDuplexSyncConnection");
|
||||||
return true;
|
return true;
|
||||||
} catch (IOException | DbException e) {
|
} catch (IOException | DbException e) {
|
||||||
logException(LOG, WARNING, e);
|
logException(LOG, WARNING, e);
|
||||||
|
|||||||
@@ -470,6 +470,10 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (now - then >= V3_MIGRATION_PERIOD_MS) retireV2HiddenService();
|
if (now - then >= V3_MIGRATION_PERIOD_MS) retireV2HiddenService();
|
||||||
else publishV2HiddenService(port, privKey2);
|
else publishV2HiddenService(port, privKey2);
|
||||||
}
|
}
|
||||||
|
if (isNullOrEmpty(privKey3)) {
|
||||||
|
TransportProperties p = callback.getLocalProperties();
|
||||||
|
privKey3 = p.get(HS_PRIVATE_KEY_V3);
|
||||||
|
}
|
||||||
publishV3HiddenService(port, privKey3);
|
publishV3HiddenService(port, privKey3);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,9 +515,11 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
try {
|
try {
|
||||||
// Use the control connection to set up the hidden service
|
// Use the control connection to set up the hidden service
|
||||||
if (privKey == null) {
|
if (privKey == null) {
|
||||||
|
LOG.info("Private key is null");
|
||||||
response = controlConnection.addOnion("NEW:ED25519-V3",
|
response = controlConnection.addOnion("NEW:ED25519-V3",
|
||||||
portLines, null);
|
portLines, null);
|
||||||
} else {
|
} else {
|
||||||
|
LOG.info("Private key is not null");
|
||||||
response = controlConnection.addOnion(privKey, portLines);
|
response = controlConnection.addOnion(privKey, portLines);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -535,12 +541,15 @@ abstract class TorPlugin implements DuplexPlugin, EventHandler, EventListener {
|
|||||||
if (privKey == null) {
|
if (privKey == null) {
|
||||||
// Publish the hidden service's onion hostname in transport props
|
// Publish the hidden service's onion hostname in transport props
|
||||||
TransportProperties p = new TransportProperties();
|
TransportProperties p = new TransportProperties();
|
||||||
|
String now = String.valueOf(clock.currentTimeMillis());
|
||||||
p.put(PROP_ONION_V3, onion3);
|
p.put(PROP_ONION_V3, onion3);
|
||||||
|
p.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY));
|
||||||
|
p.put(HS_V3_CREATED, now);
|
||||||
callback.mergeLocalProperties(p);
|
callback.mergeLocalProperties(p);
|
||||||
// Save the hidden service's private key for next time
|
// Save the hidden service's private key for next time
|
||||||
Settings s = new Settings();
|
Settings s = new Settings();
|
||||||
s.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY));
|
s.put(HS_PRIVATE_KEY_V3, response.get(HS_PRIVKEY));
|
||||||
s.put(HS_V3_CREATED, String.valueOf(clock.currentTimeMillis()));
|
s.put(HS_V3_CREATED, now);
|
||||||
callback.mergeSettings(s);
|
callback.mergeSettings(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -128,6 +128,7 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
throws DbException, GeneralSecurityException {
|
throws DbException, GeneralSecurityException {
|
||||||
SecretKey staticMasterKey = transportCrypto
|
SecretKey staticMasterKey = transportCrypto
|
||||||
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
.deriveStaticMasterKey(theirPublicKey, ourKeyPair);
|
||||||
|
LOG.info("Deriving root handshake key " + c.toString() + " " + ourKeyPair.getPublic().toString() + " them: " + theirPublicKey.toString());
|
||||||
SecretKey rootKey =
|
SecretKey rootKey =
|
||||||
transportCrypto.deriveHandshakeRootKey(staticMasterKey, false);
|
transportCrypto.deriveHandshakeRootKey(staticMasterKey, false);
|
||||||
boolean alice = transportCrypto.isAlice(theirPublicKey, ourKeyPair);
|
boolean alice = transportCrypto.isAlice(theirPublicKey, ourKeyPair);
|
||||||
@@ -135,6 +136,7 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
|
for (Entry<TransportId, TransportKeyManager> e : managers.entrySet()) {
|
||||||
TransportId t = e.getKey();
|
TransportId t = e.getKey();
|
||||||
TransportKeyManager m = e.getValue();
|
TransportKeyManager m = e.getValue();
|
||||||
|
LOG.info("Adding handshake keys for transport " + t.getString());
|
||||||
ids.put(t, m.addHandshakeKeys(txn, c, rootKey, alice));
|
ids.put(t, m.addHandshakeKeys(txn, c, rootKey, alice));
|
||||||
}
|
}
|
||||||
return ids;
|
return ids;
|
||||||
@@ -205,6 +207,14 @@ class KeyManagerImpl implements KeyManager, Service, EventListener {
|
|||||||
m.getStreamContext(txn, tag)));
|
m.getStreamContext(txn, tag)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamContext getStreamContextInHandshakeMode(ContactId c, TransportId t)
|
||||||
|
throws DbException {
|
||||||
|
return withManager(t, m ->
|
||||||
|
db.transactionWithNullableResult(false, txn ->
|
||||||
|
m.getStreamContextInHandshakeMode(txn, c)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void eventOccurred(Event e) {
|
public void eventOccurred(Event e) {
|
||||||
if (e instanceof ContactRemovedEvent) {
|
if (e instanceof ContactRemovedEvent) {
|
||||||
|
|||||||
@@ -48,4 +48,7 @@ interface TransportKeyManager {
|
|||||||
StreamContext getStreamContext(Transaction txn, byte[] tag)
|
StreamContext getStreamContext(Transaction txn, byte[] tag)
|
||||||
throws DbException;
|
throws DbException;
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
StreamContext getStreamContextInHandshakeMode(Transaction txn, ContactId c)
|
||||||
|
throws DbException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import org.briarproject.bramble.api.transport.StreamContext;
|
|||||||
import org.briarproject.bramble.api.transport.TransportKeySet;
|
import org.briarproject.bramble.api.transport.TransportKeySet;
|
||||||
import org.briarproject.bramble.api.transport.TransportKeys;
|
import org.briarproject.bramble.api.transport.TransportKeys;
|
||||||
import org.briarproject.bramble.transport.ReorderingWindow.Change;
|
import org.briarproject.bramble.transport.ReorderingWindow.Change;
|
||||||
|
import org.briarproject.bramble.util.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -182,9 +183,12 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
if (old == null || (old.getKeys().isHandshakeMode() &&
|
if (old == null || (old.getKeys().isHandshakeMode() &&
|
||||||
!ks.getKeys().isHandshakeMode()) ||
|
!ks.getKeys().isHandshakeMode()) ||
|
||||||
old.getKeySetId().getInt() < ks.getKeySetId().getInt()) {
|
old.getKeySetId().getInt() < ks.getKeySetId().getInt()) {
|
||||||
|
LOG.info("Replacing Outgoing keys!");
|
||||||
if (ks.getContactId() == null)
|
if (ks.getContactId() == null)
|
||||||
pendingContactOutContexts.put(ks.getPendingContactId(), ks);
|
pendingContactOutContexts.put(ks.getPendingContactId(), ks);
|
||||||
else contactOutContexts.put(ks.getContactId(), ks);
|
else contactOutContexts.put(ks.getContactId(), ks);
|
||||||
|
} else {
|
||||||
|
LOG.info("Not replacing Outgoing keys!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -372,6 +376,9 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
MutableTransportKeySet ks = getOutgoingKeySet(c, p);
|
MutableTransportKeySet ks = getOutgoingKeySet(c, p);
|
||||||
if (ks == null) return null;
|
if (ks == null) return null;
|
||||||
MutableTransportKeys keys = ks.getKeys();
|
MutableTransportKeys keys = ks.getKeys();
|
||||||
|
|
||||||
|
LOG.info("Using keys for outgoing connection - handshake mode: " +
|
||||||
|
keys.isHandshakeMode());
|
||||||
MutableOutgoingKeys outKeys = keys.getCurrentOutgoingKeys();
|
MutableOutgoingKeys outKeys = keys.getCurrentOutgoingKeys();
|
||||||
if (!outKeys.isActive()) throw new AssertionError();
|
if (!outKeys.isActive()) throw new AssertionError();
|
||||||
if (outKeys.getStreamCounter() > MAX_32_BIT_UNSIGNED) return null;
|
if (outKeys.getStreamCounter() > MAX_32_BIT_UNSIGNED) return null;
|
||||||
@@ -395,7 +402,18 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
try {
|
try {
|
||||||
// Look up the incoming keys for the tag
|
// Look up the incoming keys for the tag
|
||||||
TagContext tagCtx = inContexts.remove(new Bytes(tag));
|
TagContext tagCtx = inContexts.remove(new Bytes(tag));
|
||||||
if (tagCtx == null) return null;
|
if (tagCtx == null) {
|
||||||
|
LOG.info("Cannot find tag!");
|
||||||
|
for (MutableTransportKeySet t : keys.values()) {
|
||||||
|
LOG.info("Header key: " + StringUtils
|
||||||
|
.toHexString(t.getKeys().getCurrentIncomingKeys()
|
||||||
|
.getHeaderKey().getBytes()));
|
||||||
|
LOG.info("Tag key: " + StringUtils.toHexString(
|
||||||
|
t.getKeys().getCurrentIncomingKeys().getTagKey()
|
||||||
|
.getBytes()));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
MutableIncomingKeys inKeys = tagCtx.inKeys;
|
MutableIncomingKeys inKeys = tagCtx.inKeys;
|
||||||
// Create a stream context
|
// Create a stream context
|
||||||
StreamContext ctx = new StreamContext(tagCtx.contactId,
|
StreamContext ctx = new StreamContext(tagCtx.contactId,
|
||||||
@@ -443,6 +461,51 @@ class TransportKeyManagerImpl implements TransportKeyManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamContext getStreamContextInHandshakeMode(Transaction txn,
|
||||||
|
ContactId c)
|
||||||
|
throws DbException {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
MutableTransportKeySet ks = getOutgoingKeySet(c, null);
|
||||||
|
if (ks == null) return null;
|
||||||
|
MutableTransportKeys currentKeys = ks.getKeys();
|
||||||
|
LOG.info("Current keys handshake mode? " +
|
||||||
|
currentKeys.isHandshakeMode());
|
||||||
|
if (currentKeys.isHandshakeMode())
|
||||||
|
return getStreamContext(txn, c, null);
|
||||||
|
|
||||||
|
for (MutableTransportKeySet keySet : this.keys.values()) {
|
||||||
|
MutableTransportKeys keys = keySet.getKeys();
|
||||||
|
if (!keys.isHandshakeMode()) continue;
|
||||||
|
LOG.info("Found handshake mode keys");
|
||||||
|
MutableOutgoingKeys outKeys = keys.getCurrentOutgoingKeys();
|
||||||
|
// if (!outKeys.isActive()) throw new AssertionError();
|
||||||
|
if (outKeys.getStreamCounter() > MAX_32_BIT_UNSIGNED)
|
||||||
|
return null;
|
||||||
|
// Create a stream context
|
||||||
|
LOG.info("Creating handshake mode stream context");
|
||||||
|
StreamContext ctx = new StreamContext(c, null, transportId,
|
||||||
|
outKeys.getTagKey(), outKeys.getHeaderKey(),
|
||||||
|
outKeys.getStreamCounter(), keys.isHandshakeMode());
|
||||||
|
LOG.info("Tag key: " +
|
||||||
|
StringUtils.toHexString(outKeys.getTagKey().getBytes()));
|
||||||
|
LOG.info("Header key: " +
|
||||||
|
StringUtils.toHexString(outKeys.getHeaderKey().getBytes()));
|
||||||
|
// Increment the stream counter and write it back to the DB
|
||||||
|
outKeys.incrementStreamCounter();
|
||||||
|
db.incrementStreamCounter(txn, transportId,
|
||||||
|
keySet.getKeySetId());
|
||||||
|
LOG.info("Returning");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
LOG.info("Cannot find handshake mode keys");
|
||||||
|
return null;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@DatabaseExecutor
|
@DatabaseExecutor
|
||||||
@Wakeful
|
@Wakeful
|
||||||
private void updateKeys(Transaction txn) throws DbException {
|
private void updateKeys(Transaction txn) throws DbException {
|
||||||
|
|||||||
@@ -201,6 +201,9 @@ public class RestoreAccountImpl implements RestoreAccount {
|
|||||||
transportPropertyManager
|
transportPropertyManager
|
||||||
.mergeLocalProperties(propertiesEntry.getKey(),
|
.mergeLocalProperties(propertiesEntry.getKey(),
|
||||||
propertiesEntry.getValue());
|
propertiesEntry.getValue());
|
||||||
|
// for (Map.Entry<String, String> entry : propertiesEntry.getValue().entrySet()) {
|
||||||
|
// LOG.info(String.format("%s : %s", entry.getKey(), entry.getValue()));
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user