diff --git a/app/build.gradle b/app/build.gradle index ee0f2f2b2..5b8a2c4f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -148,10 +148,14 @@ android { buildConfigField "String", "CDSH_PUBLIC_KEY", "\"2fe57da347cd62431528daac5fbb290730fff684afc4cfc2ed90995f58cb3b74\"" buildConfigField "String", "CDSH_CODE_HASH", "\"ec58c0d7561de8d5657f3a4b22a635eaa305204e9359dcc80a99dfd0c5f1cbf2\"" buildConfigField "String", "CDS_MRENCLAVE", "\"c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15\"" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\"," + - "\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\", " + - "\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")"; - buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[0]" + buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"0cedba03535b41b67729ce9924185f831d7767928a1d1689acb689bc079c375f\", " + + "\"187d2739d22be65e74b65f0055e74d31310e4267e5fac2b1246cc8beba81af39\", " + + "\"ee19f1965b1eefa3dc4204eb70c04f397755f771b8c1909d080c04dad2a6a9ba\")" + buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[] {" + + "new org.thoughtcrime.securesms.KbsEnclave(\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\", " + + "\"fe7c1bfae98f9b073d220366ea31163ee82f6d04bead774f71ca8e5c40847bfe\", " + + "\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")" + + "}" buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BXu6QIKVz5MA8gstzfOgRQGqyLqOwNKHL6INkv3IHWMF\"" buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X36nOoGPs54XsEGzPdEV+itQNGUFEjY6X9Uv+Acuks7NpyGvCoKxGwgKgE5XyJ+nNKlyHHOLb6N1NuHyBrZrgtY/JYJHRooo5CEqYKBqdFnmbTVGEkCvJKxLnjwKWf+fEPoWeQFj5ObDjcKMZf2Jm2Ae69x+ikU5gBXsRmoF94GXQ==\"" buildConfigField "String[]", "LANGUAGES", "new String[]{\"" + autoResConfig().collect { s -> s.replace('-r', '_') }.join('", "') + '"}' @@ -319,10 +323,14 @@ android { buildConfigField "String", "SIGNAL_CONTACT_DISCOVERY_URL", "\"https://api-staging.directory.signal.org\"" buildConfigField "String", "SIGNAL_KEY_BACKUP_URL", "\"https://api-staging.backup.signal.org\"" buildConfigField "String", "CDS_MRENCLAVE", "\"c98e00a4e3ff977a56afefe7362a27e4961e4f19e211febfbb19b897e6b80b15\"" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9\", " + - "\"16b94ac6d2b7f7b9d72928f36d798dbb35ed32e7bb14c42b4301ad0344b46f29\", " + - "\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[0]" + buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"dd6f66d397d9e8cf6ec6db238e59a7be078dd50e9715427b9c89b409ffe53f99\", " + + "\"4200003414528c151e2dccafbc87aa6d3d66a5eb8f8c05979a6e97cb33cd493a\", " + + "\"ee19f1965b1eefa3dc4204eb70c04f397755f771b8c1909d080c04dad2a6a9ba\")" + buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[] {" + + "new org.thoughtcrime.securesms.KbsEnclave(\"823a3b2c037ff0cbe305cc48928cfcc97c9ed4a8ca6d49af6f7d6981fb60a4e9\", " + + "\"16b94ac6d2b7f7b9d72928f36d798dbb35ed32e7bb14c42b4301ad0344b46f29\", " + + "\"a3baab19ef6ce6f34ab9ebb25ba722725ae44a8872dc0ff08ad6d83a9489de87\")" + + "}" buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx\"" buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXQ==\"" buildConfigField "String", "MOBILE_COIN_ENVIRONMENT", "\"testnet\"" diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index eb6b33817..2c0080459 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -96,9 +96,10 @@ public class ApplicationMigrations { static final int JUMBOMOJI_DOWNLOAD = 52; static final int FIX_EMOJI_QUALITY = 53; static final int CHANGE_NUMBER_CAPABILITY_4 = 54; + static final int KBS_MIGRATION = 55; } - public static final int CURRENT_VERSION = 54; + public static final int CURRENT_VERSION = 55; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -413,7 +414,11 @@ public class ApplicationMigrations { } if (lastSeenVersion < Version.CHANGE_NUMBER_CAPABILITY_4) { - jobs.put(Version.CHANGE_NUMBER_CAPABILITY_4, new AttributesMigrationJob()); + jobs.put(Version.CHANGE_NUMBER_CAPABILITY_4,new AttributesMigrationJob()); + } + + if (lastSeenVersion < Version.KBS_MIGRATION) { + jobs.put(Version.KBS_MIGRATION, new KbsEnclaveMigrationJob()); } return jobs; diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/KbsRepository.java b/app/src/main/java/org/thoughtcrime/securesms/pin/KbsRepository.java index 7fcc73b01..3692beae2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/KbsRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/pin/KbsRepository.java @@ -101,7 +101,7 @@ public final class KbsRepository { if (pin == null) return null; if (basicStorageCredentials == null) { - throw new AssertionError("Cannot restore KBS key, no storage credentials supplied"); + throw new AssertionError("Cannot restore KBS key, no storage credentials supplied. Enclave: " + enclave.getEnclaveName()); } Log.i(TAG, "Preparing to restore from " + enclave.getEnclaveName()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/PinState.java b/app/src/main/java/org/thoughtcrime/securesms/pin/PinState.java index 46cb60d8a..49a54a28c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/PinState.java +++ b/app/src/main/java/org/thoughtcrime/securesms/pin/PinState.java @@ -112,10 +112,11 @@ public final class PinState { { Log.i(TAG, "onPinChangedOrCreated()"); + KbsEnclave kbsEnclave = KbsEnclaves.current(); KbsValues kbsValues = SignalStore.kbsValues(); boolean isFirstPin = !kbsValues.hasPin() || kbsValues.hasOptedOut(); MasterKey masterKey = kbsValues.getOrCreateMasterKey(); - KeyBackupService keyBackupService = ApplicationDependencies.getKeyBackupService(KbsEnclaves.current()); + KeyBackupService keyBackupService = ApplicationDependencies.getKeyBackupService(kbsEnclave); KeyBackupService.PinChangeSession pinChangeSession = keyBackupService.newPinChangeSession(); HashedPin hashedPin = PinHashing.hashPin(pin, pinChangeSession); KbsPinData kbsData = pinChangeSession.setPin(hashedPin, masterKey); @@ -127,10 +128,10 @@ public final class PinState { ApplicationDependencies.getMegaphoneRepository().markFinished(Megaphones.Event.PINS_FOR_ALL); if (isFirstPin) { - Log.i(TAG, "First time setting a PIN. Refreshing attributes to set the 'storage' capability."); + Log.i(TAG, "First time setting a PIN. Refreshing attributes to set the 'storage' capability. Enclave: " + kbsEnclave.getEnclaveName()); bestEffortRefreshAttributes(); } else { - Log.i(TAG, "Not the first time setting a PIN."); + Log.i(TAG, "Not the first time setting a PIN. Enclave: " + kbsEnclave.getEnclaveName()); } updateState(buildInferredStateFromOtherFields()); @@ -173,8 +174,12 @@ public final class PinState { assertState(State.PIN_WITH_REGISTRATION_LOCK_DISABLED); + + KbsEnclave kbsEnclave = KbsEnclaves.current(); + Log.i(TAG, "Enclave: " + kbsEnclave.getEnclaveName()); + SignalStore.kbsValues().setV2RegistrationLockEnabled(false); - ApplicationDependencies.getKeyBackupService(KbsEnclaves.current()) + ApplicationDependencies.getKeyBackupService(kbsEnclave) .newPinChangeSession(SignalStore.kbsValues().getRegistrationLockTokenResponse()) .enableRegistrationLock(SignalStore.kbsValues().getOrCreateMasterKey()); SignalStore.kbsValues().setV2RegistrationLockEnabled(true); @@ -214,9 +219,12 @@ public final class PinState { { Log.i(TAG, "onMigrateToRegistrationLockV2()"); + KbsEnclave kbsEnclave = KbsEnclaves.current(); + Log.i(TAG, "Enclave: " + kbsEnclave.getEnclaveName()); + KbsValues kbsValues = SignalStore.kbsValues(); MasterKey masterKey = kbsValues.getOrCreateMasterKey(); - KeyBackupService keyBackupService = ApplicationDependencies.getKeyBackupService(KbsEnclaves.current()); + KeyBackupService keyBackupService = ApplicationDependencies.getKeyBackupService(kbsEnclave); KeyBackupService.PinChangeSession pinChangeSession = keyBackupService.newPinChangeSession(); HashedPin hashedPin = PinHashing.hashPin(pin, pinChangeSession); KbsPinData kbsData = pinChangeSession.setPin(hashedPin, masterKey); @@ -294,6 +302,8 @@ public final class PinState { private static @NonNull KbsPinData setPinOnEnclave(@NonNull KbsEnclave enclave, @NonNull String pin, @NonNull MasterKey masterKey) throws IOException, UnauthenticatedResponseException { + Log.i(TAG, "Setting PIN on enclave: " + enclave.getEnclaveName()); + KeyBackupService kbs = ApplicationDependencies.getKeyBackupService(enclave); KeyBackupService.PinChangeSession pinChangeSession = kbs.newPinChangeSession(); HashedPin hashedPin = PinHashing.hashPin(pin, pinChangeSession); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java index 7bd3481c7..29c324162 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/RemoteAttestationCipher.java @@ -18,13 +18,19 @@ import java.security.MessageDigest; import java.security.SignatureException; import java.security.cert.CertPathValidatorException; import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; public final class RemoteAttestationCipher { private RemoteAttestationCipher() { } - private static final long SIGNATURE_BODY_VERSION = 3L; + private static final Set SIGNATURE_BODY_VERSIONS = new HashSet() {{ + add(3L); + add(4L); + }}; public static byte[] getRequestId(RemoteAttestationKeys keys, RemoteAttestationResponse response) throws InvalidCiphertextException { return AESCipher.decrypt(keys.getServerKey(), response.getIv(), response.getCiphertext(), response.getTag()); @@ -66,7 +72,7 @@ public final class RemoteAttestationCipher { SignatureBodyEntity signatureBodyEntity = JsonUtil.fromJson(signatureBody, SignatureBodyEntity.class); - if (signatureBodyEntity.getVersion() != SIGNATURE_BODY_VERSION) { + if (!SIGNATURE_BODY_VERSIONS.contains(signatureBodyEntity.getVersion())) { throw new SignatureException("Unexpected signed quote version " + signatureBodyEntity.getVersion()); } @@ -74,8 +80,8 @@ public final class RemoteAttestationCipher { throw new SignatureException("Signed quote is not the same as RA quote: " + Hex.toStringCondensed(signatureBodyEntity.getIsvEnclaveQuoteBody()) + " vs " + Hex.toStringCondensed(quote.getQuoteBytes())); } - if (!"OK".equals(signatureBodyEntity.getIsvEnclaveQuoteStatus())) { - throw new SignatureException("Quote status is: " + signatureBodyEntity.getIsvEnclaveQuoteStatus()); + if (!hasValidStatus(signatureBodyEntity)) { + throw new SignatureException("Quote status is: " + signatureBodyEntity.getIsvEnclaveQuoteStatus() + " and advisories are: " + Arrays.toString(signatureBodyEntity.getAdvisoryIds())); } if (Instant.from(ZonedDateTime.of(LocalDateTime.from(DateTimeFormatter.ofPattern("yyy-MM-dd'T'HH:mm:ss.SSSSSS").parse(signatureBodyEntity.getTimestamp())), ZoneId.of("UTC"))) @@ -89,4 +95,14 @@ public final class RemoteAttestationCipher { throw new SignatureException(e); } } + + private static boolean hasValidStatus(SignatureBodyEntity entity) { + if ("OK".equals(entity.getIsvEnclaveQuoteStatus())) { + return true; + } else if ("SW_HARDENING_NEEDED".equals(entity.getIsvEnclaveQuoteStatus())) { + return entity.getAdvisoryIds().length == 1 && "INTEL-SA-00334".equals(entity.getAdvisoryIds()[0]); + } else { + return false; + } + } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SignatureBodyEntity.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SignatureBodyEntity.java index 2a1424391..7b22fceb4 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SignatureBodyEntity.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/crypto/SignatureBodyEntity.java @@ -16,6 +16,12 @@ public class SignatureBodyEntity { @JsonProperty private String timestamp; + @JsonProperty + private String advisoryURL; + + @JsonProperty + private String[] advisoryIDs; + public byte[] getIsvEnclaveQuoteBody() { return isvEnclaveQuoteBody; } @@ -24,6 +30,14 @@ public class SignatureBodyEntity { return isvEnclaveQuoteStatus; } + public String getAdvisoryUrl() { + return advisoryURL; + } + + public String[] getAdvisoryIds() { + return advisoryIDs; + } + public Long getVersion() { return version; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/entities/RemoteAttestationRequest.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/entities/RemoteAttestationRequest.java index 7b84d1d09..b5eb6804b 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/entities/RemoteAttestationRequest.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/contacts/entities/RemoteAttestationRequest.java @@ -23,10 +23,14 @@ public class RemoteAttestationRequest { @JsonProperty private byte[] clientPublic; + @JsonProperty + private int iasVersion; + public RemoteAttestationRequest() {} public RemoteAttestationRequest(byte[] clientPublic) { this.clientPublic = clientPublic; + this.iasVersion = 4; } public byte[] getClientPublic() {