Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Will this board work with "Internalblue" - CYW920819EVB-02 #27

Closed
marcinguy opened this issue May 25, 2020 · 18 comments
Closed

Will this board work with "Internalblue" - CYW920819EVB-02 #27

marcinguy opened this issue May 25, 2020 · 18 comments

Comments

@marcinguy
Copy link

Hi,

Will this board work with Internalblue:

https://www.mouser.de/ProductDetail/Cypress-Semiconductor/CYW920819EVB-02?qs=%2Fha2pyFadugICnogBdJ27y6wc6auC18DiNMDVcMRKbY1cC%2FDSbgy9g%3D%3D

Seems like this is 02 revision.

Seems like it is also supported by Internalblue

FW_NAME = "CYW20819A1"

Not sure if in this revision.

Want to use it for: https://github.com/francozappa/bias tests.

Thanks,

@jiska2342
Copy link
Member

The one I have is also revision 2, so it's definitely supported :)

@marcinguy
Copy link
Author

@jiska2342 Thanks. Actually ordered 2 boards.

CYW20735B1 came first.

Followed the instructions and want to enter diagnostic mode

Board is connected. MAC is there

hciconfig 
hci0:	Type: BR/EDR  Bus: UART
	BD Address: MAC HERE  ACL MTU: 1008:20  SCO MTU: 64:1
	UP RUNNING 
	RX bytes:1591 acl:0 sco:0 events:101 errors:0
	TX bytes:3323 acl:0 sco:0 commands:101 errors:0

But get this

python2 enable_diag.py  
Traceback (most recent call last):
  File "enable_diag.py", line 7, in <module>
    s.send(b"\x07\xf0\x01")
socket.error: [Errno 22] Invalid argument

https://github.com/francozappa/bias/blob/master/bias/enable_diag.py

Tried also with C program:


int main() {

struct sockaddr_hci a;

memset(&a, 0, sizeof(a));
a.hci_family = AF_BLUETOOTH;
a.hci_dev = 0; //0 for hci0
a.hci_channel = 0; //1 for HCI_CHANNEL_USER
int sock;

sock = socket(AF_BLUETOOTH, SOCK_RAW,BTPROTO_HCI);

if(bind(sock, (struct sockaddr *) &a, sizeof(a))==-1)
{
perror("bind()");
}

int buf[]={0x07,0xf0,0x01};
if(send(sock, &buf,3, 0) == -1) {
perror("send()");
}
}

But also get invalid argument

Any ideas how to enter diagnostic mode?

@marcinguy
Copy link
Author

@jiska2342 Had some troubles to get latest InternalBlue running.

Had success with 0.3 release

  ____     __                    _____  __
  /  _/__  / /____ _______  ___ _/ / _ )/ /_ _____
 _/ // _ \/ __/ -_) __/ _ \/ _ `/ / _  / / // / -_)
/___/_//_/\__/\__/_/ /_//_/\_,_/_/____/_/\_,_/\__/


type <help> for usage information!

[ERROR] Could not connect to localhost on port 5037
[*] No adb devices found.
[*] HCI device: hci0  [20:73:5B:XX:XX:XX]  flags=5<UP RUNNING>
[*] HCI device: hci1  [B8:08:CF:XX:XX:XX]  flags=29<UP RUNNING PSCAN ISCAN>
 [?] Please specify device:
    => 1) hci: 20:73:5B:XX:XX:XX (hci0) <UP RUNNING>
       2) hci: B8:08:CF:XX:XX:XX (hci1) <UP RUNNING PSCAN ISCAN>
[*] Connected to hci0
[*] Chip identifier: 0x4208 (002.002.008)
[*] Using fw_0x4208.py
[*] Loaded firmware information for CYW27035B1.
[*] Try to enable debugging on H4 (warning if not supported)...
[!] _sendThreadFunc: Sending to socket failed, reestablishing connection.
    With HCI sockets, some HCI commands require root!
>  

Seems like the problem is also with

[*] Try to enable debugging on H4 (warning if not supported)...
[!] _sendThreadFunc: Sending to socket failed, reestablishing connection. 

Ran as root.

@marcinguy
Copy link
Author

