From 36b24d0a20a01d5570545e521f12d1581bf4597c Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 21 Nov 2018 17:26:06 -0800 Subject: [PATCH] Rotate sender cert at send time if it's expired. --- .../securesms/jobs/PushGroupSendJob.java | 2 ++ .../securesms/jobs/PushMediaSendJob.java | 2 ++ .../securesms/jobs/PushSendJob.java | 25 +++++++++++++++++-- .../securesms/jobs/PushTextSendJob.java | 2 ++ .../securesms/jobs/RotateCertificateJob.java | 6 +++-- 5 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index 1a0f7a9210..3d2e59f11c 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -203,6 +203,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType { throws IOException, RecipientFormattingException, InvalidNumberException, UndeliverableMessageException, UntrustedIdentityException { + rotateSenderCertificateIfNecessary(); + String groupId = message.getRecipient().getAddress().toGroupString(); Optional profileKey = getProfileKey(message.getRecipient()); MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints(); diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index b8d41cbe69..6c69992aca 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -156,6 +156,8 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType { } try { + rotateSenderCertificateIfNecessary(); + SignalServiceAddress address = getPushAddress(message.getRecipient().getAddress()); MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints(); List scaledAttachments = scaleAndStripExifFromAttachments(mediaConstraints, message.getAttachments()); diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java index 11c52595f2..3d78341f7b 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -4,6 +4,8 @@ import android.content.Context; import android.support.annotation.NonNull; import org.greenrobot.eventbus.EventBus; +import org.signal.libsignal.metadata.certificate.InvalidCertificateException; +import org.signal.libsignal.metadata.certificate.SenderCertificate; import org.thoughtcrime.securesms.ApplicationContext; import org.thoughtcrime.securesms.TextSecureExpiredException; import org.thoughtcrime.securesms.attachments.Attachment; @@ -41,8 +43,9 @@ import java.util.concurrent.TimeUnit; public abstract class PushSendJob extends SendJob { - private static final long serialVersionUID = 5906098204770900739L; - private static final String TAG = PushSendJob.class.getSimpleName(); + private static final long serialVersionUID = 5906098204770900739L; + private static final String TAG = PushSendJob.class.getSimpleName(); + private static final long CERTIFICATE_EXPIRATION_BUFFER = TimeUnit.DAYS.toMillis(1); protected PushSendJob(Context context, JobParameters parameters) { super(context, parameters); @@ -199,5 +202,23 @@ public abstract class PushSendJob extends SendJob { return sharedContacts; } + protected void rotateSenderCertificateIfNecessary() throws IOException { + try { + SenderCertificate certificate = new SenderCertificate(TextSecurePreferences.getUnidentifiedAccessCertificate(context)); + + if (System.currentTimeMillis() > (certificate.getExpiration() - CERTIFICATE_EXPIRATION_BUFFER)) { + throw new InvalidCertificateException("Certificate is expired, or close to it. Expires on: " + certificate.getExpiration() + ", currently: " + System.currentTimeMillis()); + } + + Log.d(TAG, "Certificate is valid."); + } catch (InvalidCertificateException e) { + Log.w(TAG, "Certificate was invalid at send time. Fetching a new one.", e); + RotateCertificateJob certificateJob = new RotateCertificateJob(); + ApplicationContext.getInstance(context).injectDependencies(certificateJob); + certificateJob.setContext(context); + certificateJob.onRun(); + } + } + protected abstract void onPushSend() throws Exception; } diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index f127ef458c..47aefe0192 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -151,6 +151,8 @@ public class PushTextSendJob extends PushSendJob implements InjectableType { throws UntrustedIdentityException, InsecureFallbackApprovalException, RetryLaterException { try { + rotateSenderCertificateIfNecessary(); + SignalServiceAddress address = getPushAddress(message.getIndividualRecipient().getAddress()); Optional profileKey = getProfileKey(message.getIndividualRecipient()); Optional unidentifiedAccess = UnidentifiedAccessUtil.getAccessFor(context, message.getIndividualRecipient()); diff --git a/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java b/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java index 15f9bd94f0..94ab124beb 100644 --- a/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RotateCertificateJob.java @@ -55,8 +55,10 @@ public class RotateCertificateJob extends ContextJob implements InjectableType { @Override public void onRun() throws IOException { - byte[] certificate = accountManager.getSenderCertificate(); - TextSecurePreferences.setUnidentifiedAccessCertificate(context, certificate); + synchronized (RotateCertificateJob.class) { + byte[] certificate = accountManager.getSenderCertificate(); + TextSecurePreferences.setUnidentifiedAccessCertificate(context, certificate); + } } @Override