summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Klyubin <klyubin@google.com>2015-04-30 00:01:59 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-04-30 00:01:59 +0000
commit789d9dc733d4a3a15e83eb2aa0e49f548fe81618 (patch)
treee7f5b72eff167f8b7f480c62adb85c72b90b53f2
parent850c1888f5855b340e8e26c4d7bc0580644dbcb8 (diff)
parent33c9dde90d480fe457295dde37baa730d0cbc819 (diff)
downloadframeworks_base-789d9dc733d4a3a15e83eb2aa0e49f548fe81618.zip
frameworks_base-789d9dc733d4a3a15e83eb2aa0e49f548fe81618.tar.gz
frameworks_base-789d9dc733d4a3a15e83eb2aa0e49f548fe81618.tar.bz2
am 33c9dde9: Merge "Add KeyPermanentlyInvalidatedException." into mnc-dev
* commit '33c9dde90d480fe457295dde37baa730d0cbc819': Add KeyPermanentlyInvalidatedException.
-rw-r--r--api/current.txt11
-rw-r--r--api/system-current.txt11
-rw-r--r--core/java/android/security/keymaster/KeyCharacteristics.java22
-rw-r--r--keystore/java/android/security/GateKeeper.java8
-rw-r--r--keystore/java/android/security/KeyPermanentlyInvalidatedException.java55
-rw-r--r--keystore/java/android/security/KeyStore.java73
-rw-r--r--keystore/java/android/security/KeyStoreCipherSpi.java2
-rw-r--r--keystore/java/android/security/KeyStoreHmacSpi.java2
-rw-r--r--keystore/java/android/security/KeymasterUtils.java20
-rw-r--r--keystore/java/android/security/NewFingerprintEnrolledException.java41
-rw-r--r--keystore/java/android/security/UserNotAuthenticatedException.java2
11 files changed, 164 insertions, 83 deletions
diff --git a/api/current.txt b/api/current.txt
index bc4931b..f67270e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28616,6 +28616,12 @@ package android.security {
method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
+ public class KeyPermanentlyInvalidatedException extends java.security.InvalidKeyException {
+ ctor public KeyPermanentlyInvalidatedException();
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String);
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String, java.lang.Throwable);
+ }
+
public abstract class KeyStoreKeyProperties {
}
@@ -28696,11 +28702,6 @@ package android.security {
method public boolean isCleartextTrafficPermitted();
}
- public class NewFingerprintEnrolledException extends java.security.InvalidKeyException {
- ctor public NewFingerprintEnrolledException();
- ctor public NewFingerprintEnrolledException(java.lang.String);
- }
-
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
ctor public UserNotAuthenticatedException();
ctor public UserNotAuthenticatedException(java.lang.String);
diff --git a/api/system-current.txt b/api/system-current.txt
index 503ccba..bac38d9 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -30629,6 +30629,12 @@ package android.security {
method public android.security.KeyPairGeneratorSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
}
+ public class KeyPermanentlyInvalidatedException extends java.security.InvalidKeyException {
+ ctor public KeyPermanentlyInvalidatedException();
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String);
+ ctor public KeyPermanentlyInvalidatedException(java.lang.String, java.lang.Throwable);
+ }
+
public abstract class KeyStoreKeyProperties {
}
@@ -30709,11 +30715,6 @@ package android.security {
method public boolean isCleartextTrafficPermitted();
}
- public class NewFingerprintEnrolledException extends java.security.InvalidKeyException {
- ctor public NewFingerprintEnrolledException();
- ctor public NewFingerprintEnrolledException(java.lang.String);
- }
-
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
ctor public UserNotAuthenticatedException();
ctor public UserNotAuthenticatedException(java.lang.String);
diff --git a/core/java/android/security/keymaster/KeyCharacteristics.java b/core/java/android/security/keymaster/KeyCharacteristics.java
index 458f153..03248e5 100644
--- a/core/java/android/security/keymaster/KeyCharacteristics.java
+++ b/core/java/android/security/keymaster/KeyCharacteristics.java
@@ -87,6 +87,28 @@ public class KeyCharacteristics implements Parcelable {
return result;
}
+ public Long getLong(int tag) {
+ if (hwEnforced.containsTag(tag)) {
+ return hwEnforced.getLong(tag, -1);
+ } else if (swEnforced.containsTag(tag)) {
+ return swEnforced.getLong(tag, -1);
+ } else {
+ return null;
+ }
+ }
+
+ public long getLong(int tag, long defaultValue) {
+ Long result = getLong(tag);
+ return (result != null) ? result : defaultValue;
+ }
+
+ public List<Long> getLongs(int tag) {
+ List<Long> result = new ArrayList<Long>();
+ result.addAll(hwEnforced.getLongs(tag));
+ result.addAll(swEnforced.getLongs(tag));
+ return result;
+ }
+
public Date getDate(int tag) {
Date result = hwEnforced.getDate(tag, null);
if (result == null) {
diff --git a/keystore/java/android/security/GateKeeper.java b/keystore/java/android/security/GateKeeper.java
index c9f06e9..5617836 100644
--- a/keystore/java/android/security/GateKeeper.java
+++ b/keystore/java/android/security/GateKeeper.java
@@ -15,13 +15,17 @@ public abstract class GateKeeper {
private GateKeeper() {}
public static IGateKeeperService getService() {
- return IGateKeeperService.Stub.asInterface(
+ IGateKeeperService service = IGateKeeperService.Stub.asInterface(
ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
+ if (service == null) {
+ throw new IllegalStateException("Gatekeeper service not available");
+ }
+ return service;
}
public static long getSecureUserId() throws IllegalStateException {
try {
- return GateKeeper.getService().getSecureUserId(UserHandle.myUserId());
+ return getService().getSecureUserId(UserHandle.myUserId());
} catch (RemoteException e) {
throw new IllegalStateException(
"Failed to obtain secure user ID from gatekeeper", e);
diff --git a/keystore/java/android/security/KeyPermanentlyInvalidatedException.java b/keystore/java/android/security/KeyPermanentlyInvalidatedException.java
new file mode 100644
index 0000000..229eab0
--- /dev/null
+++ b/keystore/java/android/security/KeyPermanentlyInvalidatedException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security;
+
+import java.security.InvalidKeyException;
+
+/**
+ * Indicates that the key can no longer be used because it has been permanently invalidated.
+ *
+ * <p>This can currently occur only for keys that require user authentication. Such keys are
+ * permanently invalidated once the secure lock screen is disabled (i.e., reconfigured to None,
+ * Swipe or other mode which does not authenticate the user) or when the secure lock screen is
+ * forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user
+ * authentication for every use of the key are also permanently invalidated once a new fingerprint
+ * is enrolled or once no more fingerprints are enrolled.
+ */
+public class KeyPermanentlyInvalidatedException extends InvalidKeyException {
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} without detail message and cause.
+ */
+ public KeyPermanentlyInvalidatedException() {
+ super("Key permanently invalidated");
+ }
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} with the provided detail message
+ * and no cause.
+ */
+ public KeyPermanentlyInvalidatedException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new {@code KeyPermanentlyInvalidatedException} with the provided detail message
+ * and cause.
+ */
+ public KeyPermanentlyInvalidatedException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 5d863c2..f3b447e 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -18,6 +18,8 @@ package android.security;
import com.android.org.conscrypt.NativeConstants;
+import android.content.Context;
+import android.hardware.fingerprint.IFingerprintService;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
@@ -31,6 +33,7 @@ import android.security.keymaster.OperationResult;
import android.util.Log;
import java.security.InvalidKeyException;
+import java.util.List;
import java.util.Locale;
/**
@@ -490,7 +493,8 @@ public class KeyStore {
/**
* Check if the operation referenced by {@code token} is currently authorized.
*
- * @param token An operation token returned by a call to {@link KeyStore.begin}.
+ * @param token An operation token returned by a call to
+ * {@link #begin(String, int, boolean, KeymasterArguments, byte[], KeymasterArguments) begin}.
*/
public boolean isOperationAuthorized(IBinder token) {
try {
@@ -561,27 +565,80 @@ public class KeyStore {
* Returns an {@link InvalidKeyException} corresponding to the provided
* {@link KeyStoreException}.
*/
- static InvalidKeyException getInvalidKeyException(KeyStoreException e) {
+ InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, 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();
- // TODO: Handle TBD Keymaster error code "invalid key: new fingerprint enrolled"
- // case KeymasterDefs.KM_ERROR_TBD
- // return new NewFingerprintEnrolledException();
+ {
+ // We now need to determine whether the key/operation can become usable if user
+ // authentication is performed, or whether it can never become usable again.
+ // User authentication requirements are contained in the key's characteristics. We
+ // need to check whether these requirements can be be satisfied by asking the user
+ // to authenticate.
+ KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
+ int getKeyCharacteristicsErrorCode =
+ getKeyCharacteristics(keystoreKeyAlias, null, null, keyCharacteristics);
+ if (getKeyCharacteristicsErrorCode != NO_ERROR) {
+ return new InvalidKeyException(
+ "Failed to obtained key characteristics",
+ getKeyStoreException(getKeyCharacteristicsErrorCode));
+ }
+ List<Long> keySids =
+ keyCharacteristics.getLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
+ if (keySids.isEmpty()) {
+ // Key is not bound to any SIDs -- no amount of authentication will help here.
+ return new KeyPermanentlyInvalidatedException();
+ }
+ long rootSid = GateKeeper.getSecureUserId();
+ if ((rootSid != 0) && (keySids.contains(Long.valueOf(rootSid)))) {
+ // One of the key's SIDs is the current root SID -- user can be authenticated
+ // against that SID.
+ return new UserNotAuthenticatedException();
+ }
+
+ long fingerprintOnlySid = getFingerprintOnlySid();
+ if ((fingerprintOnlySid != 0)
+ && (keySids.contains(Long.valueOf(fingerprintOnlySid)))) {
+ // One of the key's SIDs is the current fingerprint SID -- user can be
+ // authenticated against that SID.
+ return new UserNotAuthenticatedException();
+ }
+
+ // None of the key's SIDs can ever be authenticated
+ return new KeyPermanentlyInvalidatedException();
+ }
default:
return new InvalidKeyException("Keystore operation failed", e);
}
}
+ private static long getFingerprintOnlySid() {
+ IFingerprintService service = IFingerprintService.Stub.asInterface(
+ ServiceManager.getService(Context.FINGERPRINT_SERVICE));
+ if (service == null) {
+ return 0;
+ }
+
+ try {
+ long deviceId = 0; // TODO: plumb hardware id to FPMS
+ if (!service.isHardwareDetected(deviceId)) {
+ return 0;
+ }
+
+ return service.getAuthenticatorId();
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to communicate with fingerprint service", e);
+ }
+ }
+
/**
* Returns an {@link InvalidKeyException} corresponding to the provided keystore/keymaster error
* code.
*/
- static InvalidKeyException getInvalidKeyException(int errorCode) {
- return getInvalidKeyException(getKeyStoreException(errorCode));
+ InvalidKeyException getInvalidKeyException(String keystoreKeyAlias, int errorCode) {
+ return getInvalidKeyException(keystoreKeyAlias, getKeyStoreException(errorCode));
}
}
diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java
index 3b13e83..9393e32 100644
--- a/keystore/java/android/security/KeyStoreCipherSpi.java
+++ b/keystore/java/android/security/KeyStoreCipherSpi.java
@@ -303,7 +303,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
case KeymasterDefs.KM_ERROR_INVALID_NONCE:
throw new InvalidAlgorithmParameterException("Invalid IV");
}
- throw KeyStore.getInvalidKeyException(opResult.resultCode);
+ throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
}
if (opResult.token == null) {
diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java
index 175369c..8d71d1d 100644
--- a/keystore/java/android/security/KeyStoreHmacSpi.java
+++ b/keystore/java/android/security/KeyStoreHmacSpi.java
@@ -169,7 +169,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
- throw KeyStore.getInvalidKeyException(opResult.resultCode);
+ throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
}
if (opResult.token == null) {
throw new IllegalStateException("Keystore returned null operation token");
diff --git a/keystore/java/android/security/KeymasterUtils.java b/keystore/java/android/security/KeymasterUtils.java
index 7bf5475..3ccb588 100644
--- a/keystore/java/android/security/KeymasterUtils.java
+++ b/keystore/java/android/security/KeymasterUtils.java
@@ -18,12 +18,8 @@ package android.security;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.UserHandle;
import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
-import android.service.gatekeeper.IGateKeeperService;
import libcore.util.EmptyArray;
@@ -347,20 +343,6 @@ public abstract class KeymasterUtils {
return result;
}
- private static long getRootSid() {
- IGateKeeperService gatekeeperService = IGateKeeperService.Stub.asInterface(
- ServiceManager.getService("android.service.gatekeeper.IGateKeeperService"));
- if (gatekeeperService == null) {
- throw new IllegalStateException("Gatekeeper service not available");
- }
-
- try {
- return gatekeeperService.getSecureUserId(UserHandle.myUserId());
- } catch (RemoteException e) {
- throw new IllegalStateException("Failed to obtain root SID");
- }
- }
-
/**
* Adds keymaster arguments to express the key's authorization policy supported by user
* authentication.
@@ -402,7 +384,7 @@ public abstract class KeymasterUtils {
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
- long rootSid = getRootSid();
+ long rootSid = GateKeeper.getSecureUserId();
if (rootSid == 0) {
throw new IllegalStateException("Secure lock screen must be enabled"
+ " to create keys requiring user authentication");
diff --git a/keystore/java/android/security/NewFingerprintEnrolledException.java b/keystore/java/android/security/NewFingerprintEnrolledException.java
deleted file mode 100644
index 4fe210b..0000000
--- a/keystore/java/android/security/NewFingerprintEnrolledException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security;
-
-import java.security.InvalidKeyException;
-
-/**
- * Indicates that a cryptographic operation could not be performed because the key used by the
- * operation is permanently invalid because a new fingerprint was enrolled.
- */
-public class NewFingerprintEnrolledException extends InvalidKeyException {
-
- /**
- * Constructs a new {@code NewFingerprintEnrolledException} without detail message and cause.
- */
- public NewFingerprintEnrolledException() {
- super("Invalid key: new fingerprint enrolled");
- }
-
- /**
- * Constructs a new {@code NewFingerprintEnrolledException} with the provided detail message and
- * no cause.
- */
- public NewFingerprintEnrolledException(String message) {
- super(message);
- }
-}
diff --git a/keystore/java/android/security/UserNotAuthenticatedException.java b/keystore/java/android/security/UserNotAuthenticatedException.java
index 66f4dd8..2954fa7 100644
--- a/keystore/java/android/security/UserNotAuthenticatedException.java
+++ b/keystore/java/android/security/UserNotAuthenticatedException.java
@@ -20,7 +20,7 @@ import java.security.InvalidKeyException;
/**
* Indicates that a cryptographic operation could not be performed because the user has not been
- * authenticated recently enough.
+ * authenticated recently enough. Authenticating the user will resolve this issue.
*/
public class UserNotAuthenticatedException extends InvalidKeyException {