Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working on Android Xiaomi MI A1 #55

Open
Gizmo8690 opened this issue Aug 11, 2020 · 9 comments
Open

Not working on Android Xiaomi MI A1 #55

Gizmo8690 opened this issue Aug 11, 2020 · 9 comments

Comments

@Gizmo8690
Copy link

On Xiaomi MI A1 the plugin is still not working.
The constructor new cordova.plugins.SecureStorage() fails with error:

Error: User not authenticated
    at fail (securestorage.js:42)
@leolio86400
Copy link

Not sure it is related to the plugin but more to the device itself. But it is true that this is happening a lot on Android devices.

The only thing that seems to make it work is to screen lock the device and unlock using pin (not biometrics).

Does anybody have better solution than that ?

@Gizmo8690
Copy link
Author

The only thing that seems to make it work is to screen lock the device and unlock using pin (not biometrics).

I have already tried setting unlock using pin but it is still not working...

@faugusztin
Copy link

While i am not using this plugin anymore and the stacktrace i will post is old, it should give some insight in the issue.

If i remember correctly (i have a Mi A1 here if needed), the issue was the following combination:

  • user had fingerprint device unlock enabled and fingerprints enrolled
  • device was unlocked using fingerprint

In this case, Crypho's original plugin failed with following stacktrace:

09-18 10:43:48.955 15570 16023 E SecureStorage: Decrypt failed :
09-18 10:43:48.955 15570 16023 E SecureStorage: java.security.InvalidKeyException: Keystore operation failed
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getInvalidKeyException(KeyStore.java:901)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getInvalidKeyException(KeyStore.java:926)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.init(Cipher.java:1143)
09-18 10:43:48.955 15570 16023 E SecureStorage: at javax.crypto.Cipher.init(Cipher.java:1084)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.RSA.runCipher(RSA.java:97)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.RSA.decrypt(RSA.java:41)
09-18 10:43:48.955 15570 16023 E SecureStorage: at com.crypho.plugins.SecureStorage$3.run(SecureStorage.java:151)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
09-18 10:43:48.955 15570 16023 E SecureStorage: at java.lang.Thread.run(Thread.java:764)
09-18 10:43:48.955 15570 16023 E SecureStorage: Caused by: android.security.KeyStoreException: Invalid user authentication validity duration
09-18 10:43:48.955 15570 16023 E SecureStorage: at android.security.KeyStore.getKeyStoreException(KeyStore.java:835)
09-18 10:43:48.955 15570 16023 E SecureStorage: ... 17 more

I suspect the issue is on firmware level, and because Mi A1 is an 'obsolete' phone, the bug is unlikely to be fixed on HW level.

If someone has some demo application source code i can build with current version of this plugin, i am willing to test out if it is still the case.

@leolio86400
Copy link

@faugusztin yeah it seems to be a recurrent issue with low price brand phones.

Did you find any plugin that could replace this one? This plugin have been the core of lot of issues we have, so we are really considering moving out of it.

@faugusztin
Copy link

Unfortunately my answer won't help you - we reconsidered if we really needed secure storage (we did not), so we just save the few client side settings in JSON file (as local storage in browser could be wiped if disk space is an issue).

You could still keep using this plugin on compatible phones, and via phone model detection add an alternative, maybe a bit less secure storage (like the JSON file i mentioned above) for phones with issues.

Unless there is a magic combination of settings which could make this plugin work on Mi A1, that is your best alternative.

@faugusztin
Copy link

More detailed description of what happens (created a minimal case by creating a new cordova project, adding the secure storage plugin to it, then adding the android platform, adding the "Create a namespaced storage." example from the documentation to www/js/index.js of the default Cordova project).

  • When i ran the app for first time, it reported to logcat that it didn't find the namespace, but ran fine.
  • then i locked the phone using the power button
  • unlocked the phone using fingerprint
  • ran the app again. It now asks me to Re-enter my PIN, and also shows the fingerprint icon at bottom
  • no mater which option i use (PIN or fingerprint), the call results in 'Error Error: User not authenticated'.

