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: 3a8250c020
Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2020-11-26 08:46:20 +01:00
parent 605ab99912
commit 764c69a841
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
3 changed files with 45 additions and 10 deletions

View File

@ -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. - Regression-due-to :: Commit id of the regression fixed by this commit.
- Fixes-commit :: Commit id this commit fixes. - Fixes-commit :: Commit id this commit fixes.
- Updates-commit :: Commit id this commit updates. - 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. - 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-by :: Value is a name or mail address of someone how
suggested this change. suggested this change.

View File

@ -1102,8 +1102,8 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
if (table[idx].special == -1) if (table[idx].special == -1)
{ {
/* The serial number is very special. We can't use the the AID /* The serial number is very special. We can't use the AID
DO (0x4f) becuase this is the serialno per specs with the DO (0x4f) because this is the serialno per specs with the
correct appversion. We might however use a serialno 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. */ version set to 0.0 and that is what we need to return. */
char *serial = app_get_serialno (app); 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); 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); return gpg_error (GPG_ERR_INV_ID);
else if (!*s) else if (!*s)
; /* no fingerprint given: we allow this for now. */ ; /* 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; fpr = s + 1;
serial = app_get_serialno (app); 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); xfree (serial);
return gpg_error (GPG_ERR_WRONG_CARD); return gpg_error (GPG_ERR_WRONG_CARD);

View File

@ -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. /* Initialization function to change the default app_priority_list.
* LIST is a list of comma or space separated strings with application * LIST is a list of comma or space separated strings with application
* names. Unknown names will only result in warning message. * 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 && card->serialno)
{ {
if (serialno_bin_len != card->serialnolen if (!is_same_serialno (card->serialno, card->serialnolen,
|| memcmp (serialno_bin, card->serialno, card->serialnolen)) serialno_bin, serialno_bin_len))
return 0; /* The card does not match the requested S/N. */ 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); lock_card (card, ctrl);
if (serialno_bin == NULL) if (serialno_bin == NULL)
break; break;
if (card->serialnolen == serialno_bin_len if (is_same_serialno (card->serialno, card->serialnolen,
&& !memcmp (card->serialno, serialno_bin, card->serialnolen)) serialno_bin, serialno_bin_len))
break; break;
unlock_card (card); unlock_card (card);
card_prev = card; card_prev = card;
@ -805,8 +834,8 @@ app_switch_current_card (ctrl_t ctrl,
{ {
for (card = card_top; card; card = card->next) for (card = card_top; card; card = card->next)
{ {
if (card->serialnolen == serialnolen if (is_same_serialno (card->serialno, card->serialnolen,
&& !memcmp (card->serialno, serialno, card->serialnolen)) serialno, serialnolen))
break; break;
} }
if (!card) if (!card)