Prefer serial number from EF(TokenInfo) and cached serials over CARDCTL

sc_pkcs15_get_object_guid() should prefer the serial number from
EF(TokenInfo) over card->serialnr because the user may override the
card's serial number with "pkcs15-init -C --serial". The card->serialnr
should be used before calling card CTL with SC_CARDCTL_GET_SERIALNR
because it might contain a cached value.

This change *should* allow cards to be used with the minidriver even if
SC_CARDCTL_GET_SERIALNR is not implemented. For example, a driver might
set card->serialnr at initialization or the user might initialize a
PKCS#15 card with its own "--serial".

See also the discussion at the mailing list:
[Opensc-devel] AT_SIGNATURE and AT_EXCHANGE Problem
This commit is contained in:
Philip Wendland 2015-01-28 22:59:28 +01:00 committed by Viktor Tarasov
parent 08eb700b97
commit faaa11e091
1 changed files with 24 additions and 7 deletions

View File

@ -2725,19 +2725,36 @@ sc_pkcs15_get_object_guid(struct sc_pkcs15_card *p15card, const struct sc_pkcs15
rv = sc_pkcs15_get_object_id(obj, &id);
LOG_TEST_RET(ctx, rv, "Cannot get object's ID");
rv = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serialnr);
LOG_TEST_RET(ctx, rv, "'GET_SERIALNR' failed");
if (p15card->tokeninfo && p15card->tokeninfo->serial_number) {
/* The serial from EF(TokenInfo) is preferred because of the
* "--serial" parameter of pkcs15-init. */
serialnr.len = SC_MAX_SERIALNR;
rv = sc_hex_to_bin(p15card->tokeninfo->serial_number, serialnr.value, &serialnr.len);
if (rv) {
/* Fallback in case hex_to_bin fails due to unexpected characters */
serialnr.len = strlen(p15card->tokeninfo->serial_number);
if (serialnr.len > SC_MAX_SERIALNR)
serialnr.len = SC_MAX_SERIALNR;
memcpy(serialnr.value, p15card->tokeninfo->serial_number, serialnr.len);
}
} else if (p15card->card->serialnr.len) {
serialnr = p15card->card->serialnr;
} else {
rv = sc_card_ctl(p15card->card, SC_CARDCTL_GET_SERIALNR, &serialnr);
LOG_TEST_RET(ctx, rv, "'GET_SERIALNR' CTL failed and other serial numbers not present");
}
memset(guid_bin, 0, sizeof(guid_bin));
memcpy(guid_bin, id.value, id.len);
memcpy(guid_bin + id.len, serialnr.value, serialnr.len);
// If OpenSSL is available (SHA1), then rather use the hash of the data
// - this also protects against data being too short
// If OpenSSL is available (SHA1), then rather use the hash of the data
// - this also protects against data being too short
#ifdef ENABLE_OPENSSL
SHA1(guid_bin, id.len + serialnr.len, guid_bin);
id.len = SHA_DIGEST_LENGTH;
serialnr.len = 0;
SHA1(guid_bin, id.len + serialnr.len, guid_bin);
id.len = SHA_DIGEST_LENGTH;
serialnr.len = 0;
#endif
rv = sc_pkcs15_serialize_guid(guid_bin, id.len + serialnr.len, flags, (char *)out, *out_size);