You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
scdtools/src/scdtotp.c

488 lines
12 KiB
C

/*
* scdtools - Tools for Scdaemon and OpenPGP smartcards
puts("Usage: scdtotp [options]\n\
", VERSION);
exit(EXIT_SUCCESS);
}
/*
* Convert a time value (in seconds) into a moving factor for the
* TOTP algorithm as per RFC 6238.
*
* @param time Elapsed seconds since Unix epoch.
* @param step Time step parameter.
* @param buffer Byte buffer to store the formatted factor. Must be
* at least 8 bytes long.
* @param len Size of the output buffer.
*
* @return The number of bytes written to the buffer (always 8).
*/
static int
time2factor(time_t time, int step, unsigned char *buffer, size_t len)
{
unsigned n_steps;
int i, j;
n_steps = time / step;
for ( i = 0, j = 7; i < 8; i++, j-- )
buffer[i] = (n_steps & (uint64_t)(0xFF << (j * 8))) >> (j * 8);
return 8;
}
/*
* Convert a hexstring into a bytes array.
*
* @param hexstring The string to convert.
* @param buffer The output buffer.
* @param len Size of the output buffer.
*
* @return The number of bytes written to the output buffer, or
* -1 if the buffer is not large enough.
*/
static int
hexstring2bytes(const char *hexstring, unsigned char *buffer, size_t len)
{
int high_nibble, n;
unsigned val;
high_nibble = 1;
n = 0;
while ( *hexstring && n < len ) {
switch ( *hexstring ) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = *hexstring - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
val = *hexstring - 'a' + 10;
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
val = *hexstring - 'A' + 10;
break;
default:
hexstring += 1;
continue;
}
if ( high_nibble ) {
buffer[n] = val << 4;
high_nibble = 0;
}
else {
buffer[n] |= (val & 0xF);
high_nibble = 1;
n += 1;
}
hexstring += 1;
}
if ( *hexstring )
return -1; /* Buffer too small. */
return n;
}
/*
* Generate a time-based one-time password as per RFC 6238.
*
* @param step Time step parameter.
}
gcry_mac_close(mac);
}
return e;
}
struct key_data_t {
unsigned char *buffer;
size_t len;
int found;
};
/*
* Callback for the below function.
*/
static gpg_error_t
get_otp_key_cb(void *arg, const char *line)
{
struct key_data_t *key = (struct key_data_t *)arg;
{ "mac-algo", 1, NULL, 'm' },
privatedo = get_uinteger_or_die(optarg);
if ( privatedo < 1 || privatedo > 4 )
errx(EXIT_FAILURE, "DO number must be 1, 2, 3, or 4");
break;