In code it runs like this:

  • isDeviceSecure in SecureStorage.java returns true (device is secure)
  • rsa.encryptionKeysAvailable(alias) returns true (there are keys in HW)
  • AbstractRSA.userAuthenticationRequired goes through the encrypt step, but fails with decrypt with InvalidKeyException, detail says 'Keystore operation failed':
java.security.InvalidKeyException: Keystore operation failed
    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:912)
    at android.security.KeyStore.getInvalidKeyException(KeyStore.java:937)
    at android.security.keystore.KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(KeyStoreCryptoOperationUtils.java:54)
    at android.security.keystore.KeyStoreCryptoOperationUtils.getExceptionForCipherInit(KeyStoreCryptoOperationUtils.java:89)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.ensureKeystoreOperationInitialized(AndroidKeyStoreCipherSpiBase.java:265)
    at android.security.keystore.AndroidKeyStoreCipherSpiBase.engineInit(AndroidKeyStoreCipherSpiBase.java:109)
    at javax.crypto.Cipher.tryTransformWithProvider(Cipher.java:2984)
    at javax.crypto.Cipher.tryCombinations(Cipher.java:2891)
    at javax.crypto.Cipher$SpiAndProviderUpdater.updateAndGetSpiAndProvider(Cipher.java:2796)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:773)
    at javax.crypto.Cipher.init(Cipher.java:1143)
    at javax.crypto.Cipher.init(Cipher.java:1084)
    at com.crypho.plugins.AbstractRSA.runCipher(AbstractRSA.java:47)
    at com.crypho.plugins.AbstractRSA.decrypt(AbstractRSA.java:65)
    at com.crypho.plugins.AbstractRSA.userAuthenticationRequired(AbstractRSA.java:102)
    at com.crypho.plugins.SecureStorage.execute(SecureStorage.java:114)
    at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:117)
    at org.apache.cordova.CordovaPlugin.execute(CordovaPlugin.java:98)
    at org.apache.cordova.PluginManager.exec(PluginManager.java:132)
    at org.apache.cordova.CordovaBridge.jsExec(CordovaBridge.java:59)
    at org.apache.cordova.engine.SystemExposedJsApi.exec(SystemExposedJsApi.java:41)
    at android.os.MessageQueue.nativePollOnce(Native Method)
    at android.os.MessageQueue.next(MessageQueue.java:326)
    at android.os.Looper.loop(Looper.java:160)
    at android.os.HandlerThread.run(HandlerThread.java:65)
Caused by: android.security.KeyStoreException: Invalid user authentication validity duration
    at android.security.KeyStore.getKeyStoreException(KeyStore.java:846)
	... 24 more
  • That exception then triggers the unlock UI. After user enters PIN or fingerprint, the runnable in SecureStorage.onResume runs.
  • After that, AbstractRSA.userAuthenticationRequired fails with exactly the identical error message.

Then i tried to use a different alias (to generate new keys) and with the following options:

{
   android: {
      userAuthenticationValidityDuration: 5*60 
   }
} 

Same result.

As i said, i suspect a firmware bug on Xiaomi Mi A1, which somehow breaks RSA decryption (or the keys) in case fingerprint unlock is enabled. Without fingerprint unlock, the code works just fine.

@faugusztin
Copy link

The only alternative to consider on plugin's side is to have a list of devices which are not compatible with userAuthenticationRequired setting, and for those drop those two settings (setUserAuthenticationRequired and setUserAuthenticationValidityDurationSeconds) in https://github.com/mibrito707/cordova-plugin-secure-storage-echo/blob/master/src/android/RSA.java#L48. Without those two settings, there keys work fine for the encryption test, but obviously do not trigger the need for secure unlock and do not get invalidated in case of security modifications, like enrolling a new fingerprint or disabling the secure lock, which is a drawback. On other side, at least it would make the plugin usable on those devices.

@leolio86400
Copy link

Thanks @faugusztin, I opted for another way and designed a solution to remove the plugin as well. I tried to upgrade it and use the setUserAuthenticationValidityDurationSeconds up to 1 month, it got somehow worse... so better moving out of this than keeping it.
Thanks for the help though 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants