diff --git a/NEWS b/NEWS index f4d778f..4c0cd3a 100644 --- a/NEWS +++ b/NEWS @@ -6,6 +6,7 @@ Libyubikey NEWS -- History of user-visible changes. -*- outline -*- ** Better self tests. ** Fix memory leak. ** Document modhex alphabet. + ** Add different ModHex alphabets * Version 1.13 (released 2015-03-05) ** Correct hex decode with uneven characters, for example "abc". diff --git a/modhex.1.txt b/modhex.1.txt index ac0ef76..bc93255 100644 --- a/modhex.1.txt +++ b/modhex.1.txt @@ -52,6 +52,9 @@ The modhex alphabet is a base16 alphabet just as hex, they map as follows: 0 1 2 3 4 5 6 7 8 9 a b c d e f c b d e f g h i j k l n r t u v +When using yubikey devices on non-QWERTY keyboard layouts, these keys may map +to different letters. + SEE ALSO --------- YubiKeys can be obtained from Yubico: http://www.yubico.com/ diff --git a/modhex.c b/modhex.c index 57c3927..ed23435 100644 --- a/modhex.c +++ b/modhex.c @@ -157,9 +157,13 @@ main (int argc, char *argv[]) return 1; } - if (decode_p) + if (decode_p) { + if (!yubikey_modhex_p(data)) { + printf("Invalid modhex string\n"); + return 0; + } yubikey_modhex_decode (buf, data, inlen / 2); - else + } else yubikey_modhex_encode (buf, data, inlen); if (decode_p && hex_p) diff --git a/tests/selftest.c b/tests/selftest.c index 3f6c3cf..95e6a98 100644 --- a/tests/selftest.c +++ b/tests/selftest.c @@ -78,6 +78,45 @@ modhex_test3 (void) printf ("Modhex-3 success\n"); } +static void +modhex_test4 (void) +{ + char buf[1024]; + int rc; + + strcpy (buf, "jxe.uidchtnbpygk"); + rc = yubikey_modhex_p (buf); + printf ("modhex-p(\"%s\") = %d\n", buf, rc); + assert (rc == 1); + printf ("Modhex-4 success\n"); +} + +static void +modhex_test5 (void) +{ + char buf[1024]; + int rc; + + strcpy (buf, "cbsftdhuneikpglv"); + rc = yubikey_modhex_p (buf); + printf ("modhex-p(\"%s\") = %d\n", buf, rc); + assert (rc == 1); + printf ("Modhex-5 success\n"); +} + +static void +modhex_test6 (void) +{ + char buf[1024]; + char buf2[1024]; + + strcpy (buf, "vvnhvuuvihlstuhpkgvfthfpeifbnbbuscbhhphffisc"); + yubikey_modhex_decode(buf2, buf, sizeof (buf2)); + assert (memcmp (buf2, "\xff\xb6\xfe\xef\x76\xa0\xde\x60\x95\xf4\xd6\x40\x37\x41\xb1\x1e\x00\x16\x60\x64\x47\x00", 22) == 0); + + printf ("Modhex-6 success\n"); +} + static void hex_test1 (void) { @@ -315,6 +354,9 @@ main (void) modhex_test1 (); modhex_test2 (); modhex_test3 (); + modhex_test4 (); + modhex_test5 (); + modhex_test6 (); hex_test1 (); hex_test2 (); hex_test3 (); diff --git a/ykhex.c b/ykhex.c index 3987ba7..3cc4a29 100644 --- a/ykhex.c +++ b/ykhex.c @@ -33,7 +33,7 @@ #include "yubikey.h" static const char hex_trans[] = "0123456789abcdef"; -static const char modhex_trans[] = YUBIKEY_MODHEX_MAP; +//static const char modhex_trans[] = YUBIKEY_MODHEX_MAPS[0]; static void _yubikey_encode (char *dst, const char *src, size_t srcSize, @@ -113,17 +113,39 @@ yubikey_hex_p (const char *str) void yubikey_modhex_encode (char *dst, const char *src, size_t srcSize) { - _yubikey_encode (dst, src, srcSize, modhex_trans); + _yubikey_encode (dst, src, srcSize, YUBIKEY_MODHEX_MAPS[0]); } void yubikey_modhex_decode (char *dst, const char *src, size_t dstSize) { - _yubikey_decode (dst, src, dstSize, modhex_trans); + size_t i; + for (i = 0; i < N_MODHEX_MAPS; i++) { + if (_yubikey_p(src, YUBIKEY_MODHEX_MAPS[i])) { + _yubikey_decode (dst, src, dstSize, YUBIKEY_MODHEX_MAPS[0]); + } + } + _yubikey_decode (dst, src, dstSize, YUBIKEY_MODHEX_MAPS[0]); +} + +void +yubikey_modhex_decode_map(char *dst, const char *src, size_t dstSize, const char *map) +{ + _yubikey_decode(dst, src, dstSize, map); +} + +int yubikey_modhex_map_p(const char *str, const char *map) { + return _yubikey_p(str, map); } int yubikey_modhex_p (const char *str) { - return _yubikey_p (str, modhex_trans); + size_t i; + for (i = 0; i < N_MODHEX_MAPS; i++) { + if (_yubikey_p(str, YUBIKEY_MODHEX_MAPS[i])) { + return 1; + } + } + return 0; } diff --git a/yubikey.h b/yubikey.h index 39f75c0..64fb8d6 100644 --- a/yubikey.h +++ b/yubikey.h @@ -91,7 +91,13 @@ extern "C" * Low-level functions; ModHex. */ -#define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv" +#define N_MODHEX_MAPS (sizeof YUBIKEY_MODHEX_MAPS / sizeof YUBIKEY_MODHEX_MAPS[0]) +const static char* YUBIKEY_MODHEX_MAPS[] = { + "cbdefghijklnrtuv", /* default (QWERTY, AZERTY) */ + "jxe.uidchtnbpygk", /* English Dvorak */ + "cbsftdhuneikpglv", /* English Colemak */ +}; + /* ModHex encode input string SRC of length SRCSIZE and put the zero terminated output string in DST. The size of the output string DST @@ -102,9 +108,14 @@ extern "C" /* ModHex decode input string SRC of length DSTSIZE/2 into output string DST. The output string DST is always DSTSIZE/2 large plus - the terminating zero. */ + the terminating zero. + + Tries to guess the modhex map +*/ extern void yubikey_modhex_decode (char *dst, const char *src, size_t dstsize); + extern void yubikey_modhex_decode_map (char *dst, const char *src, + size_t dstsize, const char *map); /* Hex encode/decode data, same interface as modhex functions. */ extern void yubikey_hex_encode (char *dst, const char *src, size_t srcsize); @@ -113,6 +124,7 @@ extern "C" /* Return non-zero if zero-terminated input STR is a valid (mod)hex string, and zero if any non-alphabetic characters are found. */ extern int yubikey_modhex_p (const char *str); + extern int yubikey_modhex_map_p (const char *str, const char *map); extern int yubikey_hex_p (const char *str); /*