From 764c69a841abc1a4dff2fa86b4cd0b63ec737860 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Thu, 26 Nov 2020 08:46:20 +0100 Subject: [PATCH] scd: Add special serialno compare for OpenPGP cards. * scd/app.c (is_same_serialno): New. (check_application_conflict): Use this. (select_application): Ditto. (app_switch_current_card): Ditto. * scd/app-openpgp.c (check_keyidstr): Ignore the card version and also compare case insensitive. -- This is required because we change what we emit as serialno of OpenPGP cards but existing keys still use the old form of the serial number (i.e. with a firmware version). See-commit: 3a8250c02031080c6c8eebd5dea03f5f87f9ddd7 Signed-off-by: Werner Koch --- doc/HACKING | 1 + scd/app-openpgp.c | 13 +++++++++---- scd/app.c | 41 +++++++++++++++++++++++++++++++++++------ 3 files changed, 45 insertions(+), 10 deletions(-) diff --git a/doc/HACKING b/doc/HACKING index 0f7a33a25..eb46d50c9 100644 --- a/doc/HACKING +++ b/doc/HACKING @@ -220,6 +220,7 @@ Note that such a comment will be removed if the git commit option - Regression-due-to :: Commit id of the regression fixed by this commit. - Fixes-commit :: Commit id this commit fixes. - Updates-commit :: Commit id this commit updates. + - See-commit :: Commit id of a related commit. - Reported-by :: Value is a name or mail address of a bug reporte. - Suggested-by :: Value is a name or mail address of someone how suggested this change. diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c index 440c4d027..36301ee8d 100644 --- a/scd/app-openpgp.c +++ b/scd/app-openpgp.c @@ -1102,8 +1102,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name) if (table[idx].special == -1) { - /* The serial number is very special. We can't use the the AID - DO (0x4f) becuase this is the serialno per specs with the + /* The serial number is very special. We can't use the AID + DO (0x4f) because this is the serialno per specs with the correct appversion. We might however use a serialno with the version set to 0.0 and that is what we need to return. */ char *serial = app_get_serialno (app); @@ -5031,7 +5031,10 @@ check_keyidstr (app_t app, const char *keyidstr, int keyno, int *r_use_auth) return gpg_error (GPG_ERR_INV_ID); } - if (n != 32 || strncmp (keyidstr, "D27600012401", 12)) + /* For a description of the serialno compare function see + * is_same_serialno. We don't use that function because here we + * are working on a hex string. */ + if (n != 32 || ascii_strncasecmp (keyidstr, "D27600012401", 12)) return gpg_error (GPG_ERR_INV_ID); else if (!*s) ; /* no fingerprint given: we allow this for now. */ @@ -5039,7 +5042,9 @@ check_keyidstr (app_t app, const char *keyidstr, int keyno, int *r_use_auth) fpr = s + 1; serial = app_get_serialno (app); - if (strncmp (serial, keyidstr, 32)) + if (!serial || strlen (serial) != 32 + || ascii_memcasecmp (serial, "D27600012401", 12) + || ascii_memcasecmp (serial+16, keyidstr+16, 16)) { xfree (serial); return gpg_error (GPG_ERR_WRONG_CARD); diff --git a/scd/app.c b/scd/app.c index f17e2d62b..7ba714b3e 100644 --- a/scd/app.c +++ b/scd/app.c @@ -155,6 +155,35 @@ apptype_from_keyref (const char *keyref) } +/* Return true if both serilanumbers are the same. This function + * takes care of some peculiarities. */ +static int +is_same_serialno (const unsigned char *sna, size_t snalen, + const unsigned char *snb, size_t snblen) +{ + if ((!sna && !snb) || (!snalen && !snblen)) + return 1; + if (!sna || !snb) + return 0; /* One of them is NULL. (Both NULL tested above). */ + + if (snalen != snblen) + return 0; /* (No special cases for this below). */ + + /* The special case for OpenPGP cards where we ignore the version + * bytes (vvvv). Example: D276000124010304000500009D8A0000 + * ^^^^^^^^^^^^vvvvmmmmssssssssrrrr */ + if (snalen == 16 && !memcmp (sna, "\xD2\x76\x00\x01\x24\x01", 6)) + { + if (memcmp (snb, "\xD2\x76\x00\x01\x24\x01", 6)) + return 0; /* No */ + return !memcmp (sna + 8, snb + 8, 8); + } + + return !memcmp (sna, snb, snalen); +} + + + /* Initialization function to change the default app_priority_list. * LIST is a list of comma or space separated strings with application * names. Unknown names will only result in warning message. @@ -357,8 +386,8 @@ check_application_conflict (card_t card, const char *name, if (serialno_bin && card->serialno) { - if (serialno_bin_len != card->serialnolen - || memcmp (serialno_bin, card->serialno, card->serialnolen)) + if (!is_same_serialno (card->serialno, card->serialnolen, + serialno_bin, serialno_bin_len)) return 0; /* The card does not match the requested S/N. */ } @@ -734,8 +763,8 @@ select_application (ctrl_t ctrl, const char *name, card_t *r_card, lock_card (card, ctrl); if (serialno_bin == NULL) break; - if (card->serialnolen == serialno_bin_len - && !memcmp (card->serialno, serialno_bin, card->serialnolen)) + if (is_same_serialno (card->serialno, card->serialnolen, + serialno_bin, serialno_bin_len)) break; unlock_card (card); card_prev = card; @@ -805,8 +834,8 @@ app_switch_current_card (ctrl_t ctrl, { for (card = card_top; card; card = card->next) { - if (card->serialnolen == serialnolen - && !memcmp (card->serialno, serialno, card->serialnolen)) + if (is_same_serialno (card->serialno, card->serialnolen, + serialno, serialnolen)) break; } if (!card)