]> err.no Git - yubikey-personalization/commitdiff
Add flag and API for OATH initial moving factor.
authorFrank Cusack <frank@google.com>
Wed, 20 Jul 2011 10:12:11 +0000 (12:12 +0200)
committerSimon Josefsson <simon@josefsson.org>
Wed, 20 Jul 2011 10:12:11 +0000 (12:12 +0200)
Signed-off-by: Simon Josefsson <simon@josefsson.org>
libykpers-1.map
ykpers-args.c
ykpers.c
ykpers.h

index 3fb110c6f4cd1e320bb4826a9e4f0b9353fd08ba..582da7ddd865618d0d668802c2bf5a2e60caef2e 100644 (file)
@@ -116,5 +116,7 @@ LIBYKPERS_1.5 {
   yk_wait_for_key_status;
   yk_read_response_from_key;
   yk_get_serial;
+  ykp_set_oath_imf;
+  ykp_get_oath_imf;
 # Variables:
 } LIBYKPERS_1.4;
index a25d6a80a2536f40fea72cbf5923ed5194858d4f..6d8620c245e1d5baf31b9bf3f1358a924d6431ad 100644 (file)
@@ -113,6 +113,7 @@ const char *usage =
 "          [-]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"
@@ -416,6 +417,31 @@ int args_to_config(int argc, char **argv, YKP_CONFIG *cfg,
                        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) {              \
index 6f0b95428e4a7f3f78ea5a76e6d3dffa18a70625..c833653aa8eabe6ecee6b5109aba58f9096390f8 100644 (file)
--- a/ykpers.c
+++ b/ykpers.c
@@ -309,6 +309,36 @@ static bool vcheck_v22_or_greater(const YKP_CONFIG *cfg)
                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)      \
 {                                                              \
@@ -431,6 +461,7 @@ const char str_fixed[] = "fixed";
 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[] = "|";
 
@@ -569,6 +600,21 @@ int ykp_write_config(const YKP_CONFIG *cfg,
                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++) {
@@ -693,6 +739,7 @@ static const char *errtext[] = {
        "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)
 {
index cf0ef187f2e33cf74c0cdfa98154ab4a95b378c7..614cdb374295b57fc82419a7fdc3790635c0fc97 100644 (file)
--- a/ykpers.h
+++ b/ykpers.h
@@ -54,6 +54,8 @@ int ykp_HMAC_key_from_hex(YKP_CONFIG *cfg, const char *hexkey);
 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);
@@ -109,5 +111,6 @@ const char *ykp_strerror(int errnum);
 #define YKP_EYUBIKEYVER        0x03
 #define YKP_EOLDYUBIKEY        0x04
 #define YKP_EINVCONFNUM        0x05
+#define YKP_EINVAL     0x06
 
 #endif // __YKPERS_H_INCLUDED__