mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-30 16:17:02 +01: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:
parent
c1ea0b577a
commit
f9da935c3e
@ -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 (*readcert) (app_t app, const char *certid,
|
||||
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);
|
||||
gpg_error_t (*getattr) (app_t app, ctrl_t ctrl, 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);
|
||||
gpg_error_t app_readcert (app_t app, const char *certid,
|
||||
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);
|
||||
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,
|
||||
|
@ -618,13 +618,17 @@ do_readcert (app_t app, const char *certid,
|
||||
certificate parsing code in commands.c:cmd_readkey. For internal
|
||||
use PK and PKLEN may be NULL to just check for an existing key. */
|
||||
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;
|
||||
unsigned char *buffer[2];
|
||||
size_t buflen[2];
|
||||
unsigned short path[1] = { 0x4500 };
|
||||
|
||||
if (advanced)
|
||||
return GPG_ERR_NOT_SUPPORTED;
|
||||
|
||||
/* We use a generic name to retrieve PK.AUT.IFD-SPK. */
|
||||
if (!strcmp (keyid, "$IFDAUTHKEY") && app->app_local->nks_version >= 3)
|
||||
;
|
||||
@ -698,7 +702,7 @@ do_writekey (app_t app, ctrl_t ctrl,
|
||||
else
|
||||
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);
|
||||
|
||||
/* Parse the S-expression. */
|
||||
|
@ -1115,8 +1115,8 @@ retrieve_fpr_from_card (app_t app, int keyno, char *fpr)
|
||||
#if GNUPG_MAJOR_VERSION > 1
|
||||
static gpg_error_t
|
||||
retrieve_key_material (FILE *fp, const char *hexkeyid,
|
||||
const unsigned char **m, size_t *mlen,
|
||||
const unsigned char **e, size_t *elen)
|
||||
const unsigned char **m, size_t *mlen,
|
||||
const unsigned char **e, size_t *elen)
|
||||
{
|
||||
gcry_error_t err = 0;
|
||||
char *line = NULL; /* read_line() buffer. */
|
||||
@ -1146,10 +1146,10 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
||||
if (!i)
|
||||
break; /* EOF. */
|
||||
if (i < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave; /* Error. */
|
||||
}
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave; /* Error. */
|
||||
}
|
||||
if (!max_length)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_TRUNCATED);
|
||||
@ -1173,7 +1173,7 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
||||
&& nfields > 4 && !strcmp (fields[4], hexkeyid))
|
||||
found_key = 1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !strcmp (fields[0], "sub") || !strcmp (fields[0], "pub") )
|
||||
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
|
||||
key using an external helper.
|
||||
|
||||
The helper we use here is gpg itself, which should know about
|
||||
the key in any case. */
|
||||
The helper we use here is gpg itself, which should know about
|
||||
the key in any case. */
|
||||
|
||||
char fpr[41];
|
||||
char *hexkeyid;
|
||||
@ -1574,38 +1574,38 @@ get_public_key (app_t app, int keyno)
|
||||
|
||||
err = retrieve_fpr_from_card (app, keyno, fpr);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error while retrieving fpr from card: %s\n",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
{
|
||||
log_error ("error while retrieving fpr from card: %s\n",
|
||||
gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
hexkeyid = fpr + 24;
|
||||
|
||||
ret = gpgrt_asprintf
|
||||
(&command, "gpg --list-keys --with-colons --with-key-data '%s'", fpr);
|
||||
if (ret < 0)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
goto leave;
|
||||
}
|
||||
|
||||
fp = popen (command, "r");
|
||||
xfree (command);
|
||||
if (!fp)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("running gpg failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
log_error ("running gpg failed: %s\n", gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = retrieve_key_material (fp, hexkeyid, &m, &mlen, &e, &elen);
|
||||
pclose (fp);
|
||||
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));
|
||||
goto leave;
|
||||
}
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = gcry_sexp_build (&s_pkey, NULL, "(public-key(rsa(n%b)(e%b)))",
|
||||
(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
|
||||
returned. */
|
||||
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
|
||||
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;
|
||||
if (!buf)
|
||||
return gpg_error (GPG_ERR_NO_PUBKEY);
|
||||
*pklen = app->app_local->pk[keyno].keylen;;
|
||||
*pk = xtrymalloc (*pklen);
|
||||
if (!*pk)
|
||||
|
||||
if (advanced)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
*pklen = 0;
|
||||
return err;
|
||||
gcry_sexp_t s_key;
|
||||
|
||||
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;
|
||||
#else
|
||||
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)
|
||||
{
|
||||
if (!use_pinpad)
|
||||
if (!use_pinpad)
|
||||
{
|
||||
char *promptbuf = NULL;
|
||||
const char *prompt;
|
||||
@ -3990,23 +4016,23 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
||||
else
|
||||
{
|
||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
||||
;
|
||||
;
|
||||
if (n != 32)
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
else if (!*s)
|
||||
; /* no fingerprint given: we allow this for now. */
|
||||
; /* no fingerprint given: we allow this for now. */
|
||||
else if (*s == '/')
|
||||
fpr = s + 1;
|
||||
fpr = s + 1;
|
||||
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++)
|
||||
tmp_sn[n] = xtoi_2 (s);
|
||||
tmp_sn[n] = xtoi_2 (s);
|
||||
|
||||
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))
|
||||
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
|
||||
@ -4244,23 +4270,23 @@ do_decipher (app_t app, const char *keyidstr,
|
||||
else
|
||||
{
|
||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
||||
;
|
||||
;
|
||||
if (n != 32)
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
else if (!*s)
|
||||
; /* no fingerprint given: we allow this for now. */
|
||||
; /* no fingerprint given: we allow this for now. */
|
||||
else if (*s == '/')
|
||||
fpr = s + 1;
|
||||
fpr = s + 1;
|
||||
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++)
|
||||
tmp_sn[n] = xtoi_2 (s);
|
||||
tmp_sn[n] = xtoi_2 (s);
|
||||
|
||||
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))
|
||||
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
|
||||
|
@ -612,7 +612,8 @@ app_readcert (app_t app, const char *certid,
|
||||
|
||||
This function might not be supported by all applications. */
|
||||
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;
|
||||
|
||||
@ -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*/);
|
||||
if (err)
|
||||
return err;
|
||||
err= app->fnc.readkey (app, keyid, pk, pklen);
|
||||
err= app->fnc.readkey (app, advanced, keyid, pk, pklen);
|
||||
unlock_reader (app->slot);
|
||||
return err;
|
||||
}
|
||||
|
@ -729,17 +729,19 @@ cmd_readcert (assuan_context_t ctx, char *line)
|
||||
|
||||
|
||||
static const char hlp_readkey[] =
|
||||
"READKEY <keyid>\n"
|
||||
"READKEY [--advanced] <keyid>\n"
|
||||
"\n"
|
||||
"Return the public key for the given cert or key ID as a standard\n"
|
||||
"S-expression.\n"
|
||||
"In --advanced mode it returns the S-expression in advanced format.\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
|
||||
cmd_readkey (assuan_context_t ctx, char *line)
|
||||
{
|
||||
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||
int rc;
|
||||
int advanced = 0;
|
||||
unsigned char *cert = NULL;
|
||||
size_t ncert, n;
|
||||
ksba_cert_t kc = NULL;
|
||||
@ -750,11 +752,16 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
||||
if ((rc = open_card (ctrl, NULL)))
|
||||
return rc;
|
||||
|
||||
if (has_option (line, "--advanced"))
|
||||
advanced = 1;
|
||||
|
||||
line = skip_options (line);
|
||||
|
||||
line = xstrdup (line); /* Need a copy of the line. */
|
||||
/* If the application supports the READKEY function we use that.
|
||||
Otherwise we use the old way by extracting it from the
|
||||
certificate. */
|
||||
rc = app_readkey (ctrl->app_ctx, line, &pk, &pklen);
|
||||
rc = app_readkey (ctrl->app_ctx, advanced, line, &pk, &pklen);
|
||||
if (!rc)
|
||||
{ /* Yeah, got that key - send it back. */
|
||||
rc = assuan_send_data (ctx, pk, pklen);
|
||||
|
Loading…
x
Reference in New Issue
Block a user