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);