From 3854e2267487ecd129bdd0711c6d9dfbf8f7ed0d Mon Sep 17 00:00:00 2001 From: Jacky Cheung Date: Thu, 20 Oct 2016 13:55:21 -0700 Subject: [PATCH] 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 --- core/java/android/bluetooth/BluetoothGatt.java | 49 ++++++++++++++++---------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java index 9cfe4175b604..0fe2abf71402 100644 --- a/core/java/android/bluetooth/BluetoothGatt.java +++ b/core/java/android/bluetooth/BluetoothGatt.java @@ -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(); 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; } /** -- 2.11.0