Integrate IKeystoreAuthorization aidl's addAuthToken with Keystore SPI.

This CL introduces the Keystore SPI class for IKeystoreAuthorization
aidl interface and implements the calling code for addAuthToken method.

Bug: 166672367
Bug: 177830239
Bug: 177791435
Bug: 177787061
Bug: 177787180
Test: VTS test
Change-Id: I9f0adc97efadd0fa1a1f16dd5ec811f4151a2b03
This commit is contained in:
Hasini Gunasinghe
2020-12-04 17:46:20 +00:00
parent 3299d00b87
commit 5364fce817
4 changed files with 155 additions and 0 deletions

View File

@@ -483,6 +483,7 @@ java_library {
"android.hardware.vibrator-V1.2-java",
"android.hardware.vibrator-V1.3-java",
"android.security.apc-java",
"android.security.authorization-java",
"android.system.keystore2-java",
"android.system.suspend.control.internal-java",
"devicepolicyprotosnano",

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2020 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.annotation.NonNull;
import android.hardware.security.keymint.HardwareAuthToken;
import android.hardware.security.keymint.Timestamp;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* @hide This Utils class provides method(s) for AuthToken conversion.
*/
public class AuthTokenUtils {
private AuthTokenUtils(){
}
/**
* Build a HardwareAuthToken from a byte array
* @param array byte array representing an auth token
* @return HardwareAuthToken representation of an auth token
*/
public static @NonNull HardwareAuthToken toHardwareAuthToken(@NonNull byte[] array) {
final HardwareAuthToken hardwareAuthToken = new HardwareAuthToken();
// First byte is version, which does not exist in HardwareAuthToken anymore
// Next 8 bytes is the challenge.
hardwareAuthToken.challenge =
ByteBuffer.wrap(array, 1, 8).order(ByteOrder.nativeOrder()).getLong();
// Next 8 bytes is the userId
hardwareAuthToken.userId =
ByteBuffer.wrap(array, 9, 8).order(ByteOrder.nativeOrder()).getLong();
// Next 8 bytes is the authenticatorId.
hardwareAuthToken.authenticatorId =
ByteBuffer.wrap(array, 17, 8).order(ByteOrder.nativeOrder()).getLong();
// while the other fields are in machine byte order, authenticatorType and timestamp
// are in network byte order.
// Next 4 bytes is the authenticatorType.
hardwareAuthToken.authenticatorType =
ByteBuffer.wrap(array, 25, 4).order(ByteOrder.BIG_ENDIAN).getInt();
// Next 8 bytes is the timestamp.
final Timestamp timestamp = new Timestamp();
timestamp.milliSeconds =
ByteBuffer.wrap(array, 29, 8).order(ByteOrder.BIG_ENDIAN).getLong();
hardwareAuthToken.timestamp = timestamp;
// Last 32 bytes is the mac, 37:69
hardwareAuthToken.mac = new byte[32];
System.arraycopy(array, 37 /* srcPos */,
hardwareAuthToken.mac,
0 /* destPos */,
32 /* length */);
return hardwareAuthToken;
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright (C) 2020 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.annotation.NonNull;
import android.hardware.security.keymint.HardwareAuthToken;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceSpecificException;
import android.security.authorization.IKeystoreAuthorization;
import android.system.keystore2.ResponseCode;
import android.util.Log;
/**
* @hide This is the client side for IKeystoreAuthorization AIDL.
* It shall only be used by biometric authentication providers and Gatekeeper.
*/
public class Authorization {
private static final String TAG = "KeystoreAuthorization";
private static IKeystoreAuthorization sIKeystoreAuthorization;
public static final int SYSTEM_ERROR = ResponseCode.SYSTEM_ERROR;
public Authorization() {
sIKeystoreAuthorization = null;
}
private static synchronized IKeystoreAuthorization getService() {
if (sIKeystoreAuthorization == null) {
sIKeystoreAuthorization = IKeystoreAuthorization.Stub.asInterface(
ServiceManager.checkService("android.security.authorization"));
}
return sIKeystoreAuthorization;
}
/**
* Adds an auth token to keystore2.
*
* @param authToken created by Android authenticators.
* @return 0 if successful or {@code ResponseCode.SYSTEM_ERROR}.
*/
public int addAuthToken(@NonNull HardwareAuthToken authToken) {
if (!android.security.keystore2.AndroidKeyStoreProvider.isInstalled()) return 0;
try {
getService().addAuthToken(authToken);
return 0;
} catch (RemoteException e) {
Log.w(TAG, "Can not connect to keystore", e);
return SYSTEM_ERROR;
} catch (ServiceSpecificException e) {
return e.errorCode;
}
}
/**
* Add an auth token to Keystore 2.0 in the legacy serialized auth token format.
* @param authToken
* @return 0 if successful or a {@code ResponseCode}.
*/
public int addAuthToken(@NonNull byte[] authToken) {
return addAuthToken(AuthTokenUtils.toHardwareAuthToken(authToken));
}
}

View File

@@ -996,6 +996,7 @@ public class KeyStore {
*/
public int addAuthToken(byte[] authToken) {
try {
new Authorization().addAuthToken(authToken);
return mBinder.addAuthToken(authToken);
} catch (RemoteException e) {
Log.w(TAG, "Cannot connect to keystore", e);