Merge "Improve error reporting for getDecryptedObject()" into androidx-main
diff --git a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
index acea0ee..ad66feb 100644
--- a/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
+++ b/security/security-crypto/src/main/java/androidx/security/crypto/EncryptedSharedPreferences.java
@@ -499,6 +499,7 @@
return mId;
}
+ @Nullable
public static EncryptedType fromId(int id) {
switch (id) {
case 0:
@@ -518,69 +519,73 @@
}
}
- private Object getDecryptedObject(String key) {
+ private Object getDecryptedObject(String key) throws SecurityException {
if (isReservedKey(key)) {
throw new SecurityException(key + " is a reserved key for the encryption keyset.");
}
if (key == null) {
key = NULL_VALUE;
}
- Object returnValue = null;
+
try {
String encryptedKey = encryptKey(key);
String encryptedValue = mSharedPreferences.getString(encryptedKey, null);
- if (encryptedValue != null) {
- byte[] cipherText = Base64.decode(encryptedValue, Base64.DEFAULT);
- byte[] value = mValueAead.decrypt(cipherText, encryptedKey.getBytes(UTF_8));
- ByteBuffer buffer = ByteBuffer.wrap(value);
- buffer.position(0);
- int typeId = buffer.getInt();
- EncryptedType type = EncryptedType.fromId(typeId);
- switch (type) {
- case STRING:
- int stringLength = buffer.getInt();
- ByteBuffer stringSlice = buffer.slice();
- buffer.limit(stringLength);
- String stringValue = UTF_8.decode(stringSlice).toString();
- if (stringValue.equals(NULL_VALUE)) {
- returnValue = null;
- } else {
- returnValue = stringValue;
- }
- break;
- case INT:
- returnValue = buffer.getInt();
- break;
- case LONG:
- returnValue = buffer.getLong();
- break;
- case FLOAT:
- returnValue = buffer.getFloat();
- break;
- case BOOLEAN:
- returnValue = buffer.get() != (byte) 0;
- break;
- case STRING_SET:
- ArraySet<String> stringSet = new ArraySet<>();
- while (buffer.hasRemaining()) {
- int subStringLength = buffer.getInt();
- ByteBuffer subStringSlice = buffer.slice();
- subStringSlice.limit(subStringLength);
- buffer.position(buffer.position() + subStringLength);
- stringSet.add(UTF_8.decode(subStringSlice).toString());
- }
- if (stringSet.size() == 1 && NULL_VALUE.equals(stringSet.valueAt(0))) {
- returnValue = null;
- } else {
- returnValue = stringSet;
- }
- break;
- }
+ if (encryptedValue == null) {
+ return null;
+ }
+
+ byte[] cipherText = Base64.decode(encryptedValue, Base64.DEFAULT);
+ byte[] value = mValueAead.decrypt(cipherText, encryptedKey.getBytes(UTF_8));
+ ByteBuffer buffer = ByteBuffer.wrap(value);
+ buffer.position(0);
+ int typeId = buffer.getInt();
+ EncryptedType type = EncryptedType.fromId(typeId);
+ if (type == null) {
+ throw new SecurityException("Unknown type ID for encrypted pref value: " + typeId);
+ }
+
+ switch (type) {
+ case STRING:
+ int stringLength = buffer.getInt();
+ ByteBuffer stringSlice = buffer.slice();
+ buffer.limit(stringLength);
+
+ String stringValue = UTF_8.decode(stringSlice).toString();
+ if (stringValue.equals(NULL_VALUE)) {
+ return null;
+ }
+
+ return stringValue;
+ case INT:
+ return buffer.getInt();
+ case LONG:
+ return buffer.getLong();
+ case FLOAT:
+ return buffer.getFloat();
+ case BOOLEAN:
+ return buffer.get() != (byte) 0;
+ case STRING_SET:
+ ArraySet<String> stringSet = new ArraySet<>();
+
+ while (buffer.hasRemaining()) {
+ int subStringLength = buffer.getInt();
+ ByteBuffer subStringSlice = buffer.slice();
+ subStringSlice.limit(subStringLength);
+ buffer.position(buffer.position() + subStringLength);
+ stringSet.add(UTF_8.decode(subStringSlice).toString());
+ }
+
+ if (stringSet.size() == 1 && NULL_VALUE.equals(stringSet.valueAt(0))) {
+ return null;
+ }
+
+ return stringSet;
+ default:
+ throw new SecurityException("Unhandled type for encrypted pref value: " + type);
}
} catch (GeneralSecurityException ex) {
throw new SecurityException("Could not decrypt value. " + ex.getMessage(), ex);
}
- return returnValue;
}
String encryptKey(String key) {