Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F3378737
D11661.id39109.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
D11661.id39109.diff
View Options
diff --git a/patches/expo-secure-store+12.0.0.patch b/patches/expo-secure-store+12.0.0.patch
new file mode 100644
--- /dev/null
+++ b/patches/expo-secure-store+12.0.0.patch
@@ -0,0 +1,98 @@
+diff --git a/node_modules/expo-secure-store/android/src/main/java/expo/modules/securestore/SecureStoreModule.java b/node_modules/expo-secure-store/android/src/main/java/expo/modules/securestore/SecureStoreModule.java
+index 91e9b85..93208a6 100644
+--- a/node_modules/expo-secure-store/android/src/main/java/expo/modules/securestore/SecureStoreModule.java
++++ b/node_modules/expo-secure-store/android/src/main/java/expo/modules/securestore/SecureStoreModule.java
+@@ -8,6 +8,7 @@ import android.os.Build;
+ import android.preference.PreferenceManager;
+ import android.security.KeyPairGeneratorSpec;
+ import android.security.keystore.KeyGenParameterSpec;
++import android.security.keystore.KeyPermanentlyInvalidatedException;
+ import android.security.keystore.KeyProperties;
+ import android.text.TextUtils;
+ import android.util.Base64;
+@@ -39,6 +40,7 @@ import java.security.spec.InvalidParameterSpecException;
+ import java.util.Date;
+
+ import javax.crypto.Cipher;
++import javax.crypto.IllegalBlockSizeException;
+ import javax.crypto.KeyGenerator;
+ import javax.crypto.NoSuchPaddingException;
+ import javax.crypto.SecretKey;
+@@ -81,14 +83,14 @@ public class SecureStoreModule extends ExportedModule {
+ @SuppressWarnings("unused")
+ public void setValueWithKeyAsync(String value, String key, ReadableArguments options, Promise promise) {
+ try {
+- setItemImpl(key, value, options, promise);
++ setItemImpl(key, value, options, promise, false);
+ } catch (Exception e) {
+ Log.e(TAG, "Caught unexpected exception when writing to SecureStore", e);
+ promise.reject("E_SECURESTORE_WRITE_ERROR", "An unexpected error occurred when writing to SecureStore", e);
+ }
+ }
+
+- private void setItemImpl(String key, String value, ReadableArguments options, Promise promise) {
++ private void setItemImpl(String key, String value, ReadableArguments options, Promise promise, boolean keyIsInvalidated) {
+ if (key == null) {
+ promise.reject("E_SECURESTORE_NULL_KEY", "SecureStore keys must not be null");
+ return;
+@@ -109,11 +111,19 @@ public class SecureStoreModule extends ExportedModule {
+ try {
+ KeyStore keyStore = getKeyStore();
+
++
++
+ // Android API 23+ supports storing symmetric keys in the keystore and on older Android
+ // versions we store an asymmetric key pair and use hybrid encryption. We store the scheme we
+ // use in the encrypted JSON item so that we know how to decode and decrypt it when reading
+ // back a value.
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
++ // Fixing key invalidated crash
++ if(keyIsInvalidated) {
++ String alias = mAESEncrypter.getKeyStoreAlias(options);
++ keyStore.deleteEntry(alias);
++ }
++
+ KeyStore.SecretKeyEntry secretKeyEntry = getKeyEntry(KeyStore.SecretKeyEntry.class, mAESEncrypter, options);
+ mAESEncrypter.createEncryptedItem(promise, value, keyStore, secretKeyEntry, options, mAuthenticationHelper.getDefaultCallback(), (innerPromise, result) -> {
+ JSONObject obj = (JSONObject) result;
+@@ -132,10 +142,32 @@ public class SecureStoreModule extends ExportedModule {
+ Log.w(TAG, e);
+ promise.reject("E_SECURESTORE_IO_ERROR", "There was an I/O error loading the keystore for SecureStore", e);
+ return;
++ } catch (IllegalBlockSizeException e){
++ boolean isInvalidationException = e.getCause() != null && e.getCause().getMessage() != null && e.getCause().getMessage().contains("Key user not authenticated");
++
++ if(isInvalidationException && !keyIsInvalidated) {
++ setItemImpl(key, value, options, promise, true);
++ Log.w(TAG, "IllegalBlockSizeException, retrying with the key deleted");
++ return;
++ }
++ // If the issue persists after deleting the key it is likely not related to invalidation
++ promise.reject("E_SECURESTORE_ENCRYPT_ERROR", "Unable to decrypt the key", e);
+ } catch (GeneralSecurityException e) {
+- Log.w(TAG, e);
+- promise.reject("E_SECURESTORE_ENCRYPT_ERROR", "Could not encrypt the value for SecureStore", e);
+- return;
++ boolean isInvalidationException = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && e instanceof KeyPermanentlyInvalidatedException;
++
++ if (isInvalidationException && !keyIsInvalidated) {
++ // If the key has been invalidated by the OS we try to reinitialize it.
++ Log.w(TAG, "Key has been invalidated, retrying with the key deleted");
++ setItemImpl(key, value, options, promise, true);
++ } else if (isInvalidationException) {
++ Log.w(TAG, e);
++ // If reinitialization of the key fails, reject the promise
++ promise.reject("E_SECURESTORE_ENCRYPT_ERROR", "Encryption Failed. The key has been permanently invalidated and cannot be reinitialized", e);
++ } else {
++ Log.w(TAG, e);
++ promise.reject("E_SECURESTORE_ENCRYPT_ERROR", "Could not encrypt the value for SecureStore", e);
++ return;
++ }
+ } catch (JSONException e) {
+ Log.w(TAG, e);
+ promise.reject("E_SECURESTORE_ENCODE_ERROR", "Could not create an encrypted JSON item for SecureStore", e);
+@@ -661,3 +693,4 @@ public class SecureStoreModule extends ExportedModule {
+ }
+ }
+ }
++
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 28, 12:44 PM (20 h, 57 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2593787
Default Alt Text
D11661.id39109.diff (5 KB)
Attached To
Mode
D11661: Handle key permanently invalidated error to fix Android app crash
Attached
Detach File
Event Timeline
Log In to Comment