scd: Simplify the app_readkey parameters.

* scd/app-help.c (app_help_pubkey_from_cert): New.
* scd/command.c (cmd_readkey): Refactor to use that new function and
handle the --advanced flag only here.
* scd/app.c (app_readkey): Remove parm advanced.
* scd/app-common.h (struct app_ctx_s): Remove parm advanced from the
readkey member.
* scd/app-nks.c (do_readkey): Adjust for removed parm.
* scd/app-piv.c (do_readkey): Ditto.
* scd/app-openpgp.c (do_readkey): Ditto.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2019-02-26 16:42:50 +01:00
parent ac485b4f25
commit c2235d994d
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
7 changed files with 93 additions and 117 deletions

View File

@ -71,7 +71,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, int advanced, const char *certid,
gpg_error_t (*readkey) (app_t app, 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,
@ -123,6 +123,8 @@ struct app_ctx_s {
/*-- app-help.c --*/
unsigned int app_help_count_bits (const unsigned char *a, size_t len);
gpg_error_t app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip);
gpg_error_t app_help_pubkey_from_cert (const void *cert, size_t certlen,
unsigned char **r_pk, size_t *r_pklen);
size_t app_help_read_length_of_cert (int slot, int fid, size_t *r_certoff);
@ -144,7 +146,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, ctrl_t ctrl, const char *certid,
unsigned char **cert, size_t *certlen);
gpg_error_t app_readkey (app_t app, ctrl_t ctrl, int advanced,
gpg_error_t app_readkey (app_t app, ctrl_t ctrl,
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, ctrl_t ctrl, const char *name,

View File

@ -29,9 +29,9 @@
#include "../common/tlv.h"
/* Count the number of bits, assuming the A represents an unsigned big
integer of length LEN bytes. If A is NULL a length of 0 is
returned. */
/* Count the number of bits, assuming that A represents an unsigned
* big integer of length LEN bytes. If A is NULL a length of 0 is
* returned. */
unsigned int
app_help_count_bits (const unsigned char *a, size_t len)
{
@ -87,6 +87,45 @@ app_help_get_keygrip_string (ksba_cert_t cert, char *hexkeygrip)
}
gpg_error_t
app_help_pubkey_from_cert (const void *cert, size_t certlen,
unsigned char **r_pk, size_t *r_pklen)
{
gpg_error_t err;
ksba_cert_t kc;
unsigned char *pk;
size_t pklen;
*r_pk = NULL;
*r_pklen = 0;
err = ksba_cert_new (&kc);
if (err)
return err;
err = ksba_cert_init_from_mem (kc, cert, certlen);
if (err)
goto leave;
pk = ksba_cert_get_public_key (kc);
if (!pk)
{
err = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
}
pklen = gcry_sexp_canon_len (pk, 0, NULL, &err);
leave:
if (!err)
{
*r_pk = pk;
*r_pklen = pklen;
}
else
ksba_free (pk);
ksba_cert_release (kc);
return err;
}
/* Given the SLOT and the File ID FID, return the length of the
certificate contained in that file. Returns 0 if the file does not

View File

@ -618,17 +618,13 @@ 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, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen)
do_readkey (app_t app, 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)
;
@ -702,7 +698,7 @@ do_writekey (app_t app, ctrl_t ctrl,
else
return gpg_error (GPG_ERR_INV_ID);
if (!force && !do_readkey (app, 0, keyid, NULL, NULL))
if (!force && !do_readkey (app, keyid, NULL, NULL))
return gpg_error (GPG_ERR_EEXIST);
/* Parse the S-expression. */

View File

@ -1875,10 +1875,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, int advanced, const char *keyid,
unsigned char **pk, size_t *pklen)
do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
{
#if GNUPG_MAJOR_VERSION > 1
gpg_error_t err;
int keyno;
unsigned char *buf;
@ -1900,45 +1898,17 @@ do_readkey (app_t app, int advanced, const char *keyid,
if (!buf)
return gpg_error (GPG_ERR_NO_PUBKEY);
if (advanced)
*pklen = app->app_local->pk[keyno].keylen;
*pk = xtrymalloc (*pklen);
if (!*pk)
{
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);
/* Decrement for trailing '\0' */
*pklen = *pklen - 1;
}
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);
err = gpg_error_from_syserror ();
*pklen = 0;
return err;
}
memcpy (*pk, buf, *pklen);
return 0;
#else
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
#endif
}
/* Read the standard certificate of an OpenPGP v2 card. It is

View File

@ -1418,14 +1418,14 @@ do_readcert (app_t app, const char *certid,
* application has been performed. This is because we return a cached
* result from key generation. If no cached result is available, the
* error GPG_ERR_UNSUPPORTED_OPERATION is returned so that the higher
* layer can then to get the key by reading the matching certificate.
* layer can then get the key by reading the matching certificate.
* On success a canonical encoded s-expression with the public key is
* stored at (R_PK,R_PKLEN); the caller must release that buffer. On
* error R_PK and R_PKLEN are not changed and an error code is
* returned.
*/
static gpg_error_t
do_readkey (app_t app, int advanced, const char *keyrefstr,
do_readkey (app_t app, const char *keyrefstr,
unsigned char **r_pk, size_t *r_pklen)
{
gpg_error_t err;
@ -1471,19 +1471,6 @@ do_readkey (app_t app, int advanced, const char *keyrefstr,
err = make_canon_sexp (s_pkey, &pk, &pklen);
if (err)
goto leave;
if (advanced)
{
/* FIXME: How ugly - we should move that to command.c */
char *p = canon_sexp_to_string (pk, pklen);
if (!p)
{
err = gpg_error_from_syserror ();
goto leave;
}
xfree (pk);
pk = p;
pklen = strlen (pk);
}
*r_pk = pk;
pk = NULL;

View File

@ -692,7 +692,7 @@ app_readcert (app_t app, ctrl_t ctrl, const char *certid,
This function might not be supported by all applications. */
gpg_error_t
app_readkey (app_t app, ctrl_t ctrl, int advanced, const char *keyid,
app_readkey (app_t app, ctrl_t ctrl, const char *keyid,
unsigned char **pk, size_t *pklen)
{
gpg_error_t err;
@ -711,7 +711,7 @@ app_readkey (app_t app, ctrl_t ctrl, int advanced, const char *keyid,
err = lock_app (app, ctrl);
if (err)
return err;
err= app->fnc.readkey (app, advanced, keyid, pk, pklen);
err= app->fnc.readkey (app, keyid, pk, pklen);
unlock_app (app);
return err;
}

View File

@ -516,11 +516,8 @@ cmd_readkey (assuan_context_t ctx, char *line)
int rc;
int advanced = 0;
unsigned char *cert = NULL;
size_t ncert, n;
ksba_cert_t kc = NULL;
ksba_sexp_t p = NULL;
unsigned char *pk;
size_t pklen;
unsigned char *pk = NULL;
size_t ncert, pklen;
if ((rc = open_card (ctrl)))
return rc;
@ -529,83 +526,68 @@ cmd_readkey (assuan_context_t ctx, char *line)
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, ctrl, advanced, line, &pk, &pklen);
rc = app_readkey (ctrl->app_ctx, ctrl, line, &pk, &pklen);
if (!rc)
{ /* Yeah, got that key - send it back. */
rc = assuan_send_data (ctx, pk, pklen);
xfree (pk);
xfree (line);
line = NULL;
goto leave;
}
if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION
&& gpg_err_code (rc) != GPG_ERR_NOT_FOUND)
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
else
; /* Okay, got that key. */
else if (gpg_err_code (rc) == GPG_ERR_UNSUPPORTED_OPERATION
|| gpg_err_code (rc) == GPG_ERR_NOT_FOUND)
{
/* Fall back to certificate reading. */
rc = app_readcert (ctrl->app_ctx, ctrl, line, &cert, &ncert);
if (rc)
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
{
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
goto leave;
}
rc = app_help_pubkey_from_cert (cert, ncert, &pk, &pklen);
if (rc)
{
log_error ("failed to parse the certificate: %s\n",
gpg_strerror (rc));
goto leave;
}
}
xfree (line);
line = NULL;
if (rc)
goto leave;
rc = ksba_cert_new (&kc);
if (rc)
goto leave;
rc = ksba_cert_init_from_mem (kc, cert, ncert);
if (rc)
else
{
log_error ("failed to parse the certificate: %s\n", gpg_strerror (rc));
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
goto leave;
}
p = ksba_cert_get_public_key (kc);
if (!p)
{
rc = gpg_error (GPG_ERR_NO_PUBKEY);
goto leave;
}
n = gcry_sexp_canon_len (p, 0, NULL, NULL);
if (advanced)
{
gcry_sexp_t s_key;
unsigned char *pkadv;
size_t pkadvlen;
rc = gcry_sexp_new (&s_key, (void*)p, n, 0);
rc = gcry_sexp_new (&s_key, pk, pklen, 0);
if (rc)
goto leave;
pklen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, NULL, 0);
pk = xtrymalloc (pklen);
if (!pk)
pkadvlen = gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, NULL, 0);
pkadv = xtrymalloc (pkadvlen);
if (!pkadv)
{
rc = gpg_error_from_syserror ();
goto leave;
}
log_assert (pklen);
log_assert (pkadvlen);
gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, pk, pklen);
gcry_sexp_sprint (s_key, GCRYSEXP_FMT_ADVANCED, pkadv, pkadvlen);
gcry_sexp_release (s_key);
/* (One less to adjust for the trailing '\0') */
rc = assuan_send_data (ctx, pk, pklen-1);
xfree (pk);
rc = assuan_send_data (ctx, pkadv, pkadvlen-1);
xfree (pkadv);
}
else
rc = assuan_send_data (ctx, p, n);
rc = assuan_send_data (ctx, pk, pklen);
leave:
xfree (p);
ksba_cert_release (kc);
xfree (pk);
xfree (cert);
return rc;
}