Version exchange for enrollment and unlock
- Implement version exchange
- reset encryption state when IHU is connected/disconnected/unlocked for
unlock
Bug: 132448677
Test: Manully tested on IHU with companion app built from cl/250791145
Change-Id: I68bf850b903e7ba415072029281081baf813321b
diff --git a/service/proto/ble_version_exchange.proto b/service/proto/ble_version_exchange.proto
index e6c47f1..28ef351 100644
--- a/service/proto/ble_version_exchange.proto
+++ b/service/proto/ble_version_exchange.proto
@@ -6,9 +6,16 @@
option java_outer_classname = "VersionExchangeProto";
message BLEVersionExchange {
- // Required.
- int32 minSupportedVersion = 1;
+ // Minimum supported protobuf version.
+ int32 minSupportedMessagingVersion = 1;
- // Required.
- int32 maxSupportedVersion = 2;
+ // Maximum supported protobuf version.
+ int32 maxSupportedMessagingVersion = 2;
+
+ // Minimum supported version of the encryption engine.
+ int32 minSupportedSecurityVersion = 3;
+
+ // Maximum supported version of the encryption engine.
+ int32 maxSupportedSecurityVersion = 4;
+
}
diff --git a/service/src/com/android/car/trust/CarTrustAgentBleManager.java b/service/src/com/android/car/trust/CarTrustAgentBleManager.java
index 8517c98..718bd22 100644
--- a/service/src/com/android/car/trust/CarTrustAgentBleManager.java
+++ b/service/src/com/android/car/trust/CarTrustAgentBleManager.java
@@ -33,10 +33,12 @@
import com.android.car.BLEStreamProtos.BLEMessageProto.BLEMessage;
import com.android.car.BLEStreamProtos.BLEOperationProto.OperationType;
+import com.android.car.BLEStreamProtos.VersionExchangeProto.BLEVersionExchange;
import com.android.car.CarLocalServices;
import com.android.car.R;
import com.android.car.Utils;
+import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
@@ -99,6 +101,10 @@
private BluetoothGattService mUnlockGattService;
private BLEMessagePayloadStream mBleMessagePayloadStream = new BLEMessagePayloadStream();
+ // This is a boolean because there's only one supported version.
+ private boolean mIsVersionExchanged;
+ private static final int MESSAGING_VERSION = 1;
+ private static final int SECURITY_VERSION = 1;
CarTrustAgentBleManager(Context context) {
super(context);
@@ -116,6 +122,11 @@
&& device.getName() == null) {
retrieveDeviceName(device);
}
+
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Reset mIsVersionExchanged to false.");
+ }
+ mIsVersionExchanged = false;
getTrustedDeviceService().onRemoteDeviceConnected(device);
}
@@ -124,6 +135,10 @@
if (getTrustedDeviceService() != null) {
getTrustedDeviceService().onRemoteDeviceDisconnected(device);
}
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Reset mIsVersionExchanged to false.");
+ }
+ mIsVersionExchanged = false;
}
@Override
@@ -146,6 +161,19 @@
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "onCharacteristicWrite received uuid: " + uuid);
}
+ if (!mIsVersionExchanged) {
+ if (uuid.equals(mEnrollmentClientWriteUuid)) {
+ resolveBLEVersion(device, value, mEnrollmentGattService
+ .getCharacteristic(mEnrollmentServerWriteUuid));
+ } else if (uuid.equals(mUnlockClientWriteUuid)) {
+ resolveBLEVersion(device, value, mUnlockGattService
+ .getCharacteristic(mUnlockServerWriteUuid));
+ } else {
+ Log.e(TAG, "Invalid UUID, disconnect remote device.");
+ disconnectRemoteDevice();
+ }
+ return;
+ }
// This write operation is not thread safe individually, but is guarded by the callback
// here.
mBleMessagePayloadStream.write(value);
@@ -230,6 +258,44 @@
return mRandomName;
}
+ private void resolveBLEVersion(BluetoothDevice device, byte[] value,
+ BluetoothGattCharacteristic characteristic) {
+ BLEVersionExchange versionExchange;
+ try {
+ versionExchange = BLEVersionExchange.parseFrom(value);
+ } catch (IOException e) {
+ disconnectRemoteDevice();
+ Log.e(TAG, "Could not parse version exchange message", e);
+ return;
+ }
+ int minMessagingVersion = versionExchange.getMinSupportedMessagingVersion();
+ int minSecurityVersion = versionExchange.getMinSupportedSecurityVersion();
+ // The supported versions for the communication and security protocol.
+ // Only v1 is supported at this time.
+ // TODO:(b/134094617) get supported versions from BleMessageFactory
+ if (minMessagingVersion != MESSAGING_VERSION || minSecurityVersion != SECURITY_VERSION) {
+ Log.e(TAG, "No supported version (minMessagingVersion: " + minMessagingVersion
+ + ", minSecurityVersion" + minSecurityVersion + ")");
+ disconnectRemoteDevice();
+ return;
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Resolved version to (minMessagingVersion: " + minMessagingVersion
+ + ", minSecurityVersion" + minSecurityVersion + ")");
+ }
+ BLEVersionExchange headUnitVersion = BLEVersionExchange.newBuilder()
+ .setMinSupportedMessagingVersion(MESSAGING_VERSION)
+ .setMaxSupportedMessagingVersion(MESSAGING_VERSION)
+ .setMinSupportedSecurityVersion(SECURITY_VERSION)
+ .setMinSupportedSecurityVersion(SECURITY_VERSION)
+ .build();
+ setValueOnCharacteristicAndNotify(device, headUnitVersion.toByteArray(), characteristic);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Sent supported versioned to the phone.");
+ }
+ mIsVersionExchanged = true;
+ }
+
/**
* Setup the BLE GATT server for Enrollment. The GATT server for Enrollment comprises of one
* GATT Service and 2 characteristics - one for the phone to write to and one for the head unit
@@ -378,6 +444,7 @@
/**
* Sends the given message to the specified device and characteristic.
+ * The message will be splited into multiple messages wrapped in BLEMessage proto.
*
* @param device The device to send the message to.
* @param characteristic The characteristic to write to.
@@ -401,11 +468,16 @@
for (BLEMessage bleMessage : bleMessages) {
// TODO(b/131719066) get acknowledgement from the phone then continue to send packets
- characteristic.setValue(bleMessage.toByteArray());
- notifyCharacteristicChanged(device, characteristic, false);
+ setValueOnCharacteristicAndNotify(device, bleMessage.toByteArray(), characteristic);
}
}
+ void setValueOnCharacteristicAndNotify(BluetoothDevice device, byte[] message,
+ BluetoothGattCharacteristic characteristic) {
+ characteristic.setValue(message);
+ notifyCharacteristicChanged(device, characteristic, false);
+ }
+
private final AdvertiseCallback mEnrollmentAdvertisingCallback = new AdvertiseCallback() {
@Override
public void onStartSuccess(AdvertiseSettings settingsInEffect) {
diff --git a/service/src/com/android/car/trust/CarTrustAgentUnlockService.java b/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
index 1151c4e..2e57b62 100644
--- a/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
+++ b/service/src/com/android/car/trust/CarTrustAgentUnlockService.java
@@ -243,6 +243,7 @@
queueMessageForLog("onRemoteDeviceConnected (addr:" + device.getAddress() + ")");
mRemoteUnlockDevice = device;
}
+ resetEncryptionState();
mCurrentUnlockState = UNLOCK_STATE_WAITING_FOR_UNIQUE_ID;
}
@@ -255,6 +256,7 @@
synchronized (mDeviceLock) {
mRemoteUnlockDevice = null;
}
+ resetEncryptionState();
mCurrentUnlockState = UNLOCK_STATE_WAITING_FOR_UNIQUE_ID;
}
@@ -570,6 +572,7 @@
synchronized (mHandleLock) {
mUnlockHandle = null;
}
+ resetEncryptionState();
}
void dump(PrintWriter writer) {