Allow choice of the private DO containing the key

Add an option to specify the private DO slot where the key is
to be read, instead of always using private DO #1.

Note that reading from private DOs 3 and 4 will fail if the
appriopriate PIN has not been verified prior the call to
scdtotp.
develop
Damien Goutte-Gattat 8 years ago
parent c638f52731
commit 402d37b23d
  1. 6
      man/scdtotp.1.in
  2. 32
      src/scdtotp.c

@ -15,6 +15,8 @@ scdtotp \- Generate one-time passwords from an OpenPGP smartcard
.IR N ]
.RB [ \-m | --mac-algo
.IR algo ]
.RB [ \-n | --private-do
.IR N ]
.YS
.SH DESCRIPTION
@ -52,6 +54,10 @@ digits.
.BR -m ", " --mac-algo " " \fialgo\fR
Select the HMAC algorithm to use among
\fisha1\fR (default), \fisha256\fR, or \fisha512\fR.
.TP
.BR -n ", " --private-do " " \fiN\fR
Read key from private DO slot #\fiN\fR
(default is 1).
.SH REPORTING BUGS
.PP

@ -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, 12) ) {
if ( ! strncmp("PRIVATE-DO-", line, 11) ) {
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)) )

Loading…
Cancel
Save