Remove all unused KBS/SVR1 code.

This commit is contained in:
Greyson Parrelli
2023-10-16 07:33:05 -07:00
committed by Cody Henthorne
parent 5b0e71b680
commit 609e9fcdb0
24 changed files with 8 additions and 840 deletions

View File

@@ -186,7 +186,6 @@ android {
buildConfigField "String[]", "SIGNAL_CDN_IPS", cdn_ips buildConfigField "String[]", "SIGNAL_CDN_IPS", cdn_ips
buildConfigField "String[]", "SIGNAL_CDN2_IPS", cdn2_ips buildConfigField "String[]", "SIGNAL_CDN2_IPS", cdn2_ips
buildConfigField "String[]", "SIGNAL_CDN3_IPS", cdn3_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_SFU_IPS", sfu_ips
buildConfigField "String[]", "SIGNAL_CONTENT_PROXY_IPS", content_proxy_ips buildConfigField "String[]", "SIGNAL_CONTENT_PROXY_IPS", content_proxy_ips
buildConfigField "String[]", "SIGNAL_CDSI_IPS", cdsi_ips buildConfigField "String[]", "SIGNAL_CDSI_IPS", cdsi_ips
@@ -194,12 +193,6 @@ android {
buildConfigField "String", "SIGNAL_AGENT", "\"OWA\"" buildConfigField "String", "SIGNAL_AGENT", "\"OWA\""
buildConfigField "String", "CDSI_MRENCLAVE", "\"0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57\"" buildConfigField "String", "CDSI_MRENCLAVE", "\"0f6fd79cdfdaa5b2e6337f534d3baf999318b0c462a7ac1f41297a3e4b424a57\""
buildConfigField "String", "SVR2_MRENCLAVE", "\"6ee1042f9e20f880326686dd4ba50c25359f01e9f733eeba4382bca001d45094\"" 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", "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", "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\"" 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_KEY_BACKUP_URL", "\"https://api-staging.backup.signal.org\""
buildConfigField "String", "SIGNAL_SVR2_URL", "\"https://svr2.staging.signal.org\"" buildConfigField "String", "SIGNAL_SVR2_URL", "\"https://svr2.staging.signal.org\""
buildConfigField "String", "SVR2_MRENCLAVE", "\"a8a261420a6bb9b61aa25bf8a79e8bd20d7652531feb3381cbffd446d270be95\"" 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", "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", "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\"" buildConfigField "String", "GENERIC_SERVER_PUBLIC_PARAMS", "\"AHILOIrFPXX9laLbalbA9+L1CXpSbM/bTJXZGZiuyK1JaI6dK5FHHWL6tWxmHKYAZTSYmElmJ5z2A5YcirjO/yfoemE03FItyaf8W1fE4p14hzb5qnrmfXUSiAIVrhaXVwIwSzH6RL/+EO8jFIjJ/YfExfJ8aBl48CKHgu1+A6kWynhttonvWWx6h7924mIzW0Czj2ROuh4LwQyZypex4GuOPW8sgIT21KNZaafgg+KbV7XM1x1tF3XA17B4uGUaDbDw2O+nR1+U5p6qHPzmJ7ggFjSN6Utu+35dS1sS0P9N\""

View File

@@ -230,8 +230,6 @@ class ChangeNumberViewModelTest {
lateinit var changeNumberRequest: ChangePhoneNumberRequest lateinit var changeNumberRequest: ChangePhoneNumberRequest
lateinit var setPreKeysRequest: PreKeyState lateinit var setPreKeysRequest: PreKeyState
MockProvider.mockGetRegistrationLockStringFlow()
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers( InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) }, Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) },
Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) }, Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) },
@@ -318,8 +316,6 @@ class ChangeNumberViewModelTest {
lateinit var changeNumberRequest: ChangePhoneNumberRequest lateinit var changeNumberRequest: ChangePhoneNumberRequest
lateinit var setPreKeysRequest: PreKeyState lateinit var setPreKeysRequest: PreKeyState
MockProvider.mockGetRegistrationLockStringFlow()
InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers( InstrumentationApplicationDependencyProvider.addMockWebRequestHandlers(
Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) }, Post("/v1/verification/session") { MockResponse().success(MockProvider.sessionMetadataJson.copy(verified = false)) },
Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) }, Put("/v1/verification/session/${MockProvider.sessionMetadataJson.id}/code") { MockResponse().success(MockProvider.sessionMetadataJson) },

