am 33c9dde9
: Merge "Add KeyPermanentlyInvalidatedException." into mnc-dev
* commit '33c9dde90d480fe457295dde37baa730d0cbc819': Add KeyPermanentlyInvalidatedException.
This commit is contained in:
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
||||
|
Reference in New Issue
Block a user