mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-12 10:55:49 +01:00
Display toast on authentication failures
This commit is contained in:
parent
76d633cde6
commit
4926f449ec
@ -220,7 +220,10 @@ public class CmfCharacteristic {
|
||||
return;
|
||||
}
|
||||
} catch (final GeneralSecurityException e) {
|
||||
LOG.error("Failed to decrypt payload for {}", cmd, e);
|
||||
LOG.error("Failed to decrypt payload for {} ({}/{})", cmd, String.format("0x%04x", cmd1), String.format("0x%04x", cmd2), e);
|
||||
if (cmd == CmfCommand.AUTH_FAILED) {
|
||||
handler.onCommand(cmd, new byte[0]);
|
||||
}
|
||||
if (chunkCount > 1) {
|
||||
chunkBuffers.remove(cmd);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ public enum CmfCommand {
|
||||
AUTH_PAIR_REQUEST(0xffff, 0x8047),
|
||||
AUTH_PHONE_NAME(0xffff, 0x8049),
|
||||
AUTH_WATCH_MAC(0xffff, 0x0049),
|
||||
AUTH_FAILED(0xffff, 0xa061),
|
||||
AUTHENTICATED_CONFIRM_REPLY(0xffff, 0x0004),
|
||||
AUTHENTICATED_CONFIRM_REQUEST(0xffff, 0x804d),
|
||||
BATTERY(0x005c, 0x0001),
|
||||
|
@ -24,6 +24,7 @@ import android.content.SharedPreferences;
|
||||
import android.media.AudioManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -41,6 +42,7 @@ import java.util.TimeZone;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.devicesettings.DeviceSettingsPreferenceConst;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
|
||||
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventFindPhone;
|
||||
@ -219,6 +221,14 @@ public class CmfWatchProSupport extends AbstractBTLEDeviceSupport implements Cmf
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case AUTH_FAILED:
|
||||
LOG.error("Authentication failed, disconnecting");
|
||||
GB.toast(getContext(), R.string.authentication_failed_check_key, Toast.LENGTH_LONG, GB.WARN);
|
||||
final GBDevice device = getDevice();
|
||||
if (device != null) {
|
||||
GBApplication.deviceService(device).disconnect();
|
||||
}
|
||||
return;
|
||||
case AUTH_WATCH_MAC:
|
||||
LOG.debug("Got auth watch mac, requesting nonce");
|
||||
sendCommand("auth request nonce", CmfCommand.AUTH_NONCE_REQUEST, A5);
|
||||
|
@ -38,6 +38,7 @@ import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEOperation;
|
||||
@ -114,30 +115,34 @@ public class InitOperation extends AbstractBTLEOperation<HuamiSupport> {
|
||||
public boolean onCharacteristicChanged(BluetoothGatt gatt,
|
||||
BluetoothGattCharacteristic characteristic) {
|
||||
UUID characteristicUUID = characteristic.getUuid();
|
||||
if (HuamiService.UUID_CHARACTERISTIC_AUTH.equals(characteristicUUID)) {
|
||||
try {
|
||||
byte[] value = characteristic.getValue();
|
||||
huamiSupport.logMessageContent(value);
|
||||
if (value[0] == HuamiService.AUTH_RESPONSE &&
|
||||
value[1] == HuamiService.AUTH_SEND_KEY &&
|
||||
value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
TransactionBuilder builder = createTransactionBuilder("Sending the secret key to the device");
|
||||
builder.write(characteristic, requestAuthNumber());
|
||||
huamiSupport.performImmediately(builder);
|
||||
} else if (value[0] == HuamiService.AUTH_RESPONSE &&
|
||||
(value[1] & 0x0f) == HuamiService.AUTH_REQUEST_RANDOM_AUTH_NUMBER &&
|
||||
value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
byte[] eValue = handleAESAuth(value, getSecretKey());
|
||||
byte[] responseValue = org.apache.commons.lang3.ArrayUtils.addAll(
|
||||
new byte[]{(byte) (HuamiService.AUTH_SEND_ENCRYPTED_AUTH_NUMBER | cryptFlags), authFlags}, eValue);
|
||||
if (!HuamiService.UUID_CHARACTERISTIC_AUTH.equals(characteristicUUID)) {
|
||||
LOG.info("Unhandled characteristic changed: {}", characteristicUUID);
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
|
||||
TransactionBuilder builder = createTransactionBuilder("Sending the encrypted random key to the device");
|
||||
builder.write(characteristic, responseValue);
|
||||
huamiSupport.setCurrentTimeWithService(builder);
|
||||
huamiSupport.performImmediately(builder);
|
||||
} else if (value[0] == HuamiService.AUTH_RESPONSE &&
|
||||
(value[1] & 0x0f) == HuamiService.AUTH_SEND_ENCRYPTED_AUTH_NUMBER &&
|
||||
value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
try {
|
||||
final byte[] value = characteristic.getValue();
|
||||
huamiSupport.logMessageContent(value);
|
||||
if (value[0] != HuamiService.AUTH_RESPONSE) {
|
||||
LOG.warn("Got a non-response: {}", GB.hexdump(value));
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
|
||||
if (value[1] == HuamiService.AUTH_SEND_KEY && value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
TransactionBuilder builder = createTransactionBuilder("Sending the secret key to the device");
|
||||
builder.write(characteristic, requestAuthNumber());
|
||||
huamiSupport.performImmediately(builder);
|
||||
} else if ((value[1] & 0x0f) == HuamiService.AUTH_REQUEST_RANDOM_AUTH_NUMBER && value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
byte[] eValue = handleAESAuth(value, getSecretKey());
|
||||
byte[] responseValue = org.apache.commons.lang3.ArrayUtils.addAll(
|
||||
new byte[]{(byte) (HuamiService.AUTH_SEND_ENCRYPTED_AUTH_NUMBER | cryptFlags), authFlags}, eValue);
|
||||
|
||||
TransactionBuilder builder = createTransactionBuilder("Sending the encrypted random key to the device");
|
||||
builder.write(characteristic, responseValue);
|
||||
huamiSupport.setCurrentTimeWithService(builder);
|
||||
huamiSupport.performImmediately(builder);
|
||||
} else if ((value[1] & 0x0f) == HuamiService.AUTH_SEND_ENCRYPTED_AUTH_NUMBER) {
|
||||
if (value[2] == HuamiService.AUTH_SUCCESS) {
|
||||
TransactionBuilder builder = createTransactionBuilder("Authenticated, now initialize phase 2");
|
||||
builder.add(new SetDeviceStateAction(getDevice(), GBDevice.State.INITIALIZING, getContext()));
|
||||
huamiSupport.enableFurtherNotifications(builder, true);
|
||||
@ -146,17 +151,23 @@ public class InitOperation extends AbstractBTLEOperation<HuamiSupport> {
|
||||
huamiSupport.phase3Initialize(builder);
|
||||
huamiSupport.setInitialized(builder);
|
||||
huamiSupport.performImmediately(builder);
|
||||
} else if (value[2] == HuamiService.AUTH_FAIL) {
|
||||
LOG.error("Authentication failed, disconnecting");
|
||||
GB.toast(getContext(), R.string.authentication_failed_check_key, Toast.LENGTH_LONG, GB.WARN);
|
||||
final GBDevice device = getDevice();
|
||||
if (device != null) {
|
||||
GBApplication.deviceService(device).disconnect();
|
||||
}
|
||||
} else {
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
GB.toast(getContext(), "Error authenticating Huami device", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
} else {
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
LOG.info("Unhandled characteristic changed: " + characteristicUUID);
|
||||
return super.onCharacteristicChanged(gatt, characteristic);
|
||||
} catch (Exception e) {
|
||||
GB.toast(getContext(), "Error authenticating Huami device", Toast.LENGTH_LONG, GB.ERROR, e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private byte[] handleAESAuth(byte[] value, byte[] secretKey) throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException, IllegalBlockSizeException {
|
||||
|
@ -21,6 +21,7 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService.SU
|
||||
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -29,6 +30,8 @@ import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.Huami2021Service;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.huami.HuamiService;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
@ -193,10 +196,15 @@ public class InitOperation2021 extends InitOperation implements Huami2021Handler
|
||||
} catch (Exception e) {
|
||||
LOG.error("failed initializing device", e);
|
||||
}
|
||||
return;
|
||||
} else if (payload[0] == RESPONSE && payload[1] == 0x05 && payload[2] == 0x25) {
|
||||
LOG.error("Authentication failed, disconnecting");
|
||||
GB.toast(getContext(), R.string.authentication_failed_check_key, Toast.LENGTH_LONG, GB.WARN);
|
||||
final GBDevice device = getDevice();
|
||||
if (device != null) {
|
||||
GBApplication.deviceService(device).disconnect();
|
||||
}
|
||||
} else {
|
||||
LOG.info("Unhandled auth payload: {}", GB.hexdump(payload));
|
||||
return;
|
||||
LOG.warn("Unhandled auth payload: {}", GB.hexdump(payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
@ -47,6 +48,7 @@ import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.BuildConfig;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.proto.xiaomi.XiaomiProto;
|
||||
import nodomain.freeyourgadget.gadgetbridge.service.devices.xiaomi.services.AbstractXiaomiService;
|
||||
@ -116,6 +118,7 @@ public class XiaomiAuthService extends AbstractXiaomiService {
|
||||
final XiaomiProto.Command command = handleWatchNonce(cmd.getAuth().getWatchNonce());
|
||||
|
||||
if (command == null) {
|
||||
GB.toast(getSupport().getContext(), R.string.authentication_failed_check_key, Toast.LENGTH_LONG, GB.WARN);
|
||||
LOG.error("handleWatchNonce returned null, disconnecting");
|
||||
final GBDevice device = getSupport().getDevice();
|
||||
|
||||
@ -142,7 +145,13 @@ public class XiaomiAuthService extends AbstractXiaomiService {
|
||||
|
||||
getSupport().onAuthSuccess();
|
||||
} else {
|
||||
LOG.warn("could not authenticate");
|
||||
LOG.warn("Authentication failed, subtype={}, status={}", cmd.getSubtype(), cmd.getStatus());
|
||||
GB.toast(getSupport().getContext(), R.string.authentication_failed_check_key, Toast.LENGTH_LONG, GB.WARN);
|
||||
|
||||
final GBDevice device = getSupport().getDevice();
|
||||
if (device != null) {
|
||||
GBApplication.deviceService(device).disconnect();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import android.text.SpannableString;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
@ -446,6 +447,10 @@ public class GB {
|
||||
toast(context, message, displayTime, severity, null);
|
||||
}
|
||||
|
||||
public static void toast(final Context context, @StringRes final int message, final int displayTime, final int severity) {
|
||||
toast(context, context.getString(message), displayTime, severity, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and display a Toast message using the application context
|
||||
* Can be called from any thread.
|
||||
|
@ -1137,6 +1137,7 @@
|
||||
<string name="activity_prefs_chart_min_session_length">Minimal activity length (minutes)</string>
|
||||
<string name="authenticating">Authenticating</string>
|
||||
<string name="authentication_required">Authentication required</string>
|
||||
<string name="authentication_failed_check_key">Authentication failed, please check auth key</string>
|
||||
<string name="activity_prefs_sleep_duration">Preferred sleep duration in hours</string>
|
||||
<string name="device_hw">Hardware revision: %1$s</string>
|
||||
<string name="device_fw">Firmware version: %1$s</string>
|
||||
|
Loading…
Reference in New Issue
Block a user