diff --git a/host/Makefile b/host/Makefile new file mode 100644 index 0000000..696857e --- /dev/null +++ b/host/Makefile @@ -0,0 +1,5 @@ +all: + gcc hidekey.c -o hidekey -lusb-1.0 + +clean: + rm hidekey diff --git a/host/at b/host/at new file mode 100644 index 0000000..1a69a67 --- /dev/null +++ b/host/at @@ -0,0 +1 @@ +echo test +0:01 diff --git a/host/eep1 b/host/eep1 new file mode 100644 index 0000000..e31eeab Binary files /dev/null and b/host/eep1 differ diff --git a/host/eep2 b/host/eep2 new file mode 100644 index 0000000..368d6f6 Binary files /dev/null and b/host/eep2 differ diff --git a/host/hidekey b/host/hidekey new file mode 100755 index 0000000..a448bc4 Binary files /dev/null and b/host/hidekey differ diff --git a/host/hidekey.c b/host/hidekey.c new file mode 100644 index 0000000..e9e52fc --- /dev/null +++ b/host/hidekey.c @@ -0,0 +1,248 @@ +#include +#include +#include +#include + +#include + +#include "../config.h" + +const char *errorMsgs[] = { + "no error", + "write protection is enabled", + "string to long", + "invalid slot", + "unknown" +}; + +const char *writableStates[] = { + "no protection", + "true", + "false" +}; + +char * getPass(char *buffer, size_t size) { + char *r, *n; + struct termios oldt, newt; + int fd = fileno(stdin); + + tcgetattr(fd, &oldt); + + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); + + tcsetattr(fd, TCSANOW, &newt); + + r = fgets(buffer, size, stdin); + if (n = strrchr(buffer, '\n')) { + *n = '\0'; + } + + tcsetattr(fd, TCSANOW, &oldt); + + return r; +} + +char * getUser(char *buffer, size_t size) { + char *r, *n; + + r = fgets(buffer, size, stdin); + if (n = strrchr(buffer, '\n')) { + *n = '\0'; + } + + return r; +} + +int setSlot(struct libusb_device_handle *handle, uint16_t slotIndex, struct slot slot) { + return libusb_control_transfer( + handle, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, /* bmRequestType */ + USBRQ_VENDOR_SET_SLOT, /* bRequest */ + 0, /* wValue */ + slotIndex, /* wIndex */ + (uint8_t *) &slot, /* data */ + sizeof(struct slot), /* wLength */ + 500 /* timeout */ + ); +} + +struct status getStatus(struct libusb_device_handle *handle) { + struct status stat; + libusb_control_transfer( + handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + USBRQ_VENDOR_GET_STATUS, + 0, + 0, + (uint8_t *) &stat, + sizeof(stat), + 500 + ); + + return stat; +} + +int checkStatus(struct libusb_device_handle *handle) { + struct status stat = getStatus(handle); + + if (stat.error != ERROR_SUCCESS) { + fprintf(stderr, "Error orccured: %s (%u)\n", errorMsgs[stat.error], stat.error); + return stat.error; + } + + return EXIT_SUCCESS; +} + +double decodeUsbBcd(uint16_t bcd) { + double result = 0; + + result += ((bcd & 0x0f00) >> 8) * 1e-2; + result += ((bcd & 0xf000) >> 12) * 1e-1; + result += ((bcd & 0x000f) >> 0) * 1e0; + result += ((bcd & 0x00f0) >> 4) * 1e1; + + return result; +} + +int main(int argc, char *argv[]) { + struct libusb_device_handle *handle; + struct libusb_device_descriptor desc; + + int r; + + r = libusb_init(NULL); + if (r < 0) { + return EXIT_FAILURE; + } + + /* search device */ + handle = libusb_open_device_with_vid_pid(NULL, DEVICE_VID, DEVICE_PID); + if (handle == NULL) { + fprintf(stderr, "failed to open the device\n"); + return EXIT_FAILURE; + } + + /* get status */ + struct status stat = getStatus(handle); + + r = libusb_get_device_descriptor(libusb_get_device(handle), &desc); + if (r < 0) { + fprintf(stderr, "failed to get device descriptor\n"); + return EXIT_FAILURE; + } + + if (argc == 1) { + printf("usage: hidekey COMMAND [OPTIONS]\n"); + printf(" available COMMANDs and their specific OPTIONS:\n\n"); + printf(" info\n\tshow information about plugged in keys\n\n"); + printf(" set SLOT TYPE USER [PASSWORD]\n\tstore new user/password combination on stick\n\n"); + printf(" clear SLOT\n\tdelete password from SLOT\n\n"); + printf(" reset\n\tprune all passwords and reset startup counter\n\n"); + printf(" serial SERIAL\tset new serial (expert option)\n\n"); + printf("hidekey 0.1 - HIDeKey setup utility\n"); + printf("by Steffen Vogel \n"); + printf("please send bugreports to http://bugs.0l.de\n"); + } + else if (argc == 2 && strcmp(argv[1], "info") == 0) { + /* get product string */ + char productString[255]; + libusb_get_string_descriptor_ascii(handle, desc.iProduct, productString, 255); + printf("name: %s\n", productString); + + /* get product version */ + printf("version: %.2f\n", decodeUsbBcd(desc.bcdDevice)); /* decode bcd */ + + /* get serial no */ + char serialNumber[255]; + libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, serialNumber, 255); + printf("serial: %s\n", serialNumber); + + /* get status struct */ + printf("startups: %u\n", stat.counter); + printf("writable: %s\n", writableStates[stat.writable]);// ? "true" : "false"); + printf("slots: %u\n", stat.maxSlots); + printf("max user length: %u\n", stat.maxUserLen); + printf("max password length: %u\n", stat.maxPassLen); + printf("max serial length: %u\n", stat.maxSerialLen); + } + else if (argc == 2 && strcmp(argv[1], "reset") == 0) { + libusb_control_transfer( + handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + USBRQ_VENDOR_RESET, + 0, + 0, + NULL, + 0, + 500 + ); + } + else if (argc == 3 && strcmp(argv[1], "serial") == 0) { + size_t len = strlen(argv[2]); + + libusb_control_transfer( + handle, + LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, /* bmRequestType */ + USBRQ_VENDOR_SET_SERIAL,/* bRequest */ + 0, /* wValue */ + 0, /* wIndex */ + (uint8_t *) argv[2], /* data */ + len, /* wLength (string is not \0-terminated!) */ + 500 /* timeout */ + ); + } + else if (argc == 3 && strcmp(argv[1], "clear") == 0) { + uint16_t slotIndex = atoi(argv[2]); + + struct slot slot = { SLOT_EMPTY }; + setSlot(handle, slotIndex, slot); + } + else if (argc >= 4 && strcmp(argv[1], "set") == 0) { + uint16_t slotIndex = atoi(argv[2]); + uint8_t type = atoi(argv[3]); + + struct slot slot = { + .type = type, + .options = SKIP_USER | SKIP_DELIMITER | SKIP_RETURN, + .delimiter = '\t' + }; // TODO make configurable + + if (argc >= 5) { + strncpy(slot.user, argv[4], MAX_USER_LEN); + } + else { + printf("User: "); + getUser(slot.user, MAX_PASS_LEN); + } + + if (type == SLOT_STRING) { + if (argc == 6) { + strncpy(slot.pass.string, argv[5], MAX_PASS_LEN); + } + else { + char tmpPass[MAX_PASS_LEN]; + + printf("Password: "); + getPass(slot.pass.string, MAX_PASS_LEN); + + printf("\nRepeat password: "); + getPass(tmpPass, MAX_PASS_LEN); + printf("\n"); + + if (strcmp(slot.pass.string, tmpPass) != 0) { + fprintf(stderr, "Passwords didn't match!\n"); + return EXIT_FAILURE; + } + } + } + + setSlot(handle, slotIndex, slot); + } + else { + fprintf(stderr, "Unknown command\n"); + return EXIT_FAILURE; + } + + return checkStatus(handle); +}