compact TLV - add generic sc_compacttlv_find_tag() function (#1374)

* new function sc_compacttlv_find_tag()

Add function sc_compacttlv_find_tag() to search for a tag in a
compact-TLV structure.

* OpenPGP: use sc_compacttlv_find_tag()

While doing so, fix a typo affection OpenPGP v3.x cards
This commit is contained in:
Peter Marschall 2018-06-08 08:17:13 +02:00 committed by Frank Morgner
parent 6dfeb9959f
commit 266b811e55
3 changed files with 49 additions and 24 deletions

View File

@ -507,32 +507,25 @@ static void
pgp_parse_hist_bytes(sc_card_t *card, u8 *ctlv, size_t ctlv_len)
{
struct pgp_priv_data *priv = DRVDATA(card);
size_t offs;
const u8 *ptr;
for (offs = 0; offs < ctlv_len; offs++) {
switch (ctlv[offs]) {
case 0x73: /* IS07816-4 hist bytes 3rd function table */
if (offs+3 < ctlv_len) {
/* bit 0x40 in byte 3 of TL 0x73 means "extended Le/Lc" */
if (ctlv[offs+3] & 0x40) {
card->caps |= SC_CARD_CAP_APDU_EXT;
priv->ext_caps |= EXT_CAP_APDU_EXT;
}
/* bit 0x80 in byte 3 of TL 0x73 means "Command chaining" */
if ((ctlv[offs+3] & 0x40) &&
(priv->bcd_version >= OPENPGP_CARD_3_0)) {
priv->ext_caps |= EXT_CAP_CHAINING;
}
}
break;
case 0x31:
if ((offs + 1 < ctlv_len) &&
(priv->bcd_version >= OPENPGP_CARD_3_0)) {
// ToDo ...
}
break;
/* IS07816-4 hist bytes: 3rd function table */
if ((ptr = sc_compacttlv_find_tag(ctlv, ctlv_len, 0x73, NULL)) != NULL) {
/* bit 0x40 in byte 3 of TL 0x73 means "extended Le/Lc" */
if (ptr[2] & 0x40) {
card->caps |= SC_CARD_CAP_APDU_EXT;
priv->ext_caps |= EXT_CAP_APDU_EXT;
}
offs += ctlv[offs] & 0x0F;
/* bit 0x80 in byte 3 of TL 0x73 means "Command chaining" */
if ((ptr[2] & 0x80) &&
(priv->bcd_version >= OPENPGP_CARD_3_0)) {
priv->ext_caps |= EXT_CAP_CHAINING;
}
}
if ((priv->bcd_version >= OPENPGP_CARD_3_0) &&
((ptr = sc_compacttlv_find_tag(ctlv, ctlv_len, 0x31, NULL)) != NULL)) {
// ToDo ...
}
}

View File

@ -1357,6 +1357,18 @@ scconf_block *sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *drive
*/
unsigned sc_crc32(const unsigned char *value, size_t len);
/**
* Find a given tag in a compact TLV structure
* @param[in] buf input buffer holding the compact TLV structure
* @param[in] len length of the input buffer @buf in bytes
* @param[in] tag compact tag to search for - high nibble: plain tag, low nibble: length.
* If length is 0, only the plain tag is used for searching,
* in any other case, the length must also match.
* @param[out] outlen pointer where the size of the buffer returned is to be stored
* @return pointer to the tag value found within @buf, or NULL if not found/on error
*/
const u8 *sc_compacttlv_find_tag(const u8 *buf, size_t len, u8 tag, size_t *outlen);
/**
* Used to initialize the @c sc_remote_data structure --
* reset the header of the 'remote APDUs' list, set the handlers

View File

@ -948,6 +948,26 @@ unsigned sc_crc32(const unsigned char *value, size_t len)
return crc%0xffff;
}
const u8 *sc_compacttlv_find_tag(const u8 *buf, size_t len, u8 tag, size_t *outlen)
{
if (buf != NULL) {
size_t idx;
u8 plain_tag = tag & 0xF0;
size_t expected_len = tag & 0x0F;
for (idx = 0; idx < len; idx++) {
if ((buf[idx] & 0xF0) == plain_tag && idx + expected_len < len &&
(expected_len == 0 || expected_len == (buf[idx] & 0x0F))) {
if (outlen != NULL)
*outlen = buf[idx] & 0x0F;
return buf + (idx + 1);
}
idx += (buf[idx] & 0x0F);
}
}
return NULL;
}
/**************************** mutex functions ************************/
int sc_mutex_create(const sc_context_t *ctx, void **mutex)