#include <stdio.h>
#include <unistd.h>
+#include <time.h>
#include <yubikey.h>
#include <ykdef.h>
"\t-Y Send a 6 byte Yubico challenge.\n"
"\t-N Abort if Yubikey requires button press.\n"
"\t-x Challenge is hex encoded.\n"
+ "\t-t Calculate TOTP (length 6, implies -H)\n"
"\n"
"\t-v verbose\n"
"\t-V tool version\n"
"\n"
"\n"
;
-const char *optstring = "12xvhHYNV";
+const char *optstring = "12xvhHtYNV";
static void report_yk_error(void)
{
static int parse_args(int argc, char **argv,
int *slot, bool *verbose,
unsigned char **challenge, unsigned int *challenge_len,
- bool *hmac, bool *may_block,
+ bool *hmac, bool *may_block, bool *totp,
int *exit_code)
{
int c;
case 'N':
*may_block = false;
break;
+ case 't':
+ *totp = true;
+ *hmac = true;
+ break;
case 'Y':
*hmac = false;
+ *totp = false;
break;
case 'x':
hex_encoded = true;
}
}
- if (optind >= argc) {
+ if (optind >= argc && !*totp) {
/* No challenge */
fputs(usage, stderr);
return 0;
}
-
- if (hex_encoded) {
+ if (*totp && *hmac) {
+ unsigned int t_counter;
+ static unsigned char t_buf[8];
+ t_counter = (int) time(NULL);
+ t_counter = t_counter / 30;
+ memset(t_buf, 0, sizeof(t_buf));
+ t_buf[7] = t_counter & 0x000000ff;
+ t_buf[6] = (t_counter & 0x0000ff00) >> 8;
+ t_buf[5] = (t_counter & 0x00ff0000) >>16;
+ t_buf[4] = (t_counter & 0xff000000) >>24;
+ *challenge = (unsigned char *) &t_buf;
+ *challenge_len = 8;
+ }
+ else if (hex_encoded) {
static unsigned char decoded[SHA1_MAX_BLOCK_SIZE];
size_t strl = strlen(argv[optind]);
static int challenge_response(YK_KEY *yk, int slot,
unsigned char *challenge, unsigned int len,
- bool hmac, bool may_block, bool verbose)
+ bool hmac, bool may_block, bool verbose, bool totp)
{
unsigned char response[64];
unsigned char output_buf[(SHA1_MAX_BLOCK_SIZE * 2) + 1];
int yk_cmd;
unsigned int expect_bytes = 0;
+ unsigned int offset;
+ unsigned int bin_code;
memset(response, 0, sizeof(response));
memset(output_buf, 0, sizeof(output_buf));
/* HMAC responses are 160 bits, Yubico 128 */
expect_bytes = (hmac == true) ? 20 : 16;
+ if(totp){
+ offset = response[19] & 0xf ;
+ bin_code = (response[offset] & 0x7f) << 24
+ | (response[offset+1] & 0xff) << 16
+ | (response[offset+2] & 0xff) << 8
+ | (response[offset+3] & 0xff) ;
+ bin_code = bin_code % 1000000;
+ printf("%06i\n", bin_code);
+ return 1;
+ }
if (hmac) {
yubikey_hex_encode((char *)output_buf, (char *)response, expect_bytes);
} else {
bool verbose = false;
bool hmac = true;
bool may_block = true;
+ bool totp = false;
unsigned char *challenge;
unsigned int challenge_len;
int slot = 1;
if (! parse_args(argc, argv,
&slot, &verbose,
&challenge, &challenge_len,
- &hmac, &may_block,
+ &hmac, &may_block, &totp,
&exit_code))
exit(exit_code);
if (! challenge_response(yk, slot,
challenge, challenge_len,
- hmac, may_block, verbose)) {
+ hmac, may_block, verbose, totp)) {
exit_code = 1;
goto err;
}