Credential storage enhancements in Android 4.3
Our previous post was not related to Android security, but happened to coincide with the Android 4.3 announcement. Now that the post-release dust has settled, time to give it a proper welcome here as well. Being a minor update, there is nothing ground-breaking, but this 'revenge of the beans' brings some welcome enhancements and new APIs. Enough of those are related to security for some to even call 4.3 a 'security release'. Of course, the big star is SELinux, but credential storage, which has been a somewhat recurring topic on this blog, got a significant facelift too, so we'll look into it first. This post will focus mainly on the newly introduced features and interfaces, so you might want to review previous credential storage posts before continuing.
What's new in 4.3
First and foremost, the system credential store, now officially named 'Android Key Store' has a public API for storing and using app-private keys. This was possible before too, but not officially supported and somewhat clunky on pre-ICS devices. Next, while only the primary (owner) user could use the system key store pre-4.3, now it is multi-user compatible and each user gets their own keys. Finally, there is an API and even a system settings field that lets you check whether the credential store is hardware-backed (Nexus 4, Nexus 7) or software only (Galaxy Nexus). While the core functionality hasn't changed much since the previous release, the implementation strategy has evolved quite a bit, so we will look briefly into that too. That's a lot to cover, so lets' get started.
Public API
The API is outlined in the 'Security' section of the 4.3 new API introduction page, and details can be found in the official SDK reference, so we will only review it briefly. Instead of introducing yet another Android-specific API, key store access is exposed via standard JCE APIs, namely
If the device has a hardware-backed key store implementation, keys will be generated outside of the Android OS and won't be directly accessible even to the system (or root user). If the implementation is software only, keys will be encrypted with a per-user key-encryption master key. We'll discuss key protection in detail later.
KeyGenerator
and KeyStore
. Both are backed by a new Android JCE provider, AndroidKeyStoreProvider
and are accessed by passing "AndroidKeyStore"
as the type
parameter of the respective factory methods (those APIs were actually available in 4.2 as well, but were not public). For a full sample detailing their usage, refer to the BasicAndroidKeyStore
project in the Android SDK. To introduce their usage briefly, first you create a KeyPairGeneratorSpec
that describes the keys you want to generate (including a self-signed certificate), initialize a KeyPairGenerator
with it and then generate the keys by calling generateKeyPair()
. The most important parameter is the alias, which you then pass to KeyStore.getEntry()
in order to get a handle to the generated keys later. There is currently no way to specify key size or type and generated keys default to 2048 bit RSA. Here's how all this looks like:// generate a key pair Context ctx = getContext(); Calendar notBefore = Calendar.getInstance() Calendar notAfter = Calendar.getInstance(); notAfter.add(1, Calendar.YEAR); KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(ctx) .setAlias("key1") .setSubject( new X500Principal(String.format("CN=%s, OU=%s", alais, ctx.getPackageName()))) .setSerialNumber(BigInteger.ONE).setStartDate(notBefore.getTime()) .setEndDate(notAfter.getTime()).build(); KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); kpGenerator.initialize(spec); KeyPair kp = kpGenerator.generateKeyPair(); // in another part of the app, access the keys KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore"); keyStore.load(null); KeyStore.PrivateKeyEntry keyEntry = (KeyStore.PrivateKeyEntry)keyStore.getEntry("key1", null); RSAPublicKey pubKey = (RSAPublicKey)keyEntry.getCertificate().getPublicKey(); RSAPrivateKey privKey = (RSAPrivateKey) keyEntry.getPrivateKey();
If the device has a hardware-backed key store implementation, keys will be generated outside of the Android OS and won't be directly accessible even to the system (or root user). If the implementation is software only, keys will be encrypted with a per-user key-encryption master key. We'll discuss key protection in detail later.
Android 4.3 implementation
This hardware-backed design was initially implemented in the original Jelly Bean release (4.1), so what's new here? Credential storage has traditionally (since the Donut days), been implemented as a native
The actual files are owned by the
An interesting detail is that, the QSEE keystore trusted app (which may not be a dedicated app, but part of more general purpose trusted application) doesn't return simple references to protected keys, but instead uses proprietary encrypted key blobs (not unlikenCipher Thales HSMs). In this model, the only thing that is actually protected by hardware is some form of 'master' key-encryption key (KEK), and user-generated keys are only indirectly protected by being encrypted with the KEK. This allows for practically unlimited number of protected keys, but has the disadvantage that if the KEK is compromised, all externally stored key blobs are compromised as well (of course, the actual implementation might generate a dedicated KEK for each key blob created or the key can be fused in hardware; either way no details are available). Qualcomm
So, in the case of the Nexus 4, the 'hardware' is simply the ARM SoC. Are other implementations possible? Theoretically, a hardware-backed
What about TrustZone? It is being aggressively marketed as a mobile security 'silver bullet' and streaming media companies have embraced it as an 'end-to-end' DRM solution, but does it really deliver? While the ARM TrustZone architecture might be sound at its core, in the end trusted applications are just software that runs at a slightly lower level than Android. As such, they can be readily reverse engineered, and of course vulnerabilities have been found. And since they run within the Secure World they can effectively access everything on the device, including other trusted applications. When exploited, this could lead to very effective and hard to discover rootkits. To sum this up, while TrustZone secure applications might provide effective protection against Android malware running on the device, given physical access, they, as well as the TrustZone kernel, are exploitable themselves. Applied to the Android key store, this means that if there is an exploitable vulnerability in any of the underlying trusted applications the
keystore
daemon that used a local socket as its IPC interface. The daemon has finally been retired and replaced with a 'real' Binder service, which implements the IKeyStoreService interface. What's interesting here is that the service is implemented in C++, which is somewhat rare in Android. See the interface definition for details, but compared to the original keymaster
-based implementation, IKeyStoreService
gets 4 new operations: getmtime()
, duplicate()
, is_hardware_backed()
and clear_uid()
. As expected, getmtime()
returns the key modification time and duplicate()
copies a key blob (used internally for key migration). is_hardware_backed
will query the underlying keymaster
implementation and return true
when it is hardware-backed. The last new operation, clear_uid(),
is a bit more interesting. As we mentioned, the key store now supports multi-user devices and each user gets their own set of keys, stored in /data/misc/keystore/user_N
, where N
is the Android user ID. Keys names (aliases) are mapped to filenames as before, and the owner app UID now reflects the Android user ID as well. When an app that owns key store-managed keys is uninstalled for a user, only keys created by that user are deleted. If an app is completely removed from the system, its keys are deleted for all users. Since key access is tied to the app UID, this prevents a different app that happens to get the same UID from accessing an uninstalled app's keys. Key store reset, which deletes both key files and the master key, also affects only the current user. Here's how key files for the primary user might look like:1000_CACERT_ca 1000_CACERT_cacert 10248_USRCERT_myKey 10248_USRPKEY_myKey 10293_USRCERT_rsa_key0 10293_USRPKEY_rsa_key0
The actual files are owned by the
keystore
service (which runs as the keystore
Linux user) and it checks the calling UID to decide whether to grant or deny access to a key file, just as before. If the keys are protected by hardware, key files may contain only a reference to the actual key and deleting them may not destroy the underlying keys. Therefore, the del_key()
operation is optional and may not be implemented. The hardware in 'hardware-backed'
To give some perspective to the whole 'hardware-backed' idea, let's briefly discuss how it is implemented on the Nexus 4. As you may now, the Nexus 4 is based on Qualcomm's Snapdragon S4 Pro APQ8064 SoC. Like most recent ARM SoC's it is TrustZone-enabled and Qualcomm implement their Secure Execution Environment (QSEE) on top of it. Details are, as usual, quite scarce, but trusted application are separated from the main OS and the only way to interact with them is through the controlled interface the/dev/qseecom
device provides. Android applications that wish to interact with the QSEE load the proprietary libQSEEComAPI.so
library and use the functions it provides to send 'commands' to the QSEE. As with most other SEEs, the QSEECom
communication API is quite low-level and basically only allows for exchanging binary blobs (typically commands and replies), whose contents entirely depends on the secure app you are communicating with. In the case of the Nexus 4 keymaster
, the used commands are: GENERATE_KEYPAIR
, IMPORT_KEYPAIR
, SIGN_DATA
and VERIFY_DATA
. The keymaster
implementation merely creates command structures, sends them via the QSEECom
API and parses the replies. It does not contain any cryptographic code itself.An interesting detail is that, the QSEE keystore trusted app (which may not be a dedicated app, but part of more general purpose trusted application) doesn't return simple references to protected keys, but instead uses proprietary encrypted key blobs (not unlike
keymaster
key blobs are defined in AOSP code as shown below. This suggest that private exponents are encrypted using AES, most probably in CBC mode, with an added HMAC-SHA256 to check encrypted data integrity. Those might be further encrypted with the Android key store master key when stored on disk.#define KM_MAGIC_NUM (0x4B4D4B42) /* "KMKB" Key Master Key Blob in hex */ #define KM_KEY_SIZE_MAX (512) /* 4096 bits */ #define KM_IV_LENGTH (16) /* AES128 CBC IV */ #define KM_HMAC_LENGTH (32) /* SHA2 will be used for HMAC */ struct qcom_km_key_blob { uint32_t magic_num; uint32_t version_num; uint8_t modulus[KM_KEY_SIZE_MAX]; uint32_t modulus_size; uint8_t public_exponent[KM_KEY_SIZE_MAX]; uint32_t public_exponent_size; uint8_t iv[KM_IV_LENGTH]; uint8_t encrypted_private_exponent[KM_KEY_SIZE_MAX]; uint32_t encrypted_private_exponent_size; uint8_t hmac[KM_HMAC_LENGTH]; };
So, in the case of the Nexus 4, the 'hardware' is simply the ARM SoC. Are other implementations possible? Theoretically, a hardware-backed
keymaster
implementation does not need to be based on TrustZone. Any dedicated device that can generate and store keys securely can be used, the usual suspects being embedded secure elements (SE) and TPMs. However, there are no mainstream Android devices with dedicated TPMs and recent flagship devices have began shipping without embedded SEs, most probably due to carrier pressure (price is hardly a factor, since embedded SEs are usually in the same package as the NFC controller). Of course, all mobile devices have some form of UICC (SIM card), which typically can generate and store keys, so why not use that? Well, Android still doesn't have a standard API to access the UICC, even though 'vendor' firmwares often include one. So while one could theoretically implement a UICC-based keymaster
module compatible with the UICC's of your friendly neighbourhood MNO, it is not very likely to happen.Security level
So how secure are you brand new hardware-backed keys? The answer is, as usual, it depends. If they are stored in a real, dedicated, tamper-resistant hardware module, such as an embedded SE, they are as secure as the SE. And since this technology has been around for over 40 years, and even recent attacks are only effective against SEs using weak encryption algorithms, that means fairly secure. Of course, as we mentioned in the previous section, there are no currentkeymaster
implementations that use actual SEs, but we can only hope.What about TrustZone? It is being aggressively marketed as a mobile security 'silver bullet' and streaming media companies have embraced it as an 'end-to-end' DRM solution, but does it really deliver? While the ARM TrustZone architecture might be sound at its core, in the end trusted applications are just software that runs at a slightly lower level than Android. As such, they can be readily reverse engineered, and of course vulnerabilities have been found. And since they run within the Secure World they can effectively access everything on the device, including other trusted applications. When exploited, this could lead to very effective and hard to discover rootkits. To sum this up, while TrustZone secure applications might provide effective protection against Android malware running on the device, given physical access, they, as well as the TrustZone kernel, are exploitable themselves. Applied to the Android key store, this means that if there is an exploitable vulnerability in any of the underlying trusted applications the
keymaster
module depends on, key-encryption keys could be extracted and 'hardware-backed' keys could be compromised.Advanced usage
As we mentioned in the first section, Android 4.3 offers a well defined public API to the system key store. It should be sufficient for most use cases, but if needed you can connect to the
By using the
Accessing hidden services is not the only way to augment the system key store functionality. Since the
If you use this primitive to implement, for example, Bouncy Castle's
Likewise, if you need to implement RSA key exchange, you can easily make use of OAEP padding like this:
The sample application shows how to tie all of those APIs together and features an elegant and fully Holo-compatible user interface:
An added benefit of using hardware-backed keys is that, since they are not generated using Android's default
keystore
service directly (as always, not really recommended). Because it is not part of the Android SDK, the IKeyStoreService
doesn't have wrapper 'Manager' class, so if you want to get a handle to it, you need to get one directly from the ServiceManager
. That too is hidden from SDK apps, but, as usual, you can use reflection. From there, it's just a matter of calling the interface methods you need (see sample project on Github). Of course, if the calling UID doesn't have the necessary permission, access will be denied, but most operations are available to all apps.Class smClass = Class.forName("android.os.ServiceManager"); Method getService = smClass.getMethod("getService", String.class); IBinder binder = (IBinder) getService.invoke(null, "android.security.keystore"); IKeystoreService keystore = IKeystoreService.Stub.asInterface(binder);
By using the
IKeyStoreService
directly you can store symmetric keys or other secret data in the system key store by using the put()
method, which the current java.security.KeyStore
implementation does not allow (it can only store PrivateKey
's). Such data is only encrypted by the key store master key, and even the system key store is hardware-backed, data is not protected by hardware in any way.Accessing hidden services is not the only way to augment the system key store functionality. Since the
sign()
operation implements a 'raw' signature operation (RSASP1 in RFC 3447), key store-managed (including hardware-backed) keys can be used to implement signature algorithms not natively supported by Android. You don't need to use the IKeyStoreService
interface, because this operation is available through the standard JCE Cipher
interface: KeyStore ks = KeyStore.getInstance("AndroidKeyStore"); ks.load(null); KeyStore.Entry keyEntry = keyStore.getEntry("key1", null); RSAPrivteKey privKey = (RSAPrivateKey) keyEntry.getPrivateKey(); Cipher c = Cipher.getInstance("RSA/ECB/NoPadding"); cipher.init(Cipher.ENCRYPT_MODE, i privateKey); byte[] result = cipher.doFinal(in, o, in.length);
If you use this primitive to implement, for example, Bouncy Castle's
AsymmetricBlockCipher
interface, you can use any signature algorithm available in the Bouncy Castle lightweight API (we actually use Spongy Castle to stay compatible with Android 2.x without too much hastle). For example, if you want to use a more modern (and provably secure) signature algorithm than Android's default PKCS#1.5 implementation, such as RSA-PSS you can accomplish it with something like this (see sample project for AndroidRsaEngine
):AndroidRsaEngine rsa = new AndroidRsaEngine("key1", true); Digest digest = new SHA512Digest(); Digest mgf1digest = new SHA512Digest(); PSSSigner signer = new PSSSigner(rsa, digest, mgf1digest, 512 / 8); RSAKeyParameters params = new RSAKeyParameters(false, pubKey.getModulus(), pubKey.getPublicExponent()); signer.init(true, params); signer.update(signedData, 0, signedData.length); byte[] signature = signer.generateSignature();
Likewise, if you need to implement RSA key exchange, you can easily make use of OAEP padding like this:
AndroidRsaEngine rsa = new AndroidRsaEngine("key1", false); Digest digest = new SHA512Digest(); Digest mgf1digest = new SHA512Digest(); OAEPEncoding oaep = new OAEPEncoding(rsa, digest, mgf1digest, null); oaep.init(true, null); byte[] cipherText = oaep.processBlock(plainBytes, 0, plainBytes.length);
The sample application shows how to tie all of those APIs together and features an elegant and fully Holo-compatible user interface:
An added benefit of using hardware-backed keys is that, since they are not generated using Android's default
SecureRandom
implementation, they should not be affected by the recently announced SecureRandom
vulnerability (of course, since the implementation is closed, we can only hope that trusted apps' RNG actually works...). However, Bouncy Castle's PSS and OAEP implementations do use SecureRandom
internally, so you might want to seed the PRNG 'manually' before starting your app to make sure it doesn't start with the same PRNG state as other apps. The keystore
daemon/service uses /dev/urandom
directly as a source of randomness, when generating master keys used for key file encryption, so they should not be affected. RSA keys generated by the softkeymaster
OpenSSL-based software implementation might be affected, because OpenSSL uses RAND_bytes()
to generate primes, but are probably OK since the keystore
daemon/service runs in a dedicated process and the OpenSSL PRNG automatically seeds itself from /dev/urandom
on first access (unfortunately there are no official details about the 'insecure SecureRandom' problem, so we can't be certain).Summary
Android 4.3 offers a standard SDK API for generating and accessing app-private RSA keys, which makes it easier for non-system apps to store their keys securely, without implementing key protection themselves. The new Jelly Bean also offers hardware-backed key storage on supported devices, which guarantees that even system or root apps cannot extract the keys. Protection against physical access attacks depends on the implementation, with most (all?) current implementations being TrustZone-based. Low-level RSA operations with key store managed keys are also possible, which enables apps to use cryptographic algorithms not provided by Android's built-in JCE providers.
Comments
One question: you write that when an application which created keys has been uninstalled keys will be removed from keystore. I do not see this happens on my Nexus 7. After i uninstalled the application and installed again, it can find key with the same alias.
Should i do something else?
I don't know if I am asking the same but: This TrustZone which is standardized by Global Platform (they call it Trusted Execution Environment) is, according to them: "The TEE is a secure area that resides in the main processor of a smart phone (or any mobile device) and ensures that sensitive data is stored, processed and protected in a trusted environment".
My question is, can we use it then to perform "secure" calculations as in SE applets or it can only be used to store the keys?
Since a TEE application is a program it can do pretty much anything. The downside is that you have to implement an command/reply RMI communication interface between it and the client app running on Android. The implementation in 4.3 performs calculations (sign and verify), it doesn't just store keys.
Thank you for all your posts, very useful stuff...
I have a problem, I need to configure a EAP Wireless connection to set this up on users phone. I am able to install certificates and then using reflection, to fill the CA_CERT part of the enterpriseconfig for the connection but I cannot acces the client_cert, although, the certificate exists when I list all the user certificates:
I am not copying the whole code but basically:
....
private String ENTERPRISE_CLIENT_CERT = "keystore://USRCERT_CertTom";
....
private String ENTERPRISE_CA_CERT = "keystore://CACERT_CertTom";
/*EAP CA Certificate*/
if(!noEnterpriseFieldType)
wcefSetValue.invoke(wcefCaCert.get(selectedConfig), this.ENTERPRISE_CA_CERT);
/*EAp Client certificate*/
if(!noEnterpriseFieldType)
wcefSetValue.invoke(wcefClientCert.get(selectedConfig), this.ENTERPRISE_CLIENT_CERT);
The EAP CA cert is working and the client field does not change, although, keystore://USRCERT_CertTom exists. How can I have rights to put this one there then? Any idea?
If not I'd like to open the network settings of one particular network programmatically, so that the user just have to choose the client_cert but not the connection...any idea?
Thank you for your help,
Kind regards,
First of all, thank you for sharing your knowhow! I have been stopping by regularly and almost always found an answer to my security related Android problems here.
We are in the final testing phase of an app that makes use of the new app-private key feature in API Level 18. It's great that no screen lock password is required anymore to store keys.
However, we ran into the problem that all keys are wiped if a user removes his lock screen password, even if the keys were created before the user even had a screen lock password set.
Do you know how the screen lock password relates to the app-private keys? I thought that there is no relation anymore since it is possible to store app-private keys also if no screen lock password is set...
Have you had similar issues?
Best regards,
James
i need to make an Android app that save securely an RSA PrivateKey received from a web service in PKCS#8 format encoded in a base 64 String.
Sorry if i loose some information in your article, i want know if i can store an existing key using the KeyStore or is only possible saving key pairs generated as in your starting example?
Thank you very much for this study.
No doubt that Trustzone is very powerful but I still have some concern.
According to QC, non-secured application App1 (running in HLOS) can talk with secured application App2 (running in TZ).
In that case, App1 can load App2 if it knows its name and start to communicate with it through commands agreed by both sides.
I am not a security expert but let's say that a malicious application succeeded to "sniff" these transaction, all the TZ power suddenly fails.
QC agrees on that and said that developers should take the responsibility for building an authentication process between the 2 applications.
Do you have any idea how can it be done in an android OS?
Regards,
Fabrice.
I inherited an Android project which uses your classes to store sensitive information on a device. Unfortunately on 4.3 I get the error "Assertion Error 5" at org.nick.androidkeystore.android.security.KeyStore.state(KeyStore.java:74) when calling KeyStore.state(). I'm guessing this means the execute()-Method on KeyStore.java fails due to some error.
I have updated your code to the latest version as I saw your git comments regarding 4.3, however this did not solve the issue. Do you have any idea what I should try in order to pinpoint / fix this issue? As a side-note: The application is working fine on pre-4.3 devices.
Thanks and best regards,
Hendrik
The sample application works for sub-4.3 - on 4.3 I'm getting: Could not find method android.security.IKeystoreService.generate, referenced from method org.nick.androidkeystore.android.security.KeyStoreJb43.generate
I had previously overlooked your IS_JB43 statement and have now added that to my code. Now I'm getting a different error there: java.lang.RuntimeException: Unable to resume activity {myApp.MainActivity}: java.lang.RuntimeException: Unable to resume activity {myApp.CardFragment}: java.lang.NullPointerException - but I'm guessing this is due to the same origin-error the sample application throws.
Any hints are greatly appreciated!
Is the issue with the sample application possibly related to restrictions by the emulator?
I want to thank you, for writing this blog. Many times I was not able to find this information elsewhere. But I am not sure that i get all information right, so to be sure please correct me if I am wrong.
I need to securely store some BigInt values and over them compute access token. Before android ICS ,credential storage was used only for VPN connection with no application control. In ICS we can add a manage certificates and their keys, with is protected by key derived from lock screen pass/pin, but no official way to store not certificate data. By using keystore daemon directly we can store our own byte data in credential storage, but it is not official way and may not work properly on all devices. In JB4.1 was added hardware-backed credential storage but also with no official API to store custom data, and no API to recognized if hardware-backed credential storage is available. ON JB4.3 API was set public, and we can check if hardware-backed is available. We can generate and using keys outside Android OS, and if it is on hardware-backed even on root we are not able to steal keys from device. But there is still no official way how to store custom data. And there is no way how to use hardware-backed storage to execute custom cryptographic protocol outside Android OS(like applet on SmartCards). So if I am wrong please correct me.
Thanks in advice. Marek
You cannot change secure (TrustZone) applications that are pre-installed on the device, because that part of device is locked and only the manufacturer/Google has the keys. However, for most cryptographic protocols you only need private key operations (signing,etc) to be executed using the hardware-backed keystore. You can build pretty much anything (SSL, etc.) on top of that.
I need to implement custom "protocol" (it have few keys witch consit BigInteger values, and over them I compute few mathematic operations add, subtract, power mod..). And I try to find way how to idealy do the computing in TrusZone, or at least store keys securelly. But like you said TrustZone is locked foe changing applications.
What occurs in terms of SW architecture when Android is to be used with proprietary TrustZone module?
I believe that the new Android API needs to be connected to TZ API.
I heard that the Global platform group has provided a generic SW layer working on top of ARM TZ API (called tzapi).Have you heard about it?
Has Nexus4 used JB4.3 API to use Keystore with Qualcomm's TZ module?
Regards,
Fabrice.
Cf. http://nelenkov.blogspot.com/2012/07/jelly-bean-hardware-backed-credential.html
Sorry but things are still confusing me,
The example you gave when commands are sent through qseecom is only dedicated to QC according to my understanding.
Let's say that I want to develop a new secure storage module and I want it to be Android portable, can I use the GP interface? For example:
JB4.3 Keystore API --> GP API --> GP TEE --> HW
In that case I connect Android API to GP API. Is it even possible or should I get rid of Android API and assume that application will use the GP API?
Regards,
Fabrice.
GP API = Global Platform.
My only concern is where the SW layers are located from architecture perspective.
This is what I understand if we take OMAP4460 example:
1 - HW security module is M-Shield.
2 - TEE running on top of the HW is provided by TRUSTONIC and is compliant to Global Platform API.
3 - All this is fully integrated with Android 4.0's security API.
From this, I understand that Android's APIs are connected to the Global Platform API for any application to be able to access the secured world.
Am I right?
Fabrice.
I am currently working on an application that only supports 4.0.3+. Do you feel the private APIs are pretty safe to use at this point? I figure I can tackle new releases as they come out, I'm more worried about compatibility between ICS+ devices.
I can't think of any other way to store an encryption key on the device other than using this, the other solutions all involve having a user input something (pin or password) that would be used to generate the key on the fly.
I toyed around with the KeyChain as well, but I can't expect my users to understand the dialogs that Android supplies for allow use of the key/certificate.
4.4 supports other algorithms besides RSA, so you need to pass the algorithm name. Check the API docs for details.
For your reference I was able to test the AES encryption function on 4.0.3,.4.1.1, 4.1.2, 4.2.2 and 4.3 on various Samsung, Htc, and Motorola phones - all worked fine.
It looks like your latest push broke it on 4.3, because now it can't find is_hardware_backed() with a string arg to bind to in 4.3.
One final question - I'm assuming you showing the daemon for 4.3+ to show folks how they could store credentials of a type other than RSA correct?
Since the daemon still requires the user to enter a pin on 4.3+ do you think the 'Correct' approach would be:
1. Generate RSA and AES keys based on some (different) user input.
2. Wrap the AES key using the RSA Key
3. Store the RSA key in keystone via:
4.0-4.2.2 - Use the Daemon (forces an OS level pin)
4.3 + - Use the Android Keystore (no OS level pin needed)
4. Store the wrapped AES key .... where?
I'm no where near a security expert - what I'm curious about is how secure is just wrapping the AES key using the RSA key (using the Cipher.WRAP_MODE with "AESWrap" - which I think is http://www.ietf.org/rfc/rfc3394.txt) and storing that where it is easily found. Somewhere like say, SharedPreferences which is just a plaintext file.
It would be better to use the officially supported API and only use RSA keys on 4.3 (or EC on 4.4). You can wrap the AES key with the RSA one and then store it anywhere, preferably as a private file in your app's directory. As long as other apps cannot get the private key, you should be OK. Here's an example from Google:
https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault/SecretKeyWrapper.java
If you are using the daemon/service directly you can just store the AES key directly (as in my sample app), it will be encrypted on disk.
1. Can I store the EC key pair at the keystore by using the IKeyStoreService as you store the symmetric key at the keystore?
2. In the process of generating RSA key pair with KeyPairGeneratorSpec in your example, is the private key encrypted even if the ".setEncryptionRequired()" is not called?
3. The keys in keystore are encrypted with the master key, right?. When I call the keyEntry.getPrivateKey() function, is the returned private key in plain form? Is it not necessary to provide password information to get the private key?
4. Can I add user-generated key to the keystore with setKeyEntry function?
Actually, I want to use EC on devices lower than 4.4. Thus, I think that it is required to store the private key with being encryted by password or trickly using keystore.
You said that "You cannot extract the private keys". But, the code below tries to get the
private key without providing any password or encryption key.
RSAPrivateKey privKey = (RSAPrivateKey) keyEntry.getPrivateKey();
Do I understand right?
sKeyStoreService.insert("jbase", new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 }, -1, 1);
if (0 <= sKeyStoreService.exist("jbase", -1)) {
// TODO: why is this null on android 4.3?
final byte[] test = sKeyStoreService.get("jbase");
if (test == null) {
Log.d("+++", "+----------------------------------------------------");
}
}
I am using 2 equal Nexus 7, one with 4.3 and the other with 4.4.
(Update) -> I tested it now with a key generated by Crypto.generateAesKey().getEncoded() and it works now, I don't understand how the content of the key can affect the get method?
I've been following all of your articles in the field of credentials storage and I find them all very helpful !
I'm trying to better understand a question which was already asked by one of your readers: is it possible to use a private key stored in the credentials storage to decrypt data somehow ? I understand the private key never leaves the hardware and it can be used to sign data... but can it be used to decrypt data as well ?
Thanks !
First of all, congratulations about this (and others) posts related to the Android Security, you cover the internals not documented (or not well documented) by Google, very usefull! Thanks for sharing.
Could you please help me to clarify two questions about the new KeyStore in Android 4.3?
Is it right to say that:
1. With the new "AndroidKeyStore", after storing a key through the setKeyEntry(), you'll not anymore be able to get this key in the encoded form - you'll always get null in key.getEncoded() ?
2. And there's no other way to recover (programmatically export) the keys from the own Application ?
Thank you.
Regards.
Eduardo Piovesam
Thank you for this great post.
I was wondering, you say that root or system cannot access the keys of other users,
but couldn't root use setuid or something like that to impersonate a user and then retrieve & use its key?
Thanks!
By the way, i'm still a little bit confused between keychain and keystore API on Android 4.3. I mean do the keys put in the android keystore are hardware-backed or only credentials put in keychain are hardware-backed? It's not clear to me when reading the shorts sections in Android APIs and i'm quite a beginner on this topic.
My second problem is about: i'm not sure to well understand the behavior when the lock screen PIN is changed by the user. Do all the keys of all applications using the android keystore are wiped ? this behavior confuse me a lot. Can you confirm ?
Regards
* @hide This should not be made public in its present form because it
* assumes that private and secret key bytes are available and would
* preclude the use of hardware crypto.
is there a current solution for hardware devices? Its strange that methods like `kpGenerator.generateKeyPair()` are used to generate, store and return the keypair - as this now cannot be used without an IllegalStateException.
Any pointers would be much appreciated. My goal is to generate a local key pair and use the public key for encrypting a locally stored AES key which can then be hardware decrypted using the stored private key.
Many thanks!
I am wondering the same thing. Your article was very helpful. However, I can't seem to achieve my objective: encrypting and decrypting data with a RSA public key and private key, respectively. I used your example code above to generate and store the keys using the hardware-backed "AndroidKeyStore". Encryption is successful, but when I attempt to decrypt I receive this error:
java.lang.UnsupportedOperationException: private exponent cannot be extracted
at com.android.org.conscrypt.OpenSSLRSAPrivateKey.getPrivateExponent(...)
I am unsure with what I am doing wrong, or if this is the correct consequence of storing the private key in the TEE. If this is the correct consequence, then what is the purpose of storing a private key in hardware if you can never use it?
Thank you
Following the example code provided in your post under the section "Public API"
KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore");
....
RSAPublicKey pubKey = (RSAPublicKey)keyEntry.getCertificate().getPublicKey();
RSAPrivateKey privKey = (RSAPrivateKey) keyEntry.getPrivateKey();
Once I retrieve the key pair, I simply wanted to test encrypt and decrypt operations. The below code is to decrypt. However, the line marked with "<---" causes the error I wrote in my initial post trying to use the privKey.
private static byte[] decodeData(Key key, byte[] data, String transformation) throws Exception
{
Cipher cipher = Cipher.getInstance(transformation);
cipher.init(Cipher.DECRYPT_MODE, key); <-----
byte[] decrypted = cipher.doFinal(data);
return decrypted;
}
This generating the error:
java.lang.UnsupportedOperationException: private exponent cannot be extracted
at com.android.org.conscrypt.OpenSSLRSAPrivateKey.getPrivateExponent(...)
This error seems to imply that once you generate or store a key in hardware, that you can not ever retrieve it to perform operations with it such as decrypting.
Thank you for all the explanation. I am trying to configure EAP TLS on KitKat 4.2.2. Can you please explain how to set the client and server certificates.
thank you for the post.
I've made some test on my app and I've found that the keystore is not a lot secure because it is true that each app have the own private keys but if I make an app with same package I'm be able to recover the keys of other apps.
I have made some mistake or is it true ?
Beside that I found that if the app is deleted the keys are still in the keystore and can be recover with an app with same package.
Thanks for your time.
it is exactly the same thing that I have thought, of course if two app have same package and signature it is effectively the same app but I have tried to sign the second app with another certificate and this app can see the keys.
For your question, I have tried to uninstall the app and reinstall it and the reinstalled app can get the key.
My device is the galaxy 3 with Android 4.3.
Many thanks.
The keys are removed due to uninstall process and since it is not possible to install app with same package but different certificate I am not be able to recover the keys
However on Samsug s3 the keys are not removed, I think this is a security issue of Samsung device.
Thanks a lot for your time.
So if root can setuid to another user and get its keys, how is it true to say that even root cannot access those keys as you said in your post?
Comparable (although a bit less secure) to a smartcard -- you can analyze and attack it if you have physical access, but you cannot extract keys (unless you have some very expensive and specialized equipment)
I've exactly the same question. I've managed to decrypt some data successfully with a private key stored in hardware, i.e. a key generated with the AndroidKeyStore provider in the same way as explained in this article. My phone is a Nexus 4 with Anroid 4.4.
See the code below how decryption can be done. I wonder what exactly happens in this case. According to the article and other sources, the private key can not be extracted from hardware. However, I use another provider ("AndroidOpenSSL") for the decryption which (I think) means that the decryption is not done from hardware.
How is this possible?
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry("keyalias", null);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding", "AndroidOpenSSL");
PrivateKey privateKey = ((KeyStore.PrivateKeyEntry) entry).getPrivateKey();
cipher.init(Cipher.DECRYPT_MODE, privateKey);
cipher.doFinal(data);
Is it possible in 4.4 to augment the Android keystore with your own implementation, for example, to a SE embedded in a microSD?
Of course, that isn't all that is missing. If I were to "lift" KeyPairGeneratorSpec from AOSP and place it in your test app (along with IKeyStoreService...), I then get NoSuchProvider exceptions complaining about the lack of AndroidKeyStore.
So when you (and others) say that this works on older versions of Android are you just commenting on that the KeyStore functions work or are all of the test functions working? I guess it is possible that Samsung's 4.1.2 release ripped out the AndroidKeyStore provider where others haven't but I get the same error when I run on the emulator using versions 4.1.2 or 4.2.2.
On ICS, you disable all of those buttons. In fact, you disable these buttons when the current OS build is less than JB - I see that in toggleControls and the activity's findViews method. My experience would suggest that it should be checking for releases >= than JB43 but I have limited experience (one S3 running 4.1.2, one Nexus 5 running 4.4.2, and a bunch of emulator types for JB, ICS, & KK). If I'm correct, it is an easy fix to your code in the git repo.
What exactly does the "backwards compatibility" buy? I presume the point is that it provides a means to save symmetric keys (which you say in your post). Is this inherently more secure than encrypting a key and storing it in a file? I guess the answer again is how that key is encrypted.
In your reply to Brian Deblanc's comment, you point to a Google example using RSA keys to wrap an AES key and you also state that he could just store the AES key via the keystore service. Is one way better than the other? The Google example won't work on anything less than JB4.3 AFAICS. If you have to support old and new OS, what's the best approach? Is it best to handle it one way on JB4.3+ (use RSA) and the other (AES via your KeyStore service design, encrypted key in a file, ...) on older versions of Android?
Your examples are really good and greatly appreciated. I'm just searching for the best solution.
As for general strategy, using the official APIs is best, and on versions that don't have official APIs (4.1 and 4.2), the private APIs may or may not available, and may or may not work (at all or as expected). Use at your own risk, if you decide you must.
What this buys you is that you get to use OS protection instead of rolling your own, at the expense of some risk. You can achieve the same thing by deriving a key from a user-supplied password and storing encrypted keys, etc. in your app's private directory. The user will have to enter their password each time they start your app (you can also cache derived keys to make this less painful), whereas Android does the whole key decryption thing when the lockscreen is unlocked.
KeyPairGeneratorSpec spec = new KeyPairGeneratorSpec.Builder(context)
.setAlias("key1")
.setKeySize(4096)
...
Thanks for your nice article.
I'm getting an exception when trying to retrieve the generated key pair on this line:
PrivateKeyEntry keyEntry = (PrivateKeyEntry) keyStore.getEntry(RSA_KEYS_ALIAS, null);
The exception text says "chin == null"
Can you please tell me what I'm doing wrong?
Sorry for the simple question but even with all the comments above I don't understand what modifications should be done to support hardware backed based Keystore. What keystore API should the vendor handle? Where can I find the API's list that should be handled. Who should write the wrapper to connect Android keystore routines to vendor TZ applications?
By the way, Are there other feature that Google may want to leverage with Trustzone?
Thanks for he help.
Fabrice.
http://nelenkov.blogspot.jp/2012/07/jelly-bean-hardware-backed-credential.html
Typically vendors are responsible for writing the HAL 'glue' . Most devices implement DRM using TZ, it's actually the primary use case.
I am following you since a few moment due to all interesting articles you wrote about Security, especially about Secure Element access for NFC purposes. I bought also your book which is very interesting and easily understandable.
But today, I am facing to a problem I don't understand at all.
I am using the KeyStore API, to generate KeyPair, and access the public key or private key with this method :
KeyStore ks = KeyStore.getInstance("AndroidKeyStore");
ks.load(null);
KeyStore.Entry entry = ks.getEntry(alias, null);
if (!(entry instanceof KeyStore.PrivateKeyEntry)) {
Log.w(TAG, "getPublicKey() Not an instance of a PrivateKeyEntry");
}
PublicKey pub = ((KeyStore.PrivateKeyEntry) entry).getCertificate().getPublicKey();
This is pretty well working on my Nexus 5, but with another N5, it is only working for a certain time, after it stops working and I have the following line in my logcat console :
W/keystore : Could not read CACERT_myalias
Could not find anything about that on Google, so any idea about what can cause this ?
I am trying to run you application on my QC based platform.
This platform supports trustzone and Google keymaster_test is working ok and triggers the QSEECom driver.
While using your application I can key that keys are created in \data\misc\keystore but I cannot see that the QSEECom driver is triggered.
I took care to replace the keystore.default.co in \system\lib\hw but still I cannot see that the TrustZone application is triggered.
So you have any clue what I can miss here?
Thank you.
Fabrice.
http://jbp.io/2014/04/07/android-keystore-leak/
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
D/KeystoreActivity( 3044): RSA supported true
D/KeystoreActivity( 3044): RSA bound true
D/KeystoreActivity( 3044): DSA supported true
D/KeystoreActivity( 3044): DSA bound false
D/KeystoreActivity( 3044): EC supported true
D/KeystoreActivity( 3044): EC bound false
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
I can also see the 2 keys in the \data\misc\
It seems that you application and the Google Keymaster_test are using 2 different API levels. The Keymaster_test uses QSEECom driver.
The question is where is the decision to run Keystore TZ-based or not (SW-based) located? By the way, your application did detect the plaform to support HW-backed.
Fabrice.
It seems according to the log below that RSA keys is supported:
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
D/KeystoreActivity( 3044): RSA supported true
D/KeystoreActivity( 3044): RSA bound true
D/KeystoreActivity( 3044): DSA supported true
D/KeystoreActivity( 3044): DSA bound false
D/KeystoreActivity( 3044): EC supported true
D/KeystoreActivity( 3044): EC bound false
The point is that Keymaster_test google application uses the QSEECom driver API straight. Thsi is probably why I can see the TZ triggered.
You application uses Keystore API and I cannot see TZ triggered even using RSA key and even the application detected that the platform supports HW-Backed.
So the question is: Where is the decision in the Android framework to use HW-backed or not located? I believe that I may fail in that decision.
By the way, the fact that AES keys is not stored HW-backed is due to the keystore module or due to your application?
Fabrice
As for AES, the keymaster HAL only supports asymmetric keys ATM, so there is no way to generate (or store) AES keys in hardware.
It seems according to the log below that RSA keys is supported:
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
D/KeystoreActivity( 3044): RSA supported true
D/KeystoreActivity( 3044): RSA bound true
D/KeystoreActivity( 3044): DSA supported true
D/KeystoreActivity( 3044): DSA bound false
D/KeystoreActivity( 3044): EC supported true
D/KeystoreActivity( 3044): EC bound false
The point is that Keymaster_test google application uses the QSEECom driver API straight. Thsi is probably why I can see the TZ triggered.
You application uses Keystore API and I cannot see TZ triggered even using RSA key and even the application detected that the platform supports HW-Backed.
So the question is: Where is the decision in the Android framework to use HW-backed or not located? I believe that I may fail in that decision.
By the way, the fact that AES keys is not stored HW-backed is due to the keystore module or due to your application?
Fabrice
================================================================================
Nikolay,
It seems according to the log below that RSA keys is supported:
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
D/KeystoreActivity( 3044): RSA supported true
D/KeystoreActivity( 3044): RSA bound true
D/KeystoreActivity( 3044): DSA supported true
D/KeystoreActivity( 3044): DSA bound false
D/KeystoreActivity( 3044): EC supported true
D/KeystoreActivity( 3044): EC bound false
The point is that Keymaster_test google application uses the QSEECom driver API straight. Thsi is probably why I can see the TZ triggered.
You application uses Keystore API and I cannot see TZ triggered even using RSA key and even the application detected that the platform supports HW-Backed.
So the question is: Where is the decision in the Android framework to use HW-backed or not located? I believe that I may fail in that decision.
By the way, the fact that AES keys is not stored HW-backed is due to the keystore module or due to your application?
Fabrice
It seems according to the log below that RSA keys is supported:
D/KeystoreActivity( 3044): Keystore state: UNLOCKED
D/KeystoreActivity( 3044): RSA supported true
D/KeystoreActivity( 3044): RSA bound true
D/KeystoreActivity( 3044): DSA supported true
D/KeystoreActivity( 3044): DSA bound false
D/KeystoreActivity( 3044): EC supported true
D/KeystoreActivity( 3044): EC bound false
The point is that Keymaster_test google application uses the QSEECom driver API straight. Thsi is probably why I can see the TZ triggered.
You application uses Keystore API and I cannot see TZ triggered even using RSA key and even the application detected that the platform supports HW-Backed.
So the question is: Where is the decision in the Android framework to use HW-backed or not located? I believe that I may fail in that decision.
By the way, the fact that AES keys is not stored HW-backed is due to the keystore module or due to your application?
Fabrice
/data/misc/keystore.
Is this path deletes during factory reset.
Thanks/Rama.
Nice array of post, looking forward to the book. I wonder if there is an straightforward way of storing users username/password type of credential (not key/certificates) in android for an app. iOS seems to provide a simple yet effective solution in form of KeyChain (and now TouchId is also opening up). For Android 3 potential candidates i.e. AccountManager, SharedPreferences & Keychain seem to serving other usecases and not the regular username/password. What do you advice for apps which just want username/password to be stored for apps and device taking care of the encryption and access control (with different vectors of attacks possible) on these credentials.
I might be missing something obvious but i felt this is so common a usecase where apps want to store these username/password type of credential for the app without anyone else (other than the user and the app) knowing about it.
Amazing post ! Thanks for sharing !
I am working in a company specialized in NFC and obviously realized the potential of HCE when it was released with Android Kitkat.
However, we first noticed the lack of security of HCE compared to card emulation applications based on an cardlet in a SIM Card (Such as Calypso application).
But after having read your post, I wonder if that would be possible to have an application with high level of security (equivalent to an cardlet) by storing private keys in the hardware.
My first question is, Do you know if all recent mobiles (I mean released this year and with Android > 4.3) support hardware storage ? If not, could you explain me what are the hardware requirements ?
Second, if the mobile does not support hardware storage for any reason, are there real risk for the keys security using non hardware storage ? (the hidden question is, Can we think of a real secure HCE application massively deployed like transport application?)
Thank you !
'Hardware-backed' key storage is currently implemented as a TrustZone trusted app in pretty much all major devices, so it is theoretically possible that keys can be leaked due to an implementation flaw (several have already been found). See this series of articles for a detailed comparison of the security level offered by HCE versus SE: http://randomoracle.wordpress.com/2014/03/08/hce-vs-embedded-secure-element-comparing-risks-part-i/
Do you know how many different TrustZone implementation exist ? (I suppose one per chip manufacturer) ?
Thanks again for your time.
I am using AndroidKeyStore in my device admin application to store application's Public-Private key pair. I have shared public key with server and have used private key to encrypt shared prefs data.
Now, issue I am facing is when user changes device password, all keystore related files will be deleted. To fix this issue, I cache key-pair in RAM and after device password change, I tried to use keystore.setKeyEntry(), but no luck.
How can I put back existing key-pair back to android keystore ?
How can retain existing key-pair after device password change?
Can you please help me out in fixing this issue ?
If this is android default behaviour, what would be the way to secure application data even from rooted user ?
thank you so much for sharing your know-how.
I'm using code in sample https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault/SecretKeyWrapper.java to store a generated RSA key pair in the Android KeyStore, but when I execute the method unwrap I get the exception IllegalArgumentException: key.length == 0. Debugging the app I noticed that the instruction mPair.getPrivate() returns an object, but executing mPair.getPrivate().getEncoded() the result is null. I have this problem both on Android 4.4 and on Android 4.3.
Could you help me, please? Thanks a lot!!
Filippo
I was executing the instruction mPair.getPrivate().getEncoded() just for debugging purposes. The code I use is exactly the same in the sample. My problem is the exception I get when the unwrap is executed (at line 112 in the sample). I post an extract of the stack trace:
java.lang.IllegalStateException: Could not execute method of the activity
[...]
Caused by: java.lang.IllegalArgumentException: key.length == 0
at javax.crypto.spec.SecretKeySpec.(SecretKeySpec.java:62)
at com.android.org.conscrypt.OpenSSLCipherRSA.engineUnwrap(OpenSSLCipherRSA.java:333)
at javax.crypto.Cipher.unwrap(Cipher.java:1409)
at com.example.android.vault.SecretKeyWrapper.unwrap(SecretKeyWrapper.java:112)
I have the problem both on a device with hardware-backed keystore and on a device with software-only keystore encryption.
Thank you.
Filippo
After extracting them from the device, with my limited experience, openssl doesn't seem to recognize them as a private key and an X.509 certificate.
I can't tell if these contain the actual key data, as they also seem to be generated for keys that should be stored in a hardware-backed container.
struct __attribute__((packed)) blob {
uint8_t version;
uint8_t type;
uint8_t flags;
uint8_t info;
uint8_t vector[AES_BLOCK_SIZE];
uint8_t encrypted[0]; // Marks offset to encrypted data.
uint8_t digest[MD5_DIGEST_LENGTH];
uint8_t digested[0]; // Marks offset to digested data.
int32_t length; // in network byte order when encrypted
uint8_t value[VALUE_SIZE + AES_BLOCK_SIZE];
};
Thanks for some of the most informative content I have seen. I like to ask if there has been any change in the level of access and interface with the hardware. What I mean is I do not understand why we are only limited to hardware supported key creation and verification. It is my understanding that ARM architecture provides for a number of instructions, and I do not see what would prevent me from trying to implement them. I do realize that I am still limited to what the vendor provides. In my case, I have a msm8974, and the associated build environment from source. After reading the truly amazing content above, I did a search in my environment, and see that I have acess to some qsee files as follows:
~/WORKING_DIRECTORY$ tree | grep -i 'qsee'
│ │ │ │ ├── qseecomi.h
│ │ │ ├── qseecom
│ │ │ │ └── qseecom.txt
│ │ ├── qseecom.c
│ │ ├── qseecom_kernel.h
│ │ ├── qseecom_legacy.h
│ │ ├── qseecom.o
│ │ │ └── QSEEComAPI.h
│ │ ├── qseecom.h
I do not see a qseecomlib.so. I think it should be possible to implement the arm TEE instructions such as SMC using assembly, and compile with ndk.
I immensely enjoyed and learned from this article as well as every other one you had so far. I wanted to check with you to see if anything has changed as far as methods of interfacing with TEE. I built an image for my Samsung Note 3, which as you may know has the Qualcomm Snapdragon 8974. What I want to ask you is what would prevent me from writing the assembly code to issue commands to Secure environment? It sounds to me, and perhaps I need to read your article again, you say it is not possible to interface with the QSEE.
I have a little question, is it possible to store a public key in the keystore. In the method that I see we can store a Certificate or a PrivateKey but I havn't seen anything about storing a public key ...
I am a trainee in a SIM Card based application solution providing company.
I want to know is that possible with mobile handset to establish the connection with server without any usage of SIM card. In detail is it possible:
1. Mobile Device can establish a secure session with Server
2. If yes than it should be possible without SIM Card usage. Some information can be used by Mobile device from SIM Card.
3. Mobile Device can download the data and save it.
I hope i made my point clear. Please get back to me.
I am following your blog regularly and I am using the sample to store key and values to android keystore(used your sample code).And it is working fine till Lollipop but It is not working in Android M. Can you please suggest me the way how to store KEy and value to Android Keystore in Android M . I saw so many examples to store key in Amdroid M but not as a Key and Value.. Please help to get out of this.
I'm trying to understand the key blobs that are stored in /data/misc/keystore/user_X. From what I understand, even in hardware-backed keystores, the actual keys are actually stored here, but somehow encrypted (several times?) There are options to disable encryption (e.g. with setEncryptionRequired()/setUserAuthenticationRequired()), presumably there are still other encryption layers that protect the private keys in this case? Can you describe/explain how private keys are stored within the key blob, what keys are involved in encrypting what data? I'm a bit lost even after reading your piece (including the Android M update)
which is not directly accessible to Android (it's in the TEE). If you call setEncryptionRequired(true),
keys will further be encrypted with a key derived from your PIN/password. This has the side effect that
such keys will be deleted when you change your PIN/password.
If you are interested in the details, have a look here:
https://bits-please.blogspot.jp/2016/06/extracting-qualcomms-keymaster-keys.html
The 'KeyMaster keys' the blog talks about are also used to encrypt keystore key blobs.