static int _set_fixed(char *opt, YKP_CONFIG *cfg) { const char *fixed = opt; size_t fixedlen = strlen (fixed); unsigned char fixedbin[256]; size_t fixedbinlen = 0; int rc = hex_modhex_decode(fixedbin, &fixedbinlen, fixed, fixedlen, 0, 32, true); if (rc <= 0) return 0; ykp_set_fixed(cfg, fixedbin, fixedbinlen); return 1; }
int YubiKeyWriter::assembleConfig(YubiKeyConfig *ykConfig, YKP_CONFIG *cfg, bool *useAccessCode, unsigned char *accessCode) { // Check features support bool flagSrNoSupport = false; bool flagUpdateSupport = false; bool flagImfSupport = false; bool flagLedInvSupport = false; YubiKeyFinder *finder = YubiKeyFinder::getInstance(); if(finder->checkFeatureSupport( YubiKeyFinder::Feature_SerialNumber)) { flagSrNoSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_Updatable)) { flagUpdateSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_MovingFactor)) { flagImfSupport = true; } if(finder->checkFeatureSupport( YubiKeyFinder::Feature_LedInvert)) { flagLedInvSupport = true; } //Programming Mode... bool longSecretKey = false; int command = ykConfig->configSlot() == 2 ? SLOT_CONFIG2 : SLOT_CONFIG; switch(ykConfig->programmingMode()) { case YubiKeyConfig::Mode_Update: // if we're doing an update it's other commands. command = ykConfig->configSlot() == 2 ? SLOT_UPDATE2 : SLOT_UPDATE1; break; case YubiKeyConfig::Mode_Swap: // swap has it's own command command = SLOT_SWAP; break; case YubiKeyConfig::Mode_YubicoOtp: break; case YubiKeyConfig::Mode_Static: CFGFLAG(STATIC_TICKET, ykConfig->staticTicket()); CFGFLAG(SHORT_TICKET, ykConfig->shortTicket()); CFGFLAG(STRONG_PW1, ykConfig->strongPw1()); CFGFLAG(STRONG_PW2, ykConfig->strongPw2()); CFGFLAG(MAN_UPDATE, ykConfig->manUpdate()); CFGFLAG(SEND_REF, ykConfig->sendRef()); break; case YubiKeyConfig::Mode_OathHotp: TKTFLAG(OATH_HOTP, true); CFGFLAG(OATH_HOTP8, ykConfig->oathHotp8()); CFGFLAG(OATH_FIXED_MODHEX1, ykConfig->oathFixedModhex1()); CFGFLAG(OATH_FIXED_MODHEX2, ykConfig->oathFixedModhex2()); CFGFLAG(OATH_FIXED_MODHEX, ykConfig->oathFixedModhex()); //Moving Factor Seed... if(flagImfSupport && !ykp_set_oath_imf(cfg, ykConfig->oathMovingFactorSeed())) { return 0; } //For OATH-HOTP, 160 bits key is also valid longSecretKey = true; break; case YubiKeyConfig::Mode_ChalRespYubico: TKTFLAG(CHAL_RESP, true); CFGFLAG(CHAL_YUBICO, ykConfig->chalYubico()); CFGFLAG(CHAL_BTN_TRIG, ykConfig->chalBtnTrig()); break; case YubiKeyConfig::Mode_ChalRespHmac: TKTFLAG(CHAL_RESP, true); CFGFLAG(CHAL_HMAC, ykConfig->chalHmac()); CFGFLAG(HMAC_LT64, ykConfig->hmacLT64()); CFGFLAG(CHAL_BTN_TRIG, ykConfig->chalBtnTrig()); //For HMAC (not Yubico) challenge-response, 160 bits key is also valid longSecretKey = true; break; } //Configuration slot... if (!ykp_configure_command(cfg, command)) { return 0; } //Public ID... if(ykConfig->pubIdTxt().length() > 0) { qDebug() << "Pub id: " << ykConfig->pubIdTxt() << "length:" << ykConfig->pubIdTxt().length(); char pubIdStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(pubIdStr, sizeof(pubIdStr), ykConfig->pubIdTxt()); size_t pubIdStrLen = strlen(pubIdStr); unsigned char pubId[MAX_SIZE]; size_t pubIdLen = 0; int rc = YubiKeyUtil::hexModhexDecode(pubId, &pubIdLen, pubIdStr, pubIdStrLen, 0, FIXED_SIZE * 2, !ykConfig->pubIdInHex()); if (rc <= 0) { qDebug("Invalid public id: %s", pubIdStr); return 0; } ykp_set_fixed(cfg, pubId, pubIdLen); } //Private ID... if(ykConfig->pvtIdTxt().length() > 0) { qDebug() << "Pvt id: " << ykConfig->pvtIdTxt() << "length:" << ykConfig->pvtIdTxt().length(); char pvtIdStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(pvtIdStr, sizeof(pvtIdStr), ykConfig->pvtIdTxt()); size_t pvtIdStrLen = strlen(pvtIdStr); unsigned char pvtId[MAX_SIZE]; size_t pvtIdLen = 0; int rc = YubiKeyUtil::hexModhexDecode(pvtId, &pvtIdLen, pvtIdStr, pvtIdStrLen, UID_SIZE * 2, UID_SIZE * 2, false); if (rc <= 0) { qDebug("Invalid private id: %s", pvtIdStr); return 0; } ykp_set_uid(cfg, pvtId, pvtIdLen); } //Secret Key... if(ykConfig->secretKeyTxt().length() > 0) { qDebug() << "Secret key: " << ykConfig->secretKeyTxt() << "length:" << ykConfig->secretKeyTxt().length(); char secretKeyStr[MAX_SIZE]; YubiKeyUtil::qstrToRaw(secretKeyStr, sizeof(secretKeyStr), ykConfig->secretKeyTxt()); int res = 0; if(longSecretKey && strlen(secretKeyStr) == 40) { res = ykp_HMAC_key_from_hex(cfg, secretKeyStr); } else { res = ykp_AES_key_from_hex(cfg, secretKeyStr); } if (res) { qDebug() << "Bad secret key: " << secretKeyStr; return 0; } } //Configuration protection... //Current Access Code... size_t accessCodeLen = 0; if(ykConfig->currentAccessCodeTxt().length() > 0) { int rc = encodeAccessCode(ykConfig->currentAccessCodeTxt(), accessCode, &accessCodeLen); if (rc <= 0) { qDebug() << "Invalid current access code: " << ykConfig->currentAccessCodeTxt(); return 0; } } //New Access Code... unsigned char newAccessCode[MAX_SIZE]; size_t newAccessCodeLen = 0; if(ykConfig->newAccessCodeTxt().length() > 0) { int rc = encodeAccessCode(ykConfig->newAccessCodeTxt(), newAccessCode, &newAccessCodeLen); if (rc <= 0) { qDebug() << "Invalid new access code: " << ykConfig->newAccessCodeTxt(); return 0; } if(ykConfig->accMode() > 0) { int accMode = 0; if(ykConfig->accMode() == Acc_None) { accMode = YKP_ACCCODE_NONE; } else if(ykConfig->accMode() == Acc_Serial) { accMode = YKP_ACCCODE_SERIAL; } else if(ykConfig->accMode() == Acc_Random) { accMode = YKP_ACCCODE_RANDOM; } ykp_set_acccode_type(cfg, accMode); } } if(accessCodeLen > 0) { *useAccessCode = true; } if(newAccessCodeLen > 0) { //Enable/change protection ykp_set_access_code(cfg, newAccessCode, newAccessCodeLen); } else if(accessCodeLen > 0) { //Keep same protection ykp_set_access_code(cfg, accessCode, accessCodeLen); } TKTFLAG(TAB_FIRST, ykConfig->tabFirst()); TKTFLAG(APPEND_TAB1, ykConfig->appendTab1()); TKTFLAG(APPEND_TAB2, ykConfig->appendTab2()); TKTFLAG(APPEND_CR, ykConfig->appendCr()); TKTFLAG(APPEND_DELAY1, ykConfig->appendDelay1()); TKTFLAG(APPEND_DELAY2, ykConfig->appendDelay2()); //TKTFLAG(PROTECT_CFG2, ykConfig->protectCfg2()); //CFGFLAG(SEND_REF, ykConfig->sendRef()); //CFGFLAG(TICKET_FIRST, ykConfig->ticketFirst()); CFGFLAG(PACING_10MS, ykConfig->pacing10ms()); CFGFLAG(PACING_20MS, ykConfig->pacing20ms()); //CFGFLAG(ALLOW_HIDTRIG, ykConfig->allowHidtrig()); //Serial # visibility... if(flagSrNoSupport) { EXTFLAG(SERIAL_BTN_VISIBLE, ykConfig->serialBtnVisible()); EXTFLAG(SERIAL_USB_VISIBLE, ykConfig->serialUsbVisible()); EXTFLAG(SERIAL_API_VISIBLE, ykConfig->serialApiVisible()); } if(flagUpdateSupport) { EXTFLAG(ALLOW_UPDATE, ykConfig->allowUpdate()); // XXX: let update support mean these as well.. EXTFLAG(DORMANT, ykConfig->dormant()); EXTFLAG(FAST_TRIG, ykConfig->fastTrig()); EXTFLAG(USE_NUMERIC_KEYPAD, ykConfig->useNumericKeypad()); } if(flagLedInvSupport) { EXTFLAG(LED_INV, ykConfig->ledInvert()); } return 1; }
static int _set_oath_id(char *opt, YKP_CONFIG *cfg, struct config_st *ycfg, YK_KEY *yk, YK_STATUS *st) { /* For details, see YubiKey Manual 2010-09-16 section 5.3.4 - OATH-HOTP Token Identifier */ if (!(ycfg->tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP) { fprintf(stderr, "Option oath-id= only valid with -ooath-hotp or -ooath-hotp8.\n" ); return 0; } if (! ykp_set_cfgflag_OATH_FIXED_MODHEX2(cfg, true)) return 0; if (! ykp_set_extflag_SERIAL_API_VISIBLE(cfg, true)) return 0; if (strlen(opt) > 7) { if (_set_fixed(opt + 8, cfg) != 1) { fprintf(stderr, "Invalid OATH token identifier %s supplied with oath-id=.\n", opt + 8 ); return 0; } } else { /* No Token Id supplied, try to create one automatically based on * the serial number of the YubiKey. */ unsigned int serial; uint8_t oath_id[12] = {0}; if (ykds_version_major(st) > 2 || (ykds_version_major(st) == 2 && ykds_version_minor(st) >= 2)) { if (! yk_get_serial(yk, 0, 0, &serial)) { fprintf(stderr, "YubiKey refuses reading serial number. " "Can't use -ooath-id.\n" ); return 0; } } else { fprintf(stderr, "YubiKey %d.%d.%d does not support reading serial number. " "Can't use -ooath-id.\n", ykds_version_major(st), ykds_version_minor(st), ykds_version_build(st) ); return 0; } if (_format_oath_id(oath_id, sizeof(oath_id), YUBICO_OATH_VENDOR_ID_HEX, YUBICO_HOTP_EVENT_TOKEN_TYPE, serial) != 1) { fprintf(stderr, "Failed formatting OATH token identifier.\n"); return 0; } if (ykp_set_fixed(cfg, oath_id, 6) != 1) { fprintf(stderr, "Failed setting OATH token identifier.\n" ); return 0; } } return 1; }