Skip to content

Instantly share code, notes, and snippets.

@psolyca
Last active April 23, 2024 19:37
Show Gist options
  • Save psolyca/68fdfee0960737c1234f8d7f7a6c143a to your computer and use it in GitHub Desktop.
Save psolyca/68fdfee0960737c1234f8d7f7a6c143a to your computer and use it in GitHub Desktop.
Honor Band 4 RE

Introduction

Lots of works have been made to communicate with the Honor Band 3/4 in order to be used with GadgetBridge.
RE is followed in issue 1021 BTW, communication where not complete and the RE was done on BLE LPv2.
A new protocol LPv3 appeared.

Goal

RE the LPv3 BLE protocol and integrate Honor devices in GadgetBridge.

Keys

Version

BLE LPv3 appeared in Huawei Health 10.0.1.319 (HH) but LPv2 is used (For Honor Band 3 as this is the only band I have).
btsdk_sharedpreferences_name1.xml, btsdk_sharedpreferences_name2.xml and btsdk_sharedpreferences_name3.xml disappeared in HH 10.0.1.319.
LPv3 appeared on firmware 1.0.10.60 (I have 1.0.10.78). 25/09/21 : It seems recent bands use protocol version 2 (frame analyze) but LPv3 keys. 13/12/21 : Key depends on the auth version and not the protocol version.

Where to find them ?

LPv2 keys are present in libwhiteBoxJniLib.so (they were present before 10.0.1.319 but not used).
LPv3 keys are also in libwhiteBoxJniLib.so.
LPv2 keys are divided in 3 parts in libwhiteBoxJniLib.so.

  • Key1
    • part1 @00012350 : 6f 75 6a 79 6d 77 00 00
    • part2 @0001c384 : 71 34 63 6c 76 00
    • part3 @0001c739 : 39 33 37 38 79 00
  • Key2
    • part1 @00012348 : 62 31 30 6a 67 66 00 00
    • part2 @0001c38a : 64 39 79 37 76 00
    • part3 @0001c73f : 73 75 64 61 39 00

LPv3 keys are not divided in libwhiteBoxJniLib.so.

  • Key1 @0001bdbd : 35 35 20 35 33 20 38 36 20 46 43 20 36 33 20 32 30 20 30 37 20 41 41 20 38 36 20 34 39 20 33 35 20 32 32 20 42 38 20 36 41 20 45 32 20 35 43 00
  • Key2 @0001c390 : 33 33 20 30 37 20 39 42 20 43 35 20 37 41 20 38 38 20 36 44 20 33 43 20 46 35 20 36 31 20 33 37 20 30 39 20 36 46 20 32 32 20 38 30 20 30 30 00

But, thanks to @tuxuser thinking, these strings could be ASCII representation of the keys (to be checked) aka :

  • Key1 : 55 53 86 FC 63 20 07 AA 86 49 35 22 B8 6A E2 5C
  • Key2 : 33 07 9B C5 7A 88 6D 3C F5 61 37 09 6F 22 80 00

Finally these keys are:

  1. auth version 1 : 6f 75 6a 79 6d 77 71 34 63 6c 76 39 33 37 38 79 and 62 31 30 6a 67 66 64 39 79 37 76 73 75 64 61 39
  2. auth version 2 and 3 : 55 53 86 FC 63 20 07 AA 86 49 35 22 B8 6A E2 5C and 33 07 9B C5 7A 88 6D 3C F5 61 37 09 6F 22 80 00

There seems to be more keys in 3 main arrays in libwhiteBoxJniLib.so but I did not find there use yet.

  • Array1 @0001bb40
  • Array2 @0001be87 (Pointer @00110cc0)
  • Array3 @0001c477 (Pointer @00110d40)
  • Array of data with keys : @000122fc (Key1 and Key2 part 1 are here)

Final secret is stored in btsdk_sharedpreferences_name4.xml. This is not the main key (see below)

  • Before HH 10.0.1.319, the final key is stored as plain text.
  • After HH 10.0.1.319, the final key is crypted and the class containing the key EncryptData is serialized.

Master key

This applies to parsing logs from official HH app not from direct connection using https://github.com/psolyca/huawei-lpv2/blob/master/band_lpv2.py

From log

In version <11.0.4.517, master key could be reversed and find using the bonding key in Packet(service_id=1, command_id=7..).
Bonding key is the master key crypted with a secret key composed of Key1, Key2 and a key derivated from the server MAC address (aka the band). Thus, the reverse is "easy".
In version >=11.0.4.517, Packet(service_id=1, command_id=7..) is crypted, thus the bonding key is crypted and no way to reverse it. Something has changed between versions, MAC address used to be able to decrypt the packet differ from one version to another, before it was the client MAC, after it was the device MAC (to be confirmed).

From Android

There is other potential way to get master key of the device.
The key in btsdk_sharedpreferences_name4.xml is crypted with a key which is stored in Android KeyStore of the device. Getting the key from Android KeyStore...

From iOS

I do not own any iOS phone but it should be equivalent to Android in term of keys.

Crypting / Decrypting

Same as zyv works for both LPv2 and LPv3.

Bluetooth

Protocol

Reference to huawei/protocol.py
As stated, packages could be non sliced or sliced but could also be split to 256 bytes due to bluetooth maximum frame size.
The protocol has been changed to handle the partial message, sliced or not. On sliced packets, the second field (XX) is the index. 0x03 is the last one so used to check for complete message. the third field (YY) is always Unknown.

Connection and communication

In "human" readable terms, here is the way to connect and communicate to the band.

Specifications

GATT characteristics

The GATT characteristic to send the message is 0x0000fe01, the one which is received is 0x0000fe02. Some other characteristics exists 0x0000fe03 (notify) and 0x0000fe04 (unknown) but not explored yet.

Values

Values associated with the GATT characteristic are passed following a specific scheme.
More information on this scheme has already been described by @zyv in his wiki page. Also, services and commands send and received by the band/watch are described here and in Services.

Connection

Connection and pairing to band/watch is done like others BLE devices. After connecting and getting basic GATT characteristics, there is a handshake process to be completly bond to the band/watch and then everything is crypted.

Handshake is done in 4 steps:

  1. Requesting link parameters, service_id=1, command_id=1
  2. Requesting authentification, service_id=1, command_id=19
  3. Requesting bond parameters, service_id=1, command_id=15
  4. Requesting bond, service_id=1, command_id=14

Needed information for each step:

  1. Nothing
  2. Server nonce from step #1 and client nonce (generated by the app)
  3. Client serial (made from client MAC) and client MAC
  4. Client serial, device MAC (getting from pairing or connection), master key and iv (both generated by the app)

Authentification

A digest message is used to check the authentification.
This message differ for each auth version.

  1. auth version 1 : 70 FB 6C 24 03 5F DB 55 2F 38 89 8A EE DE 3F 69
  2. auth version 2 : 93 AC DE F7 6A CB 09 85 7D BF E5 26 1A AB CD 78
  3. auth version 3 : 9C 27 63 A9 CC E1 34 76 6D E3 FF 61 18 20 05 53

Communication

All communications are crypted with the master key and an Initial Vector (IV) To crypt messages sent from the app/phone, we use the Client Nonce as IV.
To uncrypt messages received from the device, we use the Server Nonce as IV, this one is sent with the message (tag=125).

Services

From HH dissassemble
Number of services : 46
Number of commands : ...
New ID added :

  • Service ID: 1
    • Command ID : 2 - SupportedServices
      • 1: Services
      • 2: ActiveServices
    • Command ID: 3 - SupportedCommands
      • 2: ServiceId
      • 3: Commands
      • 4: ActiveCommands
      • 129: SupportedCommands
    • Command ID: 7
      • 12: ProductName
      • 14: ForceSN
      • 17: CertificatModel
      • 21: HiLinkProductID
      • 22: ProductManufacture
    • Command ID: 11 - deleteDeviceAvoidDisturbingInfo
    • Command ID: 12 - onResponse (addDeviceAvoidDisturbingInfo)
    • Command ID: 14
      • 9:
    • Command ID: 16 - HandsetInfo
    • Command ID: 18 - SupportedActivity
      • 2: Activity
      • 3: SupportHeartRate
      • 129: SupportedActivity
    • Command ID: 22
      • 0: NoDualPhone
      • 1: CurentConnected
      • 2: HasBeenConnected
      • 3: DoublePhoneSituation
      • 127: NotifyDeviceOperation
    • Command ID: 23
    • Command ID: 24
    • Command ID: 25
    • Command ID: 29 - RequestDNDStatus
      • 1
    • Command ID: 33 - getDefaultSwitch
    • Command ID: 34
    • Command ID: 35
    • Command ID: 36
  • Service ID: 2
    • Command ID: 2 - NotificationConstraint
    • Command ID: 4 - NotificationEnable
    • Command ID: 5 - Capability
    • Command ID: 6 - deleteMsgToTLVS
      • 1: PromptPush
    • Command ID: 7
  • Service ID: 3
    • Command ID: 1 - setContact
    • Command ID: 2
  • Service ID: 7 - Fitness
    • Command ID: 1 - SetMotionGoalCmd
    • Command ID: 4 - GetHealthDataByFrameCountCmd
    • Command ID: 5 - GetHealthDataByFrameCompressedCmd
    • Command ID: 7 - SetActivityReminderCmd
    • Command ID: 8 - HealthDataByFrameComm
    • Command ID: 10 - GetSampleFrameCountCmd
    • Command ID: 11 - GetSampleFrameCmd
    • Command ID: 12 - GetStatusFrameCountCmd
    • Command ID: 13 - GetStatusFrameCmd
    • Command ID: 14 - SetDeviceReportThreshold
    • Command ID: 16 - SetDevCouldSummaryEnable
    • Command ID: 19 - SetHRZoneConfCmd
    • Command ID: 33 - SetMaxAndHrrHeartZoneConfCmd
    • Command ID: 24 - SleepStateCmd
    • Command ID: 28 - SetContinueMeasureHeartRateEnableCmd
    • Command ID: 30 - HeartRateRaise
    • Command ID: 34 - HeartRateRemindCmdDown
    • Command ID: 25 - dailySleepScore
    • Command ID: 26
    • Command ID: 31 - GetDesFrameCountCmd or DataFrameCommand Aw70
    • Command ID: 32 - GetDesFrameCmd or SamplePointDataCommand Aw70
  • Service ID: 8 - Alarm
    • Command ID: 1 - EventAlarm
    • Command ID: 2 - SmartAlarm
    • Command ID: 3
    • Command ID: 4
  • Service ID: 9 - OTAV2
    • Command ID: 1 - OtaAllow
    • Command ID: 2 - OtaParametersV2
    • Command ID: 3 -
    • Command ID: 4 -
    • Command ID: 6 -
    • Command ID: 9 - otaStatusNotify
    • Command ID: 11 - DeviceReadyForUpdate
  • Service ID: 10 - FileTransferTask
    • Command ID: 1 - PeriodRRIFile
    • Command ID: 2 - MaintenanceParameters
    • Command ID: 3 - FileInformation
    • Command ID: 4
    • Command ID: 6 - transfertFileEndProcess
    • Command ID: 12
  • Service ID: 11 - FindPhone
    • Command ID: 2
    • Command ID: 3 - BTLostNotification
  • Service ID: 12
    • Command ID: 2 - DeviceFontInfo
  • Service ID: 15 - Weather
    • Command ID: 2 - WeatherConstraintMsg
    • Command ID: 6 - WeatherConstraintExpandMsg
    • Command ID: 7 - WeatherErrorCode
    • Command ID: 5 - WeatherUnitToDevice
    • Command ID: 1 - WeatherToDevice
    • Command ID: 4 - DataFromDevice
    • Command ID: 3 - AtmosphereCmd2Device
  • Service ID: 22 - ExerciseAdvice
    • Command ID: 1 - RunPlanParameterforhealth
    • Command ID: 2 - RunPlanForHealth
    • Command ID: 3
    • Command ID: 4
    • Command ID: 5
    • Command ID: 12 - FitRunCourseInfo
    • Command ID: 13 - FitRunCourseData
  • Service ID: 23 - Workout
    • Command ID: 1
    • Command ID: 2 - NotificationStatusResponse
    • Command ID: 3
    • Command ID: 4
    • Command ID: 7
    • Command ID: 8 - WorkoutRecordStatistic
    • Command ID: 10 - WorkoutData
    • Command ID: 11 - RealTimeData
    • Command ID: 12 - WorkoutRecordPaceMap
    • Command ID: 13 - notificationWorkoutRecordSpeechPlayReportStatus
    • Command ID: 14
    • Command ID: 15 - RunPostureReportStatus
    • Command ID: 18 - openOrCloseReport
    • Command ID: 19 - WorkoutRecordSliceData
    • Command ID: 20 - BloodOxygenListStatistic
  • Service ID: 24 - GPSLocation
    • Command ID: 1
    • Command ID: 2 - GpsStatus
    • Command ID: 3 - GpsParameter
    • Command ID: 4
  • Service ID: 25 - HeartRate
    • Command ID: 1
    • Command ID: 3 - HeartRateResponse
  • Service ID: 26 - Wearable
    • Command ID: 1 - sendAccount
  • Service ID: 27 - Pay
    • Command ID: 1
    • Command ID: 2 - payAPDUInfo
    • Command ID: 3 - closeChannel
    • Command ID: 4 - CPLC
    • Command ID: 5 - BTCInfo
    • Command ID: 7 - transmitFile
    • Command ID: 8 - addCard
    • Command ID: 9
    • Command ID: 10
    • Command ID: 11
    • Command ID: 13
    • Command ID: 12
    • Command ID: 14
    • Command ID: 15
    • Command ID: 16
    • Command ID: 17 - NfcTagInfo
    • Command ID: 18 - NfcCommand
    • Command ID: 19 - aulthenticateMifareSector
    • Command ID: 20 - BlockData
    • Command ID: 21 - AccessCardRfInfo
    • Command ID: 22
    • Command ID: 23
  • Service ID: 28 - FileServices
    • Command ID: 1
    • Command ID: 2
    • Command ID: 3 - StarSingleFileInfor
    • Command ID: 4
    • Command ID: 5 - StarFileData
    • Command ID: 6
  • Service ID: 29 - MultiSimSendCommandUtil
    • Command ID: 1 -
    • Command ID: 3 -
    • Command ID: 6 - SimInfoQuery
    • Command ID: 7 - MultiSimStatus
    • Command ID: 8 - EsimProfileRemoveReq
  • Service ID: 31 - Ephemeris
    • Command ID: 1 -
    • Command ID: 2 - parameterConsult
    • Command ID: 3 - FileStatus
  • Service ID: 32 - StressSendCommandUtil
    • Command ID: 1 - StressRecordFrameListIndex
    • Command ID: 2 - StressRecordDetail
    • Command ID: 3 - RelaxRecordFrameListIndex
    • Command ID: 4 - RelaxRecordDetail
    • Command ID: 9 - CalibrationData
    • Command ID: 10 - AppPressInfo
  • Service ID: 33 - DeviceConfigSendCommandUtil
    • Command ID: 1 - AppStatus
    • Command ID: 2 - Return code
      • 127:
  • Service ID: 34 - OneLevelMenu
    • Command ID: 1 - BTCInfo
    • Command ID: 2 - transmitFile
  • Service ID: 35 - RriServiceSendCommandUtil
    • Command ID: 2 - AtrialAutoMeasureCommand
    • Command ID: 3 - AtrialSingleMeasureCommand
    • Command ID: 4 - ClearAtrialDataCommand
    • Command ID: 6 - EcgMeasureAuthAccountCommand
    • Command ID: 8 - EcgDetailDataCommand
  • Service ID: 36 - FitnessPosture
    • Command ID: 1 - PostureVersionInfo
    • Command ID: 4 - PostureRecord
    • Command ID: 5 - PostureRecordList
    • Command ID: 6 - CourseRecord
    • Command ID: 7 - CourseRecordList
    • Command ID: 8 - WatchStatus
    • Command ID: 9 - PostureStatusValue
    • Command ID: 10 - Reminder
    • Command ID: 11 - Result
    • Command ID: 12 - ReturnValue
  • Service ID: 37 - MusicControl
    • Command ID: 1 - AppStatus
    • Command ID: 2 - MusicInfo
    • Command ID: 3 - AppControlResponse
    • Command ID: 4 - MusicFrameCount
    • Command ID: 5 - GetMusicInfo
    • Command ID: 6 - FolderInfo
    • Command ID: 7 - OneFolderOneFrameMusicAssociation
    • Command ID: 8 - FolderMusicOperate
    • Command ID: 9 - MusicFileResponse
    • Command ID: 10 - MusicAccountInfo
    • Command ID: 11 - HistoryFrameCount
    • Command ID: 12 - GetHistoryInfo
    • Command ID: 13 - Negotiation
  • Service ID: 38 - AW70_AW70DeviceMode
    • Command ID: 1 - ModeStatus
    • COmmand ID: 2 - AutoModeDetectSwitchStatus
  • Service ID: 39 - WatchFace
    • Command ID: 1 - DeviceInfo
    • Command ID: 2 - DeviceWatchInfo
    • Command ID: 3 - OperateType
    • Command ID: 4 - InfoList
    • Command ID: 5 - reportAck
    • Command ID: 6 - GetNameCommand
    • Command ID: 7 - PreviewCommand or sendPhotoCommand
    • Command ID: 8 - PhotoWatchInfo
    • Command ID: 9 - PhotoInfoCommand
    • Command ID: 10 - TagActivate
    • Command ID: 11 - TagResult
    • Command ID: 12 - GetCapability
    • Command ID: 13 - ClipMessage
  • Service ID: 40 - CommonFile
    • Command ID: 1 - DeviceRequest
    • Command ID: 2 - FileInfo
    • Command ID: 3 - FileHashResult
    • Command ID: 4 - ConsultAck
    • Command ID: 6
    • Command ID: 7 - ResultAck
    • Command ID: 9 - CancelCommand
  • Service ID: 43 - TWS
    • Command ID: 18 - Command18
    • Command ID: 19 - FramesCommand
    • Command ID: 20 - Command20
    • Command ID: 21 - clearDeviceInfo
  • Service ID: 44 - CommonFileRequest
    • Command ID: 1 - FileInfo
    • Command ID: 2 - FileCheck
    • Command ID: 3 - RequestParameter
    • Command ID: 4 - RequestCommand
    • Command ID: 6 - RequestCommand
  • Service ID: 45 - BreathingSendCommandUtil
    • Command ID: 1 - SleepBreatheSwitch
    • Command ID: 2 - ClearSleepBreatheCommand
  • Service ID: 46 - CarNotification
    • Command ID: 1
  • Service ID: 1014

Devices

DeviceModel, DeviceId and DeviceType

  • HUAWEI B3-: "GMN-BX9", "004Z", "06E"
  • HUAWEI B3-? : "AW61", "0056", "06E"
  • HUAWEI Band 3 Pro-: "TER-B19", "002K", "06E"
  • HUAWEI Band 3i-: "ADS-B29", "005U", "06E"
  • HUAWEI Band 3e-: "AW70-B29", "004X", "06E"
  • HUAWEI Band 3e-?: "AW70-B19", "0053", "06E"
  • HUAWEI Band 3e-PRO?: "AW70-B39", "006X", "06E"
  • ?: "AW70-B39HN", "006Y", "06E"
  • HUAWEI B3 Lite-: "GRU-B09", "0050", "06E"
  • HUAWEI Sport: "ERS-B19", "0051", "06E"
  • HUAWEI B5-: "JNS-BX9", "004Y", "06E"
  • honor Band 3-: "NYX-B10", "0054", "06E"
  • HONOR Band5: "CRS-B19S", "005R", "06E"
  • HONOR Band4: "CRS-B19", "002I", "06E"
  • HONOR Band 5i-: "ADS-B19", "005T", "06E"
  • honor Watch S1-: "MES-B19", "004W", "06D"
  • honor Watch-: "TLS-B19", "002M", "06D"
  • HUAWEI WATCH GT 2 pro vidar: "LTN-B19", "005W", "06D" ??
  • MagicWatch 2 minos: "MNS-B19", "005Y", "06D"
  • ??: "HBE-B19", "005Z", "06D"
  • HUAWEI WATCH GT-: "FTN-B19", "003N", "06D"
  • PORSCHE DESIGN: "LEO-BX9", "004U", "06D"
  • HUAWEI WATCH 2: "LEO-DLXX", "004Q", "06D"
  • HUAWEI WATCH Hector: "HCT-B19", "M003", "06D"
  • HUAWEI WATCH GT 2 Diana: "DAN-B19", "005X", "06D");

Parser

Reference to parser module
Now log files could be handle with the parser module.

Documentation

Some more information about bits in DeviceConfig service (HH dissassemble) : https://codeberg.org/Freeyourgadget/Gadgetbridge/issues/1021#issuecomment-40581

Links

To get old HH versions : https://www.apkmirror.com/uploads/?q=health

ToDo list

  • Decode HH (1.0.10.319) - Done
  • Decompile HH - WIP; easier thanks to log messages and deobfuscation
  • Dissassemble libwhiteBoxJniLib.so - WIP; find LPv3 keys done, find use of other keys
  • Log more BLE communication to decode messages
  • Enhanced huawei-lpv2 code from https://github.com/zyv/huawei-lpv2/blob/master/huawei/protocol.py
  • Create a log parser to find missing information
  • Improve the log parser to print information
  • Decode BLE handshake and find device.mAuthVersion (HH ask for it to choose protocol through BLE - to be confirmed)
  • List bands/watch and their corresponding modelID / ProductID...

Reminder list

  • service 10 command 5, service 9 command 3 and service 9 command 4 contain no tlvs
@zyv
Copy link

zyv commented Sep 22, 2021

I would suggest the Band 6 user to scan his device for services and characteristics, sample code is here:

hbldh/bleak#58

Maybe this way you can quickly learn something new. In addition to that, you can decompile HH supporting Band 6 and look at the connection routines. If something has changed, you will be able to see it there, and the new characteristics must be hard coded in the app. The functions you have to search for are in Android BLE framework documentation.

@psolyca
Copy link
Author

psolyca commented Sep 22, 2021

Thanks.
Logging the bluetooth and parsing it seems to work.
It seems also that some crypted commands are sent before the key is retrieved ^^;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment