Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b008f09 authored by Jacky Cheung's avatar Jacky Cheung
Browse files

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
parent 71019735
Loading
Loading
Loading
Loading
+31 −18
Original line number Diff line number Diff line
@@ -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;
    }

    /**