Rename KeymasterException to KeyStoreException.
The code in question talks to KeyStore which returns error codes
which are a mix of keystore and keymaster error codes. To better
match the layering of KeyStore on top of keystore and keymaster,
this CL renames KeymasterException into KeyStoreException. It also
adds human-readable error messages to exceptions raised by keystore
rather than keymaster (e.g., key not found).
Bug: 18088752
Change-Id: I4cd1235e16518c9f2e8c5557a457774c6e687b88
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 94a479b..84a664e 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -26,6 +26,7 @@
import android.security.keymaster.KeyCharacteristics;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterBlob;
+import android.security.keymaster.KeymasterDefs;
import android.security.keymaster.OperationResult;
import android.util.Log;
@@ -506,4 +507,57 @@
return SYSTEM_ERROR;
}
}
+
+ public static KeyStoreException getKeyStoreException(int errorCode) {
+ if (errorCode > 0) {
+ // KeyStore layer error
+ switch (errorCode) {
+ case NO_ERROR:
+ return new KeyStoreException(errorCode, "OK");
+ case LOCKED:
+ return new KeyStoreException(errorCode, "Keystore locked");
+ case UNINITIALIZED:
+ return new KeyStoreException(errorCode, "Keystore not initialized");
+ case SYSTEM_ERROR:
+ return new KeyStoreException(errorCode, "System error");
+ case PERMISSION_DENIED:
+ return new KeyStoreException(errorCode, "Permission denied");
+ case KEY_NOT_FOUND:
+ return new KeyStoreException(errorCode, "Key not found");
+ case VALUE_CORRUPTED:
+ return new KeyStoreException(errorCode, "Key blob corrupted");
+ default:
+ return new KeyStoreException(errorCode, String.valueOf(errorCode));
+ }
+ } else {
+ // Keymaster layer error
+ switch (errorCode) {
+ case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
+ // The name of this parameter significantly differs between Keymaster and
+ // framework APIs. Use the framework wording to make life easier for developers.
+ return new KeyStoreException(errorCode,
+ "Invalid user authentication validity duration");
+ default:
+ return new KeyStoreException(errorCode,
+ KeymasterDefs.getErrorMessage(errorCode));
+ }
+ }
+ }
+
+ public static CryptoOperationException getCryptoOperationException(KeyStoreException e) {
+ switch (e.getErrorCode()) {
+ case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
+ return new KeyExpiredException();
+ case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
+ return new KeyNotYetValidException();
+ case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
+ return new UserNotAuthenticatedException();
+ default:
+ return new CryptoOperationException("Crypto operation failed", e);
+ }
+ }
+
+ public static CryptoOperationException getCryptoOperationException(int errorCode) {
+ return getCryptoOperationException(getKeyStoreException(errorCode));
+ }
}
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index afb5e36..ec358d6 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -224,7 +224,7 @@
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getCryptoOperationException(opResult.resultCode);
+ throw KeyStore.getCryptoOperationException(opResult.resultCode);
}
if (opResult.token == null) {
@@ -250,8 +250,8 @@
byte[] output;
try {
output = mMainDataStreamer.update(input, inputOffset, inputLen);
- } catch (KeymasterException e) {
- throw KeymasterUtils.getCryptoOperationException(e);
+ } catch (KeyStoreException e) {
+ throw KeyStore.getCryptoOperationException(e);
}
if (output.length == 0) {
@@ -285,7 +285,7 @@
byte[] output;
try {
output = mMainDataStreamer.doFinal(input, inputOffset, inputLen);
- } catch (KeymasterException e) {
+ } catch (KeyStoreException e) {
switch (e.getErrorCode()) {
case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
throw new IllegalBlockSizeException();
@@ -294,7 +294,7 @@
case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
throw new AEADBadTagException();
default:
- throw KeymasterUtils.getCryptoOperationException(e);
+ throw KeyStore.getCryptoOperationException(e);
}
}
diff --git a/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java
index 993614b..1f8b7e4 100644
--- a/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/KeyStoreCryptoOperationChunkedStreamer.java
@@ -80,7 +80,7 @@
mMaxChunkSize = maxChunkSize;
}
- public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeymasterException {
+ public byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException {
if (inputLength == 0) {
// No input provided
return EMPTY_BYTE_ARRAY;
@@ -120,7 +120,7 @@
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getKeymasterException(opResult.resultCode);
+ throw KeyStore.getKeyStoreException(opResult.resultCode);
}
if (opResult.inputConsumed == chunk.length) {
@@ -188,7 +188,7 @@
}
public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
- throws KeymasterException {
+ throws KeyStoreException {
if (inputLength == 0) {
// No input provided -- simplify the rest of the code
input = EMPTY_BYTE_ARRAY;
@@ -203,7 +203,7 @@
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getKeymasterException(opResult.resultCode);
+ throw KeyStore.getKeyStoreException(opResult.resultCode);
}
return concat(output, opResult.output);
@@ -213,7 +213,7 @@
* Passes all of buffered input into the the KeyStore operation (via the {@code update}
* operation) and returns output.
*/
- public byte[] flush() throws KeymasterException {
+ public byte[] flush() throws KeyStoreException {
if (mBufferedLength <= 0) {
return EMPTY_BYTE_ARRAY;
}
@@ -227,7 +227,7 @@
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getKeymasterException(opResult.resultCode);
+ throw KeyStore.getKeyStoreException(opResult.resultCode);
}
if (opResult.inputConsumed < chunk.length) {
diff --git a/keystore/java/android/security/KeymasterException.java b/keystore/java/android/security/KeyStoreException.java
similarity index 78%
rename from keystore/java/android/security/KeymasterException.java
rename to keystore/java/android/security/KeyStoreException.java
index 484be12..88e768c 100644
--- a/keystore/java/android/security/KeymasterException.java
+++ b/keystore/java/android/security/KeyStoreException.java
@@ -17,15 +17,16 @@
package android.security;
/**
- * Keymaster exception.
+ * KeyStore/keymaster exception with positive error codes coming from the KeyStore and negative
+ * ones from keymaster.
*
* @hide
*/
-public class KeymasterException extends Exception {
+public class KeyStoreException extends Exception {
private final int mErrorCode;
- public KeymasterException(int errorCode, String message) {
+ public KeyStoreException(int errorCode, String message) {
super(message);
mErrorCode = errorCode;
}
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index 6d0e1ae..a5864a4 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -117,7 +117,7 @@
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getCryptoOperationException(opResult.resultCode);
+ throw KeyStore.getCryptoOperationException(opResult.resultCode);
}
if (opResult.token == null) {
throw new CryptoOperationException("Keystore returned null operation token");
@@ -141,8 +141,8 @@
byte[] output;
try {
output = mChunkedStreamer.update(input, offset, len);
- } catch (KeymasterException e) {
- throw KeymasterUtils.getCryptoOperationException(e);
+ } catch (KeyStoreException e) {
+ throw KeyStore.getCryptoOperationException(e);
}
if ((output != null) && (output.length != 0)) {
throw new CryptoOperationException("Update operation unexpectedly produced output");
@@ -156,8 +156,8 @@
byte[] result;
try {
result = mChunkedStreamer.doFinal(null, 0, 0);
- } catch (KeymasterException e) {
- throw KeymasterUtils.getCryptoOperationException(e);
+ } catch (KeyStoreException e) {
+ throw KeyStore.getCryptoOperationException(e);
}
engineReset();
diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
index 69533b4..c9c9bd8 100644
--- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java
@@ -173,7 +173,7 @@
int errorCode = mKeyStore.generateKey(
keyAliasInKeystore, args, additionalEntropy, flags, new KeyCharacteristics());
if (errorCode != KeyStore.NO_ERROR) {
- throw KeymasterUtils.getCryptoOperationException(errorCode);
+ throw KeyStore.getCryptoOperationException(errorCode);
}
String keyAlgorithmJCA =
KeyStoreKeyConstraints.Algorithm.toJCASecretKeyAlgorithm(mAlgorithm, mDigest);
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
index c426a34..3143d4d 100644
--- a/keystore/java/android/security/KeymasterUtils.java
+++ b/keystore/java/android/security/KeymasterUtils.java
@@ -17,7 +17,6 @@
package android.security;
import android.security.keymaster.KeyCharacteristics;
-import android.security.keymaster.KeymasterDefs;
import java.util.ArrayList;
import java.util.Date;
@@ -29,36 +28,6 @@
public abstract class KeymasterUtils {
private KeymasterUtils() {}
- public static KeymasterException getKeymasterException(int keymasterErrorCode) {
- switch (keymasterErrorCode) {
- case KeymasterDefs.KM_ERROR_INVALID_AUTHORIZATION_TIMEOUT:
- // The name of this parameter significantly differs between Keymaster and framework
- // APIs. Use the framework wording to make life easier for developers.
- return new KeymasterException(keymasterErrorCode,
- "Invalid user authentication validity duration");
- default:
- return new KeymasterException(keymasterErrorCode,
- KeymasterDefs.getErrorMessage(keymasterErrorCode));
- }
- }
-
- public static CryptoOperationException getCryptoOperationException(KeymasterException e) {
- switch (e.getErrorCode()) {
- case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
- return new KeyExpiredException();
- case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
- return new KeyNotYetValidException();
- case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
- return new UserNotAuthenticatedException();
- default:
- return new CryptoOperationException("Crypto operation failed", e);
- }
- }
-
- public static CryptoOperationException getCryptoOperationException(int keymasterErrorCode) {
- return getCryptoOperationException(getKeymasterException(keymasterErrorCode));
- }
-
public static Integer getInt(KeyCharacteristics keyCharacteristics, int tag) {
if (keyCharacteristics.hwEnforced.containsTag(tag)) {
return keyCharacteristics.hwEnforced.getInt(tag, -1);