I am developing a Win32 application for a Windows 10 tablet that shall connect to a embedded device via Bluetooth. The embedded device uses the Telit BlueMod+SR as bluetooth module.
In Windows, I use the interface from "bluetoothapis.h" for Connection and Pairing and winsock2 for communication.
I have to implement pairing using passkey entry between the devices, initiated by the Windows tablet. The tablet provides passkey entry, the embedded device is display-only.
The way it works at the moment is that:
Windows creats a non-blocking socket and configures it as requiring authentication by setting SO_BTH_AUTHENTICATE.
Windows passes my Authentication Callback to BluetoothRegisterForAuthenticationEx().
Windows calls ConnectEx() on the remote BT device.
If successful, the Authentication Callback is executed, giving me the passkey (which is displayed by the embedded device).
The user is asked to input the passkey on the tablet which then compares the input with the passkey from the Authentication callback.
My problem is, although it works, I think that this is not the way the passkey entry is intended. It doesn't feel like a valid way to establish a secure connection since the embedded device seems to transmit the passkey via Bluetooth to the tablet.
Should the passkey be openly transmitted via Bluetooth from the remote device to the initiating device?
Or should the user be the only one that gives the passkey to the tablet?
If the way it is implemented is wrong:
Does somebody have an idea why the passkey is available through the Authentication Callback on Windows? I guess there is something wrong with the configuration of the BlueMod module, but I haven't been able to change the behavior.
Related
I am trying to talk to a MSC USB device (interface class 8, subclass 6, protocol 0x50) via a plain USB API with endpoints (all set up for me).
Provided I have a valid CDB, such as for "Test Unit Ready", how to I send that over the USB interface?
Where can I find examples or docs for how this is done?
Background: The actual platform is macOS, which doesn't provide SCSI-passthrough for block devices, and the native SCSI API is also not available in this case.
I have, however, been able to initiate communication on the USB level with the device, and am now trying to circumvent the blocked SCSI device level access by talking thru USB directly.
Most such devices implement the so-called “Bulk Only” protocol, which is specified here: https://usb.org/document-library/mass-storage-bulk-only-10
Essentially, you send a 31-byte “Command Block Wrapper”, which includes the CDB and is specified in section 5.1 of the spec, to the device via the bulk out endpoint. You then read or write the data to be transferred from the input bulk endpoint or to the output bulk endpoint and finally read the 13-byte command status wrapper from the bulk in pipe.
However, note that you’ll need to make sure the OS hasn’t already loaded a driver for the device - from user space, the system won’t give you access to the endpoints when a kernel driver has claimed them anyway, but if you were to attempt to use the same pipes as the default driver from a kext, you’d get unpredictable results.
I am using Windows Bluetooth LE GATT library to connect to and pair with a BLE-supporting device, D. Since D has a limited amount of storage space, if more than N Clients bond with it, then it will remove the first Long Term Key pair that was created during bonding.
Let's say that the device for which this key-pair was removed was a Windows Enabled machine. Let's call this W. The next time W attempts to connect with D, when it receives the LTK_Request_Event from W, it responds with Long_Term_Key_Requested_Negative_Reply, and W terminates the connection.
But here's where things get really exasperating. Even though the Windows BLE Stack seems to be aware of this response (because it disconnects), this does not seem to be communicated downstream to applications using the Bluetooth LE GATT library. In fact, from the application's side, a pairing request will return with "Already Paired", and does not indicate that anything went wrong. Of course, once the application tries to access protected characteristics, it won't be able to, and that, so far, is the only indication that Pairing was not successful. Even worse, the errors it receives aren't consistent. Sometimes, it gets "Unreachable". Sometimes, it gets protocol errors. Other times, it receives ABORTs.
Now, as a heuristic, I could use detection of this case as criteria for attempting to re-pair. Unfortunately, this is not ideal, since none of these errors actually imply that the device no longer honored the LTKs, and could, instead, indicate other issues, like that the device is out of range.
Is there any way to detect that existing LTKs have been rejected by the device?
Let's see what the Bluetooth specification says about this.
Bluetooth Core version 5.2, Vol 3 (Host), Part C (Generic Access Profile)
Section 10.3.2 Initiating a service request:
In this section the local device is the device initiating a service request to a
remote device. In the L2CAP protocol the local device sends the connection
request and the remote device sends the connection response. In GATT, the
local device is the GATT client and the remote device is the GATT server.
When a local device initiates a service request to a remote device it shall
behave according to the following rules:
[...]
If an LTK is available and encryption is required (LE security mode 1) then
encryption shall be enabled before the service request proceeds as defined proceed. If encryption fails either the bond no longer exists on the remote
device, or the wrong device has been connected. The local device must,
after user interaction to confirm the remote device, re-bond, perform service
discovery and re-configure the remote device. [...]
If Windows's BLE stack doesn't allow for what the specification mandates, it is not specification compliant, in my eyes, so please file an issue report at Microsoft.
The reason for requiring user interaction and not blindly re-bond is to avoid a situation where a hacker can simply spoof the bluetooth device address, indicate it has lost the bond and automatically re-bond without the user noticing anything.
EDIT:
The Security Manager chapter also has a table of actions to do when encryption fails due to deleted keys. See section 2.4.4.2 of Vol 3, Part H.
It specifically says when the devices were bonded before that the action to take when enabling encryption fails is to "Notify user of security failure."
I am using the 32feet bluetooth library to connect to a device that supports Serial Port Profile (SPP). I try to connect like this:
using (BluetoothClient client = new BluetoothClient())
{
var address = new BluetoothAddress(0xecfe7e11c3af);
BluetoothEndPoint endPoint = new BluetoothEndPoint(address, BluetoothService.SerialPort);
client.Connect(endPoint);
var stream = client.GetStream();
System.Threading.Thread.Sleep(10000);
}
Everything is great until the Connect method is called. At this point, Windows interrupts the program flow with a bubble alert that says
"A bluetooth device is trying to connect -- click to allow this"
At which point the user is led through a wizard that ends up installing drivers and a Bluetooth virtual COM port shows up in Device Manager. I don't want this to happen -- I want to simply access the stream and communicate directly with the device without windows intervening. Is this possible? What can be done to tell Windows to keep out of my business?
I'm attempting to connect to a Bluetooth 4.0 device. I've done something similar in the past with a 2.0 device and Windows does not interfere in this case.
Have a look at http://SimpleBluetooth4Win.SourceForge.net
It's a small wrapper library that uses the windows bluetooth networking API that could help you.
https://msdn.microsoft.com/en-us/library/windows/desktop/aa362932%28v=vs.85%29.aspx
In particular if your bluetooth USB dongle or bluetooth device has been correctly recognized by the appropriate drivers and the remote bluetooth device is already paired with the PC, you don't need to install a bluetooth virtual COM port that shows up in Device Manager but you simply use the write or read calls to access directly the stream for communicating with the paired device.
How do I control the network interface on Windows? Actually, the idea is quiet simple.
Establish connect to a certain adapter on a computer.
Direct whole traffic of the adapter to this program.
Give the rights to this program what must be transfer to the adapter and what should not.
I think the program has to implement any windows network adapter interface and be registered as an adapter driver. Thus, when it wants to transfer data to real adapter, the program has to call adapter driver methods. In their turn, the methods implement the same windows network interface (or that is called in other way don't really know, I hope you get the sense), don't they?
As a result, we have a kind of inheritance here.
Before use our new driver:
windows application and windows itself
________________________ windows network interface
DRIVER of Adapter1
________________________ end of OS boundaries
Adapter 1
Use our new driver:
windows application and windows itself
________________________ windows network interface
our DRIVER
________________________ windows network interface
DRIVER of Adapter1
________________________ end of OS boundaries
Adapter 1
I believe that kind of interface exists and I hope it is realized very easy.
You will likely need to hook Windows API calls to really do this. It is possible... Start by Googling hook API and Winternals - and see if you can find their sample code.
Before Winternals was bought by Microsoft they published their code. http://technet.microsoft.com/en-us/sysinternals/bb545021
The idea is this:
You write a user-mode program which controls your hooking device
driver.
Your hooking device driver determines if network traffic on
given API calls is ok.
Driver allows normal API calls to succeed if they are.
So I have a bluetooth device, this device uses SPP to transfer data between the PC and itself. It connects fine through Windows as a bluetooth device. I can find it, enter the paring code and assign it to a COM port. Now I want to be able to send data through the com port using Windows API but it is refusing to do so.
I suspect that I need to setup the COMMCONFIG Structure correctly (see below)
http://msdn.microsoft.com/en-us/library/aa363188(VS.85).aspx
Unfortunately I have no idea what is the proper setting. I know SPP is supposed to emulate the RS-232 communication... so maybe I have to study up on that to figure out the right setting? Or is there some automatic way to set the COMMCONFIG structure.
I seriously doubt it. If it would be used then you'll have no chance at guessing at the custom provider data without docs from the driver author. Pay attention to the handshake signals, serial port devices routinely ignore anything sent to them when the DTR signal is turned off. And not send anything back with DTR off. A driver would emulate that. Use EscapeCommFunction() to turn them on. Also try a serial comm program like HyperTerminal or Putty to test this so you can isolate the source of the problem.
Why not use the Bluetooth sockets API? No need for troublesome (virtual) COM ports then.
If you're using managed code then see my library 32feet.NET
If using native code, use SOCKADDR_BTH with Winsock connect etc, see e.g. Bluetooth and connect (Windows) Then you can use the standard Winsock send/recv API
Ok, I found that you can use the
GetCommConfig and GetCommState functions to figure out the settings.