Search in sources :

Example 1 with InvalidMetadataMessageException

use of org.signal.libsignal.metadata.InvalidMetadataMessageException in project Signal-Android by WhisperSystems.

the class SignalServiceCipher method decrypt.

/**
 * Decrypt a received {@link SignalServiceEnvelope}
 *
 * @param envelope The received SignalServiceEnvelope
 *
 * @return a decrypted SignalServiceContent
 */
public SignalServiceContent decrypt(SignalServiceEnvelope envelope) throws InvalidMetadataMessageException, InvalidMetadataVersionException, ProtocolInvalidKeyIdException, ProtocolLegacyMessageException, ProtocolUntrustedIdentityException, ProtocolNoSessionException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyException, ProtocolDuplicateMessageException, SelfSendException, UnsupportedDataMessageException, InvalidMessageStructureException {
    try {
        if (envelope.hasLegacyMessage()) {
            Plaintext plaintext = decrypt(envelope, envelope.getLegacyMessage());
            SignalServiceProtos.DataMessage dataMessage = SignalServiceProtos.DataMessage.parseFrom(plaintext.getData());
            SignalServiceContentProto contentProto = SignalServiceContentProto.newBuilder().setLocalAddress(SignalServiceAddressProtobufSerializer.toProtobuf(localAddress)).setMetadata(SignalServiceMetadataProtobufSerializer.toProtobuf(plaintext.metadata)).setLegacyDataMessage(dataMessage).build();
            return SignalServiceContent.createFromProto(contentProto);
        } else if (envelope.hasContent()) {
            Plaintext plaintext = decrypt(envelope, envelope.getContent());
            SignalServiceProtos.Content content = SignalServiceProtos.Content.parseFrom(plaintext.getData());
            SignalServiceContentProto contentProto = SignalServiceContentProto.newBuilder().setLocalAddress(SignalServiceAddressProtobufSerializer.toProtobuf(localAddress)).setMetadata(SignalServiceMetadataProtobufSerializer.toProtobuf(plaintext.metadata)).setContent(content).build();
            return SignalServiceContent.createFromProto(contentProto);
        }
        return null;
    } catch (InvalidProtocolBufferException e) {
        throw new InvalidMetadataMessageException(e);
    }
}
Also used : SignalServiceProtos(org.whispersystems.signalservice.internal.push.SignalServiceProtos) SignalServiceContent(org.whispersystems.signalservice.api.messages.SignalServiceContent) PlaintextContent(org.whispersystems.libsignal.protocol.PlaintextContent) UnidentifiedSenderMessageContent(org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) SignalServiceContentProto(org.whispersystems.signalservice.internal.serialize.protos.SignalServiceContentProto) InvalidMetadataMessageException(org.signal.libsignal.metadata.InvalidMetadataMessageException)

Example 2 with InvalidMetadataMessageException

use of org.signal.libsignal.metadata.InvalidMetadataMessageException in project Signal-Android by WhisperSystems.

the class SignalServiceCipher method decrypt.

private Plaintext decrypt(SignalServiceEnvelope envelope, byte[] ciphertext) throws InvalidMetadataMessageException, InvalidMetadataVersionException, ProtocolDuplicateMessageException, ProtocolUntrustedIdentityException, ProtocolLegacyMessageException, ProtocolInvalidKeyException, ProtocolInvalidVersionException, ProtocolInvalidMessageException, ProtocolInvalidKeyIdException, ProtocolNoSessionException, SelfSendException, InvalidMessageStructureException {
    try {
        byte[] paddedMessage;
        SignalServiceMetadata metadata;
        if (!envelope.hasSourceUuid() && !envelope.isUnidentifiedSender()) {
            throw new InvalidMessageStructureException("Non-UD envelope is missing a UUID!");
        }
        if (envelope.isPreKeySignalMessage()) {
            SignalProtocolAddress sourceAddress = new SignalProtocolAddress(envelope.getSourceUuid().get(), envelope.getSourceDevice());
            SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, sourceAddress));
            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));
            paddedMessage = sessionCipher.decrypt(new SignalMessage(ciphertext));
            metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
        } else if (envelope.isPlaintextContent()) {
            paddedMessage = new PlaintextContent(ciphertext).getBody();
            metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent());
        } else if (envelope.isUnidentifiedSender()) {
            SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().uuid(), localAddress.getNumber().orNull(), localDeviceId));
            DecryptionResult result = sealedSessionCipher.decrypt(certificateValidator, ciphertext, envelope.getServerReceivedTimestamp());
            SignalServiceAddress resultAddress = new SignalServiceAddress(ACI.parseOrThrow(result.getSenderUuid()), result.getSenderE164());
            Optional<byte[]> groupId = result.getGroupId();
            boolean needsReceipt = true;
            if (envelope.hasSourceUuid()) {
                Log.w(TAG, "[" + envelope.getTimestamp() + "] Received a UD-encrypted message sent over an identified channel. Marking as needsReceipt=false");
                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 {
            throw new InvalidMetadataMessageException("Unknown type: " + envelope.getType());
        }
        PushTransportDetails transportDetails = new PushTransportDetails();
        byte[] data = transportDetails.getStrippedPaddingMessageBody(paddedMessage);
        return new Plaintext(metadata, data);
    } catch (DuplicateMessageException e) {
        throw new ProtocolDuplicateMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (LegacyMessageException e) {
        throw new ProtocolLegacyMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (InvalidMessageException e) {
        throw new ProtocolInvalidMessageException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (InvalidKeyIdException e) {
        throw new ProtocolInvalidKeyIdException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (InvalidKeyException e) {
        throw new ProtocolInvalidKeyException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (UntrustedIdentityException e) {
        throw new ProtocolUntrustedIdentityException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (InvalidVersionException e) {
        throw new ProtocolInvalidVersionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    } catch (NoSessionException e) {
        throw new ProtocolNoSessionException(e, envelope.getSourceIdentifier(), envelope.getSourceDevice());
    }
}
Also used : SealedSessionCipher(org.signal.libsignal.metadata.SealedSessionCipher) ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) UntrustedIdentityException(org.whispersystems.libsignal.UntrustedIdentityException) ProtocolUntrustedIdentityException(org.signal.libsignal.metadata.ProtocolUntrustedIdentityException) ProtocolUntrustedIdentityException(org.signal.libsignal.metadata.ProtocolUntrustedIdentityException) ProtocolInvalidVersionException(org.signal.libsignal.metadata.ProtocolInvalidVersionException) InvalidVersionException(org.whispersystems.libsignal.InvalidVersionException) InvalidMessageStructureException(org.whispersystems.signalservice.api.InvalidMessageStructureException) ProtocolInvalidVersionException(org.signal.libsignal.metadata.ProtocolInvalidVersionException) PlaintextContent(org.whispersystems.libsignal.protocol.PlaintextContent) ProtocolInvalidKeyIdException(org.signal.libsignal.metadata.ProtocolInvalidKeyIdException) NoSessionException(org.whispersystems.libsignal.NoSessionException) ProtocolNoSessionException(org.signal.libsignal.metadata.ProtocolNoSessionException) ProtocolDuplicateMessageException(org.signal.libsignal.metadata.ProtocolDuplicateMessageException) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) PushTransportDetails(org.whispersystems.signalservice.internal.push.PushTransportDetails) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ProtocolLegacyMessageException(org.signal.libsignal.metadata.ProtocolLegacyMessageException) SessionCipher(org.whispersystems.libsignal.SessionCipher) SealedSessionCipher(org.signal.libsignal.metadata.SealedSessionCipher) SignalProtocolAddress(org.whispersystems.libsignal.SignalProtocolAddress) ProtocolNoSessionException(org.signal.libsignal.metadata.ProtocolNoSessionException) PreKeySignalMessage(org.whispersystems.libsignal.protocol.PreKeySignalMessage) SignalMessage(org.whispersystems.libsignal.protocol.SignalMessage) Optional(org.whispersystems.libsignal.util.guava.Optional) SignalServiceMetadata(org.whispersystems.signalservice.api.messages.SignalServiceMetadata) InvalidKeyException(org.whispersystems.libsignal.InvalidKeyException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) InvalidMetadataMessageException(org.signal.libsignal.metadata.InvalidMetadataMessageException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) DuplicateMessageException(org.whispersystems.libsignal.DuplicateMessageException) ProtocolDuplicateMessageException(org.signal.libsignal.metadata.ProtocolDuplicateMessageException) DecryptionResult(org.signal.libsignal.metadata.SealedSessionCipher.DecryptionResult) InvalidKeyIdException(org.whispersystems.libsignal.InvalidKeyIdException) ProtocolInvalidKeyIdException(org.signal.libsignal.metadata.ProtocolInvalidKeyIdException) LegacyMessageException(org.whispersystems.libsignal.LegacyMessageException) ProtocolLegacyMessageException(org.signal.libsignal.metadata.ProtocolLegacyMessageException)

Example 3 with InvalidMetadataMessageException

use of org.signal.libsignal.metadata.InvalidMetadataMessageException in project Signal-Android by WhisperSystems.

the class MessageDecryptionUtil method decrypt.

/**
 * Takes a {@link SignalServiceEnvelope} and returns a {@link DecryptionResult}, which has either
 * a plaintext {@link SignalServiceContent} or information about an error that happened.
 *
 * Excluding the data updated in our protocol stores that results from decrypting a message, this
 * method is side-effect free, preferring to return the decryption results to be handled by the
 * caller.
 */
@NonNull
public static DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) {
    SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci();
    SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireServiceId(), Recipient.self().requireE164());
    SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator());
    List<Job> jobs = new LinkedList<>();
    if (envelope.isPreKeySignalMessage()) {
        jobs.add(new RefreshPreKeysJob());
    }
    try {
        try {
            return DecryptionResult.forSuccess(cipher.decrypt(envelope), jobs);
        } catch (ProtocolInvalidVersionException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            return DecryptionResult.forError(MessageState.INVALID_VERSION, toExceptionMetadata(e), jobs);
        } catch (ProtocolInvalidKeyIdException | ProtocolInvalidKeyException | ProtocolUntrustedIdentityException | ProtocolNoSessionException | ProtocolInvalidMessageException e) {
            Log.w(TAG, String.valueOf(envelope.getTimestamp()), e);
            Recipient sender = Recipient.external(context, e.getSender());
            if (sender.supportsMessageRetries() && Recipient.self().supportsMessageRetries() && FeatureFlags.retryReceipts()) {
                jobs.add(handleRetry(context, sender, envelope, e));
                postInternalErrorNotification(context);
            } else {
                jobs.add(new AutomaticSessionResetJob(sender.getId(), e.getSenderDevice(), envelope.getTimestamp()));
            }
            return DecryptionResult.forNoop(jobs);
        } catch (ProtocolLegacyMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.LEGACY_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (ProtocolDuplicateMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.DUPLICATE_MESSAGE, toExceptionMetadata(e), jobs);
        } catch (InvalidMetadataVersionException | InvalidMetadataMessageException | InvalidMessageStructureException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forNoop(jobs);
        } catch (SelfSendException e) {
            Log.i(TAG, "Dropping UD message from self.");
            return DecryptionResult.forNoop(jobs);
        } catch (UnsupportedDataMessageException e) {
            Log.w(TAG, "[" + envelope.getTimestamp() + "] " + envelope.getSourceIdentifier() + ":" + envelope.getSourceDevice(), e);
            return DecryptionResult.forError(MessageState.UNSUPPORTED_DATA_MESSAGE, toExceptionMetadata(e), jobs);
        }
    } catch (NoSenderException e) {
        Log.w(TAG, "Invalid message, but no sender info!");
        return DecryptionResult.forNoop(jobs);
    }
}
Also used : ProtocolInvalidMessageException(org.signal.libsignal.metadata.ProtocolInvalidMessageException) ProtocolUntrustedIdentityException(org.signal.libsignal.metadata.ProtocolUntrustedIdentityException) ProtocolInvalidVersionException(org.signal.libsignal.metadata.ProtocolInvalidVersionException) InvalidMessageStructureException(org.whispersystems.signalservice.api.InvalidMessageStructureException) SelfSendException(org.signal.libsignal.metadata.SelfSendException) ProtocolInvalidKeyIdException(org.signal.libsignal.metadata.ProtocolInvalidKeyIdException) ProtocolDuplicateMessageException(org.signal.libsignal.metadata.ProtocolDuplicateMessageException) UnsupportedDataMessageException(org.whispersystems.signalservice.internal.push.UnsupportedDataMessageException) SignalServiceAddress(org.whispersystems.signalservice.api.push.SignalServiceAddress) ProtocolLegacyMessageException(org.signal.libsignal.metadata.ProtocolLegacyMessageException) SignalServiceAccountDataStore(org.whispersystems.signalservice.api.SignalServiceAccountDataStore) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) SendRetryReceiptJob(org.thoughtcrime.securesms.jobs.SendRetryReceiptJob) Job(org.thoughtcrime.securesms.jobmanager.Job) RefreshPreKeysJob(org.thoughtcrime.securesms.jobs.RefreshPreKeysJob) ProtocolNoSessionException(org.signal.libsignal.metadata.ProtocolNoSessionException) SignalServiceCipher(org.whispersystems.signalservice.api.crypto.SignalServiceCipher) Recipient(org.thoughtcrime.securesms.recipients.Recipient) AutomaticSessionResetJob(org.thoughtcrime.securesms.jobs.AutomaticSessionResetJob) LinkedList(java.util.LinkedList) InvalidMetadataMessageException(org.signal.libsignal.metadata.InvalidMetadataMessageException) ProtocolInvalidKeyException(org.signal.libsignal.metadata.ProtocolInvalidKeyException) InvalidMetadataVersionException(org.signal.libsignal.metadata.InvalidMetadataVersionException) NonNull(androidx.annotation.NonNull)

