mirror of
git://git.gnupg.org/gnupg.git
synced 2025-05-24 16:43:28 +02:00
scd: Store a new PIV public key in the certificate DO.
* scd/app-piv.c (struct genkey_result_s): Remove type and all users. (send_keypair_and_cert_info): Print certinfo only if we got a cert.. (readcert_by_tag): Add arg r_mechanism and implement reading of public keys. (get_keygrip_by_tag): Use a public key to compute the keygrip. (do_readcert): Make sure to only return a certificate. (do_readkey): Read public key from the DO if a certificate is missing. (get_key_algorithm_by_dobj): Get the algorithm also from a public key. (does_key_exist): String changes. (do_genkey): Remove result caching and store public key in the DO. -- This removes the result cache and instead stores the public key in the certificate object. This allows to properly list public keys at any time after generating a key and before a new certificate is stored there. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
fcec5b40e5
commit
5bf1212000
289
scd/app-piv.c
289
scd/app-piv.c
@ -39,6 +39,12 @@
|
|||||||
* |---------------------------------------------------------------|
|
* |---------------------------------------------------------------|
|
||||||
* (9B indicates the 24 byte PIV Card Application Administration Key)
|
* (9B indicates the 24 byte PIV Card Application Administration Key)
|
||||||
*
|
*
|
||||||
|
* - When generating a key we store the created public key in the
|
||||||
|
* corresponding data object, so that gpg and gpgsm are able to get
|
||||||
|
* the public key, create a certificate and store that then in that
|
||||||
|
* data object. That is not standard compliant but due to the use
|
||||||
|
* of other tags, it should not harm. See do_genkey for the actual
|
||||||
|
* used tag structure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
@ -153,22 +159,11 @@ struct cache_s {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* A cache item used by genkey. */
|
|
||||||
struct genkey_result_s {
|
|
||||||
struct genkey_result_s *next;
|
|
||||||
int keyref;
|
|
||||||
gcry_sexp_t s_pkey;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Object with application specific data. */
|
/* Object with application specific data. */
|
||||||
struct app_local_s {
|
struct app_local_s {
|
||||||
/* A linked list with cached DOs. */
|
/* A linked list with cached DOs. */
|
||||||
struct cache_s *cache;
|
struct cache_s *cache;
|
||||||
|
|
||||||
/* A list with results from recent genkey operations. */
|
|
||||||
struct genkey_result_s *genkey_results;
|
|
||||||
|
|
||||||
/* Various flags. */
|
/* Various flags. */
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
@ -180,7 +175,9 @@ struct app_local_s {
|
|||||||
|
|
||||||
/***** Local prototypes *****/
|
/***** Local prototypes *****/
|
||||||
static gpg_error_t get_keygrip_by_tag (app_t app, unsigned int tag,
|
static gpg_error_t get_keygrip_by_tag (app_t app, unsigned int tag,
|
||||||
char **r_keygripstr);
|
char **r_keygripstr, int *got_cert);
|
||||||
|
static gpg_error_t genkey_parse_rsa (const unsigned char *data, size_t datalen,
|
||||||
|
gcry_sexp_t *r_sexp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -193,19 +190,12 @@ 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;
|
||||||
struct genkey_result_s *gr, *gr2;
|
|
||||||
|
|
||||||
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 (gr = app->app_local->genkey_results; gr; gr = gr2)
|
|
||||||
{
|
|
||||||
gr2 = gr->next;
|
|
||||||
gcry_sexp_release (gr->s_pkey);
|
|
||||||
xfree (gr);
|
|
||||||
}
|
|
||||||
|
|
||||||
xfree (app->app_local);
|
xfree (app->app_local);
|
||||||
app->app_local = NULL;
|
app->app_local = NULL;
|
||||||
@ -567,7 +557,6 @@ put_data (int slot, unsigned int tag, ...)
|
|||||||
p += argv[i].len;
|
p += argv[i].len;
|
||||||
}
|
}
|
||||||
log_assert ( data + datalen == p );
|
log_assert ( data + datalen == p );
|
||||||
log_printhex (data, datalen, "Put data");
|
|
||||||
err = iso7816_put_data_odd (slot, -1 /* use command chaining */,
|
err = iso7816_put_data_odd (slot, -1 /* use command chaining */,
|
||||||
0x3fff, data, datalen);
|
0x3fff, data, datalen);
|
||||||
|
|
||||||
@ -978,9 +967,10 @@ send_keypair_and_cert_info (app_t app, ctrl_t ctrl, data_object_t dobj,
|
|||||||
{
|
{
|
||||||
gpg_error_t err = 0;
|
gpg_error_t err = 0;
|
||||||
char *keygripstr = NULL;
|
char *keygripstr = NULL;
|
||||||
|
int got_cert;
|
||||||
char idbuf[50];
|
char idbuf[50];
|
||||||
|
|
||||||
err = get_keygrip_by_tag (app, dobj->tag, &keygripstr);
|
err = get_keygrip_by_tag (app, dobj->tag, &keygripstr, &got_cert);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
|
||||||
@ -989,7 +979,7 @@ send_keypair_and_cert_info (app_t app, ctrl_t ctrl, data_object_t dobj,
|
|||||||
keygripstr, strlen (keygripstr),
|
keygripstr, strlen (keygripstr),
|
||||||
idbuf, strlen (idbuf),
|
idbuf, strlen (idbuf),
|
||||||
NULL, (size_t)0);
|
NULL, (size_t)0);
|
||||||
if (!only_keypair)
|
if (!only_keypair && got_cert)
|
||||||
{
|
{
|
||||||
/* All certificates are of type 100 (Regular X.509 Cert). */
|
/* All certificates are of type 100 (Regular X.509 Cert). */
|
||||||
send_status_info (ctrl, "CERTINFO",
|
send_status_info (ctrl, "CERTINFO",
|
||||||
@ -1026,20 +1016,24 @@ do_learn_status (app_t app, ctrl_t ctrl, unsigned int flags)
|
|||||||
|
|
||||||
/* Core of do_readcert which fetches the certificate based on the
|
/* Core of do_readcert which fetches the certificate based on the
|
||||||
* given tag and returns it in a freshly allocated buffer stored at
|
* given tag and returns it in a freshly allocated buffer stored at
|
||||||
* R_CERT and the length of the certificate stored at R_CERTLEN. */
|
* R_CERT and the length of the certificate stored at R_CERTLEN. If
|
||||||
|
* on success a non-zero value is stored at R_MECHANISM, the returned
|
||||||
|
* data is not certificate but a public key (in the format used by the
|
||||||
|
* container '7f49'. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
readcert_by_tag (app_t app, unsigned int tag,
|
readcert_by_tag (app_t app, unsigned int tag,
|
||||||
unsigned char **r_cert, size_t *r_certlen)
|
unsigned char **r_cert, size_t *r_certlen, int *r_mechanism)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char *buffer;
|
unsigned char *buffer;
|
||||||
size_t buflen;
|
size_t buflen;
|
||||||
void *relptr;
|
void *relptr;
|
||||||
const unsigned char *s;
|
const unsigned char *s, *s2;
|
||||||
size_t n;
|
size_t n, n2;
|
||||||
|
|
||||||
*r_cert = NULL;
|
*r_cert = NULL;
|
||||||
*r_certlen = 0;
|
*r_certlen = 0;
|
||||||
|
*r_mechanism = 0;
|
||||||
|
|
||||||
relptr = get_one_do (app, tag, &buffer, &buflen, NULL);
|
relptr = get_one_do (app, tag, &buffer, &buflen, NULL);
|
||||||
if (!relptr || !buflen)
|
if (!relptr || !buflen)
|
||||||
@ -1049,36 +1043,61 @@ readcert_by_tag (app_t app, unsigned int tag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s = find_tlv (buffer, buflen, 0x71, &n);
|
s = find_tlv (buffer, buflen, 0x71, &n);
|
||||||
if (!s || n != 1)
|
if (!s)
|
||||||
{
|
{
|
||||||
log_error ("piv: no or invalid CertInfo in 0x%X\n", tag);
|
/* No certificate; check whether a public key has been stored
|
||||||
err = gpg_error (GPG_ERR_INV_CERT_OBJ);
|
* using our own scheme. */
|
||||||
goto leave;
|
s = find_tlv (buffer, buflen, 0x7f49, &n);
|
||||||
|
if (!s || !n)
|
||||||
|
{
|
||||||
|
log_error ("piv: No public key in 0x%X\n", tag);
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
s2 = find_tlv (buffer, buflen, 0x80, &n2);
|
||||||
|
if (!s2 || n2 != 1 || !*s2)
|
||||||
|
{
|
||||||
|
log_error ("piv: No mechanism for public key in 0x%X\n", tag);
|
||||||
|
err = gpg_error (GPG_ERR_NO_PUBKEY);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
*r_mechanism = *s2;
|
||||||
}
|
}
|
||||||
if (*s == 0x01)
|
else
|
||||||
{
|
{
|
||||||
log_error ("piv: gzip compression not yet supported (tag 0x%X)\n", tag);
|
if (n != 1)
|
||||||
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
|
{
|
||||||
goto leave;
|
log_error ("piv: invalid CertInfo in 0x%X\n", tag);
|
||||||
}
|
err = gpg_error (GPG_ERR_INV_CERT_OBJ);
|
||||||
if (*s)
|
goto leave;
|
||||||
{
|
}
|
||||||
log_error ("piv: invalid CertInfo 0x%02x in 0x%X\n", *s, tag);
|
if (*s == 0x01)
|
||||||
err = gpg_error (GPG_ERR_INV_CERT_OBJ);
|
{
|
||||||
goto leave;
|
log_error ("piv: gzip compression not yet supported (tag 0x%X)\n",
|
||||||
}
|
tag);
|
||||||
|
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
|
||||||
/* Note: We don't check that the LRC octet has a length of zero as
|
goto leave;
|
||||||
* required by the specs. */
|
}
|
||||||
|
if (*s)
|
||||||
/* Get the cert from the container. */
|
{
|
||||||
s = find_tlv (buffer, buflen, 0x70, &n);
|
log_error ("piv: invalid CertInfo 0x%02x in 0x%X\n", *s, tag);
|
||||||
if (!s || !n)
|
err = gpg_error (GPG_ERR_INV_CERT_OBJ);
|
||||||
{
|
goto leave;
|
||||||
err = gpg_error (GPG_ERR_NOT_FOUND);
|
}
|
||||||
goto leave;
|
|
||||||
|
/* Note: We don't check that the LRC octet has a length of zero
|
||||||
|
* as required by the specs. */
|
||||||
|
|
||||||
|
/* Get the cert from the container. */
|
||||||
|
s = find_tlv (buffer, buflen, 0x70, &n);
|
||||||
|
if (!s || !n)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The next is common for certificate and public key. */
|
||||||
if (!(*r_cert = xtrymalloc (n)))
|
if (!(*r_cert = xtrymalloc (n)))
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -1095,17 +1114,22 @@ readcert_by_tag (app_t app, unsigned int tag,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Get the keygrip of a key from the certificate stored at TAG.
|
/* Get the keygrip in hex format of a key from the certificate stored
|
||||||
* Caller must free the string at R_KEYGRIPSTR. */
|
* at TAG. Caller must free the string at R_KEYGRIPSTR. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
get_keygrip_by_tag (app_t app, unsigned int tag, char **r_keygripstr)
|
get_keygrip_by_tag (app_t app, unsigned int tag,
|
||||||
|
char **r_keygripstr, int *r_got_cert)
|
||||||
{
|
{
|
||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char *certbuf = NULL;
|
unsigned char *certbuf = NULL;
|
||||||
size_t certbuflen;
|
size_t certbuflen;
|
||||||
|
int mechanism;
|
||||||
|
gcry_sexp_t s_pkey = NULL;
|
||||||
ksba_cert_t cert = NULL;
|
ksba_cert_t cert = NULL;
|
||||||
|
unsigned char grip[KEYGRIP_LEN];
|
||||||
|
|
||||||
*r_keygripstr = xtrymalloc (40+1);
|
*r_got_cert = 0;
|
||||||
|
*r_keygripstr = xtrymalloc (2*KEYGRIP_LEN+1);
|
||||||
if (!r_keygripstr)
|
if (!r_keygripstr)
|
||||||
{
|
{
|
||||||
err = gpg_error_from_syserror ();
|
err = gpg_error_from_syserror ();
|
||||||
@ -1113,21 +1137,41 @@ get_keygrip_by_tag (app_t app, unsigned int tag, char **r_keygripstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* We need to get the public key from the certificate. */
|
/* We need to get the public key from the certificate. */
|
||||||
err = readcert_by_tag (app, tag, &certbuf, &certbuflen);
|
err = readcert_by_tag (app, tag, &certbuf, &certbuflen, &mechanism);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
if (mechanism) /* Compute keygrip from public key. */
|
||||||
|
{
|
||||||
|
if (mechanism == PIV_ALGORITHM_RSA)
|
||||||
|
err = genkey_parse_rsa (certbuf, certbuflen, &s_pkey);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
/* Compute the keygrip. */
|
if (!gcry_pk_get_keygrip (s_pkey, grip))
|
||||||
err = ksba_cert_new (&cert);
|
{
|
||||||
if (err)
|
log_error ("piv: error computing keygrip\n");
|
||||||
goto leave;
|
err = gpg_error (GPG_ERR_GENERAL);
|
||||||
err = ksba_cert_init_from_mem (cert, certbuf, certbuflen);
|
goto leave;
|
||||||
if (err)
|
}
|
||||||
goto leave;
|
|
||||||
err = app_help_get_keygrip_string (cert, *r_keygripstr);
|
|
||||||
|
|
||||||
|
bin2hex (grip, sizeof grip, *r_keygripstr);
|
||||||
|
}
|
||||||
|
else /* Compute keygrip from certificate. */
|
||||||
|
{
|
||||||
|
*r_got_cert = 0;
|
||||||
|
err = ksba_cert_new (&cert);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = ksba_cert_init_from_mem (cert, certbuf, certbuflen);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
err = app_help_get_keygrip_string (cert, *r_keygripstr);
|
||||||
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
ksba_cert_release (cert);
|
ksba_cert_release (cert);
|
||||||
xfree (certbuf);
|
xfree (certbuf);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1193,7 +1237,9 @@ static gpg_error_t
|
|||||||
do_readcert (app_t app, const char *certid,
|
do_readcert (app_t app, const char *certid,
|
||||||
unsigned char **r_cert, size_t *r_certlen)
|
unsigned char **r_cert, size_t *r_certlen)
|
||||||
{
|
{
|
||||||
|
gpg_error_t err;
|
||||||
data_object_t dobj;
|
data_object_t dobj;
|
||||||
|
int mechanism;
|
||||||
|
|
||||||
*r_cert = NULL;
|
*r_cert = NULL;
|
||||||
*r_certlen = 0;
|
*r_certlen = 0;
|
||||||
@ -1202,7 +1248,16 @@ do_readcert (app_t app, const char *certid,
|
|||||||
if (!dobj)
|
if (!dobj)
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
|
||||||
return readcert_by_tag (app, dobj->tag, r_cert, r_certlen);
|
err = readcert_by_tag (app, dobj->tag, r_cert, r_certlen, &mechanism);
|
||||||
|
if (!err && mechanism)
|
||||||
|
{
|
||||||
|
/* Well, no certificate but a public key - we don't want it. */
|
||||||
|
xfree (*r_cert);
|
||||||
|
*r_cert = NULL;
|
||||||
|
*r_certlen = 0;
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1212,7 +1267,7 @@ do_readcert (app_t app, const char *certid,
|
|||||||
* result from key generation. If no cached result is available, the
|
* result from key generation. If no cached result is available, the
|
||||||
* error GPG_ERR_UNSUPPORTED_OPERATION is returned so that the higher
|
* 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 to get the key by reading the matching certificate.
|
||||||
* On success a canonical encoded S-expression with the public key is
|
* 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
|
* 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
|
* error R_PK and R_PKLEN are not changed and an error code is
|
||||||
* returned.
|
* returned.
|
||||||
@ -1224,7 +1279,10 @@ do_readkey (app_t app, int advanced, const char *keyrefstr,
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
data_object_t dobj;
|
data_object_t dobj;
|
||||||
int keyref;
|
int keyref;
|
||||||
struct genkey_result_s *gres;
|
unsigned char *cert = NULL;
|
||||||
|
size_t certlen;
|
||||||
|
int mechanism;
|
||||||
|
gcry_sexp_t s_pkey = NULL;
|
||||||
unsigned char *pk = NULL;
|
unsigned char *pk = NULL;
|
||||||
size_t pklen;
|
size_t pklen;
|
||||||
|
|
||||||
@ -1234,16 +1292,28 @@ do_readkey (app_t app, int advanced, const char *keyrefstr,
|
|||||||
err = gpg_error (GPG_ERR_INV_ID);
|
err = gpg_error (GPG_ERR_INV_ID);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
for (gres = app->app_local->genkey_results; gres; gres = gres->next)
|
|
||||||
if (gres->keyref == keyref)
|
err = readcert_by_tag (app, dobj->tag, &cert, &certlen, &mechanism);
|
||||||
break;
|
if (err)
|
||||||
if (!gres || !gres->s_pkey)
|
goto leave;
|
||||||
|
if (!mechanism)
|
||||||
{
|
{
|
||||||
err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
/* We got a certificate. Let the upper layer handle the
|
||||||
|
* extraction of the key. FIXME: It would be better to have a
|
||||||
|
* shared fucntion to dothis here. */
|
||||||
|
err = gpg_error (GPG_ERR_NOT_FOUND);
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = make_canon_sexp (gres->s_pkey, &pk, &pklen);
|
/* Convert the public key into the expected s-expression. */
|
||||||
|
if (mechanism == PIV_ALGORITHM_RSA)
|
||||||
|
err = genkey_parse_rsa (cert, certlen, &s_pkey);
|
||||||
|
else
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = make_canon_sexp (s_pkey, &pk, &pklen);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
if (advanced)
|
if (advanced)
|
||||||
@ -1265,7 +1335,9 @@ do_readkey (app_t app, int advanced, const char *keyrefstr,
|
|||||||
*r_pklen = pklen;
|
*r_pklen = pklen;
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
|
gcry_sexp_release (s_pkey);
|
||||||
xfree (pk);
|
xfree (pk);
|
||||||
|
xfree (cert);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1279,6 +1351,7 @@ get_key_algorithm_by_dobj (app_t app, data_object_t dobj, int *r_algo)
|
|||||||
gpg_error_t err;
|
gpg_error_t err;
|
||||||
unsigned char *certbuf = NULL;
|
unsigned char *certbuf = NULL;
|
||||||
size_t certbuflen;
|
size_t certbuflen;
|
||||||
|
int mechanism;
|
||||||
ksba_cert_t cert = NULL;
|
ksba_cert_t cert = NULL;
|
||||||
ksba_sexp_t k_pkey = NULL;
|
ksba_sexp_t k_pkey = NULL;
|
||||||
gcry_sexp_t s_pkey = NULL;
|
gcry_sexp_t s_pkey = NULL;
|
||||||
@ -1290,9 +1363,28 @@ get_key_algorithm_by_dobj (app_t app, data_object_t dobj, int *r_algo)
|
|||||||
|
|
||||||
*r_algo = 0;
|
*r_algo = 0;
|
||||||
|
|
||||||
err = readcert_by_tag (app, dobj->tag, &certbuf, &certbuflen);
|
err = readcert_by_tag (app, dobj->tag, &certbuf, &certbuflen, &mechanism);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
if (mechanism)
|
||||||
|
{
|
||||||
|
/* A public key was found. That makes it easy. */
|
||||||
|
switch (mechanism)
|
||||||
|
{
|
||||||
|
case PIV_ALGORITHM_RSA:
|
||||||
|
case PIV_ALGORITHM_ECC_P256:
|
||||||
|
case PIV_ALGORITHM_ECC_P384:
|
||||||
|
*r_algo = mechanism;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = gpg_error (GPG_ERR_PUBKEY_ALGO);
|
||||||
|
log_error ("piv: unknown mechanism %d in public key at %s\n",
|
||||||
|
mechanism, dobj->keyref);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
err = ksba_cert_new (&cert);
|
err = ksba_cert_new (&cert);
|
||||||
if (err)
|
if (err)
|
||||||
@ -1971,22 +2063,22 @@ does_key_exist (app_t app, data_object_t dobj, int generating, int force)
|
|||||||
|
|
||||||
if (found && !force)
|
if (found && !force)
|
||||||
{
|
{
|
||||||
log_error ("piv: %s", _("key already exists\n"));
|
log_error (_("key already exists\n"));
|
||||||
return gpg_error (GPG_ERR_EEXIST);
|
return gpg_error (GPG_ERR_EEXIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found)
|
if (found)
|
||||||
log_info ("piv: %s", _("existing key will be replaced\n"));
|
log_info (_("existing key will be replaced\n"));
|
||||||
else if (generating)
|
else if (generating)
|
||||||
log_info ("piv: %s", _("generating new key\n"));
|
log_info (_("generating new key\n"));
|
||||||
else
|
else
|
||||||
log_info ("piv: %s", _("writing new key\n"));
|
log_info (_("writing new key\n"));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Parse an RSA response object, consisting of the content of tag
|
/* Parse an RSA response object, consisting of the content of tag
|
||||||
* 0x7f49, into a gcrypt s-expresstion object and store that R_SEXP.
|
* 0x7f49, into a gcrypt s-expression object and store that R_SEXP.
|
||||||
* On error NULL is stored at R_SEXP. */
|
* On error NULL is stored at R_SEXP. */
|
||||||
static gpg_error_t
|
static gpg_error_t
|
||||||
genkey_parse_rsa (const unsigned char *data, size_t datalen,
|
genkey_parse_rsa (const unsigned char *data, size_t datalen,
|
||||||
@ -2096,8 +2188,6 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyrefstr, const char *keytype,
|
|||||||
size_t tmpllen;
|
size_t tmpllen;
|
||||||
const unsigned char *keydata;
|
const unsigned char *keydata;
|
||||||
size_t keydatalen;
|
size_t keydatalen;
|
||||||
gcry_sexp_t s_pkey = NULL;
|
|
||||||
struct genkey_result_s *gres;
|
|
||||||
|
|
||||||
(void)ctrl;
|
(void)ctrl;
|
||||||
(void)createtime;
|
(void)createtime;
|
||||||
@ -2151,7 +2241,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyrefstr, const char *keytype,
|
|||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
log_error (_("generating key failed\n"));
|
log_error (_("generating key failed\n"));
|
||||||
return gpg_error (GPG_ERR_CARD);
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -2171,36 +2261,20 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyrefstr, const char *keytype,
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mechanism == PIV_ALGORITHM_RSA)
|
tmpl[0] = mechanism;
|
||||||
err = genkey_parse_rsa (keydata, keydatalen, &s_pkey);
|
flush_cached_data (app, dobj->tag);
|
||||||
else
|
err = put_data (app->slot, dobj->tag,
|
||||||
err = gpg_error (GPG_ERR_BUG);
|
(int)0x80, (size_t)1, tmpl,
|
||||||
|
(int)0x7f49, (size_t)keydatalen, keydata,
|
||||||
|
(int)0, (size_t)0, NULL);
|
||||||
if (err)
|
if (err)
|
||||||
goto leave;
|
|
||||||
|
|
||||||
for (gres = app->app_local->genkey_results; gres; gres = gres->next)
|
|
||||||
if (gres->keyref == keyref)
|
|
||||||
break;
|
|
||||||
if (!gres)
|
|
||||||
{
|
{
|
||||||
gres = xtrycalloc (1, sizeof *gres);
|
log_error ("piv: failed to write key to the cert DO %s: %s\n",
|
||||||
if (!gres)
|
dobj->keyref, gpg_strerror (err));
|
||||||
{
|
goto leave;
|
||||||
err = gpg_error_from_syserror ();
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
gres->keyref = keyref;
|
|
||||||
gres->next = app->app_local->genkey_results;
|
|
||||||
app->app_local->genkey_results = gres;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
gcry_sexp_release (gres->s_pkey);
|
|
||||||
gres->s_pkey = s_pkey;
|
|
||||||
s_pkey = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
gcry_sexp_release (s_pkey);
|
|
||||||
xfree (buffer);
|
xfree (buffer);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -2230,7 +2304,6 @@ do_writecert (app_t app, ctrl_t ctrl,
|
|||||||
/* FIXME: Check that the authentication has already been done. */
|
/* FIXME: Check that the authentication has already been done. */
|
||||||
|
|
||||||
flush_cached_data (app, dobj->tag);
|
flush_cached_data (app, dobj->tag);
|
||||||
|
|
||||||
err = put_data (app->slot, dobj->tag,
|
err = put_data (app->slot, dobj->tag,
|
||||||
(int)0x70, (size_t)certlen, cert,/* Certificate */
|
(int)0x70, (size_t)certlen, cert,/* Certificate */
|
||||||
(int)0x71, (size_t)1, "", /* No compress */
|
(int)0x71, (size_t)1, "", /* No compress */
|
||||||
|
@ -544,7 +544,8 @@ cmd_readkey (assuan_context_t ctx, char *line)
|
|||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpg_err_code (rc) != GPG_ERR_UNSUPPORTED_OPERATION)
|
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));
|
log_error ("app_readkey failed: %s\n", gpg_strerror (rc));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user