/// /// Check if the specified slot has been configured /// __declspec(dllexport) int IsSlotConfigured(int slot, bool* result) { YK_INFO info; YK_KEY* key; key = yk_open_first_key(); if (key == NULL) { _lastError = yk_errno; return ERROR_CANNOT_OPEN_KEY; } yk_get_status(key, &info.status); if (slot == 1 && (info.status.touchLevel & CONFIG1_VALID) != 0) { *result = true; } else if (slot == 2 && (info.status.touchLevel & CONFIG2_VALID) != 0) { *result = true; } else { *result = false; } yk_close_key(key); return 0; }
int check_firmware_version(YK_KEY *yk, bool verbose, bool quiet) { YK_STATUS *st = ykds_alloc(); if (!yk_get_status(yk, st)) { free(st); return 0; } if (verbose) { printf("Firmware version %d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st)); fflush(stdout); } if (ykds_version_major(st) < 2 || (ykds_version_major(st) == 2 && ykds_version_minor(st) < 2)) { if (! quiet) fprintf(stderr, "Challenge-response not supported before YubiKey 2.2.\n"); free(st); return 0; } free(st); return 1; }
int yk_check_firmware_version(YK_KEY *k) { YK_STATUS st; if (!yk_get_status(k, &st)) return 0; return yk_check_firmware_version2(&st); }
static int _yk_write(YK_KEY *yk, uint8_t yk_cmd, unsigned char *buf, size_t len) { YK_STATUS stat; int seq; /* Get current sequence # from status block */ if (!yk_get_status(yk, &stat /*, 0*/)) return 0; seq = stat.pgmSeq; /* Write to Yubikey */ if (!yk_write_to_key(yk, yk_cmd, buf, len)) return 0; /* When the Yubikey clears the SLOT_WRITE_FLAG, it has processed the last write. * This wait can't be done in yk_write_to_key since some users of that function * want to get the bytes in the status message, but when writing configuration * we don't expect any data back. */ if(!yk_wait_for_key_status(yk, yk_cmd, 0, WAIT_FOR_WRITE_FLAG, false, SLOT_WRITE_FLAG, NULL)) return 0; /* Verify update */ if (!yk_get_status(yk, &stat /*, 0*/)) return 0; yk_errno = YK_EWRITEERR; /* when both configurations from a YubiKey is erased it will return * pgmSeq 0, if one is still configured after an erase pgmSeq is * counted up as usual. */ if((stat.touchLevel & (CONFIG1_VALID | CONFIG2_VALID)) == 0 && stat.pgmSeq == 0) { return 1; } return stat.pgmSeq != seq; }
YK_KEY *yk_open_first_key(void) { YK_KEY *yk = _ykusb_open_device(YUBICO_VID, YUBIKEY_PID); int rc = yk_errno; if (yk) { YK_STATUS st; if (!yk_get_status(yk, &st)) { rc = yk_errno; yk_close_key(yk); yk = NULL; } } yk_errno = rc; return yk; }
YK_KEY *yk_open_first_key(void) { int pids[] = {YUBIKEY_PID, NEO_OTP_PID, NEO_OTP_CCID_PID}; YK_KEY *yk = _ykusb_open_device(YUBICO_VID, pids, sizeof(pids)); int rc = yk_errno; if (yk) { YK_STATUS st; if (!yk_get_status(yk, &st)) { rc = yk_errno; yk_close_key(yk); yk = NULL; } } yk_errno = rc; return yk; }
/// /// Get the Info about the first YubiKey /// __declspec(dllexport) int GetInfo(YK_INFO *info) { int pid; YK_KEY* key = yk_open_first_key_with_pid(&pid); if (key == NULL) { _lastError = yk_errno; return ERROR_CANNOT_OPEN_KEY; } yk_get_status(key, &info->status); yk_get_serial(key, 0, 0, &info->serial); info->pid = pid; yk_close_key(key); return 0; }
YK_KEY *yk_open_key(int index) { int pids[] = {YUBIKEY_PID, NEO_OTP_PID, NEO_OTP_CCID_PID, NEO_OTP_U2F_PID, NEO_OTP_U2F_CCID_PID, YK4_OTP_PID, YK4_OTP_U2F_PID, YK4_OTP_CCID_PID, YK4_OTP_U2F_CCID_PID, PLUS_U2F_OTP_PID}; YK_KEY *yk = _ykusb_open_device(YUBICO_VID, pids, sizeof(pids) / sizeof(int), index); int rc = yk_errno; if (yk) { YK_STATUS st; if (!yk_get_status(yk, &st)) { rc = yk_errno; yk_close_key(yk); yk = NULL; } } yk_errno = rc; return yk; }
int yk_check_firmware_version(YK_KEY *k) { YK_STATUS st; if (!yk_get_status(k, &st)) return 0; if (!((st.versionMajor == 0 && (st.versionMinor == 9 || st.versionBuild == 9)) || (st.versionMajor == 1 && (st.versionMinor == 0 || st.versionMinor == 1 || st.versionMinor == 2 || st.versionMinor == 3)) || (st.versionMajor == 2 && (st.versionMinor == 0 || st.versionMinor == 1 || st.versionMinor == 2 || st.versionMinor == 3)))) { yk_errno = YK_EFIRMWARE; return 0; } return 1; }
void YubiKeyWriter::writeConfig(YubiKeyConfig *ykConfig) { YubiKeyFinder::getInstance()->stop(); YK_KEY *yk = 0; YK_STATUS *ykst = YubiKeyFinder::getInstance()->status(); YKP_CONFIG *cfg = ykp_alloc(); bool error = false; qDebug() << "-------------------------"; qDebug() << "Starting write config"; qDebug() << "-------------------------"; try { if (!(yk = yk_open_first_key())) { throw 0; } else if (!yk_get_status(yk, ykst)) { throw 0; } ykp_configure_version(cfg, ykst); qDebug() << "writer:configuration slot:" << ykConfig->configSlot(); bool useAccessCode; unsigned char accessCode[MAX_SIZE]; if(!assembleConfig(ykConfig, cfg, &useAccessCode, accessCode)) { throw 0; } //Log configuration... qDebug() << "-------------------------"; qDebug() << "Config data to be written to key configuration..."; char conf_buf[1024]; ykp_export_config(cfg, conf_buf, 1024, YKP_FORMAT_LEGACY); qDebug() << conf_buf; qDebug() << "-------------------------"; // Write configuration... if (!yk_write_command(yk, ykp_core_config(cfg), ykp_command(cfg), useAccessCode ? accessCode : NULL)) { qDebug() << "Failure"; throw 0; } qDebug() << "Success... config written"; emit diagnostics(QString("Successfully wrote config to slot %1").arg(ykp_config_num(cfg))); YubiKeyLogger::logConfig(ykConfig); emit configWritten(true, NULL); } catch(...) { error = true; } if (cfg) { ykp_free_config(cfg); } if (yk && !yk_close_key(yk)) { error = true; } YubiKeyFinder::getInstance()->start(); if(error) { qDebug() << "Config not written"; QString errMsg = reportError(); emit configWritten(false, errMsg); } qDebug() << "-------------------------"; qDebug() << "Stopping write config"; qDebug() << "-------------------------"; }
int main(int argc, char **argv) { YK_KEY *yk = 0; bool error = true; int exit_code = 0; /* Options */ bool serial_dec = false; bool serial_modhex = false; bool serial_hex = false; bool version = false; bool touch_level = false; bool pgm_seq = false; bool slot1 = false; bool slot2 = false; bool vid = false; bool pid = false; bool quiet = false; yk_errno = 0; if (! parse_args(argc, argv, &serial_dec, &serial_modhex, &serial_hex, &version, &touch_level, &pgm_seq, &quiet, &slot1, &slot2, &vid, &pid, &exit_code)) exit(exit_code); if (!yk_init()) { exit_code = 1; goto err; } if (!(yk = yk_open_first_key())) { exit_code = 1; goto err; } if(serial_dec || serial_modhex || serial_hex) { unsigned int serial; int ret = yk_get_serial(yk, 1, 0, &serial); if(!ret) { exit_code = 1; goto err; } if(serial_dec) { if(!quiet) printf("serial: "); printf("%d\n", serial); } if(serial_modhex || serial_hex) { char buf[64]; char hex_serial[64]; char modhex_serial[64]; char *ptr = buf; int chars = snprintf(buf + 1, 63, "%x", serial); if(chars % 2 == 1) { buf[0] = '0'; } else { ptr += 1; } if(serial_hex) { if(!quiet) printf("serial_hex: "); printf("%s\n", ptr); } if(serial_modhex) { yubikey_hex_decode(hex_serial, ptr, strlen(ptr)); yubikey_modhex_encode(modhex_serial, hex_serial, strlen(hex_serial)); if(!quiet) printf("serial_modhex: "); printf("%s\n", modhex_serial); } } } if(version || touch_level || pgm_seq || slot1 || slot2) { YK_STATUS *st = ykds_alloc(); if(!yk_get_status(yk, st)) { ykds_free(st); exit_code = 1; goto err; } if(version) { if(!quiet) printf("version: "); printf("%d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st)); } if(touch_level) { if(!quiet) printf("touch_level: "); printf("%d\n", ykds_touch_level(st)); } if(pgm_seq) { if(!quiet) printf("programming_sequence: "); printf("%d\n", ykds_pgm_seq(st)); } if(slot1) { if(!quiet) printf("slot1_status: "); printf("%d\n", (ykds_touch_level(st) & CONFIG1_VALID) == CONFIG1_VALID); } if(slot2) { if(!quiet) printf("slot2_status: "); printf("%d\n", (ykds_touch_level(st) & CONFIG2_VALID) == CONFIG2_VALID); } ykds_free(st); } if(vid || pid) { int vendor_id, product_id; if(!yk_get_key_vid_pid(yk, &vendor_id, &product_id)) { exit_code = 1; goto err; } if(vid) { if(!quiet) printf("vendor_id: "); printf("%x\n", vendor_id); } if(pid) { if(!quiet) printf("product_id: "); printf("%x\n", product_id); } } exit_code = 0; error = false; err: if (error || exit_code != 0) { report_yk_error(); } if (yk && !yk_close_key(yk)) { report_yk_error(); exit_code = 2; } if (!yk_release()) { report_yk_error(); exit_code = 2; } exit(exit_code); }
int main(int argc, char** argv) { char showmessage = 1; if((argc == 2) && (strcmp(argv[1], "-y") == 0)) showmessage = 0; if(showmessage == 1) { puts("--------------------------------------------"); puts("Hi! You're going to crack the access code of"); puts("a Yubikey. As soon as the appropriate code "); puts("is found, the AES key will be set to zeros."); puts("Brute forcing the code can take a very long "); puts("time, and with long I mean like more than a "); puts("year."); puts("(By the way you can bypass this message by "); puts("passing the -y option to the program.) "); puts("--------------------------------------------"); puts("Type \"start\" to continue."); char acknowledge[256]; fgets(acknowledge, 256, stdin); if(strcmp(acknowledge, "start\n") != 0) { puts("Quitting."); return EXIT_SUCCESS; } } yk = 0; unsigned char access_code[6]; const char* aeshash="00000000000000000000000000000000"; YKP_CONFIG *cfg = ykp_create_config(); YK_STATUS *st = ykds_alloc(); if(!yk_init()) { fputs("Failed to init Yubikey.\n", stderr); return EXIT_FAILURE; } if(!(yk = yk_open_first_key())) { fputs("No Yubikey found.\n", stderr); return EXIT_FAILURE; } if(!yk_get_status(yk,st)) { fputs("Failed to get status of the Yubikey.\n", stderr); return EXIT_FAILURE; } printf("Found Yubikey. Version: %d.%d.%d Touch level: %d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st), ykds_touch_level(st)); if(!ykp_configure_for(cfg, 1, st)) { printf("Can't set configuration to 1.\n"); return EXIT_FAILURE; } if(ykp_AES_key_from_hex(cfg, aeshash)) { fputs("Bad AES key. WTF did you do to my source?", stderr); return EXIT_FAILURE; } coreconfig = ykp_core_config(cfg); coreconfignum = ykp_config_num(cfg); bruteforce(access_code, 5); if(st) free(st); if(!yk_close_key(yk)) { fputs("Can't close Yubikey! What the hell are you doing over there?", stderr); return EXIT_FAILURE; } if(!yk_release()) { fputs("Can't release Yubikey.", stderr); return EXIT_FAILURE; } if(cfg) ykp_free_config(cfg); return EXIT_SUCCESS; }
int main(int argc, char **argv) { YK_KEY *yk = 0; bool error = true; int exit_code = 0; /* Options */ bool serial_dec = false; bool serial_modhex = false; bool serial_hex = false; bool version = false; bool touch_level = false; bool pgm_seq = false; bool quiet = false; yk_errno = 0; if (! parse_args(argc, argv, &serial_dec, &serial_modhex, &serial_hex, &version, &touch_level, &pgm_seq, &quiet, &exit_code)) exit(exit_code); if (!yk_init()) { exit_code = 1; goto err; } if (!(yk = yk_open_first_key())) { exit_code = 1; goto err; } if(serial_dec || serial_modhex || serial_hex) { unsigned int serial; int ret = yk_get_serial(yk, 1, 0, &serial); if(!ret) { exit_code = 1; goto err; } if(serial_dec) { if(!quiet) printf("serial: "); printf("%d\n", serial); } if(serial_hex) { if(!quiet) printf("serial_hex: "); printf("%x\n", serial); } if(serial_modhex) { char buf[64]; char hex_serial[64]; char modhex_serial[64]; snprintf(buf, 64, "%x", serial); yubikey_hex_decode(hex_serial, buf, strlen(buf)); yubikey_modhex_encode(modhex_serial, hex_serial, strlen(hex_serial)); if(!quiet) printf("serial_modhex: "); printf("%s\n", modhex_serial); } } if(version || touch_level || pgm_seq) { YK_STATUS *st = ykds_alloc(); if(!yk_get_status(yk, st)) { ykds_free(st); exit_code = 1; goto err; } if(version) { if(!quiet) printf("version: "); printf("%d.%d.%d\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st)); } if(touch_level) { if(!quiet) printf("touch_level: "); printf("%d\n", ykds_touch_level(st)); } if(pgm_seq) { if(!quiet) printf("programming_sequence: "); printf("%d\n", ykds_pgm_seq(st)); } ykds_free(st); } exit_code = 0; error = false; err: if (error || exit_code != 0) { report_yk_error(); } if (yk && !yk_close_key(yk)) { report_yk_error(); exit_code = 2; } if (!yk_release()) { report_yk_error(); exit_code = 2; } exit(exit_code); }
int yk_write_config(YK_KEY *yk, YK_CONFIG *cfg, int confnum, unsigned char *acc_code) { unsigned char buf[sizeof(YK_CONFIG) + ACC_CODE_SIZE]; YK_STATUS stat; int seq; uint8_t slot; /* Get current sequence # from status block */ if (!yk_get_status(yk, &stat /*, 0*/)) return 0; seq = stat.pgmSeq; /* Update checksum and insert config block in buffer if present */ memset(buf, 0, sizeof(buf)); if (cfg) { cfg->crc = ~yubikey_crc16 ((unsigned char *) cfg, sizeof(YK_CONFIG) - sizeof(cfg->crc)); cfg->crc = yk_endian_swap_16(cfg->crc); memcpy(buf, cfg, sizeof(YK_CONFIG)); } /* Append current access code if present */ if (acc_code) memcpy(buf + sizeof(YK_CONFIG), acc_code, ACC_CODE_SIZE); /* Write to Yubikey */ switch(confnum) { case 1: slot = SLOT_CONFIG; break; case 2: slot = SLOT_CONFIG2; break; } if (!yk_write_to_key(yk, slot, buf, sizeof(buf))) return 0; /* When the Yubikey clears the SLOT_WRITE_FLAG, it has processed the last write. * This wait can't be done in yk_write_to_key since some users of that function * want to get the bytes in the status message, but when writing configuration * we don't expect any data back. */ yk_wait_for_key_status(yk, slot, 0, WAIT_FOR_WRITE_FLAG, false, SLOT_WRITE_FLAG, NULL); /* Verify update */ if (!yk_get_status(yk, &stat /*, 0*/)) return 0; yk_errno = YK_EWRITEERR; if (cfg) { return stat.pgmSeq != seq; } return stat.pgmSeq == 0; }