View File

@@ -16,7 +16,6 @@ import org.mockito.kotlin.mock
import org.signal.core.util.Base64 import org.signal.core.util.Base64
import org.signal.core.util.logging.Log import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.BuildConfig import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.KbsEnclave
import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess
import org.thoughtcrime.securesms.push.SignalServiceTrustStore import org.thoughtcrime.securesms.push.SignalServiceTrustStore
import org.thoughtcrime.securesms.recipients.LiveRecipientCache 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.Verb
import org.thoughtcrime.securesms.testing.runSync import org.thoughtcrime.securesms.testing.runSync
import org.thoughtcrime.securesms.testing.success 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.api.push.TrustStore
import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl import org.whispersystems.signalservice.internal.configuration.SignalCdnUrl
import org.whispersystems.signalservice.internal.configuration.SignalCdsiUrl 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.SignalServiceConfiguration
import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl import org.whispersystems.signalservice.internal.configuration.SignalServiceUrl
import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl import org.whispersystems.signalservice.internal.configuration.SignalStorageUrl
import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url import org.whispersystems.signalservice.internal.configuration.SignalSvr2Url
import java.security.KeyStore
import java.util.Optional import java.util.Optional
/** /**
* Dependency provider used for instrumentation tests (aka androidTests). * 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 * Handles setting up a mock web server for API calls, and provides mockable versions of [SignalServiceNetworkAccess].
* [KeyBackupService].
*/ */
class InstrumentationApplicationDependencyProvider(application: Application, default: ApplicationDependencyProvider) : ApplicationDependencies.Provider by default { class InstrumentationApplicationDependencyProvider(application: Application, default: ApplicationDependencyProvider) : ApplicationDependencies.Provider by default {
private val serviceTrustStore: TrustStore private val serviceTrustStore: TrustStore
private val uncensoredConfiguration: SignalServiceConfiguration private val uncensoredConfiguration: SignalServiceConfiguration
private val serviceNetworkAccessMock: SignalServiceNetworkAccess private val serviceNetworkAccessMock: SignalServiceNetworkAccess
private val keyBackupService: KeyBackupService
private val recipientCache: LiveRecipientCache private val recipientCache: LiveRecipientCache
init { init {
@@ -80,7 +73,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def
0 to arrayOf(SignalCdnUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), 0 to arrayOf(SignalCdnUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)),
2 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)), signalStorageUrls = arrayOf(SignalStorageUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)),
signalCdsiUrls = arrayOf(SignalCdsiUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)), signalCdsiUrls = arrayOf(SignalCdsiUrl(baseUrl, "localhost", serviceTrustStore, ConnectionSpec.CLEARTEXT)),
signalSvr2Urls = arrayOf(SignalSvr2Url(baseUrl, serviceTrustStore, "localhost", ConnectionSpec.CLEARTEXT)), signalSvr2Urls = arrayOf(SignalSvr2Url(baseUrl, serviceTrustStore, "localhost", ConnectionSpec.CLEARTEXT)),
@@ -97,8 +89,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def
on { uncensoredConfiguration } doReturn uncensoredConfiguration on { uncensoredConfiguration } doReturn uncensoredConfiguration
} }
keyBackupService = mock()
recipientCache = LiveRecipientCache(application) { r -> r.run() } recipientCache = LiveRecipientCache(application) { r -> r.run() }
} }
@@ -106,10 +96,6 @@ class InstrumentationApplicationDependencyProvider(application: Application, def
return serviceNetworkAccessMock return serviceNetworkAccessMock
} }
override fun provideKeyBackupService(signalServiceAccountManager: SignalServiceAccountManager, keyStore: KeyStore, enclave: KbsEnclave): KeyBackupService {
return keyBackupService
}
override fun provideRecipientCache(): LiveRecipientCache { override fun provideRecipientCache(): LiveRecipientCache {
return recipientCache return recipientCache
} }

View File

