mirror of
git://git.gnupg.org/gnupg.git
synced 2024-05-31 22:18:03 +02:00
* app-openpgp.c (app_local_s): New field PK.
(do_deinit, do_genkey, app_openpgp_storekey): Clear it. (get_public_key, send_keypair_info): New. (do_learn_status): Send KEYPAIR info * app-common.h (app_ctx_t): Add function pointer READKEY. * app.c (app_readkey): New. * command.c (cmd_readkey): Use READKEY function if possible.
This commit is contained in:
parent
823eaefb0b
commit
8c77433de9
|
@ -1,3 +1,14 @@
|
||||||
|
2005-02-22 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* app-openpgp.c (app_local_s): New field PK.
|
||||||
|
(do_deinit, do_genkey, app_openpgp_storekey): Clear it.
|
||||||
|
(get_public_key, send_keypair_info): New.
|
||||||
|
(do_learn_status): Send KEYPAIR info
|
||||||
|
|
||||||
|
* app-common.h (app_ctx_t): Add function pointer READKEY.
|
||||||
|
* app.c (app_readkey): New.
|
||||||
|
* command.c (cmd_readkey): Use READKEY function if possible.
|
||||||
|
|
||||||
2005-01-26 Werner Koch <wk@g10code.com>
|
2005-01-26 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround
|
* ccid-driver.c (parse_ccid_descriptor): Need the CSM workaround
|
||||||
|
@ -18,7 +29,7 @@
|
||||||
side effect of the retrieval of the the C4 DO from the 6E DO the
|
side effect of the retrieval of the the C4 DO from the 6E DO the
|
||||||
cached fingerprint will get updated to the old value and later
|
cached fingerprint will get updated to the old value and later
|
||||||
when signing the generated key the checking of the fingerprint
|
when signing the generated key the checking of the fingerprint
|
||||||
fails becuase it won't match the new one. Thanks to Moritz for
|
fails because it won't match the new one. Thanks to Moritz for
|
||||||
analyzing this problem.
|
analyzing this problem.
|
||||||
(verify_chv3): Removed the CHV status reread logic because we
|
(verify_chv3): Removed the CHV status reread logic because we
|
||||||
won't cache the C4 DO anymore.
|
won't cache the C4 DO anymore.
|
||||||
|
@ -934,7 +945,8 @@
|
||||||
* scdaemon.c scdaemon.h, command.c: New. Based on the code from
|
* scdaemon.c scdaemon.h, command.c: New. Based on the code from
|
||||||
the gpg-agent.
|
the gpg-agent.
|
||||||
|
|
||||||
Copyright 2002 Free Software Foundation, Inc.
|
|
||||||
|
Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
This file is free software; as a special exception the author gives
|
This file is free software; as a special exception the author gives
|
||||||
unlimited permission to copy and/or distribute it, with or without
|
unlimited permission to copy and/or distribute it, with or without
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* app-common.h - Common declarations for all card applications
|
/* app-common.h - Common declarations for all card applications
|
||||||
* Copyright (C) 2003 Free Software Foundation, Inc.
|
* Copyright (C) 2003, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
|
@ -49,6 +49,8 @@ struct app_ctx_s {
|
||||||
int (*learn_status) (app_t app, ctrl_t ctrl);
|
int (*learn_status) (app_t app, ctrl_t ctrl);
|
||||||
int (*readcert) (app_t app, const char *certid,
|
int (*readcert) (app_t app, const char *certid,
|
||||||
unsigned char **cert, size_t *certlen);
|
unsigned char **cert, size_t *certlen);
|
||||||
|
int (*readkey) (app_t app, const char *certid,
|
||||||
|
unsigned char **pk, size_t *pklen);
|
||||||
int (*getattr) (app_t app, ctrl_t ctrl, const char *name);
|
int (*getattr) (app_t app, ctrl_t ctrl, const char *name);
|
||||||
int (*setattr) (app_t app, const char *name,
|
int (*setattr) (app_t app, const char *name,
|
||||||
int (*pincb)(void*, const char *, char **),
|
int (*pincb)(void*, const char *, char **),
|
||||||
|
@ -109,6 +111,8 @@ int app_get_serial_and_stamp (app_t app, char **serial, time_t *stamp);
|
||||||
int app_write_learn_status (app_t app, ctrl_t ctrl);
|
int app_write_learn_status (app_t app, ctrl_t ctrl);
|
||||||
int app_readcert (app_t app, const char *certid,
|
int app_readcert (app_t app, const char *certid,
|
||||||
unsigned char **cert, size_t *certlen);
|
unsigned char **cert, size_t *certlen);
|
||||||
|
int app_readkey (app_t app, const char *keyid,
|
||||||
|
unsigned char **pk, size_t *pklen);
|
||||||
int app_getattr (app_t app, ctrl_t ctrl, const char *name);
|
int app_getattr (app_t app, ctrl_t ctrl, const char *name);
|
||||||
int app_setattr (app_t app, const char *name,
|
int app_setattr (app_t app, const char *name,
|
||||||
int (*pincb)(void*, const char *, char **),
|
int (*pincb)(void*, const char *, char **),
|
||||||
|
|
|
@ -90,6 +90,7 @@ static struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* One cache item for DOs. */
|
||||||
struct cache_s {
|
struct cache_s {
|
||||||
struct cache_s *next;
|
struct cache_s *next;
|
||||||
int tag;
|
int tag;
|
||||||
|
@ -97,8 +98,20 @@ struct cache_s {
|
||||||
unsigned char data[1];
|
unsigned char data[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Object with application (i.e. OpenPGP card) specific data. */
|
||||||
struct app_local_s {
|
struct app_local_s {
|
||||||
|
/* A linked list with cached DOs. */
|
||||||
struct cache_s *cache;
|
struct cache_s *cache;
|
||||||
|
|
||||||
|
/* Keep track of the public keys. */
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int read_done; /* True if we have at least tried to read them. */
|
||||||
|
gcry_sexp_t key; /* Might be NULL if key is not available. */
|
||||||
|
} pk[3];
|
||||||
|
|
||||||
|
/* Keep track of card capabilities. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int get_challenge:1;
|
unsigned int get_challenge:1;
|
||||||
|
@ -106,6 +119,8 @@ struct app_local_s {
|
||||||
unsigned int change_force_chv:1;
|
unsigned int change_force_chv:1;
|
||||||
unsigned int private_dos:1;
|
unsigned int private_dos:1;
|
||||||
} extcap;
|
} extcap;
|
||||||
|
|
||||||
|
/* Flags used to control the application. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
unsigned int no_sync:1; /* Do not sync CHV1 and CHV2 */
|
unsigned int no_sync:1; /* Do not sync CHV1 and CHV2 */
|
||||||
|
@ -114,10 +129,16 @@ struct app_local_s {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/***** Local prototypes *****/
|
||||||
static unsigned long convert_sig_counter_value (const unsigned char *value,
|
static unsigned long convert_sig_counter_value (const unsigned char *value,
|
||||||
size_t valuelen);
|
size_t valuelen);
|
||||||
static unsigned long get_sig_counter (APP app);
|
static unsigned long get_sig_counter (app_t app);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Deconstructor. */
|
/* Deconstructor. */
|
||||||
static void
|
static void
|
||||||
do_deinit (app_t app)
|
do_deinit (app_t app)
|
||||||
|
@ -125,12 +146,19 @@ do_deinit (app_t app)
|
||||||
if (app && app->app_local)
|
if (app && app->app_local)
|
||||||
{
|
{
|
||||||
struct cache_s *c, *c2;
|
struct cache_s *c, *c2;
|
||||||
|
int i;
|
||||||
|
|
||||||
for (c = app->app_local->cache; c; c = c2)
|
for (c = app->app_local->cache; c; c = c2)
|
||||||
{
|
{
|
||||||
c2 = c->next;
|
c2 = c->next;
|
||||||
xfree (c);
|
xfree (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (i=0; i < DIM (app->app_local->pk); i++)
|
||||||
|
{
|
||||||
|
gcry_sexp_release (app->app_local->pk[i].key);
|
||||||
|
app->app_local->pk[i].read_done = 0;
|
||||||
|
}
|
||||||
xfree (app->app_local);
|
xfree (app->app_local);
|
||||||
app->app_local = NULL;
|
app->app_local = NULL;
|
||||||
}
|
}
|
||||||
|
@ -736,6 +764,156 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get the public key for KEYNO and store it as an S-expresion with
|
||||||
|
the APP handle. On error that field gets cleared. If we already
|
||||||
|
know about the public key we will just return. Note that this does
|
||||||
|
not mean a key is available; this is soley indicated by the
|
||||||
|
presence of the app->app_local->pk[KEYNO-1].key field.
|
||||||
|
|
||||||
|
Note that GnuPG 1.x does not need this and it would be too time
|
||||||
|
consuming to send it just for the fun of it. */
|
||||||
|
#if GNUPG_MAJOR_VERSION > 1
|
||||||
|
static gpg_error_t
|
||||||
|
get_public_key (app_t app, int keyno)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
unsigned char *buffer;
|
||||||
|
const unsigned char *keydata, *m, *e;
|
||||||
|
size_t buflen, keydatalen, mlen, elen;
|
||||||
|
gcry_sexp_t sexp;
|
||||||
|
|
||||||
|
if (keyno < 1 || keyno > 3)
|
||||||
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
keyno--;
|
||||||
|
|
||||||
|
/* Already cached? */
|
||||||
|
if (app->app_local->pk[keyno].read_done)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||||
|
app->app_local->pk[keyno].key = NULL;
|
||||||
|
|
||||||
|
if (app->card_version > 0x0100)
|
||||||
|
{
|
||||||
|
/* We may simply read the public key out of these cards. */
|
||||||
|
err = iso7816_read_public_key (app->slot,
|
||||||
|
keyno == 0? "\xB6" :
|
||||||
|
keyno == 1? "\xB8" : "\xA4",
|
||||||
|
2,
|
||||||
|
&buffer, &buflen);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error (_("reading public key failed: %s\n"), gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen);
|
||||||
|
if (!keydata)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_CARD);
|
||||||
|
log_error (_("response does not contain the public key data\n"));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = find_tlv (keydata, keydatalen, 0x0081, &mlen);
|
||||||
|
if (!m)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_CARD);
|
||||||
|
log_error (_("response does not contain the RSA modulus\n"));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = find_tlv (keydata, keydatalen, 0x0082, &elen);
|
||||||
|
if (!e)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_CARD);
|
||||||
|
log_error (_("response does not contain the RSA public exponent\n"));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = gcry_sexp_build (&sexp, NULL,
|
||||||
|
"(public-key (rsa (n %b) (e %b)))",
|
||||||
|
(int)mlen, m,(int)elen, e);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
log_error ("error formatting the key into an S-expression: %s\n",
|
||||||
|
gpg_strerror (err));
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
app->app_local->pk[keyno].key = sexp;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Due to a design problem in v1.0 cards we can't get the public
|
||||||
|
key out of these cards without doing a verify on CHV3.
|
||||||
|
Clearly that is not an option and thus we try to locate the
|
||||||
|
key using an external helper. */
|
||||||
|
|
||||||
|
buffer = NULL;
|
||||||
|
/* FIXME */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
/* Set a flag to indicate that we tried to read the key. */
|
||||||
|
app->app_local->pk[keyno].read_done = 1;
|
||||||
|
|
||||||
|
xfree (buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif /* GNUPG_MAJOR_VERSION > 1 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Send the KEYPAIRINFO back. KEYNO needs to be in the range [1,3].
|
||||||
|
This is used by the LEARN command. */
|
||||||
|
static gpg_error_t
|
||||||
|
send_keypair_info (app_t app, ctrl_t ctrl, int keyno)
|
||||||
|
{
|
||||||
|
gpg_error_t err = 0;
|
||||||
|
/* Note that GnuPG 1.x does not need this and it would be too time
|
||||||
|
consuming to send it just for the fun of it. */
|
||||||
|
#if GNUPG_MAJOR_VERSION > 1
|
||||||
|
gcry_sexp_t sexp;
|
||||||
|
unsigned char grip[20];
|
||||||
|
char gripstr[41];
|
||||||
|
char idbuf[50];
|
||||||
|
int i;
|
||||||
|
|
||||||
|
err = get_public_key (app, keyno);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
assert (keyno >= 1 && keyno <= 3);
|
||||||
|
sexp = app->app_local->pk[keyno-1].key;
|
||||||
|
if (!sexp)
|
||||||
|
goto leave; /* No such key. */
|
||||||
|
|
||||||
|
if (!gcry_pk_get_keygrip (sexp, grip))
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < 20; i++)
|
||||||
|
sprintf (gripstr+i*2, "%02X", grip[i]);
|
||||||
|
|
||||||
|
sprintf (idbuf, "OPENPGP.%d", keyno);
|
||||||
|
send_status_info (ctrl, "KEYPAIRINFO",
|
||||||
|
gripstr, 40,
|
||||||
|
idbuf, strlen (idbuf),
|
||||||
|
NULL, (size_t)0);
|
||||||
|
|
||||||
|
leave:
|
||||||
|
#endif /* GNUPG_MAJOR_VERSION > 1 */
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle the LEARN command for OpenPGP. */
|
||||||
static int
|
static int
|
||||||
do_learn_status (app_t app, ctrl_t ctrl)
|
do_learn_status (app_t app, ctrl_t ctrl)
|
||||||
{
|
{
|
||||||
|
@ -760,11 +938,63 @@ do_learn_status (app_t app, ctrl_t ctrl)
|
||||||
if (app->did_chv3)
|
if (app->did_chv3)
|
||||||
do_getattr (app, ctrl, "PRIVATE-DO-4");
|
do_getattr (app, ctrl, "PRIVATE-DO-4");
|
||||||
}
|
}
|
||||||
|
send_keypair_info (app, ctrl, 1);
|
||||||
|
send_keypair_info (app, ctrl, 2);
|
||||||
|
send_keypair_info (app, ctrl, 3);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Handle the READKEY command for OpenPGP. On success a canonical
|
||||||
|
encoded S-expression with the public key will get stored at PK and
|
||||||
|
its length (for assertions) at PKLEN; the caller must release that
|
||||||
|
buffer. On error PK and PKLEN are not changed and an error code is
|
||||||
|
returned. */
|
||||||
|
static int
|
||||||
|
do_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
||||||
|
{
|
||||||
|
gpg_error_t err;
|
||||||
|
int keyno;
|
||||||
|
size_t n;
|
||||||
|
unsigned char *buf;
|
||||||
|
gcry_sexp_t sexp;
|
||||||
|
|
||||||
|
if (!strcmp (keyid, "OPENPGP.1"))
|
||||||
|
keyno = 1;
|
||||||
|
else if (!strcmp (keyid, "OPENPGP.2"))
|
||||||
|
keyno = 2;
|
||||||
|
else if (!strcmp (keyid, "OPENPGP.3"))
|
||||||
|
keyno = 3;
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
|
||||||
|
err = get_public_key (app, keyno);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
sexp = app->app_local->pk[keyno-1].key;
|
||||||
|
if (!sexp)
|
||||||
|
return gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
|
||||||
|
n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, NULL, 0);
|
||||||
|
if (!n)
|
||||||
|
return gpg_error (GPG_ERR_BUG);
|
||||||
|
buf = xtrymalloc (n);
|
||||||
|
if (!buf)
|
||||||
|
return gpg_error_from_errno (errno);
|
||||||
|
n = gcry_sexp_sprint (sexp, GCRYSEXP_FMT_CANON, buf, n);
|
||||||
|
if (!n)
|
||||||
|
{
|
||||||
|
xfree (buf);
|
||||||
|
return gpg_error (GPG_ERR_BUG);
|
||||||
|
}
|
||||||
|
*pk = buf;
|
||||||
|
*pklen = n;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Verify CHV2 if required. Depending on the configuration of the
|
/* Verify CHV2 if required. Depending on the configuration of the
|
||||||
card CHV1 will also be verified. */
|
card CHV1 will also be verified. */
|
||||||
static int
|
static int
|
||||||
|
@ -1082,6 +1312,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||||
generation. This _might_ help a card to gather more entropy. */
|
generation. This _might_ help a card to gather more entropy. */
|
||||||
flush_cache (app);
|
flush_cache (app);
|
||||||
|
|
||||||
|
/* Obviously we need to remove the cached public key. */
|
||||||
|
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||||
|
app->app_local->pk[keyno].read_done = 0;
|
||||||
|
|
||||||
|
/* Check whether a key already exists. */
|
||||||
rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
|
rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
|
||||||
if (rc)
|
if (rc)
|
||||||
{
|
{
|
||||||
|
@ -1109,11 +1344,12 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||||
else
|
else
|
||||||
log_info (_("generating new key\n"));
|
log_info (_("generating new key\n"));
|
||||||
|
|
||||||
|
|
||||||
|
/* Prepare for key generation by verifying the ADmin PIN. */
|
||||||
rc = verify_chv3 (app, pincb, pincb_arg);
|
rc = verify_chv3 (app, pincb, pincb_arg);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
xfree (buffer); buffer = NULL;
|
xfree (buffer); buffer = NULL;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
|
@ -1682,7 +1918,7 @@ app_select_openpgp (app_t app)
|
||||||
|
|
||||||
app->fnc.deinit = do_deinit;
|
app->fnc.deinit = do_deinit;
|
||||||
app->fnc.learn_status = do_learn_status;
|
app->fnc.learn_status = do_learn_status;
|
||||||
app->fnc.readcert = NULL;
|
app->fnc.readkey = do_readkey;
|
||||||
app->fnc.getattr = do_getattr;
|
app->fnc.getattr = do_getattr;
|
||||||
app->fnc.setattr = do_setattr;
|
app->fnc.setattr = do_setattr;
|
||||||
app->fnc.genkey = do_genkey;
|
app->fnc.genkey = do_genkey;
|
||||||
|
@ -1818,6 +2054,9 @@ app_openpgp_storekey (app_t app, int keyno,
|
||||||
|
|
||||||
flush_cache (app);
|
flush_cache (app);
|
||||||
|
|
||||||
|
gcry_sexp_release (app->app_local->pk[keyno].key);
|
||||||
|
app->app_local->pk[keyno].read_done = 0;
|
||||||
|
|
||||||
rc = iso7816_put_data (app->slot,
|
rc = iso7816_put_data (app->slot,
|
||||||
(app->card_version > 0x0007? 0xE0 : 0xE9) + keyno,
|
(app->card_version > 0x0007? 0xE0 : 0xE9) + keyno,
|
||||||
template, template_len);
|
template, template_len);
|
||||||
|
|
26
scd/app.c
26
scd/app.c
|
@ -263,6 +263,32 @@ app_readcert (app_t app, const char *certid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read the key with ID KEYID. On success a canonical encoded
|
||||||
|
S-expression with the public key will get stored at PK and its
|
||||||
|
length (for assertions) at PKLEN; the caller must release that
|
||||||
|
buffer. On error NULL will be stored at PK and PKLEN and an error
|
||||||
|
code returned.
|
||||||
|
|
||||||
|
This function might not be supported by all applications. */
|
||||||
|
int
|
||||||
|
app_readkey (app_t app, const char *keyid, unsigned char **pk, size_t *pklen)
|
||||||
|
{
|
||||||
|
if (pk)
|
||||||
|
*pk = NULL;
|
||||||
|
if (pklen)
|
||||||
|
*pklen = 0;
|
||||||
|
|
||||||
|
if (!app || !keyid || !pk || !pklen)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
if (!app->initialized)
|
||||||
|
return gpg_error (GPG_ERR_CARD_NOT_INITIALIZED);
|
||||||
|
if (!app->fnc.readkey)
|
||||||
|
return gpg_error (GPG_ERR_UNSUPPORTED_OPERATION);
|
||||||
|
|
||||||
|
return app->fnc.readkey (app, keyid, pk, pklen);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Perform a GETATTR operation. */
|
/* Perform a GETATTR operation. */
|
||||||
int
|
int
|
||||||
app_getattr (APP app, CTRL ctrl, const char *name)
|
app_getattr (APP app, CTRL ctrl, const char *name)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* command.c - SCdaemon command handler
|
/* command.c - SCdaemon command handler
|
||||||
* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GnuPG.
|
* This file is part of GnuPG.
|
||||||
*
|
*
|
||||||
|
@ -494,9 +494,9 @@ cmd_readcert (ASSUAN_CONTEXT ctx, char *line)
|
||||||
Return the public key for the given cert or key ID as an standard
|
Return the public key for the given cert or key ID as an standard
|
||||||
S-Expression. */
|
S-Expression. */
|
||||||
static int
|
static int
|
||||||
cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
|
cmd_readkey (assuan_context_t ctx, char *line)
|
||||||
{
|
{
|
||||||
CTRL ctrl = assuan_get_pointer (ctx);
|
ctrl_t ctrl = assuan_get_pointer (ctx);
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char *cert = NULL;
|
unsigned char *cert = NULL;
|
||||||
size_t ncert, n;
|
size_t ncert, n;
|
||||||
|
@ -509,9 +509,31 @@ cmd_readkey (ASSUAN_CONTEXT ctx, char *line)
|
||||||
line = xstrdup (line); /* Need a copy of the line. */
|
line = xstrdup (line); /* Need a copy of the line. */
|
||||||
if (ctrl->app_ctx)
|
if (ctrl->app_ctx)
|
||||||
{
|
{
|
||||||
rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
|
unsigned char *pk;
|
||||||
if (rc)
|
size_t pklen;
|
||||||
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
|
|
||||||
|
/* 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);
|
||||||
|
if (!rc)
|
||||||
|
{ /* Yeah, got that key - send it back. */
|
||||||
|
rc = assuan_send_data (ctx, pk, pklen);
|
||||||
|
xfree (pk);
|
||||||
|
rc = map_assuan_err (rc);
|
||||||
|
xfree (line);
|
||||||
|
line = NULL;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
|
||||||
|
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rc = app_readcert (ctrl->app_ctx, line, &cert, &ncert);
|
||||||
|
if (rc)
|
||||||
|
log_error ("app_readcert failed: %s\n", gpg_strerror (rc));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user