Skip to content

Commit

Permalink
Use a new SVR2 enclave.
Browse files Browse the repository at this point in the history
  • Loading branch information
AsamK committed Dec 10, 2023
1 parent 2535cd9 commit 4dcdffd
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 61 deletions.
17 changes: 10 additions & 7 deletions lib/src/main/java/org/asamk/signal/manager/config/LiveConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@
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";
Expand Down Expand Up @@ -69,12 +72,12 @@ static ECPublicKey getUnidentifiedSenderTrustRoot() {
}
}

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() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,8 @@ public static ServiceEnvironmentConfig getServiceEnvironmentConfig(
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);
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
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
) {}
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,15 @@
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";
Expand Down Expand Up @@ -69,12 +72,12 @@ static ECPublicKey getUnidentifiedSenderTrustRoot() {
}
}

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() {
Expand Down
92 changes: 61 additions & 31 deletions lib/src/main/java/org/asamk/signal/manager/helper/PinHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,49 @@
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;
}
}

Expand All @@ -46,27 +56,47 @@ public void migrateRegistrationLockPin(String pin, MasterKey masterKey) throws I
}

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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
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;

Expand Down Expand Up @@ -90,7 +91,10 @@ public RegistrationManagerImpl(
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);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,14 @@
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;
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -192,9 +193,12 @@ public SignalServiceMessageSender getMessageSender() {
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() {
Expand Down

0 comments on commit 4dcdffd

Please sign in to comment.