Gradually increase the level of authentication on failed GATT operations.
When lower layer returns insufficient authentication or insufficient encryption on various GATT operations, gradually retry with increased authentication level first to AUTHENTICATION_NO_MITM, then AUTHENTICATION_MITM. Test: ported from internal branch. Change-Id: I6bcc4198ca493b7900ddd166a81d30cde896fa86
This commit is contained in:
@@ -45,14 +45,18 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
private IBluetoothGatt mService;
|
||||
private BluetoothGattCallback mCallback;
|
||||
private int mClientIf;
|
||||
private boolean mAuthRetry = false;
|
||||
private BluetoothDevice mDevice;
|
||||
private boolean mAutoConnect;
|
||||
private int mAuthRetryState;
|
||||
private int mConnState;
|
||||
private final Object mStateLock = new Object();
|
||||
private Boolean mDeviceBusy = false;
|
||||
private int mTransport;
|
||||
|
||||
private static final int AUTH_RETRY_STATE_IDLE = 0;
|
||||
private static final int AUTH_RETRY_STATE_NO_MITM = 1;
|
||||
private static final int AUTH_RETRY_STATE_MITM = 2;
|
||||
|
||||
private static final int CONN_STATE_IDLE = 0;
|
||||
private static final int CONN_STATE_CONNECTING = 1;
|
||||
private static final int CONN_STATE_CONNECTED = 2;
|
||||
@@ -260,17 +264,19 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
|
||||
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|
||||
|| status == GATT_INSUFFICIENT_ENCRYPTION)
|
||||
&& mAuthRetry == false) {
|
||||
&& (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
|
||||
try {
|
||||
mAuthRetry = true;
|
||||
mService.readCharacteristic(mClientIf, address, handle, AUTHENTICATION_MITM);
|
||||
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
|
||||
AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
|
||||
mService.readCharacteristic(mClientIf, address, handle, authReq);
|
||||
mAuthRetryState++;
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,"",e);
|
||||
}
|
||||
}
|
||||
|
||||
mAuthRetry = false;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
|
||||
BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
|
||||
if (characteristic == null) {
|
||||
@@ -309,19 +315,20 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
|
||||
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|
||||
|| status == GATT_INSUFFICIENT_ENCRYPTION)
|
||||
&& mAuthRetry == false) {
|
||||
&& (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
|
||||
try {
|
||||
mAuthRetry = true;
|
||||
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
|
||||
AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
|
||||
mService.writeCharacteristic(mClientIf, address, handle,
|
||||
characteristic.getWriteType(), AUTHENTICATION_MITM,
|
||||
characteristic.getValue());
|
||||
characteristic.getWriteType(), authReq, characteristic.getValue());
|
||||
mAuthRetryState++;
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,"",e);
|
||||
}
|
||||
}
|
||||
|
||||
mAuthRetry = false;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
|
||||
try {
|
||||
mCallback.onCharacteristicWrite(BluetoothGatt.this, characteristic, status);
|
||||
@@ -376,17 +383,19 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
|
||||
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|
||||
|| status == GATT_INSUFFICIENT_ENCRYPTION)
|
||||
&& mAuthRetry == false) {
|
||||
&& (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
|
||||
try {
|
||||
mAuthRetry = true;
|
||||
mService.readDescriptor(mClientIf, address, handle, AUTHENTICATION_MITM);
|
||||
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
|
||||
AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
|
||||
mService.readDescriptor(mClientIf, address, handle, authReq);
|
||||
mAuthRetryState++;
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,"",e);
|
||||
}
|
||||
}
|
||||
|
||||
mAuthRetry = true;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
|
||||
try {
|
||||
mCallback.onDescriptorRead(BluetoothGatt.this, descriptor, status);
|
||||
@@ -415,18 +424,20 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
|
||||
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
|
||||
|| status == GATT_INSUFFICIENT_ENCRYPTION)
|
||||
&& mAuthRetry == false) {
|
||||
&& (mAuthRetryState != AUTH_RETRY_STATE_MITM)) {
|
||||
try {
|
||||
mAuthRetry = true;
|
||||
final int authReq = (mAuthRetryState == AUTH_RETRY_STATE_IDLE) ?
|
||||
AUTHENTICATION_NO_MITM : AUTHENTICATION_MITM;
|
||||
mService.writeDescriptor(mClientIf, address, handle,
|
||||
AUTHENTICATION_MITM, descriptor.getValue());
|
||||
authReq, descriptor.getValue());
|
||||
mAuthRetryState++;
|
||||
return;
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG,"",e);
|
||||
}
|
||||
}
|
||||
|
||||
mAuthRetry = false;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
|
||||
try {
|
||||
mCallback.onDescriptorWrite(BluetoothGatt.this, descriptor, status);
|
||||
@@ -501,6 +512,7 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
mServices = new ArrayList<BluetoothGattService>();
|
||||
|
||||
mConnState = CONN_STATE_IDLE;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -514,6 +526,7 @@ public final class BluetoothGatt implements BluetoothProfile {
|
||||
|
||||
unregisterApp();
|
||||
mConnState = CONN_STATE_CLOSED;
|
||||
mAuthRetryState = AUTH_RETRY_STATE_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user