aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-piv.c
diff options
context:
space:
mode:
authorWerner Koch <[email protected]>2020-09-11 13:47:39 +0000
committerWerner Koch <[email protected]>2020-09-11 13:47:39 +0000
commitfbc1b199fdc8fd9a4ab422f005b4eb521b594c5c (patch)
tree5a658962be54a5868bd31e667d22f00d9ce91e30 /scd/app-piv.c
parentcommon: New function cmp_canon_sexp. (diff)
downloadgnupg-fbc1b199fdc8fd9a4ab422f005b4eb521b594c5c.tar.gz
gnupg-fbc1b199fdc8fd9a4ab422f005b4eb521b594c5c.zip
scd:piv: Avoid conflict when writing a cert.
* scd/app-piv.c (map_curve_name_to_oid): New. (my_cmp_public_key): New. (do_writecert): Replace simple memcmp by cmp_canon_sexp. -- GnuPG-bug-id: 5061
Diffstat (limited to 'scd/app-piv.c')
-rw-r--r--scd/app-piv.c64
1 files changed, 63 insertions, 1 deletions
diff --git a/scd/app-piv.c b/scd/app-piv.c
index 8a3c24c81..816c909cf 100644
--- a/scd/app-piv.c
+++ b/scd/app-piv.c
@@ -3355,6 +3355,66 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keyrefstr, const char *keytype,
}
+
+/* Map some names to an OID. */
+static const unsigned char *
+map_curve_name_to_oid (const unsigned char *name, size_t *namelenp)
+{
+ if (*namelenp == 8 && !memcmp (name, "nistp256", 8))
+ {
+ *namelenp = 19;
+ return "1.2.840.10045.3.1.7";
+ }
+ if (*namelenp == 8 && !memcmp (name, "nistp384", 8))
+ {
+ *namelenp = 12;
+ return "1.3.132.0.34";
+ }
+ if (*namelenp == 8 && !memcmp (name, "nistp521", 8))
+ {
+ *namelenp = 12;
+ return "1.3.132.0.35";
+ }
+ return name;
+}
+
+
+/* Communication object for my_cmp_public_key. */
+struct my_cmp_public_key_parm_s {
+ int curve_seen;
+};
+
+/* Compare function used with cmp_canon_sexp. */
+static int
+my_cmp_public_key (void *opaque, int depth,
+ const unsigned char *aval, size_t alen,
+ const unsigned char *bval, size_t blen)
+{
+ struct my_cmp_public_key_parm_s *parm = opaque;
+
+ (void)depth;
+
+ if (parm->curve_seen)
+ {
+ /* Last token was "curve" - canonicalize its argument. */
+ parm->curve_seen = 0;
+ aval = map_curve_name_to_oid (aval, &alen);
+ bval = map_curve_name_to_oid (bval, &blen);
+ }
+ else if (alen == 5 && !memcmp (aval, "curve", 5))
+ parm->curve_seen = 1;
+ else
+ parm->curve_seen = 0;
+
+ if (alen > blen)
+ return 1;
+ else if (alen < blen)
+ return -1;
+ else
+ return memcmp (aval, bval, alen);
+}
+
+
/* Write the certificate (CERT,CERTLEN) to the card at CERTREFSTR.
* CERTREFSTR is either the OID of the certificate's container data
* object or of the form "PIV.<two_hexdigit_keyref>". */
@@ -3370,6 +3430,7 @@ do_writecert (app_t app, ctrl_t ctrl,
unsigned char *pk = NULL;
unsigned char *orig_pk = NULL;
size_t pklen, orig_pklen;
+ struct my_cmp_public_key_parm_s cmp_parm = { 0 };
(void)ctrl;
(void)pincb; /* Not used; instead authentication is needed. */
@@ -3403,7 +3464,8 @@ do_writecert (app_t app, ctrl_t ctrl,
err = app_help_pubkey_from_cert (cert, certlen, &pk, &pklen);
if (err)
goto leave; /* No public key in new certificate. */
- if (orig_pklen != pklen || memcmp (orig_pk, pk, pklen))
+ if (cmp_canon_sexp (orig_pk, orig_pklen, pk, pklen,
+ my_cmp_public_key, &cmp_parm))
{
err = gpg_error (GPG_ERR_CONFLICT);
goto leave;