@ -35,6 +35,7 @@
# define DEFAULT_TIME_STEP 30
# define DEFAULT_DIGITS 6
# define MAX_KEY_SIZE 64
# define DEFAULT_PRIVATE_DO 1
static void
usage ( int status )
@ -64,6 +65,11 @@ found in a OpenPGP smartcard.\n\
' sha256 ' or ' sha512 ' . \ n \
" );
printf ( " \n \
- n , - - private - do N Read key from private data object N \ n \
( default is % d ) . \ n \
" , DEFAULT_PRIVATE_DO);
printf ( " Report bugs to <%s>. \n " , PACKAGE_BUGREPORT ) ;
exit ( status ) ;
@ -262,7 +268,7 @@ get_otp_key_cb(void *arg, const char *line)
{
struct key_data_t * key = ( struct key_data_t * ) arg ;
if ( ! strncmp ( " PRIVATE-DO- 1 " , line , 1 2 ) ) {
if ( ! strncmp ( " PRIVATE-DO- " , line , 1 1 ) ) {
const char * cursor ;
size_t n ;
@ -291,19 +297,25 @@ get_otp_key_cb(void *arg, const char *line)
* @ return 0 if successful , or a gpg_error_t error code .
*/
static gpg_error_t
get_otp_key ( unsigned char * buffer , size_t len )
get_otp_key ( unsigned privatedo , unsigned char * buffer , size_t len )
{
assuan_context_t ctx ;
gpg_error_t e ;
struct key_data_t key ;
char command [ 32 ] ;
key . buffer = buffer ;
key . len = len ;
key . found = 0 ;
if ( privatedo < 1 | | privatedo > 4 )
return gcry_error ( GPG_ERR_INV_ARG ) ;
if ( ! ( e = connect_to_scdaemon ( & ctx ) ) ) {
if ( ! ( e = assuan_transact ( ctx , " GETATTR PRIVATE-DO-1 " , NULL , NULL ,
snprintf ( command , sizeof ( command ) , " GETATTR PRIVATE-DO-%d " , privatedo ) ;
if ( ! ( e = assuan_transact ( ctx , command , NULL , NULL ,
NULL , NULL , get_otp_key_cb , & key ) ) ) {
if ( key . found )
e = gcry_error ( GPG_ERR_NO_ERROR ) ;
@ -345,7 +357,7 @@ main(int argc, char **argv)
{
int c , algo ;
unsigned char key [ MAX_KEY_SIZE * 2 + 1 ] ;
unsigned otp , step , digits ;
unsigned otp , step , digits , privatedo ;
time_t secs ;
gcry_error_t e ;
@ -356,6 +368,7 @@ main(int argc, char **argv)
{ " step " , 1 , NULL , ' s ' } ,
{ " digits " , 1 , NULL , ' d ' } ,
{ " mac-algo " , 1 , NULL , ' m ' } ,
{ " private-do " , 1 , NULL , ' n ' } ,
{ NULL , 0 , NULL , 0 }
} ;
@ -364,8 +377,9 @@ main(int argc, char **argv)
step = DEFAULT_TIME_STEP ;
digits = DEFAULT_DIGITS ;
algo = GCRY_MAC_HMAC_SHA1 ;
privatedo = DEFAULT_PRIVATE_DO ;
while ( ( c = getopt_long ( argc , argv , " hvt:s:d:m: " ,
while ( ( c = getopt_long ( argc , argv , " hvt:s:d:m: n: " ,
options , NULL ) ) ! = - 1 ) {
switch ( c ) {
case ' h ' :
@ -404,6 +418,12 @@ main(int argc, char **argv)
else
errx ( EXIT_FAILURE , " unsupported HMAC algorithm: %s " , optarg ) ;
break ;
case ' n ' :
privatedo = get_uinteger_or_die ( optarg ) ;
if ( privatedo < 1 | | privatedo > 4 )
errx ( EXIT_FAILURE , " DO number must be 1, 2, 3, or 4 " ) ;
break ;
}
}
@ -413,7 +433,7 @@ main(int argc, char **argv)
gcry_control ( GCRYCTL_DISABLE_SECMEM , 0 ) ;
gcry_control ( GCRYCTL_INITIALIZATION_FINISHED , 0 ) ;
if ( ( e = get_otp_key ( key, sizeof ( key ) ) ) )
if ( ( e = get_otp_key ( privatedo, key, sizeof ( key ) ) ) )
errx ( EXIT_FAILURE , " Cannot get key from token: %s " , gcry_strerror ( e ) ) ;
if ( ( e = generate_totp ( algo , key , secs , step , digits , & otp ) ) )