@jiska2342

I can send other packets, but enter diag shows invalid argument

This works:

from socket import socket, AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI, SOL_HCI, HCI_FILTER
from struct import pack
PASS_ALL = pack("IIIh2x", 0xffffffff, 0xffffffff, 0xffffffff, 0)
s = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI)
s.bind((1,))
s.setsockopt(SOL_HCI, HCI_FILTER, PASS_ALL)
s.send(b"\x01\x01\x10\x00")

And this, does not:

   def enableBroadcomDiagnosticLogging(self, enable):
        """
        Broadcom implemented their own H4 layer protocol. Normally H4 handles HCI
        messages like HCI commands, SCO and ACL data, and HCI events. Their types are
        0x01-0x04. Broadcoms proprietary message type is 0x07 to handle diagnostic
        messages.
        
        Diagnostic logging sets a variable checked for any LMP/LCP message when
        sending and receiving and then forwarding its contents prepended with 0x07.
        In principle, diagnostic logging can be enabled on Android by directly
        writing to the serial Bluetooth device:
        
            echo -ne '\x07\xf0\x01' >/dev/ttyHS
        
        However, Androids Bluetooth driver is not properly parsing message type 0x07.
        This causes the driver to crash when enabling diagnostics like this. A
        custom Bluetooth driver is required, which accepts diagnostic commands
        and also forwards diagnostic message outputs to the BT Snoop Log.
        """

        self.sendH4(hci.HCI.BCM_DIAG, '\xf0' + p8(enable))

@jiska2342
Copy link
Member

Hi,

Vendor diagnostics works on Linux as documented in https://github.com/seemoo-lab/internalblue/blob/master/doc/linux_bluez.md - but BlueZ fails on WICED eval boards with this, it's somewhere deep in the driver and broken. USB Broadcom is recognized correctly and you'll get a separate monitor device in Wireshark.

The BTPROTO_HCI will filter 0x07 as packet type as this is not HCI. It only takes the packet types 0x01-0x04. This is somewhere in BlueZ so you get the error with your C snippet as well as the Python socket bindings.

Sorry if this didn't work as you expected. Not sure what exactly the BIAS team did with LMP, as there are also other ways to get LMP out of the chip with binary patching etc.

The current release is using Python 3, I guess that is why you got the other errors?

@jiska2342
Copy link
Member

Ah and maybe not entirely clear from the previous post: USB and UART are implemented differently within BlueZ. So, vendor diagnostics seem to only work in the combination USB and if the device ID indicates Broadcom, even though, in theory, USB+UART, Broadcom+Cypress know this feature. Definitely saw it working well on other stacks like Android as well as in the reverse-engineered firmware itself. @psy once looked into this BlueZ issue but the code is a mess ;)

@jiska2342
Copy link
Member

Wait what?

https://github.com/francozappa/bias/blob/master/bias/enable_diag.py

@francozappa how did you get this working?

@marcinguy
Copy link
Author

Thank you very much @jiska2342 Will try to compile bluez from source. Could this be the check you mentioned: bluez/bluez@eb907a1#diff-49758a48be328c46fa27adab91b6ba73

@francozappa
Copy link

Wait what?

https://github.com/francozappa/bias/blob/master/bias/enable_diag.py

@francozappa how did you get this working?

Hi @jiska2342 ,

Thanks for helping with the devboard setup.

Once you attach to the devboard then you can send vendor-specific commands to activate diagnostic mode. I guess that you are doing a similar thing automatically with internalblue no?

@jiska2342
Copy link
Member

Thank you very much @jiska2342 Will try to compile bluez from source. Could this be the check you mentioned: bluez/bluez@eb907a1#diff-49758a48be328c46fa27adab91b6ba73

Hi @marcinguy, that looks pretty much like the check. H4 is the name of the UART protocol used. I'm not sure if that is the only check, though. Because you also need to define that HCI filter format as you had it in your raw C socket example. Also not sure how that socket error of the invalid argument is generated and how that is internally handled by BlueZ.

