Merge "Cleanup logic for per-op auth keys." into mnc-dev
This commit is contained in:
@@ -22,6 +22,7 @@ import android.security.keymaster.KeymasterDefs;
|
||||
import android.security.keymaster.OperationResult;
|
||||
|
||||
import java.security.AlgorithmParameters;
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
@@ -298,38 +299,36 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry
|
||||
mAdditionalEntropyForBegin = null;
|
||||
if (opResult == null) {
|
||||
throw new KeyStoreConnectException();
|
||||
} else if ((opResult.resultCode != KeyStore.NO_ERROR)
|
||||
&& (opResult.resultCode != KeyStore.OP_AUTH_NEEDED)) {
|
||||
switch (opResult.resultCode) {
|
||||
case KeymasterDefs.KM_ERROR_INVALID_NONCE:
|
||||
throw new InvalidAlgorithmParameterException("Invalid IV");
|
||||
}
|
||||
throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
|
||||
}
|
||||
|
||||
if (opResult.token == null) {
|
||||
throw new IllegalStateException("Keystore returned null operation token");
|
||||
}
|
||||
// The operation handle/token is now either valid for use immediately or needs to be
|
||||
// authorized through user authentication (if the error code was OP_AUTH_NEEDED).
|
||||
// Store operation token and handle regardless of the error code returned by KeyStore to
|
||||
// ensure that the operation gets aborted immediately if the code below throws an exception.
|
||||
mOperationToken = opResult.token;
|
||||
mOperationHandle = opResult.operationHandle;
|
||||
|
||||
// If necessary, throw an exception due to KeyStore operation having failed.
|
||||
GeneralSecurityException e = KeyStoreCryptoOperationUtils.getExceptionForCipherInit(
|
||||
mKeyStore, mKey, opResult.resultCode);
|
||||
if (e != null) {
|
||||
if (e instanceof InvalidKeyException) {
|
||||
throw (InvalidKeyException) e;
|
||||
} else if (e instanceof InvalidAlgorithmParameterException) {
|
||||
throw (InvalidAlgorithmParameterException) e;
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected exception type", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (mOperationToken == null) {
|
||||
throw new IllegalStateException("Keystore returned null operation token");
|
||||
}
|
||||
|
||||
loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
|
||||
mFirstOperationInitiated = true;
|
||||
mIvHasBeenUsed = true;
|
||||
mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
||||
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
|
||||
mKeyStore, opResult.token));
|
||||
|
||||
if (opResult.resultCode != KeyStore.NO_ERROR) {
|
||||
// The operation requires user authentication. Check whether such authentication is
|
||||
// possible (e.g., the key may have been permanently invalidated).
|
||||
InvalidKeyException e =
|
||||
mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
|
||||
if (!(e instanceof UserNotAuthenticatedException)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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 android.security.keymaster.KeymasterDefs;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
|
||||
/**
|
||||
* Assorted utility methods for implementing crypto operations on top of KeyStore.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
abstract class KeyStoreCryptoOperationUtils {
|
||||
private KeyStoreCryptoOperationUtils() {}
|
||||
|
||||
/**
|
||||
* Returns the {@link InvalidKeyException} to be thrown by the {@code init} method of
|
||||
* the crypto operation in response to {@code KeyStore.begin} operation or {@code null} if
|
||||
* the {@code init} method should succeed.
|
||||
*/
|
||||
static InvalidKeyException getInvalidKeyExceptionForInit(
|
||||
KeyStore keyStore, KeyStoreKey key, int beginOpResultCode) {
|
||||
if (beginOpResultCode == KeyStore.NO_ERROR) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// An error occured. However, some errors should not lead to init throwing an exception.
|
||||
// See below.
|
||||
InvalidKeyException e =
|
||||
keyStore.getInvalidKeyException(key.getAlias(), beginOpResultCode);
|
||||
switch (beginOpResultCode) {
|
||||
case KeyStore.OP_AUTH_NEEDED:
|
||||
// Operation needs to be authorized by authenticating the user. Don't throw an
|
||||
// exception is such authentication is possible for this key
|
||||
// (UserNotAuthenticatedException). An example of when it's not possible is where
|
||||
// the key is permanently invalidated (KeyPermanentlyInvalidatedException).
|
||||
if (e instanceof UserNotAuthenticatedException) {
|
||||
return null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exception to be thrown by the {@code Cipher.init} method of the crypto operation
|
||||
* in response to {@code KeyStore.begin} operation or {@code null} if the {@code init} method
|
||||
* should succeed.
|
||||
*/
|
||||
static GeneralSecurityException getExceptionForCipherInit(
|
||||
KeyStore keyStore, KeyStoreKey key, int beginOpResultCode) {
|
||||
if (beginOpResultCode == KeyStore.NO_ERROR) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Cipher-specific cases
|
||||
switch (beginOpResultCode) {
|
||||
case KeymasterDefs.KM_ERROR_INVALID_NONCE:
|
||||
return new InvalidAlgorithmParameterException("Invalid IV");
|
||||
}
|
||||
|
||||
// General cases
|
||||
return getInvalidKeyExceptionForInit(keyStore, key, beginOpResultCode);
|
||||
}
|
||||
}
|
||||
@@ -170,31 +170,27 @@ public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOp
|
||||
keymasterOutputArgs);
|
||||
if (opResult == null) {
|
||||
throw new KeyStoreConnectException();
|
||||
} else if ((opResult.resultCode != KeyStore.NO_ERROR)
|
||||
&& (opResult.resultCode != KeyStore.OP_AUTH_NEEDED)) {
|
||||
throw mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
|
||||
}
|
||||
|
||||
if (opResult.token == null) {
|
||||
throw new IllegalStateException("Keystore returned null operation token");
|
||||
}
|
||||
// The operation handle/token is now either valid for use immediately or needs to be
|
||||
// authorized through user authentication (if the error code was OP_AUTH_NEEDED).
|
||||
// Store operation token and handle regardless of the error code returned by KeyStore to
|
||||
// ensure that the operation gets aborted immediately if the code below throws an exception.
|
||||
mOperationToken = opResult.token;
|
||||
mOperationHandle = opResult.operationHandle;
|
||||
|
||||
// If necessary, throw an exception due to KeyStore operation having failed.
|
||||
InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(
|
||||
mKeyStore, mKey, opResult.resultCode);
|
||||
if (e != null) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (mOperationToken == null) {
|
||||
throw new IllegalStateException("Keystore returned null operation token");
|
||||
}
|
||||
|
||||
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
||||
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
|
||||
mKeyStore, mOperationToken));
|
||||
|
||||
if (opResult.resultCode != KeyStore.NO_ERROR) {
|
||||
// The operation requires user authentication. Check whether such authentication is
|
||||
// possible (e.g., the key may have been permanently invalidated).
|
||||
InvalidKeyException e =
|
||||
mKeyStore.getInvalidKeyException(mKey.getAlias(), opResult.resultCode);
|
||||
if (!(e instanceof UserNotAuthenticatedException)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
55
keystore/java/android/security/KeyStoreKey.java
Normal file
55
keystore/java/android/security/KeyStoreKey.java
Normal file
@@ -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.Key;
|
||||
|
||||
/**
|
||||
* {@link Key} backed by AndroidKeyStore.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class KeyStoreKey implements Key {
|
||||
private final String mAlias;
|
||||
private final String mAlgorithm;
|
||||
|
||||
public KeyStoreKey(String alias, String algorithm) {
|
||||
mAlias = alias;
|
||||
mAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
String getAlias() {
|
||||
return mAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return mAlgorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormat() {
|
||||
// This key does not export its key material
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// This key does not export its key material
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -23,33 +23,9 @@ import javax.crypto.SecretKey;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class KeyStoreSecretKey implements SecretKey {
|
||||
private final String mAlias;
|
||||
private final String mAlgorithm;
|
||||
public class KeyStoreSecretKey extends KeyStoreKey implements SecretKey {
|
||||
|
||||
public KeyStoreSecretKey(String alias, String algorithm) {
|
||||
mAlias = alias;
|
||||
mAlgorithm = algorithm;
|
||||
}
|
||||
|
||||
String getAlias() {
|
||||
return mAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAlgorithm() {
|
||||
return mAlgorithm;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFormat() {
|
||||
// This key does not export its key material
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] getEncoded() {
|
||||
// This key does not export its key material
|
||||
return null;
|
||||
super(alias, algorithm);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user