" [-]chal-hmac set/clear CHAL_HMAC\n"
" [-]hmac-lt64 set/clear HMAC_LT64\n"
" [-]chal-btn-trig set/clear CHAL_BTN_TRIG\n"
+" oath-imf=IMF set OATH Initial Moving Factor\n"
"\n"
" Extended flags for firmware version 2.2 and above:\n"
" [-]serial-btn-visible set/clear SERIAL_BTN_VISIBLE\n"
CFGFLAG("hmac-lt64", HMAC_LT64)
CFGFLAG("chal-btn-trig", CHAL_BTN_TRIG)
#undef CFGFLAG
+ else if (strncmp(optarg, "oath-imf=", 9) == 0) {
+ unsigned long imf;
+
+ if (!(ycfg->tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP) {
+ fprintf(stderr,
+ "Option oath-imf= only valid with -ooath-hotp or -ooath-hotp8.\n"
+ );
+ *exit_code = 1;
+ return 0;
+ }
+
+ if (sscanf(optarg+9, "%lu", &imf) != 1 ||
+ /* yubikey limitations */
+ imf > 65535*16 || imf % 16 != 0) {
+ fprintf(stderr,
+ "Invalid value %s for oath-imf=.\n", optarg+9
+ );
+ *exit_code = 1;
+ return 0;
+ }
+ if (! ykp_set_oath_imf(cfg, imf)) {
+ *exit_code = 1;
+ return 0;
+ }
+ }
#define EXTFLAG(o, f) \
else if (strcmp(optarg, o) == 0) { \
cfg->yk_major_version > 2;
}
+int ykp_set_oath_imf(YKP_CONFIG *cfg, unsigned long imf)
+{
+ if (!vcheck_v22_or_greater(cfg)) {
+ ykp_errno = YKP_EYUBIKEYVER;
+ return 0;
+ }
+ if (imf > 65535*16) {
+ ykp_errno = YKP_EINVAL;
+ return 0;
+ }
+ if (imf % 16 != 0) {
+ ykp_errno = YKP_EINVAL;
+ return 0;
+ }
+ /* IMF/16 is 16 bits stored big-endian in uid[4] */
+ imf /= 16;
+ cfg->ykcore_config.uid[4] = imf >> 8;
+ cfg->ykcore_config.uid[5] = imf;
+ return 1;
+}
+
+unsigned long ykp_get_oath_imf(YKP_CONFIG *cfg)
+{
+ if (!vcheck_v22_or_greater(cfg))
+ return 0;
+
+ /* we can't do a simple cast due to alignment issues */
+ return ((cfg->ykcore_config.uid[4] << 8) | cfg->ykcore_config.uid[5]) << 4;
+}
+
#define def_set_charfield(fnname,fieldname,size,extra,vcheck) \
int ykp_set_ ## fnname(YKP_CONFIG *cfg, unsigned char *input, size_t len) \
{ \
const char str_uid[] = "uid";
const char str_key[] = "key";
const char str_acc_code[] = "acc_code";
+const char str_oath_imf[] = "OATH IMF";
const char str_flags_separator[] = "|";
writer(buffer, strlen(buffer), userdata);
writer("\n", 1, userdata);
+ /* OATH IMF: */
+ if ((cfg->ykcore_config.tktFlags & TKTFLAG_OATH_HOTP) == TKTFLAG_OATH_HOTP &&
+ vcheck_v22_or_greater(cfg)) {
+ writer(str_oath_imf, strlen(str_oath_imf), userdata);
+ writer(str_key_value_separator,
+ strlen(str_key_value_separator),
+ userdata);
+ writer(str_hex_prefix,
+ strlen(str_hex_prefix),
+ userdata);
+ sprintf(buffer, "%lx", ykp_get_oath_imf(cfg));
+ writer(buffer, strlen(buffer), userdata);
+ writer("\n", 1, userdata);
+ }
+
/* ticket_flags: */
buffer[0] = '\0';
for (p = ticket_flags_map; p->flag; p++) {
"option not available for this Yubikey version",
"too old yubikey for this operation",
"invalid configuration number (this is a programming error)",
+ "invalid option/argument value",
};
const char *ykp_strerror(int errnum)
{
int ykp_set_access_code(YKP_CONFIG *cfg, unsigned char *access_code, size_t len);
int ykp_set_fixed(YKP_CONFIG *cfg, unsigned char *fixed, size_t len);
int ykp_set_uid(YKP_CONFIG *cfg, unsigned char *uid, size_t len);
+int ykp_set_oath_imf(YKP_CONFIG *cfg, unsigned long imf);
+unsigned long ykp_get_oath_imf(YKP_CONFIG *cfg);
int ykp_set_tktflag_TAB_FIRST(YKP_CONFIG *cfg, bool state);
int ykp_set_tktflag_APPEND_TAB1(YKP_CONFIG *cfg, bool state);
#define YKP_EYUBIKEYVER 0x03
#define YKP_EOLDYUBIKEY 0x04
#define YKP_EINVCONFNUM 0x05
+#define YKP_EINVAL 0x06
#endif // __YKPERS_H_INCLUDED__