-
Notifications
You must be signed in to change notification settings - Fork 33
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
Libre 2 Protocol #8
Comments
I don't have a Libre2 myself to reverse, as it is not available in the UK where I live, which is why there are no specs here for it yet. |
Just as some info. I was trying to get data from a Libre 2. I do not have one myself but had to remotely debug. The libre 2 seems to respond to the commands of the original Libre. Especially reading serial number and stuff works. But $history? or $arresult? return Garbage. This will return a lot of data, but the content is always the same thing which does not make any sense. As I do not have a device myself it is hard to debug this any further. |
I've added a file with the list of known commands from the previous FreeStyle devices in Flameeyes/glucometerutils@beecba3 You can run it with
to generate a log of responses to those. Maybe they use some of the other answers this time around. |
Using |
I think the Libre 2 is encrypting the data some how with the serial number |
Hello DreadRoberts, |
Is it possible that it is the same on Libre1 reader with the most actual firmware 2.4.8 installed? |
My previous paoting is not completely correct, the plain text command "$patch" at the end of the transfer of the original software (Libre1 FW v2.4.8)also seems to report unencrypted data. |
Is the firmware automatically updated when the Libre 1 device is connected to the Libre Software?
I also wrote a small python script to communicate with the device to test various commands (pywinusb is required): import pywinusb.hid as hid
import time
import datetime
all_devices = hid.HidDeviceFilter(vendor_id = 0x1a61).get_devices()
target_usage= hid.get_full_usage_id(0xFF00, 0x01)
data_buffer_ascii = []
def response_handler(data):
global data_buffer
global data_buffer_ascii
data_buffer = data[1:]
data_buffer_ascii = []
data_buffer_ascii.append("".join(chr(d) for d in data[3:data[2]+2])) # data[2] defines the length of the response
device = all_devices[0]
device.open()
device.set_raw_data_handler(response_handler)
data_sn = [0] * 65
data_sn[1] = 0x05 # serial number
# data[1] = 0x15 software version
device.send_output_report(data_sn)
time.sleep(0.5)
print(data_buffer_ascii) |
For a reason that isn't completely clear to me (I'm a Python absolute beginner), the |
@DreadRoberts which (country) site did you manage to find desktop software for the Libre 2? I was provided with a device to test with, but on the German website there's no desktop software at all. |
Okay I've spent a few hours looking at this and I have some updates:
I'll provide updates as I find them. |
The Libre 2 is using encrypted commands that are not fully documented yet, but at least provide information that the length is not valid for them. (Work on Libre 2 device is part of issue #8.) Update known details for initialization sequence: `0x01` is the only command that is actually needed to complete initialization on all my devices. The other pre-initialization commands appear to exist for the software to select the correct device.
End of day updates: I have updated the shared HID protocol with more details, as it looks like the initialisation is much shorter than I thought, for most other devices. The extraction script is a bit smarter about ignoring the keepalive messages. It appears to me that the way the software talks with the device is pretty much the same (beside encryption) between Libre 1 and Libre 2, so we have a high likeliness of being able to reuse most code once the encryption is defeated. In particular, while the software is using the binary mode (that I never finished reversing on the Libre 1), it also sends a couple of text commands towards the end of the connection establishment, which it does on the Libre 1 too — on that, they are So what about that encryption challenge/response? Command type The software then sends a I don't seem to be able to get this to replay, but that may be me doing something wrong for now. The fact that there are a couple of places where there's an eight bytes exchange makes me wonder if it's just AES256. |
Silly me — it needs to have 32 bytes to be AES256 — but we have 8 bytes only at best. At 64-bit encryption, options are fairly limited. DES is an option, but that sounds a bit silly. Unless they use AES with only 8 variable bytes, but even that sounds silly. We do have quite a bit of plaintext though. |
So I have not managed to find time to set up a second VM to check if there's any at-install generation of secret material, here's three separate runs of the connection handshake for my meter: https://gist.github.com/Flameeyes/2008497a37e12fd61fa4429736f7aaa4 Turns out that these are not replayable, because the I'll try to get usbpcap format into usbmon-tools so that the extraction tool works with native Windows capture, I think it's feasible. |
Did you pair a sensor with the reader? Could the eight-byte fixed sequence be an encoding of the sensor serial number, as discussed here? |
There is a sensor paired to the reader in the three traces I shared earlier. But that's not affecting the pre-encryption commands, as they behave the same in the first trace I have here, which is without any sensor paired. So I can say that the encryption of the reader communication itself is not at all related to the sensor being used. |
In that case, would it help to compare the comm_unic_ation with a different reader, to find out whether the encryption is bound to the hardware or not? (No windows here though.) |
So, I just realized I spoke too soon. When I compare the three captures I got for the initialization, two receive the same initial response (which is also the same as my initial capture, not provided), but the third does not. And indeed, now that I try to reproduce this, I get a different 16 bytes every turn. So maybe that's not some kind of serial but an actual 16-bytes key. |
What I know from the sensor is,for Libre2 data structure,there are 2 more parts than Libre1,called PatchInfo(6 bytes) and PatchUID(8 bytes). PatchUID is constant,but the last 2 bytes of PatchInfo is changing with every read. I think that the data storeed in Reader also encrypted by the sensor itself,just use the data from sensor to calculate decrypt keys |
I played around with the desktop software and noticed something which might be helpful: And if you press the update button multiple times the software crashes which sometimes leads to unencrypted packets being sent. |
So I got some news from a deep dive into the code of the software itself.
|
End-of-weekend update:
I don't think I'll have any time to work on this in the next ~week or so. If anyone is interested in digging deeper, I can provide partial exports of the data from Ghidra to work on more of it. |
Sorry for the late response, I would love to have a look at your ghidra files! I have started a project by myself but maybe you have found something I haven’t |
@DreadRoberts if you want a copy hit me by email (email in the repo) and I'll be happy to share. So I went back to this after a few more months and I have been going through some of the state machine logic to understand it:
I have not found algorithms it's using. It's definitely using a generic library for the encryption because it has more KDFs than it uses built in. |
Also it's either a stream cipher or one with 64-bit blocks. Since my first few captures had the same 15-bytes coming from the device, I can say that the same 8 bytes are always encoded with the same 8 bytes back. |
I managed to find more information:
|
Hello @Flameeyes |
Hello @Flameeyes |
any update in reading SRAM of libre pro |
I have a Libre 2 and would like to get the data from it. Did you have the chance to look at the protocol of such a device?
The text was updated successfully, but these errors were encountered: