Having a random key to encrypt local credentials through AES, I'm following the below tutorial to try to store securely that key and then be able to decrypt later on:
nelenkov.blogspot.co.uk storing applicationsecrets in androids
This tutorial explains how access to the system keystore and store your passwords in it.
The issue I'm facing it's focused in the call to UNLOCK (android.credentials.UNLOCK) the KeyStore. Devices (at the moment with API below 14) that don't have KeyStore initialized, they are showing a dialog requesting a 8 digits password.
The tutorial works fine however showing this dialog even do being only once, it's going to bother most of the users.
are there any way to skip this dialog?
I would be even happier if someone described a better way to keep locally a Key.
KeyStore can appear locked not only on pre-ICS devices. The simplest way to get KeyStore locked is:
Initialize KeyStore by setting KeyGuard (pattern, pin, or
password on the Screen Lock)
Add keys or whatever you store in the KeyStore
Go to Settings > Security and change Screen Lock to something "not
secure", for example, Slide.
Reboot your device.
After the device is booted, KeyStore will be LOCKED. com.android.credentials.UNLOCK intent will start com.android.settings.CredentialStorage activity, which, in turn, will show UnlockDialog, prompting for a password.
* KeyStore: LOCKED
* KeyGuard: OFF/ON
* Action: old unlock dialog
* Notes: assume old password, need to use it to unlock.
* if unlock, ensure key guard before install.
* if reset, treat as UNINITALIZED/OFF
KeyStore gets reset after 5 attempts to enter incorrect password. But resetting KeyStore actually doesn't turn it off or uninitialize. KeyStore remains locked and the only way to uninitialize it seems to call for com.android.credentials.RESET. But this will reset both KeyStore and KeyChain (user installed certificates).
If you want to reset KeyStore and KeyChain silently, without user confirmation, you can do it by binding to IKeyChainService and calling its reset() method. But I'd not recommend doing this. A better solution could be to display some notification message asking user to set Screen Lock manually
The 8 digit password is enforced by the your custom device firmware or a device administrator. There is no such requirement on most devices. If want to store something securely, you have to have a PIN code, Android uses it to derive the encryption key. Other options are to derive a key from your input yourself: you get to control the timing of dialogs and caching of keys, but it's the same process. Finally, you can just generate a master key and store it as a private file, other apps won't be able to read it, so you'll be fine on non-rooted devices. This is the approach recommended on the Android Developers Blog:
http://android-developers.blogspot.jp/2013/02/using-cryptography-to-store-credentials.html
Related
Following this tutorial on fingerprint authentication I should check for KeyguardManager.isKeyguardSecure() before letting users authenticate with fingerprint.
Why should I do this?
Most device manufacturers require a secure lock screen type (PIN, password, pattern) in order to use fingerprints. When changing the lock screen type to an insecure one (None, Swipe or other mode which does not authenticate the user) the fingerprints are removed.
On Samsung devices this is handled differently, by providing the user the possibility to not delete the fingerprints (and secure them with an additional password). Thereby, the user can still use the fingerprints in applications.
In case you want to allow those users, with a Samsung device, to use fingerprint authentication (in your app) even though they don't have set a secure lock screen type, you don't need to check if KeyguardManager.isKeyguardSecure() returns true.
Later in the code, the tutorial uses setUserAuthenticationRequired(true), which won't work if there is no secure keyguard.
I'm implementing fingerprint authentication in an existing Android application making use of FingerprintManagerCompat. I used a tutorial as guidance that can be found here.
(android.support.v4.content.ContextCompat)
As FingerprintManagerCompat makes use of saved fingerprints on the mobile device, any fingerprint on the device can be used to login to the application.
Is it possible to see which one of the fingerprints on the device were used to unlock and if so is there a method to get all saved fingerprints that are available on the device?
I looked around for information on if this is possible and I cant seem to find anything. I have found that Samsung Pass SDK does have functionality to see what fingerprint is used but the product owner does not want the me to use Samsung's Pass SDK as his penetration testing team found that it is not very secure.
Is there a method to get all saved fingerprints that are available on the device?
No.
Is it possible to see which one of the fingerprints on the device were used to unlock
No.
However, there are some limitations to which fingerprints can be used to authenticate within your app. The result of a fingerprint authentication is that you make a cryptographic key available to perform some cryptographic operation (e.g. creating a digital signature). So when you add a user in your app you'd typically create a cryptographic key that you associate with that user. Then later on when the user wants to perform some action that requires him/her to be authenticated, you do the fingerprint authentication, which gives you access to the key, which use can use to do whatever it is that you need to do to verify that the user should be allowed to perform the action.
What happens when a new fingerprint is enrolled is that any existing cryptographic keys that require fingerprint authentication will be permanently invalidated.
That leaves us with the scenario where there are multiple enrolled fingerprint before the user is added in your app. I'm not aware of any way to do anything about this with the current APIs. So the best you can do might be to add some step in your fingerprint-enabling UI flow where the user is asked to verify that only they have enrolled a fingerprint on the device (e.g. by checking a checkbox or clicking a button).
Android supports cloud and local backup of APK files, application data, and so on. Is the device keystore included in the backup?
(I don't think you can extract private keys from an hardware-backed keystore even in rooted devices, not so sure about the software-based version used when there is no hardware support.)
No. The whole point behind the hardware-backed keystore is that it's resistant to even privileged attacks with root access.
For this reason, not even the OS can access raw key material from the hardware-backed keystore.
While it would be theoretically possible for the OS to do a keystore backup on lower end devices with a software-backed keystore, this is simply not done or allowed by the OS for security reasons.
You cannot back up the Keystore, so when your encrypted data will be restored you won't be able to decrypt it.
You have to find a different way to backup data, for example:
Store user data one backend
Use a user-stored token to decrypt the backup
Have a static password for all apps
Export backup manually by the user in settings
I wrote about it more here:
https://medium.com/#thecodeside/android-auto-backup-keystore-encryption-broken-heart-love-story-8277c8b10505
A July 13 2016 check with official says no:
"What gets backed up with Android Backup Service
Google Calendar settings
Wi-Fi networks & passwords
Home screen wallpapers
Gmail settings
Apps installed through Google Play (backed up on the Play Store app)
Display settings (Brightness & Sleep)
Language & Input settings
Date & Time
Third-party app settings & data (varies by app)
Note: Not all apps use Android Backup Service. Some apps may not back up and restore all data."
Of course backing up and restoring apps that use the KeyStore without the KeyStore itself being backed up and restored with the account makes little or no sense.
Though it's possible they did not update their docs my best guess is that the KeyStore is backed up but that information is not made widely available.
Possibly due to the backup not being encrypted prior to transport which is the Google back up standard. They may have made an exception for the keystore but that would indicate all other data isn't as secure when transported nor when received by their servers (they do encrypt the data once they receive it).
I'm currently looking at the possibilities of storing/using secrets keys in an Android application. I've found Nikolay Elenkov's blog very helpful regarding this topic and I've learnt a lot of things about the Android keystore and some hardware-based implementations.
Still I've got some questions about security and user experience aspects.
Software keystore
For what I understood, in this configuration a masterkey is derived (using PBKDF2) from a user password (plus a salt to prevent rainbow tables attacks) and used to encrypt secrets. As far as I know, the password is the one used for the lock screen.
On a non-rooted phone, only the user 'keystore' is able to read/write the encrypted files and whenever an application want to access a file, it has to call the keystore daemon which checks if its UID is authorized to access this file (the authorizations are stored in a sqlite database).
But there are still some details I couldn't figure out :
Does using the keystore enforce the use of a password-protected lock screen ?
Does the user have to input his/her password every time an access to the encrypted keys is required ?
Given it's a software-only mechanism, I think a secret key will always end up decrypted in RAM whenever it's used for cryptographic operations, right ?
Hardware-based keystore
As for the hardware-based implementation, it seems that SoC manufacturers provide solutions compliant to [Global Platform TEE][2] (Trusted Execution Environment) with embedded Trusted Applications and APIs that enable Google to provide an hardware-backed implementation of its keystore. It's thus possible to store secret keys in the TEE, ask for RSA key pair creation inside the TEE and sign or check data using secret keys stored inside the TEE. This way, one can use secret keys for basic cryptographic operations without them ever leaving the TEE.
If I got it right, access control to those keys is provided by the Google keystore daemon using the same mechanism as in the software implementation. The only difference is that references to the keys stored in the TEE are used instead of the encrypted keys themselves.
If everything stated before is correct, I guess it would be possible on a rooted phone to modify the permissions database so that an application with an arbitrary UID can have data signed with any key stored in the TEE. Am I right ?
Thanks for your time!
Does using the keystore enforce the use of a password-protected lock
screen ?
Yes, user is forced to use lock screen, protected with password, pin, or pattern.
Does the user have to input his/her password every time an access to
the encrypted keys is required ?
No, once the device is unloked, KeyStore becomes unlocked as well and there's no need to enter additional passwords. However, application should check if the KeyStore is unlocked, because user could disable the lock screen protection in Settings. Once key locked is disabled, KeyStore becomes uninitialized and must be unlocked again.Several times I faced a strange behavior, when the KeyStore was locked, but I didn't have lock screen protection set up. I was prompted to enter a password or pin code to enter the KeyStore. However, it was not possible, since I didn't have any passwords. I assume some system apps were locking the KeyStore. I had to reset it to re-initialize.
Given it's a software-only mechanism, I think a secret key will
always end up decrypted in RAM whenever it's used for cryptographic
operations, right ?
Yes, all keys retrieved from the KeyStore will reside in RAM until garbage-collected or deinitialized. But you can obtain the key each time you need it, not keeping it in some long-living variable.
Unfortunately, I'm not familiar with HW-backed KeyStore. Cannot say anything about it.
Your analysis of the TEE-based hardware-backed scenario is correct. The private key bits generated in the TEE (which isn't necessarily compliant with the Global Platform specs) never leave the TEE and private key operations are performed inside it.
You're also correct that the handles to the TEE-based keys are stored in Keystore, so it's possible for root to access and use any of them, or to move them around so any app can use them.
My objective:
Create an EAP WiFi configuration - including the CA Certificate - in Android programmitcally.
Problem:
How do I install a CA Certificate programmatically (and then reference that certificate in the EAP WiFi configuration)?
I found a very useful link already that allows me to create and save EAP WiFi configurations here:
How to programmatically create and read WEP/EAP WiFi configurations in Android?
However this assumes that you have already installed the CA Certificate on the device. I would like to install the certificate within my app - either from the resources in the app, or sent from a server.
Is this even possible? (Rooting is not an option in this case.)
If so, how?
Additional info...
I also found a way to add a certificate to a KeyStore:
https://stackoverflow.com/a/4490543/1172101
However this is used specifically for creating a secure socket and connecting via HTTPS. I want to use the certificate for WiFi.
Unfortunately, I have yet to find a way to install a CA Certificate programmatically - from within the app.
However, it is possible to install a certificate via the Web browser in Android. Thus, the solution (for now) is to:
Launch an intent to open a URL in the Web browser that goes directly to the CA certificate.
This works but there are some challenges:
The user must name the certificate. This is a challenge because we are adding the WiFi configuration programmitically. Thus we have to ask the user to give the certificate the same name.
The user must enter a password. If they don't have a password set up, the user will create one and enter it twice. If they have set a security password, the user will have to remember that same password and enter it.
Assuming the user successfully completes these steps, he is left hanging in the browser.
This leads to a few questions:
From my app, is there a way to force a name for the certificate that the user installs via the browser?
From my app, is there any way to know when the certificate installation has completed and then give focus back to my app?
Just let me know if you need any clarification.
You cannot install it directly since non-system applications don't have access to the key store. On ICS, there is an API for this KeyChain.createInstallIntent() that would launch a system dialog asking the user whether they want to install the certificate. On pre-ICS you can achieve the same thing by launching the install intent using the component name directly (this may or may not work on all devices though). Going through the browser is actually a roundabout way of doing the same thing.
As for your questions:
you cannot specify/force a name. Why do you care about the actual name?
Not really through the browser. If you use the system intent, you can return to your activity and will get a callback if you use startActivityForResult().
Update: Android 4.3 has WifiEnterpriseConfig which both creates a profile and installs keys and certificates in the system credential store. You only need the CHANGE_WIFI_STATE permission.
I am currently looking to solve the same issues. The best thing that I have found is KeyChain.choosePrivateKeyAlias() allowing the user to select which certificate to use for the SSL. From there you can retrieve the Alias name and pass it to the enterprise wifi configuration.
I'm looking for the same... as for your question, #Nikolay:
you cannot specify/force a name. Why do you care about the actual name?
The EAP profile needs the name of the already-installed-CA. If you look at the example in part 4, you can specify:
final String ENTERPRISE_CA_CERT = "";
In the example, the profile does not use the CA name, but that could be the case for other EAP profiles.