Aggregations

InvalidMetadataMessageException (org.signal.libsignal.metadata.InvalidMetadataMessageException)3 ProtocolDuplicateMessageException (org.signal.libsignal.metadata.ProtocolDuplicateMessageException)2 ProtocolInvalidKeyException (org.signal.libsignal.metadata.ProtocolInvalidKeyException)2 ProtocolInvalidKeyIdException (org.signal.libsignal.metadata.ProtocolInvalidKeyIdException)2 ProtocolInvalidMessageException (org.signal.libsignal.metadata.ProtocolInvalidMessageException)2 ProtocolInvalidVersionException (org.signal.libsignal.metadata.ProtocolInvalidVersionException)2 ProtocolLegacyMessageException (org.signal.libsignal.metadata.ProtocolLegacyMessageException)2 ProtocolNoSessionException (org.signal.libsignal.metadata.ProtocolNoSessionException)2 ProtocolUntrustedIdentityException (org.signal.libsignal.metadata.ProtocolUntrustedIdentityException)2 PlaintextContent (org.whispersystems.libsignal.protocol.PlaintextContent)2 InvalidMessageStructureException (org.whispersystems.signalservice.api.InvalidMessageStructureException)2 SignalServiceAddress (org.whispersystems.signalservice.api.push.SignalServiceAddress)2 NonNull (androidx.annotation.NonNull)1 InvalidProtocolBufferException (com.google.protobuf.InvalidProtocolBufferException)1 LinkedList (java.util.LinkedList)1 InvalidMetadataVersionException (org.signal.libsignal.metadata.InvalidMetadataVersionException)1 SealedSessionCipher (org.signal.libsignal.metadata.SealedSessionCipher)1 DecryptionResult (org.signal.libsignal.metadata.SealedSessionCipher.DecryptionResult)1 SelfSendException (org.signal.libsignal.metadata.SelfSendException)1 UnidentifiedSenderMessageContent (org.signal.libsignal.metadata.protocol.UnidentifiedSenderMessageContent)1