For security reasons I want to store my private key in the HSM and then share the private key with another app via the KeyChain
. The KeyStore
mentions that it can be backed by the HSM but I haven't found any documentation that states it's possible with the KeyChain
.
Based on the KeyChain documentation, the KeyChain is the proper way to share between apps:
Use the KeyChain API when you want system-wide credentials. When an app requests the use of any credential through the KeyChain API, users get to choose, through a system-provided UI, which of the installed credentials an app can access. This allows several apps to use the same set of credentials with user consent.
So, is it possible to secure the Android KeyChain with an HSM?
After a lot of searching, I finally found that the answer is yes, it is possible.
The Android 4.3 changelog seems to be the only place that documents it:
Android also now supports hardware-backed storage for your
KeyChain
credentials, providing more security by making the keys unavailable for extraction. That is, once keys are in a hardware-backed key store (Secure Element, TPM, or TrustZone), they can be used for cryptographic operations but the private key material cannot be exported. Even the OS kernel cannot access this key material.
I tested this with code and it seems that once you import a KeyPair
into the KeyChain
it is automatically put into secure hardware. This is the Kotlin code that I ran to test:
GlobalScope.launch {
context?.let { it1 ->
val privKey = KeyChain.getPrivateKey(it1, "device_certificate")
Log.d("App", privKey.toString()) // Shows that this is an AndroidKeyStoreRSAPrivateKey
val keyFactory: KeyFactory = KeyFactory.getInstance(privKey?.algorithm, "AndroidKeyStore")
val keyInfo: KeyInfo = keyFactory.getKeySpec(privKey, KeyInfo::class.java)
if (keyInfo.isInsideSecureHardware()) {
Log.d("App", "The key is in secure hardware!")
}
else {
Log.d("App", "The key is not in secure hardware!")
}
}
}
which printed "The key is in secure hardware!".