Limit supported cipher suites

This commit is contained in:
yostyle 2021-10-07 11:36:29 +02:00
parent 3a387c5e32
commit cbcb620ad1
5 changed files with 23 additions and 20 deletions

1
changelog.d/4192.misc Normal file
View file

@ -0,0 +1 @@
Limit supported TLS versions and cipher suites

View file

@ -16,6 +16,7 @@
package org.matrix.android.sdk.api package org.matrix.android.sdk.api
import okhttp3.ConnectionSpec
import org.matrix.android.sdk.api.crypto.MXCryptoConfig import org.matrix.android.sdk.api.crypto.MXCryptoConfig
import java.net.Proxy import java.net.Proxy
@ -44,6 +45,10 @@ data class MatrixConfiguration(
* You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port). * You can create one using for instance Proxy(proxyType, InetSocketAddress.createUnresolved(hostname, port).
*/ */
val proxy: Proxy? = null, val proxy: Proxy? = null,
/**
* TLS versions and cipher suites limitation for unauthenticated requests
*/
val connectionSpec: ConnectionSpec = ConnectionSpec.RESTRICTED_TLS,
/** /**
* True to advertise support for call transfers to other parties on Matrix calls. * True to advertise support for call transfers to other parties on Matrix calls.
*/ */

View file

@ -19,6 +19,7 @@ package org.matrix.android.sdk.api.auth.data
import android.net.Uri import android.net.Uri
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import okhttp3.CipherSuite import okhttp3.CipherSuite
import okhttp3.ConnectionSpec
import okhttp3.TlsVersion import okhttp3.TlsVersion
import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder import org.matrix.android.sdk.api.auth.data.HomeServerConnectionConfig.Builder
import org.matrix.android.sdk.internal.network.ssl.Fingerprint import org.matrix.android.sdk.internal.network.ssl.Fingerprint
@ -191,32 +192,25 @@ data class HomeServerConnectionConfig(
/** /**
* Convenient method to limit the TLS versions and cipher suites for this Builder * Convenient method to limit the TLS versions and cipher suites for this Builder
* Ref: * Ref:
* - https://www.ssi.gouv.fr/uploads/2017/02/security-recommendations-for-tls_v1.1.pdf * - https://www.ssi.gouv.fr/uploads/2017/07/anssi-guide-recommandations_de_securite_relatives_a_tls-v1.2.pdf
* - https://developer.android.com/reference/javax/net/ssl/SSLEngine * - https://developer.android.com/reference/javax/net/ssl/SSLEngine
* *
* @param tlsLimitations true to use Tls limitations * @param tlsLimitations true to use Tls limitations
* @param enableCompatibilityMode set to true for Android < 20 * @param enableCompatibilityMode set to true for Android < 20
* @return this builder * @return this builder
*/ */
@Deprecated("TLS versions and cipher suites are limited by default")
fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder { fun withTlsLimitations(tlsLimitations: Boolean, enableCompatibilityMode: Boolean): Builder {
if (tlsLimitations) { if (tlsLimitations) {
withShouldAcceptTlsExtensions(false) withShouldAcceptTlsExtensions(false)
// Tls versions // TlS versions
addAcceptedTlsVersion(TlsVersion.TLS_1_2) ConnectionSpec.RESTRICTED_TLS.tlsVersions?.let { this.tlsVersions.addAll(it) }
addAcceptedTlsVersion(TlsVersion.TLS_1_3)
forceUsageOfTlsVersions(enableCompatibilityMode) forceUsageOfTlsVersions(enableCompatibilityMode)
// Cipher suites // Cipher suites
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) ConnectionSpec.RESTRICTED_TLS.cipherSuites?.let { this.tlsCipherSuites.addAll(it) }
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256)
addAcceptedTlsCipherSuite(CipherSuite.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256)
if (enableCompatibilityMode) { if (enableCompatibilityMode) {
// Adopt some preceding cipher suites for Android < 20 to be able to negotiate // Adopt some preceding cipher suites for Android < 20 to be able to negotiate

View file

@ -20,6 +20,7 @@ import com.facebook.stetho.okhttp3.StethoInterceptor
import com.squareup.moshi.Moshi import com.squareup.moshi.Moshi
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import okhttp3.ConnectionSpec
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import org.matrix.android.sdk.BuildConfig import org.matrix.android.sdk.BuildConfig
@ -29,6 +30,7 @@ import org.matrix.android.sdk.internal.network.TimeOutInterceptor
import org.matrix.android.sdk.internal.network.UserAgentInterceptor import org.matrix.android.sdk.internal.network.UserAgentInterceptor
import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor import org.matrix.android.sdk.internal.network.interceptors.CurlLoggingInterceptor
import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger import org.matrix.android.sdk.internal.network.interceptors.FormattedJsonHttpLogger
import java.util.Collections
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@Module @Module
@ -66,6 +68,8 @@ internal object NetworkModule {
httpLoggingInterceptor: HttpLoggingInterceptor, httpLoggingInterceptor: HttpLoggingInterceptor,
curlLoggingInterceptor: CurlLoggingInterceptor, curlLoggingInterceptor: CurlLoggingInterceptor,
apiInterceptor: ApiInterceptor): OkHttpClient { apiInterceptor: ApiInterceptor): OkHttpClient {
val spec = ConnectionSpec.Builder(matrixConfiguration.connectionSpec).build()
return OkHttpClient.Builder() return OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) .connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(60, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS)
@ -87,6 +91,7 @@ internal object NetworkModule {
proxy(it) proxy(it)
} }
} }
.connectionSpecs(Collections.singletonList(spec))
.build() .build()
} }

View file

@ -177,15 +177,13 @@ internal object CertUtil {
val trustPinned = arrayOf<TrustManager>(PinnedTrustManagerProvider.provide(hsConfig.allowedFingerprints, defaultTrustManager)) val trustPinned = arrayOf<TrustManager>(PinnedTrustManagerProvider.provide(hsConfig.allowedFingerprints, defaultTrustManager))
val sslSocketFactory: SSLSocketFactory val sslSocketFactory = if (hsConfig.forceUsageTlsVersions && !hsConfig.tlsVersions.isNullOrEmpty()) {
if (hsConfig.forceUsageTlsVersions && hsConfig.tlsVersions != null) {
// Force usage of accepted Tls Versions for Android < 20 // Force usage of accepted Tls Versions for Android < 20
sslSocketFactory = TLSSocketFactory(trustPinned, hsConfig.tlsVersions) TLSSocketFactory(trustPinned, hsConfig.tlsVersions)
} else { } else {
val sslContext = SSLContext.getInstance("TLS") val sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustPinned, java.security.SecureRandom()) sslContext.init(null, trustPinned, java.security.SecureRandom())
sslSocketFactory = sslContext.socketFactory sslContext.socketFactory
} }
return PinnedSSLSocketFactory(sslSocketFactory, defaultTrustManager!!) return PinnedSSLSocketFactory(sslSocketFactory, defaultTrustManager!!)
@ -237,14 +235,14 @@ internal object CertUtil {
* @return a list of accepted TLS specifications. * @return a list of accepted TLS specifications.
*/ */
fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> { fun newConnectionSpecs(hsConfig: HomeServerConnectionConfig): List<ConnectionSpec> {
val builder = ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) val builder = ConnectionSpec.Builder(ConnectionSpec.RESTRICTED_TLS)
val tlsVersions = hsConfig.tlsVersions val tlsVersions = hsConfig.tlsVersions
if (null != tlsVersions && tlsVersions.isNotEmpty()) { if (!tlsVersions.isNullOrEmpty()) {
builder.tlsVersions(*tlsVersions.toTypedArray()) builder.tlsVersions(*tlsVersions.toTypedArray())
} }
val tlsCipherSuites = hsConfig.tlsCipherSuites val tlsCipherSuites = hsConfig.tlsCipherSuites
if (null != tlsCipherSuites && tlsCipherSuites.isNotEmpty()) { if (!tlsCipherSuites.isNullOrEmpty()) {
builder.cipherSuites(*tlsCipherSuites.toTypedArray()) builder.cipherSuites(*tlsCipherSuites.toTypedArray())
} }