Remove UserCertificatesProvider:

`rustls-platform-verifier` automatically checks the user certs too, so there's no need to provide them separately.

This should also improve start times since we don't need to load the user certs when starting the app, which was a really slow operation.
This commit is contained in:
Jorge Martín
2026-06-18 14:04:37 +02:00
committed by Jorge Martin Espinosa
parent 8eafab20aa
commit 3586824a0d
7 changed files with 0 additions and 113 deletions
@@ -19,7 +19,6 @@ import io.element.android.libraries.featureflag.api.FeatureFlagService
import io.element.android.libraries.featureflag.api.FeatureFlags
import io.element.android.libraries.matrix.api.paths.SessionPaths
import io.element.android.libraries.matrix.impl.analytics.UtdTracker
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
import io.element.android.libraries.matrix.impl.paths.getSessionPaths
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
import io.element.android.libraries.matrix.impl.room.TimelineEventFilterFactory
@@ -60,7 +59,6 @@ class RustMatrixClientFactory(
private val sessionStore: SessionStore,
private val userAgentProvider: UserAgentProvider,
private val proxyProvider: ProxyProvider,
private val userCertificatesProvider: UserCertificatesProvider,
private val clock: SystemClock,
private val analyticsService: AnalyticsService,
private val featureFlagService: FeatureFlagService,
@@ -152,7 +150,6 @@ class RustMatrixClientFactory(
}
.setSessionDelegate(sessionDelegate)
.userAgent(userAgentProvider.provide())
.addRootCertificates(userCertificatesProvider.provides())
.autoEnableBackups(true)
.autoEnableCrossSigning(true)
.roomKeyRecipientStrategy(
@@ -13,19 +13,16 @@ import dev.zacsweers.metro.ContributesBinding
import io.element.android.libraries.core.extensions.runCatchingExceptions
import io.element.android.libraries.matrix.api.auth.HomeServerLoginCompatibilityChecker
import io.element.android.libraries.matrix.impl.ClientBuilderProvider
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
import timber.log.Timber
@ContributesBinding(AppScope::class)
class RustHomeServerLoginCompatibilityChecker(
private val clientBuilderProvider: ClientBuilderProvider,
private val userCertificatesProvider: UserCertificatesProvider,
) : HomeServerLoginCompatibilityChecker {
override suspend fun check(url: String): Result<Boolean> = runCatchingExceptions {
clientBuilderProvider.provide()
.inMemoryStore()
.serverNameOrHomeserverUrl(url)
.addRootCertificates(userCertificatesProvider.provides())
.build()
.use {
it.homeserverLoginDetails()
@@ -1,76 +0,0 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.certificates
import dev.zacsweers.metro.AppScope
import dev.zacsweers.metro.ContributesBinding
import timber.log.Timber
import java.security.KeyStore
import java.security.KeyStoreException
@ContributesBinding(AppScope::class)
class DefaultUserCertificatesProvider : UserCertificatesProvider {
/**
* Get additional user-installed certificates from the `AndroidCAStore` `Keystore`.
*
* The Rust HTTP client doesn't include user-installed certificates in its internal certificate
* store. This means that whatever the user installs will be ignored.
*
* While most users don't need user-installed certificates some special deployments or debugging
* setups using a proxy might want to use them.
*
* @return A list of byte arrays where each byte array is a single user-installed certificate
* in encoded form.
*/
override fun provides(): List<ByteArray> {
// At least for API 34 the `AndroidCAStore` `Keystore` type contained user certificates as well.
// I have not found this to be documented anywhere.
val keyStore: KeyStore = try {
KeyStore.getInstance("AndroidCAStore")
} catch (e: KeyStoreException) {
Timber.w(e, "Failed to get AndroidCAStore keystore")
return emptyList()
}
val aliases = try {
keyStore.load(null)
keyStore.aliases()
} catch (e: Exception) {
Timber.w(e, "Failed to load and get aliases AndroidCAStore keystore")
return emptyList()
}
return aliases.toList()
.filter { alias ->
// The certificate alias always contains the prefix `system` or
// `user` and the MD5 subject hash separated by a colon.
//
// The subject hash can be calculated using openssl as such:
// openssl x509 -subject_hash_old -noout -in mycert.cer
//
// Again, I have not found this to be documented somewhere.
alias.startsWith("user")
}
.mapNotNull { alias ->
try {
keyStore.getEntry(alias, null)
} catch (e: Exception) {
Timber.w(e, "Failed to get entry for alias $alias")
null
}
}
.filterIsInstance<KeyStore.TrustedCertificateEntry>()
.map { trustedCertificateEntry ->
trustedCertificateEntry.trustedCertificate.encoded
}
.also {
// Let's at least log the number of user-installed certificates we found,
// since the alias isn't particularly useful nor does the issuer seem to
// be easily available.
Timber.i("Found ${it.size} additional user-provided certificates.")
}
}
}
@@ -1,12 +0,0 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.certificates
interface UserCertificatesProvider {
fun provides(): List<ByteArray>
}
@@ -12,7 +12,6 @@ import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider
import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider
import io.element.android.libraries.matrix.impl.room.FakeTimelineEventFilterFactory
import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
@@ -58,7 +57,6 @@ fun TestScope.createRustMatrixClientFactory(
coroutineDispatchers = testCoroutineDispatchers(),
sessionStore = sessionStore,
userAgentProvider = SimpleUserAgentProvider(),
userCertificatesProvider = FakeUserCertificatesProvider(),
proxyProvider = FakeProxyProvider(),
clock = FakeSystemClock(),
analyticsService = FakeAnalyticsService(),
@@ -1,16 +0,0 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.auth
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
class FakeUserCertificatesProvider : UserCertificatesProvider {
override fun provides(): List<ByteArray> {
return emptyList()
}
}
@@ -49,6 +49,5 @@ class RustHomeserverLoginCompatibilityCheckerTest {
FakeFfiClient(homeserverLoginDetailsResult = result)
}
},
userCertificatesProvider = FakeUserCertificatesProvider(),
)
}