blob: 0f5e031277d45175f98a7137aea922ed311eb260 [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.car.trust;
import android.bluetooth.BluetoothDevice;
import android.util.Log;
import com.android.car.Utils;
import com.android.internal.annotations.GuardedBy;
import java.io.PrintWriter;
/**
* A service that interacts with the Trust Agent {@link CarBleTrustAgent} and a comms (BLE) service
* {@link CarTrustAgentBleManager} to receive the necessary credentials to authenticate
* an Android user.
*/
public class CarTrustAgentUnlockService {
private static final String TAG = "CarTrustAgentUnlock";
private final CarTrustedDeviceService mTrustedDeviceService;
private final CarTrustAgentBleManager mCarTrustAgentBleManager;
private CarTrustAgentUnlockDelegate mUnlockDelegate;
// Locks
private final Object mTokenLock = new Object();
private final Object mHandleLock = new Object();
private final Object mDeviceLock = new Object();
@GuardedBy("mTokenLock")
private byte[] mUnlockToken;
@GuardedBy("mHandleLock")
private byte[] mUnlockHandle;
@GuardedBy("mDeviceLock")
private BluetoothDevice mRemoteUnlockDevice;
CarTrustAgentUnlockService(CarTrustedDeviceService service,
CarTrustAgentBleManager bleService) {
mTrustedDeviceService = service;
mCarTrustAgentBleManager = bleService;
}
/**
* The interface that an unlock delegate has to implement to get the auth credentials from
* the unlock service.
*/
interface CarTrustAgentUnlockDelegate {
/**
* Called when the Unlock service has the auth credentials to pass.
*
* @param user user being authorized
* @param token escrow token for the user
* @param handle the handle corresponding to the escrow token
*/
void onUnlockDataReceived(int user, byte[] token, long handle);
}
/**
* Set a delegate that implements {@link CarTrustAgentUnlockDelegate}. The delegate will be
* handed the auth related data (token and handle) when it is received from the remote
* trusted device. The delegate is expected to use that to authorize the user.
*/
void setUnlockRequestDelegate(CarTrustAgentUnlockDelegate delegate) {
mUnlockDelegate = delegate;
}
/**
* Start Unlock Advertising
*/
void startUnlockAdvertising() {
mTrustedDeviceService.getCarTrustAgentEnrollmentService().stopEnrollmentAdvertising();
stopUnlockAdvertising();
mCarTrustAgentBleManager.startUnlockAdvertising();
}
/**
* Stop unlock advertising
*/
void stopUnlockAdvertising() {
mCarTrustAgentBleManager.stopUnlockAdvertising();
// Also disconnect from the peer.
if (mRemoteUnlockDevice != null) {
mCarTrustAgentBleManager.disconnectRemoteDevice(mRemoteUnlockDevice);
}
}
void init() {
mCarTrustAgentBleManager.setupUnlockBleServer();
}
void release() {
synchronized (mDeviceLock) {
mRemoteUnlockDevice = null;
}
}
void onRemoteDeviceConnected(BluetoothDevice device) {
synchronized (mDeviceLock) {
if (mRemoteUnlockDevice != null) {
// TBD, return when this is encountered?
Log.e(TAG, "Unexpected: Cannot connect to another device when already connected");
}
mRemoteUnlockDevice = device;
}
}
void onRemoteDeviceDisconnected(BluetoothDevice device) {
// sanity checking
if (!device.equals(mRemoteUnlockDevice) && device.getAddress() != null) {
Log.e(TAG, "Disconnected from an unknown device:" + device.getAddress());
}
synchronized (mDeviceLock) {
mRemoteUnlockDevice = null;
}
}
void onUnlockTokenReceived(byte[] value) {
synchronized (mTokenLock) {
mUnlockToken = value;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Unlock Token: " + mUnlockToken);
}
if (mUnlockToken == null || mUnlockHandle == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Unlock Handle not available yet");
}
return;
}
if (mUnlockDelegate == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "No Unlock delegate");
}
return;
}
mUnlockDelegate.onUnlockDataReceived(
mTrustedDeviceService.getUserHandleByTokenHandle(Utils.bytesToLong(mUnlockHandle)),
mUnlockToken,
Utils.bytesToLong(mUnlockHandle));
synchronized (mTokenLock) {
mUnlockToken = null;
}
synchronized (mHandleLock) {
mUnlockHandle = null;
}
}
void onUnlockHandleReceived(byte[] value) {
synchronized (mHandleLock) {
mUnlockHandle = value;
}
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Unlock Handle: " + mUnlockHandle);
}
if (mUnlockToken == null || mUnlockHandle == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Unlock Token not available yet");
}
return;
}
if (mUnlockDelegate == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "No Unlock delegate");
}
return;
}
mUnlockDelegate.onUnlockDataReceived(
mTrustedDeviceService.getUserHandleByTokenHandle(Utils.bytesToLong(mUnlockHandle)),
mUnlockToken,
Utils.bytesToLong(mUnlockHandle));
synchronized (mUnlockToken) {
mUnlockToken = null;
}
synchronized (mHandleLock) {
mUnlockHandle = null;
}
}
void dump(PrintWriter writer) {
}
}