@@ -1,22 +1,12 @@
package org.thoughtcrime.securesms.testing 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.IdentityKeyPair
import org.signal.libsignal.protocol.ecc.Curve import org.signal.libsignal.protocol.ecc.Curve
import org.signal.libsignal.protocol.state.PreKeyRecord import org.signal.libsignal.protocol.state.PreKeyRecord
import org.signal.libsignal.protocol.util.KeyHelper import org.signal.libsignal.protocol.util.KeyHelper
import org.signal.libsignal.protocol.util.Medium import org.signal.libsignal.protocol.util.Medium
import org.signal.libsignal.svr2.PinHash
import org.thoughtcrime.securesms.crypto.PreKeyUtil import org.thoughtcrime.securesms.crypto.PreKeyUtil
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore 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.messages.multidevice.DeviceInfo
import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.push.SignedPreKeyEntity 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 { fun createPreKeyResponse(identity: IdentityKeyPair = SignalStore.account().aciIdentityKey, deviceId: Int): PreKeyResponse {
val signedPreKeyRecord = PreKeyUtil.generateSignedPreKey(SecureRandom().nextInt(Medium.MAX_VALUE), identity.privateKey) val signedPreKeyRecord = PreKeyUtil.generateSignedPreKey(SecureRandom().nextInt(Medium.MAX_VALUE), identity.privateKey)
val oneTimePreKey = PreKeyRecord(SecureRandom().nextInt(Medium.MAX_VALUE), Curve.generateKeyPair()) val oneTimePreKey = PreKeyRecord(SecureRandom().nextInt(Medium.MAX_VALUE), Curve.generateKeyPair())

View File

@@ -124,7 +124,7 @@ fun SvrPlaygroundScreenLightTheme() {
Surface { Surface {
SvrPlaygroundScreen( SvrPlaygroundScreen(
state = InternalSvrPlaygroundState( state = InternalSvrPlaygroundState(
options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) options = persistentListOf(SvrImplementation.SVR2)
) )
) )
} }
@@ -138,7 +138,7 @@ fun SvrPlaygroundScreenDarkTheme() {
Surface { Surface {
SvrPlaygroundScreen( SvrPlaygroundScreen(
state = InternalSvrPlaygroundState( state = InternalSvrPlaygroundState(
options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) options = persistentListOf(SvrImplementation.SVR2)
) )
) )
} }

View File

@@ -13,5 +13,5 @@ data class InternalSvrPlaygroundState(
enum class SvrImplementation( enum class SvrImplementation(
val title: String val title: String
) { ) {
SVR1("KBS"), SVR2("SVR2") SVR2("SVR2")
} }

View File

@@ -19,13 +19,12 @@ import org.thoughtcrime.securesms.BuildConfig
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.whispersystems.signalservice.api.svr.SecureValueRecovery import org.whispersystems.signalservice.api.svr.SecureValueRecovery
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1
class InternalSvrPlaygroundViewModel : ViewModel() { class InternalSvrPlaygroundViewModel : ViewModel() {
private val _state: MutableState<InternalSvrPlaygroundState> = mutableStateOf( private val _state: MutableState<InternalSvrPlaygroundState> = mutableStateOf(
InternalSvrPlaygroundState( InternalSvrPlaygroundState(
options = persistentListOf(SvrImplementation.SVR1, SvrImplementation.SVR2) options = persistentListOf(SvrImplementation.SVR2)
) )
) )
val state: State<InternalSvrPlaygroundState> = _state val state: State<InternalSvrPlaygroundState> = _state
@@ -104,7 +103,6 @@ class InternalSvrPlaygroundViewModel : ViewModel() {
private fun SvrImplementation.toImplementation(): SecureValueRecovery { private fun SvrImplementation.toImplementation(): SecureValueRecovery {
return when (this) { return when (this) {
SvrImplementation.SVR1 -> SecureValueRecoveryV1(ApplicationDependencies.getKeyBackupService(BuildConfig.KBS_ENCLAVE))
SvrImplementation.SVR2 -> ApplicationDependencies.getSignalServiceAccountManager().getSecureValueRecoveryV2(BuildConfig.SVR2_MRENCLAVE) SvrImplementation.SVR2 -> ApplicationDependencies.getSignalServiceAccountManager().getSecureValueRecoveryV2(BuildConfig.SVR2_MRENCLAVE)
} }
} }

View File

@@ -14,13 +14,11 @@ import org.thoughtcrime.securesms.database.model.GroupRecord;
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
import org.thoughtcrime.securesms.groups.GroupManager; import org.thoughtcrime.securesms.groups.GroupManager;
import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.pin.KbsEnclaves;
import org.thoughtcrime.securesms.subscription.Subscriber; import org.thoughtcrime.securesms.subscription.Subscriber;
import org.thoughtcrime.securesms.util.ServiceUtil; import org.thoughtcrime.securesms.util.ServiceUtil;
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter; import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
import org.whispersystems.signalservice.internal.EmptyResponse; import org.whispersystems.signalservice.internal.EmptyResponse;
import org.whispersystems.signalservice.internal.ServiceResponse; import org.whispersystems.signalservice.internal.ServiceResponse;
import org.whispersystems.signalservice.internal.contacts.crypto.UnauthenticatedResponseException;
import java.io.IOException; import java.io.IOException;
import java.text.Collator; import java.text.Collator;

View File

@@ -10,7 +10,6 @@ import androidx.annotation.VisibleForTesting;
import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.core.util.concurrent.DeadlockDetector;
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations;
import org.thoughtcrime.securesms.KbsEnclave;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl; 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.AppForegroundObserver;
import org.thoughtcrime.securesms.util.EarlyMessageCache; import org.thoughtcrime.securesms.util.EarlyMessageCache;
import org.thoughtcrime.securesms.util.FrameRateTracker; 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.ExoPlayerPool;
import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache; import org.thoughtcrime.securesms.video.exo.GiphyMp4Cache;
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool;
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat;
import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; 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 org.whispersystems.signalservice.internal.util.Util;
import java.security.KeyManagementException; import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -199,10 +195,6 @@ public class ApplicationDependencies {
return groupsV2Operations; return groupsV2Operations;
} }
public static @NonNull KeyBackupService getKeyBackupService(@NonNull KbsEnclave enclave) {
return provider.provideKeyBackupService(getSignalServiceAccountManager(), IasKeyStore.getIasKeyStore(application), enclave);
}
public static @NonNull GroupsV2StateProcessor getGroupsV2StateProcessor() { public static @NonNull GroupsV2StateProcessor getGroupsV2StateProcessor() {
if (groupsV2StateProcessor == null) { if (groupsV2StateProcessor == null) {
synchronized (LOCK) { synchronized (LOCK) {
@@ -724,7 +716,6 @@ public class ApplicationDependencies {
@NonNull ProfileService provideProfileService(@NonNull ClientZkProfileOperations profileOperations, @NonNull SignalServiceMessageReceiver signalServiceMessageReceiver, @NonNull SignalWebSocket signalWebSocket); @NonNull ProfileService provideProfileService(@NonNull ClientZkProfileOperations profileOperations, @NonNull SignalServiceMessageReceiver signalServiceMessageReceiver, @NonNull SignalWebSocket signalWebSocket);
@NonNull DeadlockDetector provideDeadlockDetector(); @NonNull DeadlockDetector provideDeadlockDetector();
@NonNull ClientZkReceiptOperations provideClientZkReceiptOperations(@NonNull SignalServiceConfiguration signalServiceConfiguration); @NonNull ClientZkReceiptOperations provideClientZkReceiptOperations(@NonNull SignalServiceConfiguration signalServiceConfiguration);
@NonNull KeyBackupService provideKeyBackupService(@NonNull SignalServiceAccountManager signalServiceAccountManager, @NonNull KeyStore keyStore, @NonNull KbsEnclave enclave);
@NonNull ScheduledMessageManager provideScheduledMessageManager(); @NonNull ScheduledMessageManager provideScheduledMessageManager();
} }
} }

View File

@@ -8,14 +8,12 @@ import android.os.HandlerThread;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.signal.core.util.Hex;
import org.signal.core.util.ThreadUtil; import org.signal.core.util.ThreadUtil;
import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.core.util.concurrent.DeadlockDetector;
import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.concurrent.SignalExecutors;
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations;
import org.thoughtcrime.securesms.BuildConfig; import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.KbsEnclave;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock; 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.GiphyMp4Cache;
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool;
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat;
import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; 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.configuration.SignalServiceConfiguration;
import org.whispersystems.signalservice.internal.websocket.WebSocketConnection; import org.whispersystems.signalservice.internal.websocket.WebSocketConnection;
import java.security.KeyStore;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -394,15 +390,6 @@ public class ApplicationDependencyProvider implements ApplicationDependencies.Pr
return provideClientZkOperations(signalServiceConfiguration).getReceiptOperations(); 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<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull SignalWebSocketHealthMonitor healthMonitor) { @NonNull WebSocketFactory provideWebSocketFactory(@NonNull Supplier<SignalServiceConfiguration> signalServiceConfigurationSupplier, @NonNull SignalWebSocketHealthMonitor healthMonitor) {
return new WebSocketFactory() { return new WebSocketFactory() {
@Override @Override

View File

@@ -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
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession import org.whispersystems.signalservice.api.svr.SecureValueRecovery.PinChangeSession
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1
import kotlin.concurrent.withLock import kotlin.concurrent.withLock
import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.days
@@ -83,14 +82,7 @@ class ResetSvrGuessCountJob private constructor(
Result.success() Result.success()
} }
if (!svr2Result.isSuccess) {
return svr2Result 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)
} }
} }

View File

@@ -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<KbsEnclave> all() {
return Util.join(Collections.singletonList(BuildConfig.KBS_ENCLAVE), fallbacks());
}
public static @NonNull List<KbsEnclave> fallbacks() {
return Arrays.asList(BuildConfig.KBS_FALLBACKS);
}
}

View File

@@ -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
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse import org.whispersystems.signalservice.api.svr.SecureValueRecovery.BackupResponse
import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse import org.whispersystems.signalservice.api.svr.SecureValueRecovery.RestoreResponse
import org.whispersystems.signalservice.api.svr.SecureValueRecoveryV1
import org.whispersystems.signalservice.internal.push.AuthCredentials import org.whispersystems.signalservice.internal.push.AuthCredentials
import java.io.IOException import java.io.IOException
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -41,10 +40,9 @@ object SvrRepository {
val TAG = Log.tag(SvrRepository::class.java) val TAG = Log.tag(SvrRepository::class.java)
private val svr2: SecureValueRecovery = ApplicationDependencies.getSignalServiceAccountManager().getSecureValueRecoveryV2(BuildConfig.SVR2_MRENCLAVE) 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. */ /** An ordered list of SVR implementations. They should be in priority order, with the most important one listed first. */
private val implementations: List<SecureValueRecovery> = listOf(svr2, svr1) private val implementations: List<SecureValueRecovery> = listOf(svr2)
/** /**
* A lock that ensures that only one thread at a time is altering the various pieces of SVR state. * 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) Log.i(TAG, "restoreMasterKeyPreRegistration()", true)
val operations: List<Pair<SecureValueRecovery, () -> RestoreResponse>> = listOf( val operations: List<Pair<SecureValueRecovery, () -> RestoreResponse>> = listOf(
svr2 to { restoreMasterKeyPreRegistration(svr2, credentials.svr2, userPin) }, svr2 to { restoreMasterKeyPreRegistration(svr2, credentials.svr2, userPin) }
svr1 to { restoreMasterKeyPreRegistration(svr1, credentials.svr1, userPin) }
) )
for ((implementation, operation) in operations) { for ((implementation, operation) in operations) {

View File

@@ -48,7 +48,6 @@ open class SignalServiceNetworkAccess(context: Context) {
BuildConfig.STORAGE_URL.stripProtocol() to BuildConfig.SIGNAL_STORAGE_IPS.toSet(), BuildConfig.STORAGE_URL.stripProtocol() to BuildConfig.SIGNAL_STORAGE_IPS.toSet(),
BuildConfig.SIGNAL_CDN_URL.stripProtocol() to BuildConfig.SIGNAL_CDN_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_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.SIGNAL_SFU_URL.stripProtocol() to BuildConfig.SIGNAL_SFU_IPS.toSet(),
BuildConfig.CONTENT_PROXY_HOST.stripProtocol() to BuildConfig.SIGNAL_CONTENT_PROXY_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(), 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(), 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() 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(), 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(), 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(), 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)), 2 to arrayOf(SignalCdnUrl(BuildConfig.SIGNAL_CDN2_URL, serviceTrustStore)),
3 to arrayOf(SignalCdnUrl(BuildConfig.SIGNAL_CDN3_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)), signalStorageUrls = arrayOf(SignalStorageUrl(BuildConfig.STORAGE_URL, serviceTrustStore)),
signalCdsiUrls = arrayOf(SignalCdsiUrl(BuildConfig.SIGNAL_CDSI_URL, serviceTrustStore)), signalCdsiUrls = arrayOf(SignalCdsiUrl(BuildConfig.SIGNAL_CDSI_URL, serviceTrustStore)),
signalSvr2Urls = arrayOf(SignalSvr2Url(BuildConfig.SIGNAL_SVR2_URL, serviceTrustStore)), signalSvr2Urls = arrayOf(SignalSvr2Url(BuildConfig.SIGNAL_SVR2_URL, serviceTrustStore)),
@@ -299,7 +296,6 @@ open class SignalServiceNetworkAccess(context: Context) {
2 to cdn2Urls, 2 to cdn2Urls,
3 to cdn3Urls 3 to cdn3Urls
), ),
signalKeyBackupServiceUrls = kbsUrls,
signalStorageUrls = storageUrls, signalStorageUrls = storageUrls,
signalCdsiUrls = cdsiUrls, signalCdsiUrls = cdsiUrls,
signalSvr2Urls = svr2Urls, signalSvr2Urls = svr2Urls,

View File

@@ -5,7 +5,6 @@ import androidx.annotation.NonNull;
import org.signal.core.util.concurrent.DeadlockDetector; import org.signal.core.util.concurrent.DeadlockDetector;
import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations; import org.signal.libsignal.zkgroup.profiles.ClientZkProfileOperations;
import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations; import org.signal.libsignal.zkgroup.receipts.ClientZkReceiptOperations;
import org.thoughtcrime.securesms.KbsEnclave;
import org.thoughtcrime.securesms.components.TypingStatusRepository; import org.thoughtcrime.securesms.components.TypingStatusRepository;
import org.thoughtcrime.securesms.components.TypingStatusSender; import org.thoughtcrime.securesms.components.TypingStatusSender;
import org.thoughtcrime.securesms.crypto.storage.SignalServiceDataStoreImpl; 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.GiphyMp4Cache;
import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool; import org.thoughtcrime.securesms.video.exo.SimpleExoPlayerPool;
import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat; import org.thoughtcrime.securesms.webrtc.audio.AudioManagerCompat;
import org.whispersystems.signalservice.api.KeyBackupService;
import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.SignalServiceDataStore; import org.whispersystems.signalservice.api.SignalServiceDataStore;
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; 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.api.services.ProfileService;
import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration;
import java.security.KeyStore;
import java.util.function.Supplier; import java.util.function.Supplier;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
@@ -231,11 +228,6 @@ public class MockApplicationDependencyProvider implements ApplicationDependencie
return null; return null;
} }
@Override
public @NonNull KeyBackupService provideKeyBackupService(@NonNull SignalServiceAccountManager signalServiceAccountManager, @NonNull KeyStore keyStore, @NonNull KbsEnclave enclave) {
return null;
}
@Override @Override
public @NonNull ScheduledMessageManager provideScheduledMessageManager() { public @NonNull ScheduledMessageManager provideScheduledMessageManager() {
return null; return null;

View File

@@ -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.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.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.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.sfu_ips='new String[]{"34.95.127.167"}'
ext.content_proxy_ips='new String[]{"107.178.250.75"}' ext.content_proxy_ips='new String[]{"107.178.250.75"}'
ext.svr2_ips='new String[]{"20.119.62.85"}' ext.svr2_ips='new String[]{"20.119.62.85"}'

View File

@@ -131,7 +131,6 @@ task resolveStaticIps {
ext.cdn_ips='${staticIpResolver.resolveToBuildConfig("cdn.signal.org")}' ext.cdn_ips='${staticIpResolver.resolveToBuildConfig("cdn.signal.org")}'
ext.cdn2_ips='${staticIpResolver.resolveToBuildConfig("cdn2.signal.org")}' ext.cdn2_ips='${staticIpResolver.resolveToBuildConfig("cdn2.signal.org")}'
ext.cdn3_ips='${staticIpResolver.resolveToBuildConfig("cdn3.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.sfu_ips='${staticIpResolver.resolveToBuildConfig("sfu.voip.signal.org")}'
ext.content_proxy_ips='${staticIpResolver.resolveToBuildConfig("contentproxy.signal.org")}' ext.content_proxy_ips='${staticIpResolver.resolveToBuildConfig("contentproxy.signal.org")}'
ext.svr2_ips='${staticIpResolver.resolveToBuildConfig("svr2.signal.org")}' ext.svr2_ips='${staticIpResolver.resolveToBuildConfig("svr2.signal.org")}'

View File

@@ -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.
* <p>
* 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;
}
}

View File

@@ -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;
}
}

View File

@@ -179,30 +179,10 @@ public class SignalServiceAccountManager {
return new SecureValueRecoveryV2(configuration, mrEnclave, pushServiceSocket); 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 { public WhoAmIResponse getWhoAmI() throws IOException {
return this.pushServiceSocket.getWhoAmI(); 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. * Register/Unregister a Google Cloud Messaging registration ID.
* *

View File

@@ -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 ""
}
}
}

View File

@@ -10,7 +10,6 @@ import java.util.Optional
class SignalServiceConfiguration( class SignalServiceConfiguration(
val signalServiceUrls: Array<SignalServiceUrl>, val signalServiceUrls: Array<SignalServiceUrl>,
val signalCdnUrlMap: Map<Int, Array<SignalCdnUrl>>, val signalCdnUrlMap: Map<Int, Array<SignalCdnUrl>>,
val signalKeyBackupServiceUrls: Array<SignalKeyBackupServiceUrl>,
val signalStorageUrls: Array<SignalStorageUrl>, val signalStorageUrls: Array<SignalStorageUrl>,
val signalCdsiUrls: Array<SignalCdsiUrl>, val signalCdsiUrls: Array<SignalCdsiUrl>,
val signalSvr2Urls: Array<SignalSvr2Url>, val signalSvr2Urls: Array<SignalSvr2Url>,

View File

@@ -316,7 +316,6 @@ public class PushServiceSocket {
private final ServiceConnectionHolder[] serviceClients; private final ServiceConnectionHolder[] serviceClients;
private final Map<Integer, ConnectionHolder[]> cdnClientsMap; private final Map<Integer, ConnectionHolder[]> cdnClientsMap;
private final ConnectionHolder[] keyBackupServiceClients;
private final ConnectionHolder[] storageClients; private final ConnectionHolder[] storageClients;
private final CredentialsProvider credentialsProvider; private final CredentialsProvider credentialsProvider;
@@ -336,7 +335,6 @@ public class PushServiceSocket {
this.automaticNetworkRetry = automaticNetworkRetry; this.automaticNetworkRetry = automaticNetworkRetry;
this.serviceClients = createServiceConnectionHolders(configuration.getSignalServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy()); this.serviceClients = createServiceConnectionHolders(configuration.getSignalServiceUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy());
this.cdnClientsMap = createCdnClientsMap(configuration.getSignalCdnUrlMap(), 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.storageClients = createConnectionHolders(configuration.getSignalStorageUrls(), configuration.getNetworkInterceptors(), configuration.getDns(), configuration.getSignalProxy());
this.random = new SecureRandom(); this.random = new SecureRandom();
this.clientZkProfileOperations = clientZkProfileOperations; this.clientZkProfileOperations = clientZkProfileOperations;
@@ -1281,34 +1279,10 @@ public class PushServiceSocket {
return getAuthCredentials(authPath).asBasic(); 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 { public AuthCredentials getPaymentsAuthorization() throws IOException {
return getAuthCredentials(PAYMENTS_AUTH_PATH); 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<String> 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 { public TurnServerInfo getTurnServerInfo() throws IOException {
String response = makeServiceRequest(TURN_SERVER_INFO, "GET", null); String response = makeServiceRequest(TURN_SERVER_INFO, "GET", null);
return JsonUtil.fromJson(response, TurnServerInfo.class); return JsonUtil.fromJson(response, TurnServerInfo.class);
@@ -2113,82 +2087,6 @@ public class PushServiceSocket {
return request.build(); 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<String> 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) private Response makeStorageRequest(String authorization, String path, String method, RequestBody body, ResponseCodeHandler responseCodeHandler)
throws PushNetworkException, NonSuccessfulResponseCodeException throws PushNetworkException, NonSuccessfulResponseCodeException
{ {

View File

@@ -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<String, RemoteAttestation> 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<String, RemoteAttestation> attestations = new HashMap<>();
if (response.getAttestations().isEmpty() || response.getAttestations().size() > 3) {
throw new MalformedResponseException("Incorrect number of attestations: " + response.getAttestations().size());
}
for (Map.Entry<String, RemoteAttestationResponse> 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<String> parseCookies(Response response) {
List<String> rawCookies = response.headers("Set-Cookie");
List<String> cookies = new LinkedList<>();
for (String cookie : rawCookies) {
cookies.add(cookie.split(";")[0]);
}
return cookies;
}
private static RemoteAttestation validateAndBuildRemoteAttestation(RemoteAttestationResponse response,
List<String> 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<String> cookies;
private ResponsePair(String body, List<String> cookies) {
this.body = body;
this.cookies = cookies;
}
}
}