From 0558d5f0b386ee3b7e4059e50effff161f16147c Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 9 Feb 2022 12:12:41 -0500 Subject: [PATCH] Clear sender key shared state on archive and prekey message receive. We need to clear the sender key shared state whenever a registrationId changes. We don't have good hooks for that on Android, so instead we're just going to reset on every archive and prekey receive. It's a little overzealous, but given these are rare events anyway, it shouldn't be a big deal. --- .../SignalServiceAccountDataStoreImpl.java | 2 ++ .../messages/MessageDecryptionUtil.java | 9 +++++---- .../api/SignalServiceMessageSender.java | 2 -- .../api/crypto/SignalServiceCipher.java | 16 +++++++++++----- 4 files changed, 18 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceAccountDataStoreImpl.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceAccountDataStoreImpl.java index a4628079e7..4cb0dcce8d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceAccountDataStoreImpl.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceAccountDataStoreImpl.java @@ -19,6 +19,7 @@ import org.whispersystems.signalservice.api.SignalServiceAccountDataStore; import org.whispersystems.signalservice.api.push.DistributionId; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Set; import java.util.UUID; @@ -139,6 +140,7 @@ public class SignalServiceAccountDataStoreImpl implements SignalServiceAccountDa @Override public void archiveSession(SignalProtocolAddress address) { sessionStore.archiveSession(address); + senderKeyStore.clearSenderKeySharedWith(Collections.singleton(address)); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java index 3e823a9fcf..e6dbaf3cf7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java @@ -47,6 +47,7 @@ import org.whispersystems.libsignal.protocol.DecryptionErrorMessage; import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.InvalidMessageStructureException; +import org.whispersystems.signalservice.api.SignalServiceAccountDataStore; import org.whispersystems.signalservice.api.crypto.ContentHint; import org.whispersystems.signalservice.api.crypto.SignalServiceCipher; import org.whispersystems.signalservice.api.messages.SignalServiceContent; @@ -76,10 +77,10 @@ public final class MessageDecryptionUtil { * caller. */ public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) { - SignalProtocolStore axolotlStore = ApplicationDependencies.getProtocolStore().aci(); - SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireAci(), Recipient.self().requireE164()); - SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), axolotlStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator()); - List jobs = new LinkedList<>(); + SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci(); + SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireAci(), Recipient.self().requireE164()); + SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator()); + List jobs = new LinkedList<>(); if (envelope.isPreKeySignalMessage()) { jobs.add(new RefreshPreKeysJob()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 3ea58481f0..40b37c56b8 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -2058,8 +2058,6 @@ public class SignalServiceMessageSender { for (SignalProtocolAddress address : addressesToClear) { store.archiveSession(address); } - - store.clearSenderKeySharedWith(addressesToClear); } private List convertToProtocolAddresses(SignalServiceAddress recipient, List devices) { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java index 8665170049..c42c5ae8e7 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java @@ -40,9 +40,9 @@ import org.whispersystems.libsignal.logging.Log; import org.whispersystems.libsignal.protocol.CiphertextMessage; import org.whispersystems.libsignal.protocol.PreKeySignalMessage; import org.whispersystems.libsignal.protocol.SignalMessage; -import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.InvalidMessageStructureException; +import org.whispersystems.signalservice.api.SignalServiceAccountDataStore; import org.whispersystems.signalservice.api.SignalSessionLock; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; @@ -50,7 +50,6 @@ import org.whispersystems.signalservice.api.messages.SignalServiceMetadata; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.DistributionId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.OutgoingPushMessage; import org.whispersystems.signalservice.internal.push.PushTransportDetails; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; @@ -59,6 +58,7 @@ import org.whispersystems.signalservice.internal.serialize.SignalServiceAddressP import org.whispersystems.signalservice.internal.serialize.SignalServiceMetadataProtobufSerializer; import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceContentProto; +import java.util.Collections; import java.util.List; /** @@ -69,15 +69,15 @@ public class SignalServiceCipher { @SuppressWarnings("unused") private static final String TAG = SignalServiceCipher.class.getSimpleName(); - private final SignalProtocolStore signalProtocolStore; - private final SignalSessionLock sessionLock; + private final SignalServiceAccountDataStore signalProtocolStore; + private final SignalSessionLock sessionLock; private final SignalServiceAddress localAddress; private final int localDeviceId; private final CertificateValidator certificateValidator; public SignalServiceCipher(SignalServiceAddress localAddress, int localDeviceId, - SignalProtocolStore signalProtocolStore, + SignalServiceAccountDataStore signalProtocolStore, SignalSessionLock sessionLock, CertificateValidator certificateValidator) { @@ -195,6 +195,8 @@ public class SignalServiceCipher { paddedMessage = sessionCipher.decrypt(new PreKeySignalMessage(ciphertext)); metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent()); + + signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(sourceAddress)); } else if (envelope.isSignalMessage()) { SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSourceUuid().get(), envelope.getSourceDevice()); SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress)); @@ -213,6 +215,10 @@ public class SignalServiceCipher { needsReceipt = false; } + if (result.getCiphertextMessageType() == CiphertextMessage.PREKEY_TYPE) { + signalProtocolStore.clearSenderKeySharedWith(Collections.singleton(new SignalProtocolAddress(result.getSenderUuid(), result.getDeviceId()))); + } + paddedMessage = result.getPaddedMessage(); metadata = new SignalServiceMetadata(resultAddress, result.getDeviceId(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), needsReceipt, envelope.getServerGuid(), groupId); } else {