In Android, how to ensure that Private Key is stored inside secure hardware
Asked Answered
C

1

7

KeyInfo's isInsideSecureHardware-method's return value seems to depend on device model, os version, and some other random factors.

For example when using Sony xperia z5 compact with older os version isInsideSecureHardware() could return true for some time and then suddenly start returning false for the same Private Key. With the latest os version (32.2.A.0.224) it seems to return only false. Huawei Nexus 6P returns always true.

Is there a way to make sure that the key is stored in secure hardware?

Here is my current code:

KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KeyProperties.KEY_ALGORITHM_RSA, "AndroidKeyStore");
keyPairGenerator.initialize(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_DECRYPT | KeyProperties.PURPOSE_ENCRYPT)
                                    .setUserAuthenticationRequired(true)
                                    .setBlockModes(KeyProperties.BLOCK_MODE_ECB)
                                    .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1)
                                    .build());
KeyPair keyPair = keyPairGenerator.generateKeyPair();
// Check that private key is inside secure hardware
KeyFactory factory = KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
KeyInfo keyInfo = factory.getKeySpec(key, KeyInfo.class);
boolean secure = keyInfo.isInsideSecureHardware(); //  this usually returns false

Thanks!

Edit: In sony support forum there is a topic about the same problem: https://talk.sonymobile.com/t5/Android-development/hardware-backed-keystore/td-p/1154124

It was mentioned that following warning is printed to logs:

W keystore: Primary keymaster device failed to generate key, falling back to SW.

Cymoid answered 4/7, 2016 at 7:4 Comment(0)
R
3

According to the Android API, the only way to verify it is to first create the key then look at the information to ensure it is hardware-backed.

Looking at the specs for the phone, it was originally released on Lollipop. That was before the official Marshmallow Fingerprint API/hardware specs and manufacturers were doing their own thing. This article mentions the device you are using specifically (http://blog.elcomsoft.com/2016/06/fingerprint-unlock-security-ios-vs-google-android-part-ii/). I am wondering if whether the true values you were getting back were incorrect and then due to your O/S upgrade it fixed the logic (or broke it?). The O/S upgrade version you mention contains "1 April 2016 Google security patches"

I have a few questions:

  1. What does isUserAuthenticationRequirementEnforcedBySecureHardware() 1 return on your device now? Is the value consistent? If it's false that could tell you that the fingerprint reader is not considered secure (or there is an O/S defect)

  2. What does older OS version mean, exactly? Lollipop? Have you tried resetting to factory defaults?

Ramachandra answered 27/8, 2016 at 21:58 Comment(3)
Please, don't write an answer to the question when you want to ask for clarifications. Comments are better for that.Offprint
Hi, Sorry for taking this long to answer. The isUserAuthenticationRequirementEnforcedBySecureHardware() returns false with the current version. Seems to be consistent. The older version was 32.1.A.1.185. With that version the isUserAuthenticationRequirementEnforcedBySecureHardware() returns true. Restoring factory settings did not fix the problem. About the fingerprint scanner: The same problem remains when I set UserAuthenticationRequired to false. So there is no longer anything that is related to fingerprint scanning.Cymoid
@Offprint It seems the author asks these questions, to answer the original question in a more appropriate way. Also, this answer does contain, some good pointers that helped me, such as "According to the Android API, the only way to verify it is to first create the key then look at the information to ensure it is hardware-backed."Derosa

© 2022 - 2024 — McMap. All rights reserved.