From b8f2eab2851d54416166c65cbc6bc9dfb1cf48ba Mon Sep 17 00:00:00 2001 From: Tollef Fog Heen Date: Sat, 30 Jan 2010 10:06:05 +0000 Subject: [PATCH] Add OATH-HOTP support In addition, rewrite help output to make it more readable and ticket- and configuration flag parsing to make it easier to read. --- libykpers-1.map | 5 ++ ykcore/ykdef.h | 30 ++++++--- ykpers.c | 18 +++++- ykpers.h | 5 ++ ykpersonalize.c | 165 +++++++++++++++++++++--------------------------- 5 files changed, 121 insertions(+), 102 deletions(-) diff --git a/libykpers-1.map b/libykpers-1.map index 2f07de5..edd4d16 100644 --- a/libykpers-1.map +++ b/libykpers-1.map @@ -70,6 +70,10 @@ LIBYKPERS_1.0 { ykp_set_cfgflag_STRONG_PW1; ykp_set_cfgflag_STRONG_PW2; ykp_set_cfgflag_TICKET_FIRST; + ykp_set_cfgflag_OATH_HOTP8; + ykp_set_cfgflag_OATH_FIXED_MODHEX1; + ykp_set_cfgflag_OATH_FIXED_MODHEX2; + ykp_set_cfgflag_OATH_FIXED_MODHEX; ykp_set_fixed; ykp_set_tktflag_APPEND_CR; ykp_set_tktflag_APPEND_DELAY1; @@ -78,6 +82,7 @@ LIBYKPERS_1.0 { ykp_set_tktflag_APPEND_TAB2; ykp_set_tktflag_PROTECT_CFG2; ykp_set_tktflag_TAB_FIRST; + ykp_set_tktflag_OATH_HOTP; ykp_set_uid; ykp_strerror; ykp_write_config; diff --git a/ykcore/ykdef.h b/ykcore/ykdef.h index 55bb70f..16be86e 100644 --- a/ykcore/ykdef.h +++ b/ykcore/ykdef.h @@ -3,11 +3,12 @@ ** ** ** Y K D E F - Common Yubikey project header ** ** ** -** Date / Rev / Sign / Remark ** -** 06-06-03 / 0.9.0 / J E / Main ** -** 06-08-25 / 1.0.0 / J E / Rewritten for final spec ** -** 08-06-03 / 1.3.0 / J E / Added static OTP feature ** -** 09-06-02 / 2.0.0 / J E / Added version 2 flags ** +** Date / Rev / Sign / Remark ** +** 06-06-03 / 0.9.0 / J E / Main ** +** 06-08-25 / 1.0.0 / J E / Rewritten for final spec ** +** 08-06-03 / 1.3.0 / J E / Added static OTP feature ** +** 09-06-02 / 2.0.0 / J E / Added version 2 flags ** +** 09-09-23 / 2.1.0 / J E / Added version 2.1 flags (OATH-HOTP) ** ** ** *****************************************************************************************/ @@ -55,6 +56,7 @@ struct ticket_st { #define FIXED_SIZE 16 /* Max size of fixed field */ #define KEY_SIZE 16 /* Size of AES key */ +#define KEY_SIZE_OATH 20 /* Size of OATH-HOTP key (key field + first 4 of UID field) */ #define ACC_CODE_SIZE 6 /* Size of access code to re-program device */ struct config_st { @@ -72,7 +74,7 @@ struct config_st { /* Ticket flags **************************************************************/ -/* Yubikey 1 and newer */ +/* Yubikey 1 and above */ #define TKTFLAG_TAB_FIRST 0x01 /* Send TAB before first part */ #define TKTFLAG_APPEND_TAB1 0x02 /* Send TAB after first part */ #define TKTFLAG_APPEND_TAB2 0x04 /* Send TAB after second part */ @@ -80,12 +82,15 @@ struct config_st { #define TKTFLAG_APPEND_DELAY2 0x10 /* Add 0.5s delay after second part */ #define TKTFLAG_APPEND_CR 0x20 /* Append CR as final character */ -/* Yubikey 2 only */ +/* Yubikey 2 and above */ #define TKTFLAG_PROTECT_CFG2 0x80 /* Block update of config 2 unless config 2 is configured and has this bit set */ +/* Yubikey 2.1 and above */ +#define TKTFLAG_OATH_HOTP 0x40 /* OATH HOTP mode */ + /* Configuration flags *******************************************************/ -/* Yubikey 1 and newer */ +/* Yubikey 1 and above */ #define CFGFLAG_SEND_REF 0x01 /* Send reference string (0..F) before data */ #define CFGFLAG_PACING_10MS 0x04 /* Add 10ms intra-key pacing */ #define CFGFLAG_PACING_20MS 0x08 /* Add 20ms intra-key pacing */ @@ -95,12 +100,19 @@ struct config_st { #define CFGFLAG_TICKET_FIRST 0x02 /* Send ticket first (default is fixed part) */ #define CFGFLAG_ALLOW_HIDTRIG 0x10 /* Allow trigger through HID/keyboard */ -/* Yubikey 2 only */ +/* Yubikey 2 and above */ #define CFGFLAG_SHORT_TICKET 0x02 /* Send truncated ticket (half length) */ #define CFGFLAG_STRONG_PW1 0x10 /* Strong password policy flag #1 (mixed case) */ #define CFGFLAG_STRONG_PW2 0x40 /* Strong password policy flag #2 (subtitute 0..7 to digits) */ #define CFGFLAG_MAN_UPDATE 0x80 /* Allow manual (local) update of static OTP */ +/* Yubikey 2.1 and above */ +#define CFGFLAG_OATH_HOTP8 0x02 /* Generate 8 digits HOTP rather than 6 digits */ +#define CFGFLAG_OATH_FIXED_MODHEX1 0x10 /* First byte in fixed part sent as modhex */ +#define CFGFLAG_OATH_FIXED_MODHEX2 0x40 /* First two bytes in fixed part sent as modhex */ +#define CFGFLAG_OATH_FIXED_MODHEX 0x50 /* Fixed part sent as modhex */ +#define CFGFLAG_OATH_FIXED_MASK 0x50 /* Mask to get out fixed flags */ + /* Navigation */ /* NOTE: Navigation isn't available since Yubikey 1.3.5 and is strongly diff --git a/ykpers.c b/ykpers.c index 497abd7..e77ee0c 100644 --- a/ykpers.c +++ b/ykpers.c @@ -229,6 +229,13 @@ static bool vcheck_no_v1(const YKP_CONFIG *cfg) return cfg->yk_major_version > 1; } +static bool vcheck_v21_or_greater(const YKP_CONFIG *cfg) +{ + return (cfg->yk_major_version == 2 && + cfg->yk_minor_version >= 1) || + cfg->yk_major_version > 2; +} + #define def_set_charfield(fnname,fieldname,size,extra,vcheck) \ int ykp_set_ ## fnname(YKP_CONFIG *cfg, unsigned char *input, size_t len) \ { \ @@ -300,6 +307,7 @@ def_set_tktflag(APPEND_DELAY1,vcheck_all) def_set_tktflag(APPEND_DELAY2,vcheck_all) def_set_tktflag(APPEND_CR,vcheck_all) def_set_tktflag(PROTECT_CFG2,vcheck_no_v1) +def_set_tktflag(OATH_HOTP,vcheck_v21_or_greater) def_set_cfgflag(SEND_REF,vcheck_all) def_set_cfgflag(TICKET_FIRST,vcheck_v1) @@ -311,7 +319,10 @@ def_set_cfgflag(SHORT_TICKET,vcheck_no_v1) def_set_cfgflag(STRONG_PW1,vcheck_no_v1) def_set_cfgflag(STRONG_PW2,vcheck_no_v1) def_set_cfgflag(MAN_UPDATE,vcheck_no_v1) - +def_set_cfgflag(OATH_HOTP8,vcheck_v21_or_greater) +def_set_cfgflag(OATH_FIXED_MODHEX1,vcheck_v21_or_greater) +def_set_cfgflag(OATH_FIXED_MODHEX2,vcheck_v21_or_greater) +def_set_cfgflag(OATH_FIXED_MODHEX,vcheck_v21_or_greater) const char str_key_value_separator[] = ": "; const char str_hex_prefix[] = "h:"; @@ -338,6 +349,7 @@ struct map_st ticket_flags_map[] = { { TKTFLAG_APPEND_DELAY2, "APPEND_DELAY2", vcheck_all }, { TKTFLAG_APPEND_CR, "APPEND_CR", vcheck_all }, { TKTFLAG_PROTECT_CFG2, "PROTECT_CFG2", vcheck_no_v1 }, + { TKTFLAG_OATH_HOTP, "PROTECT_OATH_HOTP", vcheck_v21_or_greater }, { 0, "" } }; @@ -353,6 +365,10 @@ struct map_st config_flags_map[] = { { CFGFLAG_STRONG_PW1, "STRONG_PW1", vcheck_no_v1 }, { CFGFLAG_STRONG_PW2, "STRONG_PW2", vcheck_no_v1 }, { CFGFLAG_MAN_UPDATE, "MAN_UPDATE", vcheck_no_v1 }, + { CFGFLAG_OATH_HOTP8, "OATH_HOTP8", vcheck_v21_or_greater }, + { CFGFLAG_OATH_FIXED_MODHEX1, "OATH_FIXED_MODHEX1", vcheck_v21_or_greater }, + { CFGFLAG_OATH_FIXED_MODHEX2, "OATH_FIXED_MODHEX2", vcheck_v21_or_greater }, + { CFGFLAG_OATH_FIXED_MODHEX, "OATH_FIXED_MODHEX", vcheck_v21_or_greater }, { 0, "" } }; diff --git a/ykpers.h b/ykpers.h index 193286a..cb394d2 100644 --- a/ykpers.h +++ b/ykpers.h @@ -61,6 +61,7 @@ int ykp_set_tktflag_APPEND_DELAY1(YKP_CONFIG *cfg, bool state); int ykp_set_tktflag_APPEND_DELAY2(YKP_CONFIG *cfg, bool state); int ykp_set_tktflag_APPEND_CR(YKP_CONFIG *cfg, bool state); int ykp_set_tktflag_PROTECT_CFG2(YKP_CONFIG *cfg, bool state); +int ykp_set_tktflag_OATH_HOTP(YKP_CONFIG *cfg, bool state); int ykp_set_cfgflag_SEND_REF(YKP_CONFIG *cfg, bool state); int ykp_set_cfgflag_TICKET_FIRST(YKP_CONFIG *cfg, bool state); @@ -72,6 +73,10 @@ int ykp_set_cfgflag_SHORT_TICKET(YKP_CONFIG *cfg, bool state); int ykp_set_cfgflag_STRONG_PW1(YKP_CONFIG *cfg, bool state); int ykp_set_cfgflag_STRONG_PW2(YKP_CONFIG *cfg, bool state); int ykp_set_cfgflag_MAN_UPDATE(YKP_CONFIG *cfg, bool state); +int ykp_set_cfgflag_OATH_HOTP8(YKP_CONFIG *cfg, bool state); +int ykp_set_cfgflag_OATH_FIXED_MODHEX1(YKP_CONFIG *cfg, bool state); +int ykp_set_cfgflag_OATH_FIXED_MODHEX2(YKP_CONFIG *cfg, bool state); +int ykp_set_cfgflag_OATH_FIXED_MODHEX(YKP_CONFIG *cfg, bool state); int ykp_write_config(const YKP_CONFIG *cfg, int (*writer)(const char *buf, size_t count, diff --git a/ykpersonalize.c b/ykpersonalize.c index 826bad1..02d7267 100644 --- a/ykpersonalize.c +++ b/ykpersonalize.c @@ -1,6 +1,7 @@ /* -*- mode:C; c-file-style: "bsd" -*- */ /* * Copyright (c) 2008, 2009, Yubico AB + * Copyright (c) 2010 Tollef Fog Heen * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -65,30 +66,43 @@ const char *usage = " MUST be 12 characters long.\n" " access=xxxxxxxxxxx New access code to set, in HEX.\n" " MUST be 12 characters long.\n" -" [-]tab-first set/clear the TAB_FIRST ticket flag.\n" -" [-]append-tab1 set/clear the APPEND_TAB1 ticket flag.\n" -" [-]append-tab2 set/clear the APPEND_TAB2 ticket flag.\n" -" [-]append-delay1 set/clear the APPEND_DELAY1 ticket flag.\n" -" [-]append-delay2 set/clear the APPEND_DELAY2 ticket flag.\n" -" [-]append-cr set/clear the APPEND_CR ticket flag.\n" -" [-]protect-cfg2 set/clear the PROTECT_CFG2 ticket flag.\n" -" (only with Yubikey II!)\n" -" [-]send-ref set/clear the SEND_REF configuration flag.\n" -" [-]ticket-first set/clear the TICKET_FIRST configuration flag.\n" -" (only with Yubikey I!)\n" -" [-]pacing-10ms set/clear the PACING_10MS configuration flag.\n" -" [-]pacing-20ms set/clear the PACING_20MS configuration flag.\n" -" [-]allow-hidtrig set/clear the ALLOW_HIDTRIG configuration flag.\n" -" (only with Yubikey I!)\n" -" [-]static-ticket set/clear the STATIC_TICKET configuration flag.\n" -" [-]short-ticket set/clear the SHORT_TICKET configuration flag.\n" -" (only with Yubikey II!)\n" -" [-]strong-pw1 set/clear the STRONG_PW1 configuration flag.\n" -" (only with Yubikey II!)\n" -" [-]strong-pw2 set/clear the STRONG_PW2 configuration flag.\n" -" (only with Yubikey II!)\n" -" [-]man-update set/clear the MAN_UPDATE configuration flag.\n" -" (only with Yubikey II!)\n" +"\n" +" Ticket flags for all firmware versions:\n" +" [-]tab-first set/clear TAB_FIRST\n" +" [-]append-tab1 set/clear APPEND_TAB1\n" +" [-]append-tab2 set/clear APPEND_TAB2\n" +" [-]append-delay1 set/clear APPEND_DELAY1\n" +" [-]append-delay2 set/clear APPEND_DELAY2\n" +" [-]append-cr set/clear APPEND_CR\n" +"\n" +" Ticket flags for firmware version 2.0 and above:\n" +" [-]protect-cfg2 set/clear PROTECT_CFG2\n" +"\n" +" Ticket flags for firmware version 2.1 and above:\n" +" [-]oath-hotp set/clear OATH_HOTP\n" +"\n" +" Configuration flags for all firmware versions:\n" +" [-]send-ref set/clear SEND_REF\n" +" [-]pacing-10ms set/clear PACING_10MS\n" +" [-]pacing-20ms set/clear PACING_20MS\n" +" [-]static-ticket set/clear STATIC_TICKET\n" +"\n" +" Configuration flags for firmware version 1.x only:\n" +" [-]ticket-first set/clear TICKET_FIRST\n" +" [-]allow-hidtrig set/clear ALLOW_HIDTRIG\n" +"\n" +" Configuration flags for firmware version 2.0 and above:\n" +" [-]short-ticket set/clear SHORT_TICKET\n" +" [-]strong-pw1 set/clear STRONG_PW1\n" +" [-]strong-pw2 set/clear STRONG_PW2\n" +" [-]man-update set/clear MAN_UPDATE\n" +"\n" +" Configuration flags for firmware version 2.1 and above:\n" +" [-]oath-hotp8 set/clear OATH_HOTP8\n" +" [-]oath-fixed-modhex1 set/clear OATH_FIXED_MODHEX1\n" +" [-]oath-fixed-modhex2 set/clear OATH_FIXED_MODHEX2\n" +" [-]oath-fixed-modhex set/clear OATH_MODHEX\n" +"\n" "-y always commit (do not prompt)\n" "\n" "-v verbose\n" @@ -326,74 +340,41 @@ int main(int argc, char **argv) ykp_set_access_code(cfg, accbin, accbinlen); new_access_code = true; } - else if (strcmp(optarg, "tab-first") == 0) - ykp_set_tktflag_TAB_FIRST(cfg, true); - else if (strcmp(optarg, "-tab-first") == 0) - ykp_set_tktflag_TAB_FIRST(cfg, false); - else if (strcmp(optarg, "append-tab1") == 0) - ykp_set_tktflag_APPEND_TAB1(cfg, true); - else if (strcmp(optarg, "-append-tab1") == 0) - ykp_set_tktflag_APPEND_TAB1(cfg, false); - else if (strcmp(optarg, "append-tab2") == 0) - ykp_set_tktflag_APPEND_TAB1(cfg, true); - else if (strcmp(optarg, "-append-tab2") == 0) - ykp_set_tktflag_APPEND_TAB1(cfg, false); - else if (strcmp(optarg, "append-delay1") == 0) - ykp_set_tktflag_APPEND_DELAY1(cfg, true); - else if (strcmp(optarg, "-append-delay1") == 0) - ykp_set_tktflag_APPEND_DELAY1(cfg, false); - else if (strcmp(optarg, "append-delay2") == 0) - ykp_set_tktflag_APPEND_DELAY2(cfg, true); - else if (strcmp(optarg, "-append-delay2") == 0) - ykp_set_tktflag_APPEND_DELAY2(cfg, false); - else if (strcmp(optarg, "append-cr") == 0) - ykp_set_tktflag_APPEND_CR(cfg, true); - else if (strcmp(optarg, "-append-cr") == 0) - ykp_set_tktflag_APPEND_CR(cfg, false); - else if (strcmp(optarg, "protect-cfg2") == 0) - ykp_set_tktflag_PROTECT_CFG2(cfg, true); - else if (strcmp(optarg, "-protect-cfg2") == 0) - ykp_set_tktflag_PROTECT_CFG2(cfg, false); - else if (strcmp(optarg, "send-ref") == 0) - ykp_set_cfgflag_SEND_REF(cfg, true); - else if (strcmp(optarg, "-send-ref") == 0) - ykp_set_cfgflag_SEND_REF(cfg, false); - else if (strcmp(optarg, "ticket-first") == 0) - ykp_set_cfgflag_TICKET_FIRST(cfg, true); - else if (strcmp(optarg, "-ticket-first") == 0) - ykp_set_cfgflag_TICKET_FIRST(cfg, false); - else if (strcmp(optarg, "pacing-10ms") == 0) - ykp_set_cfgflag_PACING_10MS(cfg, true); - else if (strcmp(optarg, "-pacing-10ms") == 0) - ykp_set_cfgflag_PACING_10MS(cfg, false); - else if (strcmp(optarg, "pacing-20ms") == 0) - ykp_set_cfgflag_PACING_20MS(cfg, true); - else if (strcmp(optarg, "-pacing-20ms") == 0) - ykp_set_cfgflag_PACING_20MS(cfg, false); - else if (strcmp(optarg, "allow-hidtrig") == 0) - ykp_set_cfgflag_ALLOW_HIDTRIG(cfg, true); - else if (strcmp(optarg, "-allow-hidtrig") == 0) - ykp_set_cfgflag_ALLOW_HIDTRIG(cfg, false); - else if (strcmp(optarg, "static-ticket") == 0) - ykp_set_cfgflag_STATIC_TICKET(cfg, true); - else if (strcmp(optarg, "-static-ticket") == 0) - ykp_set_cfgflag_STATIC_TICKET(cfg, false); - else if (strcmp(optarg, "short-ticket") == 0) - ykp_set_cfgflag_SHORT_TICKET(cfg, true); - else if (strcmp(optarg, "-short-ticket") == 0) - ykp_set_cfgflag_SHORT_TICKET(cfg, false); - else if (strcmp(optarg, "strong-pw1") == 0) - ykp_set_cfgflag_STRONG_PW1(cfg, true); - else if (strcmp(optarg, "-strong-pw1") == 0) - ykp_set_cfgflag_STRONG_PW1(cfg, false); - else if (strcmp(optarg, "strong-pw2") == 0) - ykp_set_cfgflag_STRONG_PW2(cfg, true); - else if (strcmp(optarg, "-strong-pw2") == 0) - ykp_set_cfgflag_STRONG_PW2(cfg, false); - else if (strcmp(optarg, "man-update") == 0) - ykp_set_cfgflag_MAN_UPDATE(cfg, true); - else if (strcmp(optarg, "-man-update") == 0) - ykp_set_cfgflag_MAN_UPDATE(cfg, false); +#define TKTFLAG(o, f) \ + else if (strcmp(optarg, o) == 0) \ + ykp_set_tktflag_##f(cfg, true); \ + else if (strcmp(optarg, "-" o) == 0) \ + ykp_set_tktflag_##f(cfg, false) + TKTFLAG("tab-first", TAB_FIRST); + TKTFLAG("append-tab1", APPEND_TAB1); + TKTFLAG("append-tab2", APPEND_TAB2); + TKTFLAG("append-delay1", APPEND_DELAY1); + TKTFLAG("append-delay2", APPEND_DELAY2); + TKTFLAG("append-cr", APPEND_CR); + TKTFLAG("protect-cfg2", PROTECT_CFG2); + TKTFLAG("oath-hotp", OATH_HOTP); +#undef TKTFLAG + +#define CFGFLAG(o, f) \ + else if (strcmp(optarg, o) == 0) \ + ykp_set_cfgflag_##f(cfg, true); \ + else if (strcmp(optarg, "-" o) == 0) \ + ykp_set_cfgflag_##f(cfg, false) + CFGFLAG("send-ref", SEND_REF); + CFGFLAG("ticket-first", TICKET_FIRST); + CFGFLAG("pacing-10ms", PACING_10MS); + CFGFLAG("pacing-20ms", PACING_20MS); + CFGFLAG("allow-hidtrig", ALLOW_HIDTRIG); + CFGFLAG("static-ticket", STATIC_TICKET); + CFGFLAG("short-ticket", SHORT_TICKET); + CFGFLAG("strong-pw1", STRONG_PW1); + CFGFLAG("strong-pw2", STRONG_PW2); + CFGFLAG("man-update", MAN_UPDATE); + CFGFLAG("oath-hotp8", OATH_HOTP8); + CFGFLAG("oath-fixed-modhex1", OATH_FIXED_MODHEX1); + CFGFLAG("oath-fixed-modhex2", OATH_FIXED_MODHEX2); + CFGFLAG("oath-fixed-modhex", OATH_FIXED_MODHEX); +#undef CFGFLAG else { fprintf(stderr, "Unknown option '%s'\n", optarg); -- 2.39.5