aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-p15.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2021-04-12 09:41:00 +0000
committerWerner Koch <[email protected]>2021-04-12 09:41:00 +0000
commitecb9265b8dc03a153044e19be804d4c2d2caa4e8 (patch)
tree12eed0f7e38d4c0adf03cc7e72f691a240e022bf /scd/app-p15.c
parentdoc: Register DCO for Jakub Jelen. (diff)
downloadgnupg-ecb9265b8dc03a153044e19be804d4c2d2caa4e8.tar.gz
gnupg-ecb9265b8dc03a153044e19be804d4c2d2caa4e8.zip
scd:p15: Match private keys with certificates also by labels.
* scd/app-p15.c (cdf_object_from_label): New. (cdf_object_from_certid): Fallback to label matching. (read_p15_info): Ditto. (keygrip_from_prkdf): Ditto. Replace duplicated code by a call to cdf_object_from_objid. -- In case there is no certificate for a private key we now also try to find a certificate using a matching label. Signed-off-by: Werner Koch <[email protected]>
Diffstat (limited to 'scd/app-p15.c')
-rw-r--r--scd/app-p15.c87
1 files changed, 59 insertions, 28 deletions
diff --git a/scd/app-p15.c b/scd/app-p15.c
index 20c6e06eb..6ad207cfe 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -887,6 +887,34 @@ cdf_object_from_objid (app_t app, size_t objidlen, const unsigned char *objid,
}
+/* Find a certificate object by its label and store a pointer to it at
+ * R_CDF. */
+static gpg_error_t
+cdf_object_from_label (app_t app, const char *label, cdf_object_t *r_cdf)
+{
+ cdf_object_t cdf;
+
+ if (!label)
+ return gpg_error (GPG_ERR_NOT_FOUND);
+
+ for (cdf = app->app_local->certificate_info; cdf; cdf = cdf->next)
+ if (cdf->label && !strcmp (cdf->label, label))
+ break;
+ if (!cdf)
+ for (cdf = app->app_local->trusted_certificate_info; cdf; cdf = cdf->next)
+ if (cdf->label && !strcmp (cdf->label, label))
+ break;
+ if (!cdf)
+ for (cdf = app->app_local->useful_certificate_info; cdf; cdf = cdf->next)
+ if (cdf->label && !strcmp (cdf->label, label))
+ break;
+ if (!cdf)
+ return gpg_error (GPG_ERR_NOT_FOUND);
+ *r_cdf = cdf;
+ return 0;
+}
+
+
/* Find a certificate object by the certificate ID CERTID and store a
* pointer to it at R_CDF. */
static gpg_error_t
@@ -896,12 +924,24 @@ cdf_object_from_certid (app_t app, const char *certid, cdf_object_t *r_cdf)
size_t objidlen;
unsigned char *objid;
cdf_object_t cdf;
+ prkdf_object_t prkdf;
err = parse_certid (app, certid, &objid, &objidlen);
if (err)
return err;
err = cdf_object_from_objid (app, objidlen, objid, &cdf);
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ {
+ /* Try again by finding the certid in the prkdf and matching by
+ * label. */
+ for (prkdf = app->app_local->private_key_info; prkdf; prkdf = prkdf->next)
+ if (prkdf->objidlen == objidlen
+ && !memcmp (prkdf->objid, objid, objidlen))
+ break;
+ if (prkdf)
+ err = cdf_object_from_label (app, prkdf->label, &cdf);
+ }
xfree (objid);
if (err)
return err;
@@ -3518,17 +3558,19 @@ read_p15_info (app_t app)
char *extusage;
char *p, *pend;
int seen;
+ gpg_error_t errx;
if (opt.debug)
log_printhex (prkdf->objid, prkdf->objidlen, "p15: prkdf id=");
- if (cdf_object_from_objid (app, prkdf->objidlen, prkdf->objid, &cdf))
+ if (cdf_object_from_objid (app, prkdf->objidlen, prkdf->objid, &cdf)
+ && cdf_object_from_label (app, prkdf->label, &cdf))
continue; /* No matching certificate. */
if (!cdf->cert) /* Read and parse the certificate. */
readcert_by_cdf (app, cdf, NULL, NULL);
if (!cdf->cert)
continue; /* Unsupported or broken certificate. */
- if (ksba_cert_get_ext_key_usages (cdf->cert, &extusage))
+ if ((errx=ksba_cert_get_ext_key_usages (cdf->cert, &extusage)))
continue; /* No extended key usage attribute. */
if (opt.debug)
@@ -3801,33 +3843,22 @@ keygrip_from_prkdf (app_t app, prkdf_object_t prkdf)
xfree (prkdf->serial_number);
prkdf->serial_number = NULL;
- /* FIXME: We should check whether a public key directory file and a
- matching public key for PRKDF is available. This should make
- extraction of the key much easier. My current test card doesn't
- have one, so we can only use the fallback solution by looking for
- a matching certificate and extract the key from there. */
+ /* We could have also checked whether a public key directory file
+ * and a matching public key for PRKDF is available. This would
+ * make extraction of the key faster. However, this way we don't
+ * have a way to look at extended key attributes to check gpgusage.
+ * FIXME: Add public key lookup if no certificate was found. */
- /* Look for a matching certificate. A certificate matches if the Id
- matches the one of the private key info. */
- for (cdf = app->app_local->certificate_info; cdf; cdf = cdf->next)
- if (cdf->objidlen == prkdf->objidlen
- && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
- break;
- if (!cdf)
- for (cdf = app->app_local->trusted_certificate_info; cdf; cdf = cdf->next)
- if (cdf->objidlen == prkdf->objidlen
- && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
- break;
- if (!cdf)
- for (cdf = app->app_local->useful_certificate_info; cdf; cdf = cdf->next)
- if (cdf->objidlen == prkdf->objidlen
- && !memcmp (cdf->objid, prkdf->objid, prkdf->objidlen))
- break;
- if (!cdf)
- {
- err = gpg_error (GPG_ERR_NOT_FOUND);
- goto leave;
- }
+ /* Look for a matching certificate. A certificate matches if the id
+ * matches the one of the private key info. If none was found we
+ * also try to match on the label. */
+ err = cdf_object_from_objid (app, prkdf->objidlen, prkdf->objid, &cdf);
+ if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+ err = cdf_object_from_label (app, prkdf->label, &cdf);
+ if (!err && !cdf)
+ err = gpg_error (GPG_ERR_NOT_FOUND);
+ if (err)
+ goto leave;
err = readcert_by_cdf (app, cdf, &der, &derlen);
if (err)