]> nmode's Git Repositories - signal-cli/commitdiff
Use a new SVR2 enclave.
authorAsamK <asamk@gmx.de>
Sun, 10 Dec 2023 18:30:36 +0000 (19:30 +0100)
committerAsamK <asamk@gmx.de>
Sun, 10 Dec 2023 18:30:36 +0000 (19:30 +0100)
lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java
lib/src/main/java/org/asamk/signal/manager/config/ServiceConfig.java
lib/src/main/java/org/asamk/signal/manager/config/ServiceEnvironmentConfig.java
lib/src/main/java/org/asamk/signal/manager/config/StagingConfig.java
lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
lib/src/main/java/org/asamk/signal/manager/internal/RegistrationManagerImpl.java
lib/src/main/java/org/asamk/signal/manager/internal/SignalDependencies.java

index 300371bd077f0e44d44e63480f527144a0d465ad..a0806e315567b0e788b840f032f7a1defbe53e0b 100644 (file)
@@ -20,12 +20,15 @@ import java.util.Optional;
 import okhttp3.Dns;
 import okhttp3.Interceptor;
 
+import static org.asamk.signal.manager.api.ServiceEnvironment.LIVE;
+
 class LiveConfig {
 
     private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
             .decode("BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF");
     private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
-    private static final String SVR2_MRENCLAVE = "6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094";
+    private static final String SVR2_MRENCLAVE = "a6622ad4656e1abcd0bc0ff17c229477747d2ded0495c4ebee7ed35c1789fa97";
+    private static final String SVR2_MRENCLAVE_DEPRECATED = "6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094";
 
     private static final String URL = "https://chat.signal.org";
     private static final String CDN_URL = "https://cdn.signal.org";
@@ -69,12 +72,12 @@ class LiveConfig {
         }
     }
 
-    static String getCdsiMrenclave() {
-        return CDSI_MRENCLAVE;
-    }
-
-    static String getSvr2Mrenclave() {
-        return SVR2_MRENCLAVE;
+    static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
+        return new ServiceEnvironmentConfig(LIVE,
+                createDefaultServiceConfiguration(interceptors),
+                getUnidentifiedSenderTrustRoot(),
+                CDSI_MRENCLAVE,
+                List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
     }
 
     private LiveConfig() {
index 18ff2ce8c706061ccde2262317cd82274c383c6c..cd103f801d088ed9958a411a362651d9890b91a0 100644 (file)
@@ -43,16 +43,8 @@ public class ServiceConfig {
         final var interceptors = List.of(userAgentInterceptor);
 
         return switch (serviceEnvironment) {
-            case LIVE -> new ServiceEnvironmentConfig(serviceEnvironment,
-                    LiveConfig.createDefaultServiceConfiguration(interceptors),
-                    LiveConfig.getUnidentifiedSenderTrustRoot(),
-                    LiveConfig.getCdsiMrenclave(),
-                    LiveConfig.getSvr2Mrenclave());
-            case STAGING -> new ServiceEnvironmentConfig(serviceEnvironment,
-                    StagingConfig.createDefaultServiceConfiguration(interceptors),
-                    StagingConfig.getUnidentifiedSenderTrustRoot(),
-                    StagingConfig.getCdsiMrenclave(),
-                    StagingConfig.getSvr2Mrenclave());
+            case LIVE -> LiveConfig.getServiceEnvironmentConfig(interceptors);
+            case STAGING -> StagingConfig.getServiceEnvironmentConfig(interceptors);
         };
     }
 }
index 9664dcae0ab96152fabea6c90c1564d845d74693..f4622064c939d850ce7274e4b8c52c1224d626cb 100644 (file)
@@ -4,10 +4,12 @@ import org.asamk.signal.manager.api.ServiceEnvironment;
 import org.signal.libsignal.protocol.ecc.ECPublicKey;
 import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
 
+import java.util.List;
+
 public record ServiceEnvironmentConfig(
         ServiceEnvironment type,
         SignalServiceConfiguration signalServiceConfiguration,
         ECPublicKey unidentifiedSenderTrustRoot,
         String cdsiMrenclave,
-        String svr2Mrenclave
+        List<String> svr2Mrenclaves
 ) {}
index f90ae48b1588741b9f85d0506488c1399902176f..4409b0054752c44f2c13e1d33b4358828d7dda3b 100644 (file)
@@ -20,12 +20,15 @@ import java.util.Optional;
 import okhttp3.Dns;
 import okhttp3.Interceptor;
 
+import static org.asamk.signal.manager.api.ServiceEnvironment.STAGING;
+
 class StagingConfig {
 
     private static final byte[] UNIDENTIFIED_SENDER_TRUST_ROOT = Base64.getDecoder()
             .decode("BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx");
     private static final String CDSI_MRENCLAVE = "0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57";
-    private static final String SVR2_MRENCLAVE = "a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95";
+    private static final String SVR2_MRENCLAVE = "acb1973aa0bbbd14b3b4e06f145497d948fd4a98efc500fcce363b3b743ec482";
+    private static final String SVR2_MRENCLAVE_DEPRECATED = "a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95";
 
     private static final String URL = "https://chat.staging.signal.org";
     private static final String CDN_URL = "https://cdn-staging.signal.org";
@@ -69,12 +72,12 @@ class StagingConfig {
         }
     }
 
-    static String getCdsiMrenclave() {
-        return CDSI_MRENCLAVE;
-    }
-
-    static String getSvr2Mrenclave() {
-        return SVR2_MRENCLAVE;
+    static ServiceEnvironmentConfig getServiceEnvironmentConfig(List<Interceptor> interceptors) {
+        return new ServiceEnvironmentConfig(STAGING,
+                createDefaultServiceConfiguration(interceptors),
+                getUnidentifiedSenderTrustRoot(),
+                CDSI_MRENCLAVE,
+                List.of(SVR2_MRENCLAVE, SVR2_MRENCLAVE_DEPRECATED));
     }
 
     private StagingConfig() {
index 824b278bca8f012034ec9d939f7ac6f8a7e1f50e..0bcfe09ee3559c8a9d19cc0a2b1d8ca05b5ede36 100644 (file)
@@ -5,39 +5,49 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.whispersystems.signalservice.api.kbs.MasterKey;
 import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
-import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
 import org.whispersystems.signalservice.internal.push.AuthCredentials;
 import org.whispersystems.signalservice.internal.push.LockedException;
 
 import java.io.IOException;
+import java.util.List;
 
 public class PinHelper {
 
     private static final Logger logger = LoggerFactory.getLogger(PinHelper.class);
 
-    private final SecureValueRecoveryV2 secureValueRecoveryV2;
+    private final List<SecureValueRecovery> secureValueRecoveries;
 
-    public PinHelper(final SecureValueRecoveryV2 secureValueRecoveryV2) {
-        this.secureValueRecoveryV2 = secureValueRecoveryV2;
+    public PinHelper(final List<SecureValueRecovery> secureValueRecoveries) {
+        this.secureValueRecoveries = secureValueRecoveries;
     }
 
     public void setRegistrationLockPin(
             String pin, MasterKey masterKey
     ) throws IOException {
-        final var backupResponse = secureValueRecoveryV2.setPin(pin, masterKey).execute();
-        switch (backupResponse) {
-            case SecureValueRecovery.BackupResponse.Success success -> {
+        IOException exception = null;
+        for (final var secureValueRecovery : secureValueRecoveries) {
+            try {
+                final var backupResponse = secureValueRecovery.setPin(pin, masterKey).execute();
+                switch (backupResponse) {
+                    case SecureValueRecovery.BackupResponse.Success success -> {
+                    }
+                    case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
+                            logger.warn("Backup svr2 failed: ServerRejected");
+                    case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
+                            logger.warn("Backup svr2 failed: EnclaveNotFound");
+                    case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
+                            logger.warn("Backup svr2 failed: ExposeFailure");
+                    case SecureValueRecovery.BackupResponse.ApplicationError error ->
+                            throw new IOException(error.getException());
+                    case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
+                    case null, default -> throw new AssertionError("Unexpected response");
+                }
+            } catch (IOException e) {
+                exception = e;
             }
-            case SecureValueRecovery.BackupResponse.ServerRejected serverRejected ->
-                    logger.warn("Backup svr2 failed: ServerRejected");
-            case SecureValueRecovery.BackupResponse.EnclaveNotFound enclaveNotFound ->
-                    logger.warn("Backup svr2 failed: EnclaveNotFound");
-            case SecureValueRecovery.BackupResponse.ExposeFailure exposeFailure ->
-                    logger.warn("Backup svr2 failed: ExposeFailure");
-            case SecureValueRecovery.BackupResponse.ApplicationError error ->
-                    throw new IOException(error.getException());
-            case SecureValueRecovery.BackupResponse.NetworkError error -> throw error.getException();
-            case null, default -> throw new AssertionError("Unexpected response");
+        }
+        if (exception != null) {
+            throw exception;
         }
     }
 
@@ -46,27 +56,47 @@ public class PinHelper {
     }
 
     public void removeRegistrationLockPin() throws IOException {
-        final var deleteResponse = secureValueRecoveryV2.deleteData();
-        switch (deleteResponse) {
-            case SecureValueRecovery.DeleteResponse.Success success -> {
+        IOException exception = null;
+        for (final var secureValueRecovery : secureValueRecoveries) {
+            try {
+                final var deleteResponse = secureValueRecovery.deleteData();
+                switch (deleteResponse) {
+                    case SecureValueRecovery.DeleteResponse.Success success -> {
+                    }
+                    case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
+                            logger.warn("Delete svr2 failed: ServerRejected");
+                    case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
+                            logger.warn("Delete svr2 failed: EnclaveNotFound");
+                    case SecureValueRecovery.DeleteResponse.ApplicationError error ->
+                            throw new IOException(error.getException());
+                    case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
+                    case null, default -> throw new AssertionError("Unexpected response");
+                }
+            } catch (IOException e) {
+                exception = e;
             }
-            case SecureValueRecovery.DeleteResponse.ServerRejected serverRejected ->
-                    logger.warn("Delete svr2 failed: ServerRejected");
-            case SecureValueRecovery.DeleteResponse.EnclaveNotFound enclaveNotFound ->
-                    logger.warn("Delete svr2 failed: EnclaveNotFound");
-            case SecureValueRecovery.DeleteResponse.ApplicationError error ->
-                    throw new IOException(error.getException());
-            case SecureValueRecovery.DeleteResponse.NetworkError error -> throw error.getException();
-            case null, default -> throw new AssertionError("Unexpected response");
+        }
+        if (exception != null) {
+            throw exception;
         }
     }
 
     public SecureValueRecovery.RestoreResponse.Success getRegistrationLockData(
-            String pin, LockedException e
+            String pin, LockedException lockedException
     ) throws IOException, IncorrectPinException {
-        var svr2Credentials = e.getSvr2Credentials();
+        var svr2Credentials = lockedException.getSvr2Credentials();
         if (svr2Credentials != null) {
-            return getRegistrationLockData(secureValueRecoveryV2, svr2Credentials, pin);
+            IOException exception = null;
+            for (final var secureValueRecovery : secureValueRecoveries) {
+                try {
+                    return getRegistrationLockData(secureValueRecovery, svr2Credentials, pin);
+                } catch (IOException e) {
+                    exception = e;
+                }
+            }
+            if (exception != null) {
+                throw exception;
+            }
         }
 
         return null;
index d66ab214c8b1544164df41e5a8c655dce8ce4ebb..ec200966080bd3ff8f2029d86dd53c65f64bb53d 100644 (file)
@@ -45,6 +45,7 @@ import org.whispersystems.signalservice.api.push.ServiceIdType;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.push.exceptions.AlreadyVerifiedException;
 import org.whispersystems.signalservice.api.push.exceptions.DeprecatedVersionException;
+import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
 import org.whispersystems.signalservice.internal.push.VerifyAccountResponse;
 import org.whispersystems.signalservice.internal.util.DynamicCredentialsProvider;
 
@@ -90,7 +91,10 @@ public class RegistrationManagerImpl implements RegistrationManager {
                 userAgent,
                 groupsV2Operations,
                 ServiceConfig.AUTOMATIC_NETWORK_RETRY);
-        final var secureValueRecoveryV2 = accountManager.getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave());
+        final var secureValueRecoveryV2 = serviceEnvironmentConfig.svr2Mrenclaves()
+                .stream()
+                .map(mr -> (SecureValueRecovery) accountManager.getSecureValueRecoveryV2(mr))
+                .toList();
         this.pinHelper = new PinHelper(secureValueRecoveryV2);
     }
 
index 8b5f3e269d0dff0440a3bf49150302494ff6a02c..9fb7aff49c3eb04a9c1b2633673daea203a88330 100644 (file)
@@ -16,13 +16,14 @@ import org.whispersystems.signalservice.api.groupsv2.GroupsV2Api;
 import org.whispersystems.signalservice.api.groupsv2.GroupsV2Operations;
 import org.whispersystems.signalservice.api.push.SignalServiceAddress;
 import org.whispersystems.signalservice.api.services.ProfileService;
-import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV2;
+import org.whispersystems.signalservice.api.svr.SecureValueRecovery;
 import org.whispersystems.signalservice.api.util.CredentialsProvider;
 import org.whispersystems.signalservice.api.util.UptimeSleepTimer;
 import org.whispersystems.signalservice.api.websocket.WebSocketFactory;
 import org.whispersystems.signalservice.internal.push.PushServiceSocket;
 import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
 
+import java.util.List;
 import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Supplier;
@@ -50,7 +51,7 @@ public class SignalDependencies {
     private SignalServiceMessageReceiver messageReceiver;
     private SignalServiceMessageSender messageSender;
 
-    private SecureValueRecoveryV2 secureValueRecoveryV2;
+    private List<SecureValueRecovery> secureValueRecoveryV2;
     private ProfileService profileService;
     private SignalServiceCipher cipher;
 
@@ -192,9 +193,12 @@ public class SignalDependencies {
                         pushServiceSocket));
     }
 
-    public SecureValueRecoveryV2 getSecureValueRecoveryV2() {
+    public List<SecureValueRecovery> getSecureValueRecoveryV2() {
         return getOrCreate(() -> secureValueRecoveryV2,
-                () -> secureValueRecoveryV2 = getAccountManager().getSecureValueRecoveryV2(serviceEnvironmentConfig.svr2Mrenclave()));
+                () -> secureValueRecoveryV2 = serviceEnvironmentConfig.svr2Mrenclaves()
+                        .stream()
+                        .map(mr -> (SecureValueRecovery) getAccountManager().getSecureValueRecoveryV2(mr))
+                        .toList());
     }
 
     public ProfileService getProfileService() {