Open sdebruyn opened 5 years ago
Does this happen consistently?
It looks like perhaps the keystore is locked or uninitialized. I may need a logcat possibly to see more on it. Will investigate
Also, where are you running the code? Are you running it in background code at all or a service?
Logcat:
01-18 18:11:04.721 android.hardware.keymaster@3.0-service 1373 - D TrustyKeymaster Device received get_key_characteristics
01-18 18:11:04.721 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster calling trusty_keymaster_call insize 199 msg size 203
01-18 18:11:04.721 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster Received 4 byte response
01-18 18:11:04.721 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster Error: Response of size 4 contained error code -33
01-18 18:11:04.726 android.hardware.keymaster@3.0-service 1373 - D TrustyKeymaster Device received get_key_characteristics
01-18 18:11:04.726 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster calling trusty_keymaster_call insize 199 msg size 203
01-18 18:11:04.726 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster Received 4 byte response
01-18 18:11:04.726 android.hardware.keymaster@3.0-service 1373 - E TrustyKeymaster Error: Response of size 4 contained error code -33
When I get the exception, it's on thread 1 (so the UI thread I suppose). It's during the init phase of MVVMCross.
It doesn't happen consistently, but when it happens, it keeps happening until I clear the app's data.
Are you reading / writing to the storage from different threads at all? @jamesmontemagno maybe this has something to do with that change you did to not save settings synchronously - or was that just for preferences? I know that secure storage has some hand in preferences for some things.
Yes, probably from different threads. However not at that same time. My app can't do anything unless it has the key to unlock the database which is the first thing it retrieved from SecureStorage at startup. Did I miss something in the docs about the thread I should be using?
I don't think we expect any issues. Not sure how hard it would be, but is it possible to wrap the calls to read/write to secure storage in MainThread.BeginInvokeOnMainThread
and see if the issue is still happening? If it does, then we can look to see if something is corrupting the data. If it fixes the problem, we can have a look at what we can do to fix this.
I'm also running into a similar issue. The Set call was being called from a background thread. Switching it to force the set call from the main thread (Device.BeginInvokeOnMainThread
) had no impact.
[MonoDroid] System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Java.Security.UnrecoverableKeyException: Failed to obtain information about key ---> Java.Lang.Exception: Invalid key blob
[MonoDroid] --- End of inner exception stack trace ---
[MonoDroid] at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00089] in <da9f450baed342f3af31c42cec968688>:0
[MonoDroid] at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0001f] in <da9f450baed342f3af31c42cec968688>:0
[MonoDroid] at Java.Security.KeyStore.GetKey (System.String alias, System.Char[] password) [0x00043] in <ea97b6d670fe4c1ba9dadb89b2fa0103>:0
[MonoDroid] at Xamarin.Essentials.AndroidKeyStore.GetSymmetricKey () [0x00011] in C:\agent\_work\69\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:164
[MonoDroid] at Xamarin.Essentials.AndroidKeyStore.GetKey () [0x0002d] in C:\agent\_work\69\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:108
[MonoDroid] at Xamarin.Essentials.AndroidKeyStore.Encrypt (System.String data) [0x00000] in C:\agent\_work\69\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:249
[MonoDroid] at Xamarin.Essentials.SecureStorage.PlatformSetAsync (System.String key, System.String data) [0x00014] in C:\agent\_work\69\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:48
[MonoDroid] at Xamarin.Essentials.SecureStorage.SetAsync (System.String key, System.String value) [0x00021] in C:\agent\_work\69\s\Xamarin.Essentials\SecureStorage\SecureStorage.shared.cs:27
[MonoDroid] at app.xam.Services.LocalStorageServiceBase.set_SasToken (app.xam.Member.SasToken value) [0x0001a] in /Users/kensykora/Workspace/app.xam/src/app.xam/Services/LocalStorageServiceBase.cs:296
[MonoDroid] at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke(System.Reflection.MonoMethod,object,object[],System.Exception&)
[MonoDroid] at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x0003b] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
[MonoDroid] --- End of inner exception stack trace ---
[MonoDroid] at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00054] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
[MonoDroid] at System.Reflection.MonoProperty.SetValue (System.Object obj, System.Object value, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] index, System.Globalization.CultureInfo culture) [0x0005d] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
[MonoDroid] at System.Reflection.PropertyInfo.SetValue (System.Object obj, System.Object value) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
[MonoDroid] at app.xam.Services.LocalStorageServiceBase+<ClearAll>d__46.MoveNext () [0x001fb] in /Users/kensykora/Workspace/app.xam/src/app.xam/Services/LocalStorageServiceBase.cs:247
[MonoDroid] --- End of stack trace from previous location where exception was thrown ---
[MonoDroid] at app.xam.Services.Login.LoginService+<UserLogin>d__21.MoveNext () [0x007e5] in /Users/kensykora/Workspace/app.xam/src/app.xam/Services/Login/LoginService.cs:471
[MonoDroid] --- End of stack trace from previous location where exception was thrown ---
[MonoDroid] at app.xam.Services.Login.LoginService+<UserLogin>d__20.MoveNext () [0x00054] in /Users/kensykora/Workspace/app.xam/src/app.xam/Services/Login/LoginService.cs:364
[MonoDroid] --- End of stack trace from previous location where exception was thrown ---
[MonoDroid] at app.xam.Services.Login.LoginService+<Auth_Completed>d__25.MoveNext () [0x00085] in /Users/kensykora/Workspace/app.xam/src/app.xam/Services/Login/LoginService.cs:544
[MonoDroid] --- End of stack trace from previous location where exception was thrown ---
[MonoDroid] at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__6_0 (System.Object state) [0x00000] in <d4a23bbd2f544c30a48c44dd622ce09f>:0
[MonoDroid] at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <ea97b6d670fe4c1ba9dadb89b2fa0103>:0
[MonoDroid] at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <ea97b6d670fe4c1ba9dadb89b2fa0103>:0
[MonoDroid] at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00009] in <ea97b6d670fe4c1ba9dadb89b2fa0103>:0
[MonoDroid] at (wrapper dynamic-method) System.Object.35(intptr,intptr)
The issue seems to be some sort or race condition.
Can you try not running on other threads or tasks and just on the main and see if you get this issue. A repro of the issue would be very helpful so we can diagnose it better.
I've tried to run at the Main thread and I also getting the error. I have a private repo and I could share with you @jamesmontemagno, but I think you will need some steps to use the app, because it's a not-yet-commercial app. How can we do that ?
Most likely need to try to integrate this: https://stackoverflow.com/questions/36488219/android-security-keystoreexception-invalid-key-blob. I am curious if our changes in 1.1.0 fix this though with some of the things we did in the preferences part....
I assume just a snippet is code is fine.
Android Cipher is not thread safe so that is usually where people see issues.
@jamesmontemagno Any news?
@jbravobr can you share the repo with me
I'm experiencing the same issue:
Java.Security.UnrecoverableKeyException: Failed to obtain information about key ---> Java.Lang.Exception: Invalid key blob --- End of inner exception stack trace --- at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00089] in <fdf05f528e174febb3e55b587dbab368>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0001f] in <fdf05f528e174febb3e55b587dbab368>:0 at Java.Security.KeyStore.GetKey (System.String alias, System.Char[] password) [0x00039] in /Users/builder/jenkins/workspace/monodroid-multibranch_d16-0-ROFMKET2X57L6OM33VV4CLSC53EGKYMXL7RAG3T2HOJWPTP3PQCA/monodroid/external/xamarin-android/src/Mono.Android/obj/Release/android-27/mcw/Java.Security.KeyStore.cs:1439 at Xamarin.Essentials.AndroidKeyStore.GetSymmetricKey () [0x00011] in D:\a\1\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:173 at Xamarin.Essentials.AndroidKeyStore.GetKey () [0x0002d] in D:\a\1\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:117 at Xamarin.Essentials.AndroidKeyStore.Decrypt (System.Byte[] data) [0x00009] in D:\a\1\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:301 at Xamarin.Essentials.SecureStorage.PlatformGetAsync (System.String key) [0x0004f] in D:\a\1\s\Xamarin.Essentials\SecureStorage\SecureStorage.android.cs:35 at Xamarin.Essentials.SecureStorage.GetAsync (System.String key) [0x00013] in D:\a\1\s\Xamarin.Essentials\SecureStorage\SecureStorage.shared.cs:16
Any updates on this? I'm using Xamarin Essentials 1.1.0
I just started experiencing the same issue.
problem too! if it will happen periodically, how can we use it for saving important data??
Having the same problem on 1.1.0
I'm getting this issue when I close the emulator for some time, then, when I try to use my app again, it throws at the Get
call.
Update: as James posted, apparently it has something to do with unlocking the device and a race condition, this answer has more info: https://stackoverflow.com/questions/36652675/java-security-unrecoverablekeyexception-failed-to-obtain-information-about-priv
Update 2: I was able to repro this consistently when I use quick boot with my emulator. I just have to close the emulator and redeploy using quick boot. When the app tries to access the key it throws an exception. If the above answer is correct, this might be because of the 30s wait time.
I stumbled across this same issue myself today (1.2.0) I assumed it was because I was running my app in an emulator.
It looks like the aws-amplify team ran into this same issue in their aws-sdk-android repo.
They merged a PR to address this issue which essentially gives up on a key when they get an UnrecoverableKeyException
.
Here's the code where they treat all exceptions in KeyStore.getKey
equivalently and here is the code where they give up on the encryption key for any failure in retrieving it.
Quoting the commit message:
Causes of Failures
1. The retrieval of secrets from disk fails due to the encryption key being lost. a. End-user changes lock screen type which wipes off the encryption keys in the Android KeyStore. This could happen when the app is in foreground, background, closed. 2. The retrieval of secrets from disk fails due to the wrong encryption key used. a. End-user uninstalls the app which wipes off the encryption key in Android KeyStore. The encrypted secrets are backed up by Android and restored when the app is installed again. No 3. The retrieval of secrets from disk fails due to the encryption key not being recoverable. a. A cause has not been identified why key is not recoverable.
Item 3a is the most important here: They discovered that encryption keys are mysteriously unrecoverable under certain circumstances, but they did not determine what those circumstances are.
Proposed Fix
Under all these circumstances, the
AWSKeyValueStore
would returnnull
forget
operations and not write to disk forput
operations.
This is a reiteration of the above: Namely that their approach is to give up on any key for which they encounter an UnrecoverableKeyException
.
Any progress on this issue?
Also running into this issue after factory resetting an Android Emulator.
running into this scenario too, is there a possibility to simply check if the securestorage is available/accessible?
Any update on this?
I wasn't able to reproduce the issue myself and I am sure most of the time everything is working correctly, but our users once in a while reports this issue. We have reports from Android 6 (Huawei P8 Lite, Huawei Honor 7) and Android 7 (Samsung Galaxy S6).
We are running Essentials 1.6.1
Source = mscorlib, HasInnerException = True Message: Java.Security.GeneralSecurityException - Failed to obtain information about key Description: at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualObjectMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x0008e] in <df2b1e5310a74b778689790f99a7dc0f>:0 at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeNonvirtualObjectMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0001f] in <df2b1e5310a74b778689790f99a7dc0f>:0 at Java.Security.KeyStore.GetKey (System.String alias, System.Char[] password) [0x00043] in <292545bfee9340a1aa549c5f9bc1c1d2>:0 at Xamarin.Essentials.AndroidKeyStore.GetSymmetricKey () [0x00011] in <e6ec74ce2f2b4217bb44a200049f9d8c>:0 at Xamarin.Essentials.AndroidKeyStore.GetKey () [0x0002d] in <e6ec74ce2f2b4217bb44a200049f9d8c>:0 at Xamarin.Essentials.AndroidKeyStore.Decrypt (System.Byte[] data) [0x00009] in <e6ec74ce2f2b4217bb44a200049f9d8c>:0 at Xamarin.Essentials.SecureStorage.PlatformGetAsync (System.String key) [0x000a6] in <e6ec74ce2f2b4217bb44a200049f9d8c>:0 at Xamarin.Essentials.SecureStorage.GetAsync (System.String key) [0x00013] in <e6ec74ce2f2b4217bb44a200049f9d8c>:0 at CompanyName.Mobile.ProjectName.Backend.DataAccess.AccountStorage.SecureStorageAccountStore.GetAccountsServiceAsync () [0x0000a] in <a99d086ced8a45f1ab0b0d3448b568d7>:0 at CompanyName.Mobile.ProjectName.Backend.DataAccess.AccountStorage.SecureStorageAccountStore.LoadAccountData () [0x0006f] in <a99d086ced8a45f1ab0b0d3448b568d7>:0 at CompanyName.Mobile.ProjectName.Backend.Managers.LoginManager.TryPermanentLogin (System.Threading.CancellationToken token) [0x00073] in <a99d086ced8a45f1ab0b0d3448b568d7>:0 at CompanyName.Mobile.ProjectName.ViewModels.LoginViewModel.TryPermanentLogin () [0x000ba] in <41da5024a1f9467195e6ed4f44c0cf8f>:0 at CompanyName.Mobile.ProjectName.Views.LoginPage.OnPageLoaded () [0x00067] in <41da5024a1f9467195e6ed4f44c0cf8f>:0 at CompanyName.Mobile.Framework.Controls.Forms.Pages.CompanyNamePage.OnFirstAppearing () [0x0006a] in <a210d4c9b0604428afced6684aba0fe8>:0 at CompanyName.Mobile.Framework.Controls.Forms.Pages.CompanyNamePage.OnAppearing () [0x00081] in <a210d4c9b0604428afced6684aba0fe8>:0 at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in <58b28471d446476e88d4063427987bef>:0 at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <292545bfee9340a1aa549c5f9bc1c1d2>:0 at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <292545bfee9340a1aa549c5f9bc1c1d2>:0 at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <292545bfee9340a1aa549c5f9bc1c1d2>:0 at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.20(intptr,intptr) --- End of managed Java.Security.GeneralSecurityException stack trace --- java.security.UnrecoverableKeyException: Failed to obtain information about key at android.security.keystore.AndroidKeyStoreProvider.loadAndroidKeyStoreSecretKeyFromKeystore(AndroidKeyStoreProvider.java:275) at android.security.keystore.AndroidKeyStoreSpi.engineGetKey(AndroidKeyStoreSpi.java:97) at java.security.KeyStore.getKey(KeyStore.java:253) at crc64720bb2db43a66fe9.NavigationPageRenderer.n_onAttachedToWindow(Native Method) at crc64720bb2db43a66fe9.NavigationPageRenderer.onAttachedToWindow(NavigationPageRenderer.java:49) at android.view.View.dispatchAttachedToWindow(View.java:14624) at android.view.ViewGroup.dispatchAttachedToWindow(ViewGroup.java:2838) at android.view.ViewGroup.addViewInner(ViewGroup.java:4365) at android.view.ViewGroup.addView(ViewGroup.java:4162) at android.view.ViewGroup.addView(ViewGroup.java:4103) at android.view.ViewGroup.addView(ViewGroup.java:4076) at mono.java.lang.RunnableImplementor.n_run(Native Method) at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:30) at android.os.Handler.handleCallback(Handler.java:743) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:150) at android.app.ActivityThread.main(ActivityThread.java:5621) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:794) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:684) Caused by: android.security.KeyStoreException: -65536 at android.security.KeyStore.getKeyStoreException(KeyStore.java:632) ... 20 more
Description
I get an exception when calling GetAsync and SetAsync in SecureStorage
Steps to Reproduce
Tried to call GetAsync on a key that should exist. Later tried to call SetAsync for that same key. I don't have a repro yet, but I provided a lot of stack trace & debug info...
Exception happens both in GetAsync and SetAsync
Expected Behavior
Just return the value
Actual Behavior
Exception thrown.
Exception message: Failed to obtain information about key Exception type: Java.Security.UnrecoverableKeyException Exception stacktrace:
Inner exception is of type Java.Lang.Exception Inner exception message: -32 Inner exception stacktrace:
Basic Information
Contents of xamarin essentials preferences file:
IDE info