Page MenuHomePhabricator

D11661.id39109.diff
No OneTemporary

D11661.id39109.diff

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

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)

Event Timeline