forked from bitwarden/android
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bitwarden#4416 add possibility to select a client certificate for mTLS
- Loading branch information
Showing
20 changed files
with
339 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
app/src/main/java/com/x8bit/bitwarden/data/platform/datasource/network/util/TLSHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
package com.x8bit.bitwarden.data.platform.datasource.network.util | ||
|
||
import com.x8bit.bitwarden.data.platform.repository.KeyChainRepository | ||
import java.net.Socket | ||
import java.security.KeyStore | ||
import java.security.Principal | ||
import java.security.PrivateKey | ||
import java.security.cert.X509Certificate | ||
import javax.inject.Inject | ||
import javax.inject.Named | ||
import javax.net.ssl.SSLContext | ||
import javax.net.ssl.TrustManagerFactory | ||
import javax.net.ssl.X509ExtendedKeyManager | ||
import javax.net.ssl.X509TrustManager | ||
import okhttp3.OkHttpClient | ||
|
||
class TLSHelper @Inject constructor( | ||
@Named("keyChainRepository") private val keyChainRepository: KeyChainRepository, | ||
) { | ||
fun setupOkHttpClientSSLSocketFactory(builder: OkHttpClient.Builder): OkHttpClient.Builder { | ||
val trustManagerFactory = | ||
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()) | ||
trustManagerFactory.init(null as KeyStore?) | ||
val trustManagers = trustManagerFactory.trustManagers | ||
|
||
val sslContext = SSLContext.getInstance("TLS") | ||
sslContext.init(arrayOf(getMTLSKeyManagerForOKHTTP()), trustManagers, null) | ||
|
||
builder.sslSocketFactory(sslContext.socketFactory, trustManagers[0] as X509TrustManager) | ||
|
||
return builder | ||
} | ||
|
||
private fun getMTLSKeyManagerForOKHTTP(): X509ExtendedKeyManager { | ||
return object : X509ExtendedKeyManager() { | ||
override fun getClientAliases( | ||
p0: String?, | ||
p1: Array<out Principal>?, | ||
): Array<String> { | ||
return emptyArray() | ||
} | ||
|
||
override fun chooseClientAlias( | ||
p0: Array<out String>?, | ||
p1: Array<out Principal>?, | ||
p2: Socket?, | ||
): String { | ||
return "" | ||
} | ||
|
||
override fun getServerAliases( | ||
p0: String?, | ||
p1: Array<out Principal>?, | ||
): Array<String> { | ||
return arrayOf() | ||
} | ||
|
||
override fun chooseServerAlias( | ||
p0: String?, | ||
p1: Array<out Principal>?, | ||
p2: Socket?, | ||
): String { | ||
return "" | ||
} | ||
|
||
override fun getCertificateChain(p0: String?): Array<X509Certificate>? { | ||
return keyChainRepository.getCertificateChain() | ||
} | ||
|
||
override fun getPrivateKey(p0: String?): PrivateKey? { | ||
return keyChainRepository.getPrivateKey() | ||
} | ||
} | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
...c/main/java/com/x8bit/bitwarden/data/platform/repository/ChoosePrivateKeyAliasCallback.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package com.x8bit.bitwarden.data.platform.repository | ||
|
||
import android.security.KeyChainAliasCallback | ||
|
||
interface ChoosePrivateKeyAliasCallback { | ||
fun getCallback(): KeyChainAliasCallback | ||
} |
12 changes: 12 additions & 0 deletions
12
...in/java/com/x8bit/bitwarden/data/platform/repository/ChoosePrivateKeyAliasCallbackImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.x8bit.bitwarden.data.platform.repository | ||
|
||
import android.security.KeyChainAliasCallback | ||
|
||
class ChoosePrivateKeyAliasCallbackImpl constructor(val callback: (String?) -> Unit) : | ||
ChoosePrivateKeyAliasCallback { | ||
override fun getCallback(): KeyChainAliasCallback { | ||
return KeyChainAliasCallback { | ||
callback(it) | ||
} | ||
} | ||
} |
15 changes: 15 additions & 0 deletions
15
app/src/main/java/com/x8bit/bitwarden/data/platform/repository/KeyChainRepository.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.x8bit.bitwarden.data.platform.repository | ||
|
||
import android.app.Activity | ||
import java.security.PrivateKey | ||
import java.security.cert.X509Certificate | ||
|
||
interface KeyChainRepository { | ||
fun configure(activity: Activity) | ||
|
||
fun choosePrivateKeyAlias(callback: ChoosePrivateKeyAliasCallback) | ||
|
||
fun getPrivateKey(): PrivateKey? | ||
|
||
fun getCertificateChain(): Array<X509Certificate>? | ||
} |
65 changes: 65 additions & 0 deletions
65
app/src/main/java/com/x8bit/bitwarden/data/platform/repository/KeyChainRepositoryImpl.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package com.x8bit.bitwarden.data.platform.repository | ||
|
||
import android.app.Activity | ||
import android.security.KeyChain | ||
import com.x8bit.bitwarden.data.platform.datasource.disk.EnvironmentDiskSource | ||
import com.x8bit.bitwarden.data.platform.repository.util.toEnvironmentUrlsOrDefault | ||
import timber.log.Timber | ||
import java.security.PrivateKey | ||
import java.security.cert.X509Certificate | ||
import javax.inject.Inject | ||
|
||
class KeyChainRepositoryImpl @Inject constructor( | ||
environmentDiskSource: EnvironmentDiskSource, | ||
) : KeyChainRepository { | ||
private var activity: Activity? = null | ||
private var alias: String? = null | ||
private var key: PrivateKey? = null | ||
private var chain: Array<X509Certificate>? = null | ||
|
||
init { | ||
alias = | ||
environmentDiskSource.preAuthEnvironmentUrlData.toEnvironmentUrlsOrDefault().environmentUrlData.keyAlias | ||
} | ||
|
||
override fun configure(activity: Activity) { | ||
this.activity = activity | ||
} | ||
|
||
override fun choosePrivateKeyAlias(callback: ChoosePrivateKeyAliasCallback) { | ||
if (activity == null) { | ||
Timber.tag(this.javaClass.name) | ||
.d("activity is not set yet -- trying to choose private key alias") | ||
return | ||
} | ||
|
||
KeyChain.choosePrivateKeyAlias(activity!!, { a -> | ||
callback.getCallback().alias(a) | ||
alias = a | ||
}, null, null, null, alias) | ||
} | ||
|
||
override fun getPrivateKey(): PrivateKey? { | ||
if (key == null && activity != null && !alias.isNullOrEmpty()) { | ||
key = try { | ||
KeyChain.getPrivateKey(activity!!, alias!!) | ||
} catch (e: Exception) { | ||
null | ||
} | ||
} | ||
|
||
return key | ||
} | ||
|
||
override fun getCertificateChain(): Array<X509Certificate>? { | ||
if (chain == null && activity != null && !alias.isNullOrEmpty()) { | ||
chain = try { | ||
KeyChain.getCertificateChain(activity!!, alias!!) | ||
} catch (e: Exception) { | ||
null | ||
} | ||
} | ||
|
||
return chain | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.