1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-13 00:09:51 +02:00

scd: Add --advanced option for READKEY.

* scd/command.c (cmd_readkey) : Support ADVANCED arg.
* scd/app.c (app_readcert): Add ADVANCED arg.
* scd/app-openpgp.c (do_readkey): Implement ADVANCED arg.
* scd/app-nks.c (do_readkey): Error return with GPG_ERR_NOT_SUPPORTED.

--
"SCD READKEY --advanced OPENPGP.3" returns key in advanced format.
With this suport, poldi-ctrl will be no longer needed.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2016-11-04 13:45:57 +09:00
parent c1ea0b577a
commit f9da935c3e
5 changed files with 99 additions and 61 deletions

View File

@ -72,7 +72,7 @@ struct app_ctx_s {
gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags); gpg_error_t (*learn_status) (app_t app, ctrl_t ctrl, unsigned int flags);
gpg_error_t (*readcert) (app_t app, const char *certid, gpg_error_t (*readcert) (app_t app, const char *certid,
unsigned char **cert, size_t *certlen); unsigned char **cert, size_t *certlen);
gpg_error_t (*readkey) (app_t app, const char *certid, gpg_error_t (*readkey) (app_t app, int advanced, const char *certid,
unsigned char **pk, size_t *pklen); unsigned char **pk, size_t *pklen);
gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, const char *name); gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, const char *name);
gpg_error_t (*setattr) (app_t app, const char *name, gpg_error_t (*setattr) (app_t app, const char *name,
@ -154,7 +154,7 @@ gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl,
unsigned int flags); unsigned int flags);
gpg_error_t app_readcert (app_t app, const char *certid, gpg_error_t app_readcert (app_t app, const char *certid,
unsigned char **cert, size_t *certlen); unsigned char **cert, size_t *certlen);
gpg_error_t app_readkey (app_t app, const char *keyid, gpg_error_t app_readkey (app_t app, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen); unsigned char **pk, size_t *pklen);
gpg_error_t app_getattr (app_t app, ctrl_t ctrl, const char *name); gpg_error_t app_getattr (app_t app, ctrl_t ctrl, const char *name);
gpg_error_t app_setattr (app_t app, const char *name, gpg_error_t app_setattr (app_t app, const char *name,

View File

@ -618,13 +618,17 @@ do_readcert (app_t app, const char *certid,
certificate parsing code in commands.c:cmd_readkey. For internal certificate parsing code in commands.c:cmd_readkey. For internal
use PK and PKLEN may be NULL to just check for an existing key. */ use PK and PKLEN may be NULL to just check for an existing key. */
static gpg_error_t static gpg_error_t
do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) do_readkey (app_t app, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen)
{ {
gpg_error_t err; gpg_error_t err;
unsigned char *buffer[2]; unsigned char *buffer[2];
size_t buflen[2]; size_t buflen[2];
unsigned short path[1] = { 0x4500 }; unsigned short path[1] = { 0x4500 };
if (advanced)
return GPG_ERR_NOT_SUPPORTED;
/* We use a generic name to retrieve PK.AUT.IFD-SPK. */ /* We use a generic name to retrieve PK.AUT.IFD-SPK. */
if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3) if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
; ;
@ -698,7 +702,7 @@ do_writekey (app_t app, ctrl_t ctrl,
else else
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
if (!force && !do_readkey (app, keyid, NULL, NULL)) if (!force && !do_readkey (app, 0, keyid, NULL, NULL))
return gpg_error (GPG_ERR_EEXIST); return gpg_error (GPG_ERR_EEXIST);
/* Parse the S-expression. */ /* Parse the S-expression. */

View File

@ -1115,8 +1115,8 @@ retrieve_fpr_from_card (app_t app, int keyno, char *fpr)
#if GNUPG_MAJOR_VERSION > 1 #if GNUPG_MAJOR_VERSION > 1
static gpg_error_t static gpg_error_t
retrieve_key_material (FILE *fp, const char *hexkeyid, retrieve_key_material (FILE *fp, const char *hexkeyid,
const unsigned char **m, size_t *mlen, const unsigned char **m, size_t *mlen,
const unsigned char **e, size_t *elen) const unsigned char **e, size_t *elen)
{ {
gcry_error_t err = 0; gcry_error_t err = 0;
char *line = NULL; /* read_line() buffer. */ char *line = NULL; /* read_line() buffer. */
@ -1146,10 +1146,10 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
if (!i) if (!i)
break; /* EOF. */ break; /* EOF. */
if (i < 0) if (i < 0)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
goto leave; /* Error. */ goto leave; /* Error. */
} }
if (!max_length) if (!max_length)
{ {
err = gpg_error (GPG_ERR_TRUNCATED); err = gpg_error (GPG_ERR_TRUNCATED);
@ -1173,7 +1173,7 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
&& nfields > 4 && !strcmp (fields[4], hexkeyid)) && nfields > 4 && !strcmp (fields[4], hexkeyid))
found_key = 1; found_key = 1;
continue; continue;
} }
if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") ) if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") )
break; /* Next key - stop. */ break; /* Next key - stop. */
@ -1561,8 +1561,8 @@ get_public_key (app_t app, int keyno)
Clearly that is not an option and thus we try to locate the Clearly that is not an option and thus we try to locate the
key using an external helper. key using an external helper.
The helper we use here is gpg itself, which should know about The helper we use here is gpg itself, which should know about
the key in any case. */ the key in any case. */
char fpr[41]; char fpr[41];
char *hexkeyid; char *hexkeyid;
@ -1574,38 +1574,38 @@ get_public_key (app_t app, int keyno)
err = retrieve_fpr_from_card (app, keyno, fpr); err = retrieve_fpr_from_card (app, keyno, fpr);
if (err) if (err)
{ {
log_error ("error while retrieving fpr from card: %s\n", log_error ("error while retrieving fpr from card: %s\n",
gpg_strerror (err)); gpg_strerror (err));
goto leave; goto leave;
} }
hexkeyid = fpr + 24; hexkeyid = fpr + 24;
ret = gpgrt_asprintf ret = gpgrt_asprintf
(&command, "gpg --list-keys --with-colons --with-key-data '%s'", fpr); (&command, "gpg --list-keys --with-colons --with-key-data '%s'", fpr);
if (ret < 0) if (ret < 0)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
goto leave; goto leave;
} }
fp = popen (command, "r"); fp = popen (command, "r");
xfree (command); xfree (command);
if (!fp) if (!fp)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
log_error ("running gpg failed: %s\n", gpg_strerror (err)); log_error ("running gpg failed: %s\n", gpg_strerror (err));
goto leave; goto leave;
} }
err = retrieve_key_material (fp, hexkeyid, &m, &mlen, &e, &elen); err = retrieve_key_material (fp, hexkeyid, &m, &mlen, &e, &elen);
pclose (fp); pclose (fp);
if (err) if (err)
{ {
log_error ("error while retrieving key material through pipe: %s\n", log_error ("error while retrieving key material through pipe: %s\n",
gpg_strerror (err)); gpg_strerror (err));
goto leave; goto leave;
} }
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))", err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
(int)mlen, m, (int)elen, e); (int)mlen, m, (int)elen, e);
@ -1726,7 +1726,8 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
buffer. On error PK and PKLEN are not changed and an error code is buffer. On error PK and PKLEN are not changed and an error code is
returned. */ returned. */
static gpg_error_t static gpg_error_t
do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) do_readkey (app_t app, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen)
{ {
#if GNUPG_MAJOR_VERSION > 1 #if GNUPG_MAJOR_VERSION > 1
gpg_error_t err; gpg_error_t err;
@ -1749,15 +1750,40 @@ do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
buf = app->app_local->pk[keyno].key; buf = app->app_local->pk[keyno].key;
if (!buf) if (!buf)
return gpg_error (GPG_ERR_NO_PUBKEY); return gpg_error (GPG_ERR_NO_PUBKEY);
*pklen = app->app_local->pk[keyno].keylen;;
*pk = xtrymalloc (*pklen); if (advanced)
if (!*pk)
{ {
err = gpg_error_from_syserror (); gcry_sexp_t s_key;
*pklen = 0;
return err; err = gcry_sexp_new (&s_key, buf, app->app_local->pk[keyno].keylen, 0);
if (err)
return err;
*pklen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, NULL, 0);
*pk = xtrymalloc (*pklen);
if (!*pk)
{
err = gpg_error_from_syserror ();
*pklen = 0;
return err;
}
gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, *pk, *pklen);
gcry_sexp_release (s_key);
} }
memcpy (*pk, buf, *pklen); else
{
*pklen = app->app_local->pk[keyno].keylen;
*pk = xtrymalloc (*pklen);
if (!*pk)
{
err = gpg_error_from_syserror ();
*pklen = 0;
return err;
}
memcpy (*pk, buf, *pklen);
}
return 0; return 0;
#else #else
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
@ -2366,7 +2392,7 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
} }
else if (chvno == 1 || chvno == 3) else if (chvno == 1 || chvno == 3)
{ {
if (!use_pinpad) if (!use_pinpad)
{ {
char *promptbuf = NULL; char *promptbuf = NULL;
const char *prompt; const char *prompt;
@ -3990,23 +4016,23 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
else else
{ {
for (s=keyidstr, n=0; hexdigitp (s); s++, n++) for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
; ;
if (n != 32) if (n != 32)
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
else if (!*s) else if (!*s)
; /* no fingerprint given: we allow this for now. */ ; /* no fingerprint given: we allow this for now. */
else if (*s == '/') else if (*s == '/')
fpr = s + 1; fpr = s + 1;
else else
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
for (s=keyidstr, n=0; n < 16; s += 2, n++) for (s=keyidstr, n=0; n < 16; s += 2, n++)
tmp_sn[n] = xtoi_2 (s); tmp_sn[n] = xtoi_2 (s);
if (app->serialnolen != 16) if (app->serialnolen != 16)
return gpg_error (GPG_ERR_INV_CARD); return gpg_error (GPG_ERR_INV_CARD);
if (memcmp (app->serialno, tmp_sn, 16)) if (memcmp (app->serialno, tmp_sn, 16))
return gpg_error (GPG_ERR_WRONG_CARD); return gpg_error (GPG_ERR_WRONG_CARD);
} }
/* If a fingerprint has been specified check it against the one on /* If a fingerprint has been specified check it against the one on
@ -4244,23 +4270,23 @@ do_decipher (app_t app, const char *keyidstr,
else else
{ {
for (s=keyidstr, n=0; hexdigitp (s); s++, n++) for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
; ;
if (n != 32) if (n != 32)
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
else if (!*s) else if (!*s)
; /* no fingerprint given: we allow this for now. */ ; /* no fingerprint given: we allow this for now. */
else if (*s == '/') else if (*s == '/')
fpr = s + 1; fpr = s + 1;
else else
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
for (s=keyidstr, n=0; n < 16; s += 2, n++) for (s=keyidstr, n=0; n < 16; s += 2, n++)
tmp_sn[n] = xtoi_2 (s); tmp_sn[n] = xtoi_2 (s);
if (app->serialnolen != 16) if (app->serialnolen != 16)
return gpg_error (GPG_ERR_INV_CARD); return gpg_error (GPG_ERR_INV_CARD);
if (memcmp (app->serialno, tmp_sn, 16)) if (memcmp (app->serialno, tmp_sn, 16))
return gpg_error (GPG_ERR_WRONG_CARD); return gpg_error (GPG_ERR_WRONG_CARD);
} }
/* If a fingerprint has been specified check it against the one on /* If a fingerprint has been specified check it against the one on

View File

@ -612,7 +612,8 @@ app_readcert (app_t app, const char *certid,
This function might not be supported by all applications. */ This function might not be supported by all applications. */
gpg_error_t gpg_error_t
app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen) app_readkey (app_t app, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen)
{ {
gpg_error_t err; gpg_error_t err;
@ -630,7 +631,7 @@ app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
err = lock_reader (app->slot, NULL /*FIXME*/); err = lock_reader (app->slot, NULL /*FIXME*/);
if (err) if (err)
return err; return err;
err= app->fnc.readkey (app, keyid, pk, pklen); err= app->fnc.readkey (app, advanced, keyid, pk, pklen);
unlock_reader (app->slot); unlock_reader (app->slot);
return err; return err;
} }

View File

@ -729,17 +729,19 @@ cmd_readcert (assuan_context_t ctx, char *line)
static const char hlp_readkey[] = static const char hlp_readkey[] =
"READKEY <keyid>\n" "READKEY [--advanced] <keyid>\n"
"\n" "\n"
"Return the public key for the given cert or key ID as a standard\n" "Return the public key for the given cert or key ID as a standard\n"
"S-expression.\n" "S-expression.\n"
"In --advanced mode it returns the S-expression in advanced format.\n"
"\n" "\n"
"Note, that this function may even be used on a locked card."; "Note that this function may even be used on a locked card.";
static gpg_error_t static gpg_error_t
cmd_readkey (assuan_context_t ctx, char *line) cmd_readkey (assuan_context_t ctx, char *line)
{ {
ctrl_t ctrl = assuan_get_pointer (ctx); ctrl_t ctrl = assuan_get_pointer (ctx);
int rc; int rc;
int advanced = 0;
unsigned char *cert = NULL; unsigned char *cert = NULL;
size_t ncert, n; size_t ncert, n;
ksba_cert_t kc = NULL; ksba_cert_t kc = NULL;
@ -750,11 +752,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
if ((rc = open_card (ctrl, NULL))) if ((rc = open_card (ctrl, NULL)))
return rc; return rc;
if (has_option (line, "--advanced"))
advanced = 1;
line = skip_options (line);
line = xstrdup (line); /* Need a copy of the line. */ line = xstrdup (line); /* Need a copy of the line. */
/* If the application supports the READKEY function we use that. /* If the application supports the READKEY function we use that.
Otherwise we use the old way by extracting it from the Otherwise we use the old way by extracting it from the
certificate. */ certificate. */
rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen); rc = app_readkey (ctrl->app_ctx, advanced, line, &pk, &pklen);
if (!rc) if (!rc)
{ /* Yeah, got that key - send it back. */ { /* Yeah, got that key - send it back. */
rc = assuan_send_data (ctx, pk, pklen); rc = assuan_send_data (ctx, pk, pklen);