blob: 0f5e031277d45175f98a7137aea922ed311eb260 [file] [log] [blame]
Ram Periathiruvadide0ca082019-03-20 11:16:44 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.car.trust;
18
19import android.bluetooth.BluetoothDevice;
20import android.util.Log;
21
22import com.android.car.Utils;
23import com.android.internal.annotations.GuardedBy;
24
25import java.io.PrintWriter;
26
27/**
28 * A service that interacts with the Trust Agent {@link CarBleTrustAgent} and a comms (BLE) service
29 * {@link CarTrustAgentBleManager} to receive the necessary credentials to authenticate
30 * an Android user.
31 */
32public class CarTrustAgentUnlockService {
33 private static final String TAG = "CarTrustAgentUnlock";
34 private final CarTrustedDeviceService mTrustedDeviceService;
35 private final CarTrustAgentBleManager mCarTrustAgentBleManager;
36 private CarTrustAgentUnlockDelegate mUnlockDelegate;
37 // Locks
38 private final Object mTokenLock = new Object();
39 private final Object mHandleLock = new Object();
40 private final Object mDeviceLock = new Object();
41
42 @GuardedBy("mTokenLock")
43 private byte[] mUnlockToken;
44 @GuardedBy("mHandleLock")
45 private byte[] mUnlockHandle;
46 @GuardedBy("mDeviceLock")
47 private BluetoothDevice mRemoteUnlockDevice;
48
49 CarTrustAgentUnlockService(CarTrustedDeviceService service,
50 CarTrustAgentBleManager bleService) {
51 mTrustedDeviceService = service;
52 mCarTrustAgentBleManager = bleService;
53 }
54
55 /**
56 * The interface that an unlock delegate has to implement to get the auth credentials from
57 * the unlock service.
58 */
59 interface CarTrustAgentUnlockDelegate {
60 /**
61 * Called when the Unlock service has the auth credentials to pass.
62 *
63 * @param user user being authorized
64 * @param token escrow token for the user
65 * @param handle the handle corresponding to the escrow token
66 */
67 void onUnlockDataReceived(int user, byte[] token, long handle);
68 }
69
70 /**
71 * Set a delegate that implements {@link CarTrustAgentUnlockDelegate}. The delegate will be
72 * handed the auth related data (token and handle) when it is received from the remote
73 * trusted device. The delegate is expected to use that to authorize the user.
74 */
75 void setUnlockRequestDelegate(CarTrustAgentUnlockDelegate delegate) {
76 mUnlockDelegate = delegate;
77 }
78
79 /**
80 * Start Unlock Advertising
81 */
82 void startUnlockAdvertising() {
83 mTrustedDeviceService.getCarTrustAgentEnrollmentService().stopEnrollmentAdvertising();
84 stopUnlockAdvertising();
85 mCarTrustAgentBleManager.startUnlockAdvertising();
86 }
87
88 /**
89 * Stop unlock advertising
90 */
91 void stopUnlockAdvertising() {
92 mCarTrustAgentBleManager.stopUnlockAdvertising();
93 // Also disconnect from the peer.
94 if (mRemoteUnlockDevice != null) {
95 mCarTrustAgentBleManager.disconnectRemoteDevice(mRemoteUnlockDevice);
96 }
97 }
98
99 void init() {
100 mCarTrustAgentBleManager.setupUnlockBleServer();
101 }
102
103 void release() {
104 synchronized (mDeviceLock) {
105 mRemoteUnlockDevice = null;
106 }
107 }
108
109 void onRemoteDeviceConnected(BluetoothDevice device) {
110 synchronized (mDeviceLock) {
111 if (mRemoteUnlockDevice != null) {
112 // TBD, return when this is encountered?
113 Log.e(TAG, "Unexpected: Cannot connect to another device when already connected");
114 }
115 mRemoteUnlockDevice = device;
116 }
117 }
118
119 void onRemoteDeviceDisconnected(BluetoothDevice device) {
120 // sanity checking
121 if (!device.equals(mRemoteUnlockDevice) && device.getAddress() != null) {
122 Log.e(TAG, "Disconnected from an unknown device:" + device.getAddress());
123 }
124 synchronized (mDeviceLock) {
125 mRemoteUnlockDevice = null;
126 }
127 }
128
129 void onUnlockTokenReceived(byte[] value) {
130 synchronized (mTokenLock) {
131 mUnlockToken = value;
132 }
133 if (Log.isLoggable(TAG, Log.DEBUG)) {
134 Log.d(TAG, "Unlock Token: " + mUnlockToken);
135 }
136 if (mUnlockToken == null || mUnlockHandle == null) {
137 if (Log.isLoggable(TAG, Log.DEBUG)) {
138 Log.d(TAG, "Unlock Handle not available yet");
139 }
140 return;
141 }
142 if (mUnlockDelegate == null) {
143 if (Log.isLoggable(TAG, Log.DEBUG)) {
144 Log.d(TAG, "No Unlock delegate");
145 }
146 return;
147 }
148 mUnlockDelegate.onUnlockDataReceived(
149 mTrustedDeviceService.getUserHandleByTokenHandle(Utils.bytesToLong(mUnlockHandle)),
150 mUnlockToken,
151 Utils.bytesToLong(mUnlockHandle));
152
153 synchronized (mTokenLock) {
154 mUnlockToken = null;
155 }
156 synchronized (mHandleLock) {
157 mUnlockHandle = null;
158 }
159 }
160
161 void onUnlockHandleReceived(byte[] value) {
162 synchronized (mHandleLock) {
163 mUnlockHandle = value;
164 }
165 if (Log.isLoggable(TAG, Log.DEBUG)) {
166 Log.d(TAG, "Unlock Handle: " + mUnlockHandle);
167 }
168 if (mUnlockToken == null || mUnlockHandle == null) {
169 if (Log.isLoggable(TAG, Log.DEBUG)) {
170 Log.d(TAG, "Unlock Token not available yet");
171 }
172 return;
173 }
174
175 if (mUnlockDelegate == null) {
176 if (Log.isLoggable(TAG, Log.DEBUG)) {
177 Log.d(TAG, "No Unlock delegate");
178 }
179 return;
180 }
181 mUnlockDelegate.onUnlockDataReceived(
182 mTrustedDeviceService.getUserHandleByTokenHandle(Utils.bytesToLong(mUnlockHandle)),
183 mUnlockToken,
184 Utils.bytesToLong(mUnlockHandle));
185
186 synchronized (mUnlockToken) {
187 mUnlockToken = null;
188 }
189 synchronized (mHandleLock) {
190 mUnlockHandle = null;
191 }
192 }
193
194 void dump(PrintWriter writer) {
195 }
196}