From faaa11e091001f063dac46f29f0aad28c2494a18 Mon Sep 17 00:00:00 2001 From: Philip Wendland Date: Wed, 28 Jan 2015 22:59:28 +0100 Subject: [PATCH] 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 --- src/libopensc/pkcs15.c | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index fa1120ee..346e30a6 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -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);