From 609e9fcdb0657c9ebb1da04ebb8b773daf985598 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Mon, 16 Oct 2023 07:33:05 -0700 Subject: [PATCH] Remove all unused KBS/SVR1 code. --- app/build.gradle | 13 - .../changenumber/ChangeNumberViewModelTest.kt | 4 - ...umentationApplicationDependencyProvider.kt | 16 +- .../securesms/testing/MockProvider.kt | 22 -- .../svr/InternalSvrPlaygroundFragment.kt | 4 +- .../svr/InternalSvrPlaygroundState.kt | 2 +- .../svr/InternalSvrPlaygroundViewModel.kt | 4 +- .../delete/DeleteAccountRepository.java | 2 - .../dependencies/ApplicationDependencies.java | 9 - .../ApplicationDependencyProvider.java | 13 - .../securesms/jobs/ResetSvrGuessCountJob.kt | 10 +- .../securesms/pin/KbsEnclaves.java | 26 -- .../securesms/pin/SvrRepository.kt | 7 +- .../push/SignalServiceNetworkAccess.kt | 4 - .../MockApplicationDependencyProvider.java | 8 - app/static-ips.gradle | 1 - .../plugins/src/main/java/translations.gradle | 1 - .../signalservice/api/KeyBackupService.java | 303 ------------------ .../api/KeyBackupServicePinException.java | 17 - .../api/SignalServiceAccountManager.java | 20 -- .../api/svr/SecureValueRecoveryV1.kt | 124 ------- .../SignalServiceConfiguration.kt | 1 - .../internal/push/PushServiceSocket.java | 102 ------ .../internal/push/RemoteAttestationUtil.java | 135 -------- 24 files changed, 8 insertions(+), 840 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/pin/KbsEnclaves.java delete mode 100644 libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupService.java delete mode 100644 libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupServicePinException.java delete mode 100644 libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/SecureValueRecoveryV1.kt delete mode 100644 libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java diff --git a/app/build.gradle b/app/build.gradle index 94ae63e38d..9b81d3ebb1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -186,7 +186,6 @@ android { buildConfigField "String[]", "SIGNAL_CDN_IPS", cdn_ips buildConfigField "String[]", "SIGNAL_CDN2_IPS", cdn2_ips buildConfigField "String[]", "SIGNAL_CDN3_IPS", cdn3_ips - buildConfigField "String[]", "SIGNAL_KBS_IPS", kbs_ips buildConfigField "String[]", "SIGNAL_SFU_IPS", sfu_ips buildConfigField "String[]", "SIGNAL_CONTENT_PROXY_IPS", content_proxy_ips buildConfigField "String[]", "SIGNAL_CDSI_IPS", cdsi_ips @@ -194,12 +193,6 @@ android { buildConfigField "String", "SIGNAL_AGENT", "\"OWA\"" buildConfigField "String", "CDSI_MRENCLAVE", "\"0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57\"" buildConfigField "String", "SVR2_MRENCLAVE", "\"6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094\"" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"e18376436159cda3ad7a45d9320e382e4a497f26b0dca34d8eab0bd0139483b5\", " + - "\"3a485adb56e2058ef7737764c738c4069dd62bc457637eafb6bbce1ce29ddb89\", " + - "\"45627094b2ea4a66f4cf0b182858a8dcf4b8479122c3820fe7fd0551a6d4cf5c\")" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[] { new org.thoughtcrime.securesms.KbsEnclave(\"0cedba03535b41b67729ce9924185f831d7767928a1d1689acb689bc079c375f\", " + - "\"187d2739d22be65e74b65f0055e74d31310e4267e5fac2b1246cc8beba81af39\", " + - "\"ee19f1965b1eefa3dc4204eb70c04f397755f771b8c1909d080c04dad2a6a9ba\") }" 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+ikU5gBXsRmoF94GXTLfN0/vLt98KDPnxwAQL9j5V1jGOY8jQl6MLxEs56cwXN0dqCnImzVH3TZT1cJ8SW1BRX6qIVxEzjsSGx3yxF3suAilPMqGRp4ffyopjMD1JXiKR2RwLKzizUe5e8XyGOy9fplzhw3jVzTRyUZTRSZKkMLWcQ/gv0E4aONNqs4P\"" buildConfigField "String", "GENERIC_SERVER_PUBLIC_PARAMS", "\"AByD873dTilmOSG0TjKrvpeaKEsUmIO8Vx9BeMmftwUs9v7ikPwM8P3OHyT0+X3EUMZrSe9VUp26Wai51Q9I8mdk0hX/yo7CeFGJyzoOqn8e/i4Ygbn5HoAyXJx5eXfIbqpc0bIxzju4H/HOQeOpt6h742qii5u/cbwOhFZCsMIbElZTaeU+BWMBQiZHIGHT5IE0qCordQKZ5iPZom0HeFa8Yq0ShuEyAl0WINBiY6xE3H/9WnvzXBbMuuk//eRxXgzO8ieCeK8FwQNxbfXqZm6Ro1cMhCOF3u7xoX83QhpN\"" @@ -373,12 +366,6 @@ android { buildConfigField "String", "SIGNAL_KEY_BACKUP_URL", "\"https://api-staging.backup.signal.org\"" buildConfigField "String", "SIGNAL_SVR2_URL", "\"https://svr2.staging.signal.org\"" buildConfigField "String", "SVR2_MRENCLAVE", "\"a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95\"" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave", "KBS_ENCLAVE", "new org.thoughtcrime.securesms.KbsEnclave(\"39963b736823d5780be96ab174869a9499d56d66497aa8f9b2244f777ebc366b\", " + - "\"ee1d0d972b7ea903615670de43ab1b6e7a825e811c70a29bb5fe0f819e0975fa\", " + - "\"45627094b2ea4a66f4cf0b182858a8dcf4b8479122c3820fe7fd0551a6d4cf5c\")" - buildConfigField "org.thoughtcrime.securesms.KbsEnclave[]", "KBS_FALLBACKS", "new org.thoughtcrime.securesms.KbsEnclave[] { new org.thoughtcrime.securesms.KbsEnclave(\"dd6f66d397d9e8cf6ec6db238e59a7be078dd50e9715427b9c89b409ffe53f99\", " + - "\"4200003414528c151e2dccafbc87aa6d3d66a5eb8f8c05979a6e97cb33cd493a\", " + - "\"ee19f1965b1eefa3dc4204eb70c04f397755f771b8c1909d080c04dad2a6a9ba\") }" buildConfigField "String", "UNIDENTIFIED_SENDER_TRUST_ROOT", "\"BbqY1DzohE4NUZoVF+L18oUPrK3kILllLEJh2UnPSsEx\"" buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"ABSY21VckQcbSXVNCGRYJcfWHiAMZmpTtTELcDmxgdFbtp/bWsSxZdMKzfCp8rvIs8ocCU3B37fT3r4Mi5qAemeGeR2X+/YmOGR5ofui7tD5mDQfstAI9i+4WpMtIe8KC3wU5w3Inq3uNWVmoGtpKndsNfwJrCg0Hd9zmObhypUnSkfYn2ooMOOnBpfdanRtrvetZUayDMSC5iSRcXKpdlukrpzzsCIvEwjwQlJYVPOQPj4V0F4UXXBdHSLK05uoPBCQG8G9rYIGedYsClJXnbrgGYG3eMTG5hnx4X4ntARBgELuMWWUEEfSK0mjXg+/2lPmWcTZWR9nkqgQQP0tbzuiPm74H2wMO4u1Wafe+UwyIlIT9L7KLS19Aw8r4sPrXZSSsOZ6s7M1+rTJN0bI5CKY2PX29y5Ok3jSWufIKcgKOnWoP67d5b2du2ZVJjpjfibNIHbT/cegy/sBLoFwtHogVYUewANUAXIaMPyCLRArsKhfJ5wBtTminG/PAvuBdJ70Z/bXVPf8TVsR292zQ65xwvWTejROW6AZX6aqucUj\"" buildConfigField "String", "GENERIC_SERVER_PUBLIC_PARAMS", "\"AHILOIrFPXX9laLbalbA9+L1CXpSbM/bTJXZGZiuyK1JaI6dK5FHHWL6tWxmHKYAZTSYmElmJ5z2A5YcirjO/yfoemE03FItyaf8W1fE4p14hzb5qnrmfXUSiAIVrhaXVwIwSzH6RL/+EO8jFIjJ/YfExfJ8aBl48CKHgu1+A6kWynhttonvWWx6h7924mIzW0Czj2ROuh4LwQyZypex4GuOPW8sgIT21KNZaafgg+KbV7XM1x1tF3XA17B4uGUaDbDw2O+nR1+U5p6qHPzmJ7ggFjSN6Utu+35dS1sS0P9N\"" diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberViewModelTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberViewModelTest.kt index a6640d660e..49e18a29d6 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberViewModelTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/components/settings/app/changenumber/ChangeNumberViewModelTest.kt @@ -230,8 +230,6 @@ class ChangeNumberViewModelTest { lateinit var changeNumberRequest: ChangePhoneNumberRequest lateinit var setPreKeysRequest: PreKeyState - MockProvider.mockGetRegistrationLockStringFlow() - InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers( Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) }, Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) }, @@ -318,8 +316,6 @@ class ChangeNumberViewModelTest { lateinit var changeNumberRequest: ChangePhoneNumberRequest lateinit var setPreKeysRequest: PreKeyState - MockProvider.mockGetRegistrationLockStringFlow() - InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers( Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) }, Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) }, diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt index 2a693da130..24bd1b35dd 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/dependencies/InstrumentationApplicationDependencyProvider.kt @@ -16,7 +16,6 @@ import org.mockito.kotlin.mock import org.signal.core.util.Base64 import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.BuildConfig -import org.thoughtcrime.securesms.KbsEnclave import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess import org.thoughtcrime.securesms.push.SignalServiceTrustStore import org.thoughtcrime.securesms.recipients.LiveRecipientCache @@ -24,31 +23,25 @@ import org.thoughtcrime.securesms.testing.Get import org.thoughtcrime.securesms.testing.Verb import org.thoughtcrime.securesms.testing.runSync import org.thoughtcrime.securesms.testing.success -import org.whispersystems.signalservice.api.KeyBackupService -import org.whispersystems.signalservice.api.SignalServiceAccountManager import org.whispersystems.signalservice.api.push.TrustStore import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl -import org.whispersystems.signalservice.internal.configuration.SignalKeyBackupServiceUrl import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url -import java.security.KeyStore import java.util.Optional /** * Dependency provider used for instrumentation tests (aka androidTests). * - * Handles setting up a mock web server for API calls, and provides mockable versions of [SignalServiceNetworkAccess] and - * [KeyBackupService]. + * Handles setting up a mock web server for API calls, and provides mockable versions of [SignalServiceNetworkAccess]. */ class InstrumentationApplicationDependencyProvider(application: Application, default: ApplicationDependencyProvider) : ApplicationDependencies.Provider by default { private val serviceTrustStore: TrustStore private val uncensoredConfiguration: SignalServiceConfiguration private val serviceNetworkAccessMock: SignalServiceNetworkAccess - private val keyBackupService: KeyBackupService private val recipientCache: LiveRecipientCache init { @@ -80,7 +73,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def 0 to arrayOf(SignalCdnUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), 2 to arrayOf(SignalCdnUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)) ), - signalKeyBackupServiceUrls = arrayOf(SignalKeyBackupServiceUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), signalStorageUrls = arrayOf(SignalStorageUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), signalCdsiUrls = arrayOf(SignalCdsiUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), signalSvr2Urls = arrayOf(SignalSvr2Url(baseUrl, serviceTrustStore, "localhost", ConnectionSpec.CLEARTEXT)), @@ -97,8 +89,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def on { uncensoredConfiguration } doReturn uncensoredConfiguration } - keyBackupService = mock() - recipientCache = LiveRecipientCache(application) { r -> r.run() } } @@ -106,10 +96,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def return serviceNetworkAccessMock } - override fun provideKeyBackupService(signalServiceAccountManager: SignalServiceAccountManager, keyStore: KeyStore, enclave: KbsEnclave): KeyBackupService { - return keyBackupService - } - override fun provideRecipientCache(): LiveRecipientCache { return recipientCache } diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MockProvider.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MockProvider.kt index 1c75ed204e..4175150446 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MockProvider.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/testing/MockProvider.kt @@ -1,22 +1,12 @@ package org.thoughtcrime.securesms.testing -import org.mockito.kotlin.anyOrNull -import org.mockito.kotlin.doReturn -import org.mockito.kotlin.stub -import org.signal.core.util.Hex import org.signal.libsignal.protocol.IdentityKeyPair import org.signal.libsignal.protocol.ecc.Curve import org.signal.libsignal.protocol.state.PreKeyRecord import org.signal.libsignal.protocol.util.KeyHelper import org.signal.libsignal.protocol.util.Medium -import org.signal.libsignal.svr2.PinHash import org.thoughtcrime.securesms.crypto.PreKeyUtil -import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.keyvalue.SignalStore -import org.thoughtcrime.securesms.test.BuildConfig -import org.whispersystems.signalservice.api.KeyBackupService -import org.whispersystems.signalservice.api.SvrPinData -import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.api.messages.multidevice.DeviceInfo import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.SignedPreKeyEntity @@ -78,18 +68,6 @@ object MockProvider { } } - fun mockGetRegistrationLockStringFlow() { - val session: KeyBackupService.RestoreSession = object : KeyBackupService.RestoreSession { - override fun hashSalt(): ByteArray = Hex.fromStringCondensed("cba811749042b303a6a7efa5ccd160aea5e3ea243c8d2692bd13d515732f51a8") - override fun restorePin(hashedPin: PinHash?): SvrPinData = SvrPinData(MasterKey.createNew(SecureRandom()), null) - } - - val kbsService = ApplicationDependencies.getKeyBackupService(BuildConfig.KBS_ENCLAVE) - kbsService.stub { - on { newRegistrationSession(anyOrNull(), anyOrNull()) } doReturn session - } - } - fun createPreKeyResponse(identity: IdentityKeyPair = SignalStore.account().aciIdentityKey, deviceId: Int): PreKeyResponse { val signedPreKeyRecord = PreKeyUtil.generateSignedPreKey(SecureRandom().nextInt(Medium.MAX_VALUE), identity.privateKey) val oneTimePreKey = PreKeyRecord(SecureRandom().nextInt(Medium.MAX_VALUE), Curve.generateKeyPair()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundFragment.kt index f741957c09..6b195fa557 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundFragment.kt @@ -124,7 +124,7 @@ fun SvrPlaygroundScreenLightTheme() { Surface { SvrPlaygroundScreen( state = InternalSvrPlaygroundState( - options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) + options = persistentListOf(SvrImplementation.SVR2) ) ) } @@ -138,7 +138,7 @@ fun SvrPlaygroundScreenDarkTheme() { Surface { SvrPlaygroundScreen( state = InternalSvrPlaygroundState( - options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) + options = persistentListOf(SvrImplementation.SVR2) ) ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundState.kt index 77355588fd..0f49cd8de1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundState.kt @@ -13,5 +13,5 @@ data class InternalSvrPlaygroundState( enum class SvrImplementation( val title: String ) { - SVR1("KBS"), SVR2("SVR2") + SVR2("SVR2") } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundViewModel.kt index 095a24e6ee..191ad7deff 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundViewModel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/internal/svr/InternalSvrPlaygroundViewModel.kt @@ -19,13 +19,12 @@ import org.thoughtcrime.securesms.BuildConfig import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.keyvalue.SignalStore import org.whispersystems.signalservice.api.svr.SecureValueRecovery -import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1 class InternalSvrPlaygroundViewModel : ViewModel() { private val _state: MutableState = mutableStateOf( InternalSvrPlaygroundState( - options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) + options = persistentListOf(SvrImplementation.SVR2) ) ) val state: State = _state @@ -104,7 +103,6 @@ class InternalSvrPlaygroundViewModel : ViewModel() { private fun SvrImplementation.toImplementation(): SecureValueRecovery { return when (this) { - SvrImplementation.SVR1 -> SecureValueRecoveryV1(ApplicationDependencies.getKeyBackupService(BuildConfig.KBS_ENCLAVE)) SvrImplementation.SVR2 -> ApplicationDependencies.getSignalServiceAccountManager().getSecureValueRecoveryV2(BuildConfig.SVR2_MRENCLAVE) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/delete/DeleteAccountRepository.java b/app/src/main/java/org/thoughtcrime/securesms/delete/DeleteAccountRepository.java index 49d64c5ece..afc1ba38f4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/delete/DeleteAccountRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/delete/DeleteAccountRepository.java @@ -14,13 +14,11 @@ import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.pin.KbsEnclaves; import org.thoughtcrime.securesms.subscription.Subscriber; import org.thoughtcrime.securesms.util.ServiceUtil; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.internal.EmptyResponse; import org.whispersystems.signalservice.internal.ServiceResponse; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; import java.io.IOException; import java.text.Collator; diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencies.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencies.java index a16f335017..c41060c0e0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencies.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencies.java @@ -10,7 +10,6 @@ import androidx.annotation.VisibleForTesting; import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; -import org.thoughtcrime.securesms.KbsEnclave; import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl; @@ -41,12 +40,10 @@ import org.thoughtcrime.securesms.shakereport.ShakeToReport; import org.thoughtcrime.securesms.util.AppForegroundObserver; import org.thoughtcrime.securesms.util.EarlyMessageCache; import org.thoughtcrime.securesms.util.FrameRateTracker; -import org.thoughtcrime.securesms.util.IasKeyStore; import org.thoughtcrime.securesms.video.exo.ExoPlayerPool; import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; -import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; @@ -63,7 +60,6 @@ import org.whispersystems.signalservice.internal.util.BlacklistingTrustManager; import org.whispersystems.signalservice.internal.util.Util; import java.security.KeyManagementException; -import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.util.function.Supplier; @@ -199,10 +195,6 @@ public class ApplicationDependencies { return groupsV2Operations; } - public static @NonNull KeyBackupService getKeyBackupService(@NonNull KbsEnclave enclave) { - return provider.provideKeyBackupService(getSignalServiceAccountManager(), IasKeyStore.getIasKeyStore(application), enclave); - } - public static @NonNull GroupsV2StateProcessor getGroupsV2StateProcessor() { if (groupsV2StateProcessor == null) { synchronized (LOCK) { @@ -724,7 +716,6 @@ public class ApplicationDependencies { @NonNull ProfileService provideProfileService(@NonNull ClientZkProfileOperations profileOperations, @NonNull SignalServiceMessageReceiver signalServiceMessageReceiver, @NonNull SignalWebSocket signalWebSocket); @NonNull DeadlockDetector provideDeadlockDetector(); @NonNull ClientZkReceiptOperations provideClientZkReceiptOperations(@NonNull SignalServiceConfiguration signalServiceConfiguration); - @NonNull KeyBackupService provideKeyBackupService(@NonNull SignalServiceAccountManager signalServiceAccountManager, @NonNull KeyStore keyStore, @NonNull KbsEnclave enclave); @NonNull ScheduledMessageManager provideScheduledMessageManager(); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java index 7c2b93b38a..876b247e81 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java +++ b/app/src/main/java/org/thoughtcrime/securesms/dependencies/ApplicationDependencyProvider.java @@ -8,14 +8,12 @@ import android.os.HandlerThread; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; -import org.signal.core.util.Hex; import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.KbsEnclave; import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.ReentrantSessionLock; @@ -74,7 +72,6 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; -import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; @@ -94,7 +91,6 @@ import org.whispersystems.signalservice.api.websocket.WebSocketFactory; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; import org.whispersystems.signalservice.internal.websocket.WebSocketConnection; -import java.security.KeyStore; import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -394,15 +390,6 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr return provideClientZkOperations(signalServiceConfiguration).getReceiptOperations(); } - @Override - public @NonNull KeyBackupService provideKeyBackupService(@NonNull SignalServiceAccountManager signalServiceAccountManager, @NonNull KeyStore keyStore, @NonNull KbsEnclave enclave) { - return signalServiceAccountManager.getKeyBackupService(keyStore, - enclave.getEnclaveName(), - Hex.fromStringOrThrow(enclave.getServiceId()), - enclave.getMrEnclave(), - 10); - } - @NonNull WebSocketFactory provideWebSocketFactory(@NonNull Supplier signalServiceConfigurationSupplier, @NonNull SignalWebSocketHealthMonitor healthMonitor) { return new WebSocketFactory() { @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResetSvrGuessCountJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResetSvrGuessCountJob.kt index bb542091fc..91a8bfcc54 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResetSvrGuessCountJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResetSvrGuessCountJob.kt @@ -16,7 +16,6 @@ import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.api.svr.SecureValueRecovery import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession -import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1 import kotlin.concurrent.withLock import kotlin.time.Duration.Companion.days @@ -83,14 +82,7 @@ class ResetSvrGuessCountJob private constructor( Result.success() } - if (!svr2Result.isSuccess) { - return svr2Result - } else { - Log.d(TAG, "SVR2 reset complete. Marking as such so we do not retry it if SVR1 fails.") - svr2Complete = true - } - - return resetGuessCount(SecureValueRecoveryV1(ApplicationDependencies.getKeyBackupService(BuildConfig.KBS_ENCLAVE)), pin, masterKey) + return svr2Result } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/KbsEnclaves.java b/app/src/main/java/org/thoughtcrime/securesms/pin/KbsEnclaves.java deleted file mode 100644 index df0d209ed7..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/KbsEnclaves.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.thoughtcrime.securesms.pin; - -import androidx.annotation.NonNull; - -import org.thoughtcrime.securesms.BuildConfig; -import org.thoughtcrime.securesms.KbsEnclave; -import org.thoughtcrime.securesms.util.Util; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -public final class KbsEnclaves { - - public static @NonNull KbsEnclave current() { - return BuildConfig.KBS_ENCLAVE; - } - - public static @NonNull List all() { - return Util.join(Collections.singletonList(BuildConfig.KBS_ENCLAVE), fallbacks()); - } - - public static @NonNull List fallbacks() { - return Arrays.asList(BuildConfig.KBS_FALLBACKS); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/pin/SvrRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/pin/SvrRepository.kt index 0a5ca545ea..9155454c36 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/pin/SvrRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/pin/SvrRepository.kt @@ -29,7 +29,6 @@ import org.whispersystems.signalservice.api.kbs.MasterKey import org.whispersystems.signalservice.api.svr.SecureValueRecovery import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse -import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1 import org.whispersystems.signalservice.internal.push.AuthCredentials import java.io.IOException import java.util.concurrent.TimeUnit @@ -41,10 +40,9 @@ object SvrRepository { val TAG = Log.tag(SvrRepository::class.java) private val svr2: SecureValueRecovery = ApplicationDependencies.getSignalServiceAccountManager().getSecureValueRecoveryV2(BuildConfig.SVR2_MRENCLAVE) - private val svr1: SecureValueRecovery = SecureValueRecoveryV1(ApplicationDependencies.getKeyBackupService(BuildConfig.KBS_ENCLAVE)) /** An ordered list of SVR implementations. They should be in priority order, with the most important one listed first. */ - private val implementations: List = listOf(svr2, svr1) + private val implementations: List = listOf(svr2) /** * A lock that ensures that only one thread at a time is altering the various pieces of SVR state. @@ -72,8 +70,7 @@ object SvrRepository { Log.i(TAG, "restoreMasterKeyPreRegistration()", true) val operations: List RestoreResponse>> = listOf( - svr2 to { restoreMasterKeyPreRegistration(svr2, credentials.svr2, userPin) }, - svr1 to { restoreMasterKeyPreRegistration(svr1, credentials.svr1, userPin) } + svr2 to { restoreMasterKeyPreRegistration(svr2, credentials.svr2, userPin) } ) for ((implementation, operation) in operations) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt index 4ee13d52e4..acc1c0f110 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/push/SignalServiceNetworkAccess.kt @@ -48,7 +48,6 @@ open class SignalServiceNetworkAccess(context: Context) { BuildConfig.STORAGE_URL.stripProtocol() to BuildConfig.SIGNAL_STORAGE_IPS.toSet(), BuildConfig.SIGNAL_CDN_URL.stripProtocol() to BuildConfig.SIGNAL_CDN_IPS.toSet(), BuildConfig.SIGNAL_CDN2_URL.stripProtocol() to BuildConfig.SIGNAL_CDN2_IPS.toSet(), - BuildConfig.SIGNAL_KEY_BACKUP_URL.stripProtocol() to BuildConfig.SIGNAL_KBS_IPS.toSet(), BuildConfig.SIGNAL_SFU_URL.stripProtocol() to BuildConfig.SIGNAL_SFU_IPS.toSet(), BuildConfig.CONTENT_PROXY_HOST.stripProtocol() to BuildConfig.SIGNAL_CONTENT_PROXY_IPS.toSet(), BuildConfig.SIGNAL_CDSI_URL.stripProtocol() to BuildConfig.SIGNAL_CDSI_IPS.toSet(), @@ -176,7 +175,6 @@ open class SignalServiceNetworkAccess(context: Context) { 2 to fUrls.map { SignalCdnUrl(it, F_CDN2_HOST, fTrustStore, APP_CONNECTION_SPEC) }.toTypedArray(), 3 to fUrls.map { SignalCdnUrl(it, F_CDN3_HOST, fTrustStore, APP_CONNECTION_SPEC) }.toTypedArray() ), - signalKeyBackupServiceUrls = fUrls.map { SignalKeyBackupServiceUrl(it, F_KBS_HOST, fTrustStore, APP_CONNECTION_SPEC) }.toTypedArray(), signalStorageUrls = fUrls.map { SignalStorageUrl(it, F_STORAGE_HOST, fTrustStore, APP_CONNECTION_SPEC) }.toTypedArray(), signalCdsiUrls = fUrls.map { SignalCdsiUrl(it, F_CDSI_HOST, fTrustStore, APP_CONNECTION_SPEC) }.toTypedArray(), signalSvr2Urls = fUrls.map { SignalSvr2Url(it, fTrustStore, F_SVR2_HOST, APP_CONNECTION_SPEC) }.toTypedArray(), @@ -229,7 +227,6 @@ open class SignalServiceNetworkAccess(context: Context) { 2 to arrayOf(SignalCdnUrl(BuildConfig.SIGNAL_CDN2_URL, serviceTrustStore)), 3 to arrayOf(SignalCdnUrl(BuildConfig.SIGNAL_CDN3_URL, serviceTrustStore)) ), - signalKeyBackupServiceUrls = arrayOf(SignalKeyBackupServiceUrl(BuildConfig.SIGNAL_KEY_BACKUP_URL, serviceTrustStore)), signalStorageUrls = arrayOf(SignalStorageUrl(BuildConfig.STORAGE_URL, serviceTrustStore)), signalCdsiUrls = arrayOf(SignalCdsiUrl(BuildConfig.SIGNAL_CDSI_URL, serviceTrustStore)), signalSvr2Urls = arrayOf(SignalSvr2Url(BuildConfig.SIGNAL_SVR2_URL, serviceTrustStore)), @@ -299,7 +296,6 @@ open class SignalServiceNetworkAccess(context: Context) { 2 to cdn2Urls, 3 to cdn3Urls ), - signalKeyBackupServiceUrls = kbsUrls, signalStorageUrls = storageUrls, signalCdsiUrls = cdsiUrls, signalSvr2Urls = svr2Urls, diff --git a/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.java b/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.java index 82dc7d545d..561e9d5754 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.java +++ b/app/src/test/java/org/thoughtcrime/securesms/dependencies/MockApplicationDependencyProvider.java @@ -5,7 +5,6 @@ import androidx.annotation.NonNull; import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; -import org.thoughtcrime.securesms.KbsEnclave; import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl; @@ -33,7 +32,6 @@ import org.thoughtcrime.securesms.util.FrameRateTracker; import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; -import org.whispersystems.signalservice.api.KeyBackupService; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; @@ -45,7 +43,6 @@ import org.whispersystems.signalservice.api.services.DonationsService; import org.whispersystems.signalservice.api.services.ProfileService; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; -import java.security.KeyStore; import java.util.function.Supplier; import static org.mockito.Mockito.mock; @@ -231,11 +228,6 @@ public class MockApplicationDependencyProvider implements ApplicationDependencie return null; } - @Override - public @NonNull KeyBackupService provideKeyBackupService(@NonNull SignalServiceAccountManager signalServiceAccountManager, @NonNull KeyStore keyStore, @NonNull KbsEnclave enclave) { - return null; - } - @Override public @NonNull ScheduledMessageManager provideScheduledMessageManager() { return null; diff --git a/app/static-ips.gradle b/app/static-ips.gradle index 0cf8771e08..7ddc6cbe74 100644 --- a/app/static-ips.gradle +++ b/app/static-ips.gradle @@ -3,7 +3,6 @@ ext.storage_ips='new String[]{"142.250.81.243"}' ext.cdn_ips='new String[]{"18.238.55.2","18.238.55.54","18.238.55.7","18.238.55.78"}' ext.cdn2_ips='new String[]{"104.18.37.148","172.64.150.108"}' ext.cdn3_ips='new String[]{"104.18.37.148","172.64.150.108"}' -ext.kbs_ips='new String[]{"18.238.4.110","18.238.4.119","18.238.4.19","18.238.4.94"}' ext.sfu_ips='new String[]{"34.95.127.167"}' ext.content_proxy_ips='new String[]{"107.178.250.75"}' ext.svr2_ips='new String[]{"20.119.62.85"}' diff --git a/build-logic/plugins/src/main/java/translations.gradle b/build-logic/plugins/src/main/java/translations.gradle index cf3fd7416b..27d4d0d689 100644 --- a/build-logic/plugins/src/main/java/translations.gradle +++ b/build-logic/plugins/src/main/java/translations.gradle @@ -131,7 +131,6 @@ task resolveStaticIps { ext.cdn_ips='${staticIpResolver.resolveToBuildConfig("cdn.signal.org")}' ext.cdn2_ips='${staticIpResolver.resolveToBuildConfig("cdn2.signal.org")}' ext.cdn3_ips='${staticIpResolver.resolveToBuildConfig("cdn3.signal.org")}' - ext.kbs_ips='${staticIpResolver.resolveToBuildConfig("api.backup.signal.org")}' ext.sfu_ips='${staticIpResolver.resolveToBuildConfig("sfu.voip.signal.org")}' ext.content_proxy_ips='${staticIpResolver.resolveToBuildConfig("contentproxy.signal.org")}' ext.svr2_ips='${staticIpResolver.resolveToBuildConfig("svr2.signal.org")}' diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupService.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupService.java deleted file mode 100644 index e5bf352953..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupService.java +++ /dev/null @@ -1,303 +0,0 @@ -package org.whispersystems.signalservice.api; - -import org.signal.libsignal.protocol.InvalidKeyException; -import org.signal.libsignal.protocol.logging.Log; -import org.signal.libsignal.svr2.PinHash; -import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException; -import org.whispersystems.signalservice.api.kbs.KbsData; -import org.whispersystems.signalservice.api.kbs.MasterKey; -import org.whispersystems.signalservice.api.kbs.PinHashUtil; -import org.whispersystems.signalservice.internal.contacts.crypto.KeyBackupCipher; -import org.whispersystems.signalservice.internal.contacts.crypto.Quote; -import org.whispersystems.signalservice.internal.contacts.crypto.RemoteAttestation; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException; -import org.whispersystems.signalservice.internal.contacts.entities.KeyBackupRequest; -import org.whispersystems.signalservice.internal.contacts.entities.KeyBackupResponse; -import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse; -import org.whispersystems.signalservice.internal.keybackup.protos.BackupResponse; -import org.whispersystems.signalservice.internal.keybackup.protos.RestoreResponse; -import org.whispersystems.signalservice.internal.push.AuthCredentials; -import org.whispersystems.signalservice.internal.push.PushServiceSocket; -import org.whispersystems.signalservice.internal.push.RemoteAttestationUtil; -import org.whispersystems.signalservice.internal.util.Util; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.SecureRandom; -import java.security.SignatureException; -import java.util.Locale; - -public class KeyBackupService { - - private static final String TAG = KeyBackupService.class.getSimpleName(); - - private final KeyStore iasKeyStore; - private final String enclaveName; - private final byte[] serviceId; - private final String mrenclave; - private final PushServiceSocket pushServiceSocket; - private final int maxTries; - - KeyBackupService(KeyStore iasKeyStore, - String enclaveName, - byte[] serviceId, - String mrenclave, - PushServiceSocket pushServiceSocket, - int maxTries) - { - this.iasKeyStore = iasKeyStore; - this.enclaveName = enclaveName; - this.serviceId = serviceId; - this.mrenclave = mrenclave; - this.pushServiceSocket = pushServiceSocket; - this.maxTries = maxTries; - } - - /** - * Use this if you don't want to validate that the server has not changed since you last set the pin. - */ - public PinChangeSession newPinChangeSession() - throws IOException - { - return newSession(pushServiceSocket.getKeyBackupServiceAuthorization().asBasic(), null); - } - - /** - * Use this if you want to validate that the server has not changed since you last set the pin. - * The supplied token will have to match for the change to be successful. - */ - public PinChangeSession newPinChangeSession(TokenResponse currentToken) - throws IOException - { - return newSession(pushServiceSocket.getKeyBackupServiceAuthorization().asBasic(), currentToken); - } - - /** - * Only call before registration, to see how many tries are left. - *

- * Pass the token to {@link #newRegistrationSession(String, TokenResponse)}. - */ - public TokenResponse getToken(String authAuthorization) throws IOException { - return pushServiceSocket.getKeyBackupServiceToken(authAuthorization, enclaveName); - } - - /** - * Retrieve the authorization token to be used with other requests. - */ - public AuthCredentials getAuthorization() throws IOException { - return pushServiceSocket.getKeyBackupServiceAuthorization(); - } - - /** - * Use this during registration, good for one try, on subsequent attempts, pass the token from the previous attempt. - * - * @param tokenResponse Supplying a token response from a failed previous attempt prevents certain attacks. - */ - public RestoreSession newRegistrationSession(String authAuthorization, TokenResponse tokenResponse) - throws IOException - { - return newSession(authAuthorization, tokenResponse); - } - - public String getEnclaveName() { - return enclaveName; - } - - public String getMrenclave() { - return mrenclave; - } - - private Session newSession(String authorization, TokenResponse currentToken) - throws IOException - { - TokenResponse token = currentToken != null ? currentToken : pushServiceSocket.getKeyBackupServiceToken(authorization, enclaveName); - - return new Session(authorization, token); - } - - private class Session implements RestoreSession, PinChangeSession { - - private final String authorization; - private final TokenResponse currentToken; - - Session(String authorization, TokenResponse currentToken) { - this.authorization = authorization; - this.currentToken = currentToken; - } - - @Override - public byte[] hashSalt() { - return currentToken.getBackupId(); - } - - @Override - public SvrPinData restorePin(PinHash hashedPin) - throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, SvrNoDataException, InvalidKeyException - { - int attempt = 0; - SecureRandom random = new SecureRandom(); - TokenResponse token = currentToken; - - while (true) { - - attempt++; - - try { - return restorePin(hashedPin, token); - } catch (TokenException tokenException) { - - token = tokenException.getToken(); - - if (tokenException instanceof KeyBackupServicePinException) { - throw (KeyBackupServicePinException) tokenException; - } - - if (tokenException.isCanAutomaticallyRetry() && attempt < 5) { - // back off randomly, between 250 and 8000 ms - int backoffMs = 250 * (1 << (attempt - 1)); - - Util.sleep(backoffMs + random.nextInt(backoffMs)); - } else { - throw new UnauthenticatedResponseException("Token mismatch, expended all automatic retries"); - } - } - } - } - - private SvrPinData restorePin(PinHash hashedPin, TokenResponse token) - throws UnauthenticatedResponseException, IOException, TokenException, SvrNoDataException, InvalidKeyException - { - try { - final int remainingTries = token.getTries(); - final RemoteAttestation remoteAttestation = getAndVerifyRemoteAttestation(); - final KeyBackupRequest request = KeyBackupCipher.createKeyRestoreRequest(hashedPin.accessKey(), token, remoteAttestation, serviceId); - final KeyBackupResponse response = pushServiceSocket.putKbsData(authorization, request, remoteAttestation.getCookies(), enclaveName); - final RestoreResponse status = KeyBackupCipher.getKeyRestoreResponse(response, remoteAttestation); - - TokenResponse nextToken = status.token != null ? new TokenResponse(token.getBackupId(), status.token.toByteArray(), status.tries) - : token; - - Log.i(TAG, "Restore " + status.status); - switch (status.status) { - case OK: - KbsData kbsData = PinHashUtil.decryptSvrDataIVCipherText(hashedPin, status.data_.toByteArray()); - MasterKey masterKey = kbsData.getMasterKey(); - return new SvrPinData(masterKey, nextToken); - case PIN_MISMATCH: - Log.i(TAG, "Restore PIN_MISMATCH"); - throw new KeyBackupServicePinException(nextToken); - case TOKEN_MISMATCH: - Log.i(TAG, "Restore TOKEN_MISMATCH"); - // if the number of tries has not fallen, the pin is correct we're just using an out of date token - boolean canRetry = remainingTries == status.tries; - Log.i(TAG, String.format(Locale.US, "Token MISMATCH remainingTries: %d, status.getTries(): %d", remainingTries, status.tries)); - throw new TokenException(nextToken, canRetry); - case MISSING: - Log.i(TAG, "Restore OK! No data though"); - throw new SvrNoDataException(); - case NOT_YET_VALID: - throw new UnauthenticatedResponseException("Key is not valid yet, clock mismatch"); - default: - throw new AssertionError("Unexpected case"); - } - } catch (InvalidCiphertextException e) { - throw new UnauthenticatedResponseException(e); - } - } - - private RemoteAttestation getAndVerifyRemoteAttestation() throws UnauthenticatedResponseException, IOException, InvalidKeyException { - try { - return RemoteAttestationUtil.getAndVerifyRemoteAttestation(pushServiceSocket, PushServiceSocket.ClientSet.KeyBackup, iasKeyStore, enclaveName, mrenclave, authorization); - } catch (Quote.InvalidQuoteFormatException | UnauthenticatedQuoteException | InvalidCiphertextException | SignatureException e) { - throw new UnauthenticatedResponseException(e); - } - } - - @Override - public SvrPinData setPin(PinHash pinHash, MasterKey masterKey) throws IOException, UnauthenticatedResponseException { - KbsData newKbsData = PinHashUtil.createNewKbsData(pinHash, masterKey); - TokenResponse tokenResponse = putKbsData(newKbsData.getKbsAccessKey(), - newKbsData.getCipherText(), - enclaveName, - currentToken); - - return new SvrPinData(masterKey, tokenResponse); - } - - @Override - public void removePin() - throws IOException, UnauthenticatedResponseException - { - try { - RemoteAttestation remoteAttestation = getAndVerifyRemoteAttestation(); - KeyBackupRequest request = KeyBackupCipher.createKeyDeleteRequest(currentToken, remoteAttestation, serviceId); - KeyBackupResponse response = pushServiceSocket.putKbsData(authorization, request, remoteAttestation.getCookies(), enclaveName); - - KeyBackupCipher.getKeyDeleteResponseStatus(response, remoteAttestation); - } catch (InvalidCiphertextException | InvalidKeyException e) { - throw new UnauthenticatedResponseException(e); - } - } - - @Override - public void enableRegistrationLock(MasterKey masterKey) throws IOException { - pushServiceSocket.setRegistrationLockV2(masterKey.deriveRegistrationLock()); - } - - @Override - public void disableRegistrationLock() throws IOException { - pushServiceSocket.disableRegistrationLockV2(); - } - - private TokenResponse putKbsData(byte[] kbsAccessKey, byte[] kbsData, String enclaveName, TokenResponse token) - throws IOException, UnauthenticatedResponseException - { - try { - RemoteAttestation remoteAttestation = getAndVerifyRemoteAttestation(); - KeyBackupRequest request = KeyBackupCipher.createKeyBackupRequest(kbsAccessKey, kbsData, token, remoteAttestation, serviceId, maxTries); - KeyBackupResponse response = pushServiceSocket.putKbsData(authorization, request, remoteAttestation.getCookies(), enclaveName); - BackupResponse backupResponse = KeyBackupCipher.getKeyBackupResponse(response, remoteAttestation); - BackupResponse.Status status = backupResponse.status; - - switch (status) { - case OK: - return backupResponse.token != null ? new TokenResponse(token.getBackupId(), backupResponse.token.toByteArray(), maxTries) : token; - case ALREADY_EXISTS: - throw new UnauthenticatedResponseException("Already exists"); - case NOT_YET_VALID: - throw new UnauthenticatedResponseException("Key is not valid yet, clock mismatch"); - default: - throw new AssertionError("Unknown response status " + status); - } - } catch (InvalidCiphertextException | InvalidKeyException e) { - throw new UnauthenticatedResponseException(e); - } - } - } - - public interface HashSession { - - byte[] hashSalt(); - } - - public interface RestoreSession extends HashSession { - - SvrPinData restorePin(PinHash hashedPin) - throws UnauthenticatedResponseException, IOException, KeyBackupServicePinException, SvrNoDataException, InvalidKeyException; - } - - public interface PinChangeSession extends HashSession { - /** Creates a PIN. Does nothing to registration lock. */ - SvrPinData setPin(PinHash hashedPin, MasterKey masterKey) throws IOException, UnauthenticatedResponseException; - - /** Removes the PIN data from KBS. */ - void removePin() throws IOException, UnauthenticatedResponseException; - - /** Enables registration lock. This assumes a PIN is set. */ - void enableRegistrationLock(MasterKey masterKey) throws IOException; - - /** Disables registration lock. The user keeps their PIN. */ - void disableRegistrationLock() throws IOException; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupServicePinException.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupServicePinException.java deleted file mode 100644 index 79668ebde6..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/KeyBackupServicePinException.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.whispersystems.signalservice.api; - -import org.whispersystems.signalservice.internal.contacts.entities.TokenResponse; - -public final class KeyBackupServicePinException extends TokenException { - - private final int triesRemaining; - - public KeyBackupServicePinException(TokenResponse nextToken) { - super(nextToken, false); - this.triesRemaining = nextToken.getTries(); - } - - public int getTriesRemaining() { - return triesRemaining; - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index fbaf774da9..ad761c1dc8 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -179,30 +179,10 @@ public class SignalServiceAccountManager { return new SecureValueRecoveryV2(configuration, mrEnclave, pushServiceSocket); } - /** - * V1 PINs are no longer used in favor of V2 PINs stored on KBS. - * - * You can remove a V1 PIN, but typically this is unnecessary, as setting a V2 PIN via - * {@link KeyBackupService.PinChangeSession#enableRegistrationLock(MasterKey)}} will automatically clear the - * V1 PIN on the service. - */ - public void removeRegistrationLockV1() throws IOException { - this.pushServiceSocket.removeRegistrationLockV1(); - } - public WhoAmIResponse getWhoAmI() throws IOException { return this.pushServiceSocket.getWhoAmI(); } - public KeyBackupService getKeyBackupService(KeyStore iasKeyStore, - String enclaveName, - byte[] serviceId, - String mrenclave, - int tries) - { - return new KeyBackupService(iasKeyStore, enclaveName, serviceId, mrenclave, pushServiceSocket, tries); - } - /** * Register/Unregister a Google Cloud Messaging registration ID. * diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/SecureValueRecoveryV1.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/SecureValueRecoveryV1.kt deleted file mode 100644 index a0caec7852..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/svr/SecureValueRecoveryV1.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2023 Signal Messenger, LLC - * SPDX-License-Identifier: AGPL-3.0-only - */ - -package org.whispersystems.signalservice.api.svr - -import org.signal.libsignal.svr2.PinHash -import org.whispersystems.signalservice.api.KeyBackupService -import org.whispersystems.signalservice.api.KeyBackupServicePinException -import org.whispersystems.signalservice.api.SvrNoDataException -import org.whispersystems.signalservice.api.SvrPinData -import org.whispersystems.signalservice.api.kbs.MasterKey -import org.whispersystems.signalservice.api.kbs.PinHashUtil -import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException -import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse -import org.whispersystems.signalservice.api.svr.SecureValueRecovery.DeleteResponse -import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession -import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException -import org.whispersystems.signalservice.internal.push.AuthCredentials -import java.io.IOException -import kotlin.jvm.Throws - -/** - * An implementation of the [SecureValueRecovery] interface backed by the [KeyBackupService]. - */ -class SecureValueRecoveryV1(private val kbs: KeyBackupService) : SecureValueRecovery { - - companion object { - const val TAG = "SVR1" - } - - override fun setPin(userPin: String, masterKey: MasterKey): PinChangeSession { - return Svr1PinChangeSession(userPin, masterKey) - } - - override fun resumePinChangeSession(userPin: String, masterKey: MasterKey, serializedChangeSession: String): PinChangeSession { - return setPin(userPin, masterKey) - } - - override fun restoreDataPreRegistration(authorization: AuthCredentials, userPin: String): RestoreResponse { - return restoreData({ authorization }, userPin) - } - - override fun restoreDataPostRegistration(userPin: String): RestoreResponse { - return restoreData({ kbs.authorization }, userPin) - } - - override fun deleteData(): DeleteResponse { - return try { - kbs.newPinChangeSession().removePin() - DeleteResponse.Success - } catch (e: UnauthenticatedResponseException) { - DeleteResponse.ApplicationError(e) - } catch (e: NonSuccessfulResponseCodeException) { - when (e.code) { - 404 -> DeleteResponse.EnclaveNotFound - 508 -> DeleteResponse.ServerRejected - else -> DeleteResponse.NetworkError(e) - } - } catch (e: IOException) { - DeleteResponse.NetworkError(e) - } - } - - @Throws(IOException::class) - override fun authorization(): AuthCredentials { - return kbs.authorization - } - - override fun toString(): String { - return "SVR1::${kbs.enclaveName}::${kbs.mrenclave}" - } - - private fun restoreData(fetchAuthorization: () -> AuthCredentials, userPin: String): RestoreResponse { - return try { - val authorization: AuthCredentials = fetchAuthorization() - val session = kbs.newRegistrationSession(authorization.asBasic(), null) - val pinHash: PinHash = PinHashUtil.hashPin(userPin, session.hashSalt()) - - val data: SvrPinData = session.restorePin(pinHash) - RestoreResponse.Success(data.masterKey, authorization) - } catch (e: SvrNoDataException) { - RestoreResponse.Missing - } catch (e: KeyBackupServicePinException) { - RestoreResponse.PinMismatch(e.triesRemaining) - } catch (e: IOException) { - RestoreResponse.NetworkError(e) - } catch (e: Exception) { - RestoreResponse.ApplicationError(e) - } - } - - inner class Svr1PinChangeSession( - private val userPin: String, - private val masterKey: MasterKey - ) : PinChangeSession { - override fun execute(): BackupResponse { - return try { - val session = kbs.newPinChangeSession() - val pinHash: PinHash = PinHashUtil.hashPin(userPin, session.hashSalt()) - - val data: SvrPinData = session.setPin(pinHash, masterKey) - BackupResponse.Success(data.masterKey, kbs.authorization) - } catch (e: UnauthenticatedResponseException) { - BackupResponse.ApplicationError(e) - } catch (e: NonSuccessfulResponseCodeException) { - when (e.code) { - 404 -> BackupResponse.EnclaveNotFound - 508 -> BackupResponse.ServerRejected - else -> BackupResponse.NetworkError(e) - } - } catch (e: IOException) { - BackupResponse.NetworkError(e) - } - } - - /** No real need to serialize */ - override fun serialize(): String { - return "" - } - } -} diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/configuration/SignalServiceConfiguration.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/configuration/SignalServiceConfiguration.kt index 5671e22f04..bf2a7013da 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/configuration/SignalServiceConfiguration.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/configuration/SignalServiceConfiguration.kt @@ -10,7 +10,6 @@ import java.util.Optional class SignalServiceConfiguration( val signalServiceUrls: Array, val signalCdnUrlMap: Map>, - val signalKeyBackupServiceUrls: Array, val signalStorageUrls: Array, val signalCdsiUrls: Array, val signalSvr2Urls: Array, diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index 074b8bd0b5..c3ef8fd2f4 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -316,7 +316,6 @@ public class PushServiceSocket { private final ServiceConnectionHolder[] serviceClients; private final Map cdnClientsMap; - private final ConnectionHolder[] keyBackupServiceClients; private final ConnectionHolder[] storageClients; private final CredentialsProvider credentialsProvider; @@ -336,7 +335,6 @@ public class PushServiceSocket { this.automaticNetworkRetry = automaticNetworkRetry; this.serviceClients = createServiceConnectionHolders(configuration.getSignalServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy()); this.cdnClientsMap = createCdnClientsMap(configuration.getSignalCdnUrlMap(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy()); - this.keyBackupServiceClients = createConnectionHolders(configuration.getSignalKeyBackupServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy()); this.storageClients = createConnectionHolders(configuration.getSignalStorageUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy()); this.random = new SecureRandom(); this.clientZkProfileOperations = clientZkProfileOperations; @@ -1281,34 +1279,10 @@ public class PushServiceSocket { return getAuthCredentials(authPath).asBasic(); } - public String getContactDiscoveryAuthorization() throws IOException { - return getCredentials(DIRECTORY_AUTH_PATH); - } - - public AuthCredentials getKeyBackupServiceAuthorization() throws IOException { - return getAuthCredentials(KBS_AUTH_PATH); - } - public AuthCredentials getPaymentsAuthorization() throws IOException { return getAuthCredentials(PAYMENTS_AUTH_PATH); } - public TokenResponse getKeyBackupServiceToken(String authorizationToken, String enclaveName) - throws IOException - { - try (Response response = makeRequest(ClientSet.KeyBackup, authorizationToken, null, "/v1/token/" + enclaveName, "GET", null)) { - return readBodyJson(response, TokenResponse.class); - } - } - - public KeyBackupResponse putKbsData(String authorizationToken, KeyBackupRequest request, List cookies, String mrenclave) - throws IOException - { - try (Response response = makeRequest(ClientSet.KeyBackup, authorizationToken, cookies, "/v1/backup/" + mrenclave, "PUT", JsonUtil.toJson(request))) { - return readBodyJson(response, KeyBackupResponse.class); - } - } - public TurnServerInfo getTurnServerInfo() throws IOException { String response = makeServiceRequest(TURN_SERVER_INFO, "GET", null); return JsonUtil.fromJson(response, TurnServerInfo.class); @@ -2113,82 +2087,6 @@ public class PushServiceSocket { return request.build(); } - - private ConnectionHolder[] clientsFor(ClientSet clientSet) { - switch (clientSet) { - case KeyBackup: - return keyBackupServiceClients; - default: - throw new AssertionError("Unknown attestation purpose"); - } - } - - Response makeRequest(ClientSet clientSet, String authorization, List cookies, String path, String method, String body) - throws PushNetworkException, NonSuccessfulResponseCodeException - { - ConnectionHolder connectionHolder = getRandom(clientsFor(clientSet), random); - - OkHttpClient okHttpClient = connectionHolder.getClient() - .newBuilder() - .connectTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS) - .readTimeout(soTimeoutMillis, TimeUnit.MILLISECONDS) - .build(); - - Request.Builder request = new Request.Builder().url(connectionHolder.getUrl() + path); - - if (body != null) { - request.method(method, RequestBody.create(MediaType.parse("application/json"), body)); - } else { - request.method(method, null); - } - - if (connectionHolder.getHostHeader().isPresent()) { - request.addHeader("Host", connectionHolder.getHostHeader().get()); - } - - if (authorization != null) { - request.addHeader("Authorization", authorization); - } - - if (cookies != null && !cookies.isEmpty()) { - request.addHeader("Cookie", Util.join(cookies, "; ")); - } - - Call call = okHttpClient.newCall(request.build()); - - synchronized (connections) { - connections.add(call); - } - - Response response; - - try { - response = call.execute(); - - if (response.isSuccessful()) { - return response; - } - } catch (IOException e) { - throw new PushNetworkException(e); - } finally { - synchronized (connections) { - connections.remove(call); - } - } - - switch (response.code()) { - case 401: - case 403: - throw new AuthorizationFailedException(response.code(), "Authorization failed!"); - case 409: - throw new RemoteAttestationResponseExpiredException("Remote attestation response expired"); - case 429: - throw new RateLimitException(response.code(), "Rate limit exceeded: " + response.code()); - } - - throw new NonSuccessfulResponseCodeException(response.code(), "Response: " + response); - } - private Response makeStorageRequest(String authorization, String path, String method, RequestBody body, ResponseCodeHandler responseCodeHandler) throws PushNetworkException, NonSuccessfulResponseCodeException { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java b/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java deleted file mode 100644 index f0fc2f7234..0000000000 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/internal/push/RemoteAttestationUtil.java +++ /dev/null @@ -1,135 +0,0 @@ -package org.whispersystems.signalservice.internal.push; - -import org.signal.libsignal.protocol.InvalidKeyException; -import org.signal.libsignal.protocol.ecc.Curve; -import org.signal.libsignal.protocol.ecc.ECKeyPair; -import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException; -import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; -import org.whispersystems.signalservice.internal.contacts.crypto.Quote; -import org.whispersystems.signalservice.internal.contacts.crypto.RemoteAttestation; -import org.whispersystems.signalservice.internal.contacts.crypto.RemoteAttestationCipher; -import org.whispersystems.signalservice.internal.contacts.crypto.RemoteAttestationKeys; -import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedQuoteException; -import org.whispersystems.signalservice.internal.contacts.entities.MultiRemoteAttestationResponse; -import org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationRequest; -import org.whispersystems.signalservice.internal.contacts.entities.RemoteAttestationResponse; -import org.whispersystems.signalservice.internal.util.JsonUtil; - -import java.io.IOException; -import java.security.KeyStore; -import java.security.SignatureException; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import okhttp3.Response; -import okhttp3.ResponseBody; - -public final class RemoteAttestationUtil { - - private RemoteAttestationUtil() { - } - - public static RemoteAttestation getAndVerifyRemoteAttestation(PushServiceSocket socket, - PushServiceSocket.ClientSet clientSet, - KeyStore iasKeyStore, - String enclaveName, - String mrenclave, - String authorization) - throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException - { - ECKeyPair keyPair = buildKeyPair(); - ResponsePair result = makeAttestationRequest(socket, clientSet, authorization, enclaveName, keyPair); - RemoteAttestationResponse response = JsonUtil.fromJson(result.body, RemoteAttestationResponse.class); - - return validateAndBuildRemoteAttestation(response, result.cookies, iasKeyStore, keyPair, mrenclave); - } - - public static Map getAndVerifyMultiRemoteAttestation(PushServiceSocket socket, - PushServiceSocket.ClientSet clientSet, - KeyStore iasKeyStore, - String enclaveName, - String mrenclave, - String authorization) - throws IOException, Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException - { - ECKeyPair keyPair = buildKeyPair(); - ResponsePair result = makeAttestationRequest(socket, clientSet, authorization, enclaveName, keyPair); - MultiRemoteAttestationResponse response = JsonUtil.fromJson(result.body, MultiRemoteAttestationResponse.class); - Map attestations = new HashMap<>(); - - if (response.getAttestations().isEmpty() || response.getAttestations().size() > 3) { - throw new MalformedResponseException("Incorrect number of attestations: " + response.getAttestations().size()); - } - - for (Map.Entry entry : response.getAttestations().entrySet()) { - attestations.put(entry.getKey(), - validateAndBuildRemoteAttestation(entry.getValue(), - result.cookies, - iasKeyStore, - keyPair, - mrenclave)); - } - - return attestations; - } - - private static ECKeyPair buildKeyPair() { - return Curve.generateKeyPair(); - } - - private static ResponsePair makeAttestationRequest(PushServiceSocket socket, - PushServiceSocket.ClientSet clientSet, - String authorization, - String enclaveName, - ECKeyPair keyPair) - throws IOException - { - RemoteAttestationRequest attestationRequest = new RemoteAttestationRequest(keyPair.getPublicKey().getPublicKeyBytes()); - - try (Response response = socket.makeRequest(clientSet, authorization, Collections.emptyList(), "/v1/attestation/" +enclaveName, "PUT", JsonUtil.toJson(attestationRequest))) { - return new ResponsePair(PushServiceSocket.readBodyString(response), parseCookies(response)); - } - } - - private static List parseCookies(Response response) { - List rawCookies = response.headers("Set-Cookie"); - List cookies = new LinkedList<>(); - - for (String cookie : rawCookies) { - cookies.add(cookie.split(";")[0]); - } - - return cookies; - } - - private static RemoteAttestation validateAndBuildRemoteAttestation(RemoteAttestationResponse response, - List cookies, - KeyStore iasKeyStore, - ECKeyPair keyPair, - String mrenclave) - throws Quote.InvalidQuoteFormatException, InvalidCiphertextException, UnauthenticatedQuoteException, SignatureException, InvalidKeyException - { - RemoteAttestationKeys keys = new RemoteAttestationKeys(keyPair, response.getServerEphemeralPublic(), response.getServerStaticPublic()); - Quote quote = new Quote(response.getQuote()); - byte[] requestId = RemoteAttestationCipher.getRequestId(keys, response); - - RemoteAttestationCipher.verifyServerQuote(quote, response.getServerStaticPublic(), mrenclave); - - RemoteAttestationCipher.verifyIasSignature(iasKeyStore, response.getCertificates(), response.getSignatureBody(), response.getSignature(), quote); - - return new RemoteAttestation(requestId, keys, cookies); - } - - private static class ResponsePair { - final String body; - final List cookies; - - private ResponsePair(String body, List cookies) { - this.body = body; - this.cookies = cookies; - } - } -}