summaryrefslogtreecommitdiffstats
path: root/reversing_tools/abbott/encrypted_setup_extractor.py
diff options
context:
space:
mode:
Diffstat (limited to 'reversing_tools/abbott/encrypted_setup_extractor.py')
-rw-r--r--reversing_tools/abbott/encrypted_setup_extractor.py179
1 files changed, 0 insertions, 179 deletions
diff --git a/reversing_tools/abbott/encrypted_setup_extractor.py b/reversing_tools/abbott/encrypted_setup_extractor.py
deleted file mode 100644
index cc57f0f..0000000
--- a/reversing_tools/abbott/encrypted_setup_extractor.py
+++ /dev/null
@@ -1,179 +0,0 @@
-#!/usr/bin/env python3
-#
-# SPDX-FileCopyrightText: © 2019 The usbmon-tools Authors
-# SPDX-FileCopyrightText: © 2020 The glucometerutils Authors
-#
-# SPDX-License-Identifier: Apache-2.0
-
-import argparse
-import logging
-import sys
-
-import construct
-import usbmon
-import usbmon.pcapng
-
-_SERIAL_NUMBER_RESPONSE_TYPE = 0x06
-_ENCRYPTION_SETUP_REQ_TYPE = 0x14
-_ENCRYPTION_SETUP_RESP_TYPE = 0x33
-
-
-_START_AUTHORIZE_CMD = 0x11
-_CHALLENGE_CMD = 0x16
-_CHALLENGE_RESPONSE_CMD = 0x17
-
-
-_ABBOTT_VENDOR_ID = 0x1A61
-_LIBRE2_PRODUCT_ID = 0x3950
-
-_SERIAL_NO = construct.Struct(
- message_type=construct.Const(_SERIAL_NUMBER_RESPONSE_TYPE, construct.Byte),
- length=construct.Const(14, construct.Byte),
- serial_number=construct.PaddedString(13, "ascii"),
- termination=construct.Const(0, construct.Byte),
-)
-
-_CHALLENGE = construct.Struct(
- message_type=construct.Const(_ENCRYPTION_SETUP_RESP_TYPE, construct.Byte),
- length=construct.Const(16, construct.Byte),
- subcmd=construct.Const(_CHALLENGE_CMD, construct.Byte),
- challenge=construct.Bytes(8),
- iv=construct.Bytes(7),
-)
-
-_CHALLENGE_RESPONSE = construct.Struct(
- message_type=construct.Const(_ENCRYPTION_SETUP_REQ_TYPE, construct.Byte),
- length=construct.Const(26, construct.Byte),
- subcmd=construct.Const(_CHALLENGE_RESPONSE_CMD, construct.Byte),
- challenge_response_encrypted=construct.Bytes(16),
- const=construct.Const(1, construct.Byte),
- mac=construct.Bytes(8),
-)
-
-
-def main():
- if sys.version_info < (3, 7):
- raise Exception("Unsupported Python version, please use at least Python 3.7.")
-
- parser = argparse.ArgumentParser()
-
- parser.add_argument(
- "--device_address",
- action="store",
- type=str,
- help=(
- "Device address (busnum.devnum) of the device to extract capture"
- " of. If none provided, device descriptors will be relied on."
- ),
- )
-
- parser.add_argument(
- "--vlog",
- action="store",
- required=False,
- type=int,
- help=(
- "Python logging level. See the levels at"
- " https://docs.python.org/3/library/logging.html#logging-levels"
- ),
- )
-
- parser.add_argument(
- "pcap_files",
- action="store",
- type=argparse.FileType(mode="rb"),
- help="Path to the pcapng file with the USB capture.",
- nargs="+",
- )
-
- args = parser.parse_args()
-
- logging.basicConfig(level=args.vlog)
-
- for pcap_file in args.pcap_files:
- session = usbmon.pcapng.parse_stream(pcap_file, retag_urbs=False)
-
- if not args.device_address:
- for descriptor in session.device_descriptors.values():
- if (
- descriptor.vendor_id == _ABBOTT_VENDOR_ID
- and descriptor.product_id == _LIBRE2_PRODUCT_ID
- ):
- if (
- args.device_address
- and args.device_address != descriptor.address
- ):
- raise Exception(
- "Multiple Libre2 devices present in capture, please"
- " provide a --device_address flag."
- )
- device_address = descriptor.address
- else:
- device_address = descriptor.address
-
- descriptor = session.device_descriptors.get(device_address, None)
- if descriptor:
- assert descriptor.vendor_id == _ABBOTT_VENDOR_ID
- assert descriptor.product_id == _LIBRE2_PRODUCT_ID
-
- serial_number = "UNKNOWN"
- challenge = "UNKNOWN"
- iv = "UNKNOWN"
- encrypted_challenge = "UNKNOWN"
- mac = "UNKNOWN"
-
- for first, second in session.in_pairs():
- # Ignore stray callbacks/errors.
- if not first.type == usbmon.constants.PacketType.SUBMISSION:
- continue
-
- if not first.address.startswith(f"{device_address}."):
- # No need to check second, they will be linked.
- continue
-
- if first.xfer_type == usbmon.constants.XferType.INTERRUPT:
- pass
- elif (
- first.xfer_type == usbmon.constants.XferType.CONTROL
- and not first.setup_packet
- or first.setup_packet.type == usbmon.setup.Type.CLASS
- ):
- pass
- else:
- continue
-
- if first.direction == usbmon.constants.Direction.OUT:
- packet = first
- else:
- packet = second
-
- if not packet.payload:
- continue
-
- assert len(packet.payload) >= 2
-
- message_type = packet.payload[0]
-
- if message_type == _SERIAL_NUMBER_RESPONSE_TYPE:
- obj = _SERIAL_NO.parse(packet.payload)
- serial_number = obj.serial_number
- elif (
- message_type == _ENCRYPTION_SETUP_RESP_TYPE
- and packet.payload[2] == _CHALLENGE_CMD
- ):
- obj = _CHALLENGE.parse(packet.payload)
- challenge = obj.challenge.hex()
- iv = obj.iv.hex()
- elif (
- message_type == _ENCRYPTION_SETUP_REQ_TYPE
- and packet.payload[2] == _CHALLENGE_RESPONSE_CMD
- ):
- obj = _CHALLENGE_RESPONSE.parse(packet.payload)
- encrypted_challenge = obj.challenge_response_encrypted.hex()
- mac = obj.mac.hex()
-
- print(f"{serial_number},{challenge},{iv},{encrypted_challenge},{mac}")
-
-
-if __name__ == "__main__":
- main()