The setup as it should work with the driver/chip combo is as follows:

  • echo 1 into the vendor_diag file
  • Open btmon (part of BlueZ tools) and it already parses LMP without any modifications and see the LMP traffic decoded
  • Otherwise, a MONITOR device or so should pop up in Wireshark once there is vendor_diag enabled

As the combination of the correct chip and so on is rare, I only saw that once myself when I booted Ubuntu on a MacBook. I still have that MacBook here but not really the time to debug why all the other combinations do not work with BlueZ as they should be working.

@francozappa you can always send vendor-specific HCI commands (H4 type 0x01) via BlueZ. However, BlueZ filters diagnostic messages (H4 type 0x07). Really, no idea how your code ever worked on BlueZ. And from a security perspective, it's a good thing to decouple the vendor-specific H4 packet type from the remaining stack.

The Android stack also filters type 0x07 and this is one of the things our InternalBlue patch for Android 6+7 enables besides debugging over the BT snoop socket in general.

The macOS and iOS stack are pretty much aware of all proprietary Broadcom features. Using Apple's Bluetooth PacketLogger, I initially found the H4 type 0x07.

@marcinguy
Copy link
Author

@jiska2342 Thank you again.

Compiled bluez with adding 0x7 support in several places, but it seems Kernel is also involved. Tried to link C program against modified version of bluez also do GDB to skip the check of 0x7, but then it got another error. So it seems there is Kernel also involved here. But then I am a novice here :)

I don't have the file /sys/kernel/debug/bluetooth/hci0/vendor_diag

ls -la /sys/kernel/debug/bluetooth/hci0
total 0
drwxr-xr-x 2 root root 0 Mai 29 12:03 .
drwxr-xr-x 4 root root 0 Mai 29 09:03 ..
-rw-r--r-- 1 root root 0 Mai 29 12:03 adv_channel_map
-rw-r--r-- 1 root root 0 Mai 29 12:03 adv_max_interval
-rw-r--r-- 1 root root 0 Mai 29 12:03 adv_min_interval
-rw-r--r-- 1 root root 0 Mai 29 12:03 auto_accept_delay
-r--r--r-- 1 root root 0 Mai 29 12:03 blacklist
-rw-r--r-- 1 root root 0 Mai 29 12:03 conn_info_max_age
-rw-r--r-- 1 root root 0 Mai 29 12:03 conn_info_min_age
-rw-r--r-- 1 root root 0 Mai 29 12:03 conn_latency
-rw-r--r-- 1 root root 0 Mai 29 12:03 conn_max_interval
-rw-r--r-- 1 root root 0 Mai 29 12:03 conn_min_interval
-r--r--r-- 1 root root 0 Mai 29 12:03 dev_class
-r--r--r-- 1 root root 0 Mai 29 12:03 device_id
-r--r--r-- 1 root root 0 Mai 29 12:03 device_list
-rw-r--r-- 1 root root 0 Mai 29 12:03 discov_interleaved_timeout
-rw-r--r-- 1 root root 0 Mai 29 12:03 dut_mode
-r--r--r-- 1 root root 0 Mai 29 12:03 features
-rw-r--r-- 1 root root 0 Mai 29 12:03 force_static_address
-r--r--r-- 1 root root 0 Mai 29 12:03 hardware_error
-r--r--r-- 1 root root 0 Mai 29 12:03 hci_revision
-r--r--r-- 1 root root 0 Mai 29 12:03 hci_version
-r-------- 1 root root 0 Mai 29 12:03 identity
-r-------- 1 root root 0 Mai 29 12:03 identity_resolving_keys
-rw-r--r-- 1 root root 0 Mai 29 12:03 idle_timeout
-r--r--r-- 1 root root 0 Mai 29 12:03 inquiry_cache
-rw-r--r-- 1 root root 0 Mai 29 12:08 le_max_key_size
-rw-r--r-- 1 root root 0 Mai 29 12:08 le_min_key_size
-r-------- 1 root root 0 Mai 29 12:03 link_keys
-r-------- 1 root root 0 Mai 29 12:03 long_term_keys
-r--r--r-- 1 root root 0 Mai 29 12:03 manufacturer
-rw-r--r-- 1 root root 0 Mai 29 12:03 quirk_simultaneous_discovery
-rw-r--r-- 1 root root 0 Mai 29 12:03 quirk_strict_duplicate_filter
-r--r--r-- 1 root root 0 Mai 29 12:03 random_address
-r-------- 1 root root 0 Mai 29 12:03 remote_oob
-rw-r--r-- 1 root root 0 Mai 29 12:03 rpa_timeout
-r--r--r-- 1 root root 0 Mai 29 12:03 sc_only_mode
-rw-r--r-- 1 root root 0 Mai 29 12:03 sniff_max_interval
-rw-r--r-- 1 root root 0 Mai 29 12:03 sniff_min_interval
-r--r--r-- 1 root root 0 Mai 29 12:03 ssp_debug_mode
-r--r--r-- 1 root root 0 Mai 29 12:03 static_address
-rw-r--r-- 1 root root 0 Mai 29 12:03 supervision_timeout
-r--r--r-- 1 root root 0 Mai 29 12:03 use_debug_keys
-r--r--r-- 1 root root 0 Mai 29 12:03 uuids
-r--r--r-- 1 root root 0 Mai 29 12:03 voice_setting
-r--r--r-- 1 root root 0 Mai 29 12:03 white_list
-r--r--r-- 1 root root 0 Mai 29 12:03 white_list_size

How can I see the LMP messages?

Will try with @francozappa modified Kernel, seem like last resort:

francozappa/bias#3 (comment)

@jiska2342
Copy link
Member

The file /sys/kernel/debug/bluetooth/hci0/vendor_diag is only created if the BlueZ drivers have a good day and know your chip and decide that it is on the honored list of Broadcom devices that support this feature. It's hardcoded black magic somewhere deep in BlueZ that even follows different logic depending on USB or UART.

Ah and maybe another funny detail to add about the InternalBlue implementations of these stacks. On iOS as well as on Android 8+, we're currently just echoing into the UART device. For iOS, we disable bluetoothd in order to do this as the access is blocking. On Android, it's non-blocking, so we just echo into /dev/ttySAC0 like some maniacs and hope that we don't run into any concurrency issues with bluetoothd running in parallel.

On Linux, the access to /dev/ttyUSB0 or whatever the device gets assigned is blocking. That means, you cannot echo into it just for fun to send a H4 UART message starting with 0x07. And, even if you manage to send such a message, I'm not sure if the BlueZ stack would parse the messages returned by the stack which start with 0x07.

On Android, if you enable diagnostics with 0x07, the stack will crash once it's getting the first 0x07 answer because it cannot parse it. On UART H4, each packet type has a slightly different format with hard-coded type, length, value. If you break it, the stack will decide to handle it as a hardware fault and start bluetoothd etc all over again.

@jiska2342
Copy link
Member

How can I see the LMP messages?

Will try with @francozappa modified Kernel, seem like last resort:

francozappa/bias#3 (comment)

Probably the only way to get it working, yes. Definitely won't work on the normal BlueZ stack.

@marcinguy
Copy link
Author

@jiska2342 With the modified kernel it seems to work.

@jiska2342
Copy link
Member

Okay, great :D
Might be a thing then to create a patch from it and ping @holtmann? Would be cool to have it as part of BlueZ.

@marcinguy
Copy link
Author

@jiska2342 To wrap up this subject. It seems like Bluez was not involved, hindering this. Only patched Kernel solved this. If you want I can make a PR to add link to @francozappa modified kernel to have it work in Linux/Bluez setup (I can provide full tree, compiled image). No need to touch Bluez. Feel free to close the issue from my side.

@LHKST
Copy link

LHKST commented Jan 28, 2021

@jiska2342 To wrap up this subject. It seems like Bluez was not involved, hindering this. Only patched Kernel solved this. If you want I can make a PR to add link to @francozappa modified kernel to have it work in Linux/Bluez setup (I can provide full tree, compiled image). No need to touch Bluez. Feel free to close the issue from my side.

If it's convenient for me to get the compiled image from you? Many thanks.

@jiska2342
Copy link
Member

I created a diff, which should make it easier to create a pre-compiled kernel :)

https://github.com/seemoo-lab/internalblue/blob/master/linux/bias_linux-4.14.111.diff

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants