scd:p15: Skip deleted records.

* scd/app-p15.c (select_and_read_record): Special case deleted
records.  Support 3 byte TLVs.
(read_ef_prkdf): Skip deleted records.
(read_ef_pukdf): Ditto.
(read_ef_cdf): Ditto.
(read_ef_aodf): Ditto.
--

This fixes a problem with some CardOS 5 applications.
This commit is contained in:
Werner Koch 2022-12-07 10:16:50 +01:00
parent f32d0c9c0f
commit 061efac03f
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 37 additions and 8 deletions

View File

@ -744,7 +744,15 @@ select_and_read_record (app_t app, unsigned short efid, int recno,
/* On CardOS with a Linear TLV file structure the records starts
* with some tag (often the record number) followed by the length
* byte for this record. Detect and remove this prefix. */
if (*buflen > 2 && (*buffer)[0] != 0x30 && (*buffer)[1] == *buflen - 2)
if (*buflen == 2 && !(*buffer)[0] && !(*buffer)[1])
; /* deleted record. */
else if (*buflen > 3 && (*buffer)[0] == 0xff
&& buf16_to_uint ((*buffer)+1) == *buflen - 3)
{
memmove (*buffer, *buffer + 3, *buflen - 3);
*buflen = *buflen - 3;
}
else if (*buflen > 2 && (*buffer)[0] != 0x30 && (*buffer)[1] == *buflen - 2)
{
memmove (*buffer, *buffer + 2, *buflen - 2);
*buflen = *buflen - 2;
@ -1771,6 +1779,9 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
starting with 0x00 or 0xff as these values are commonly used to
pad data blocks and are no valid ASN.1 encoding. Note the
special handling for record mode at the end of the loop. */
if (record_mode && buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
while (n && *p && *p != 0xff)
{
const unsigned char *pp;
@ -2028,6 +2039,8 @@ read_ef_prkdf (app_t app, unsigned short fid, prkdf_object_t *result)
err = 0;
goto leave;
}
if (buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
p = buffer;
n = buflen;
}
@ -2077,6 +2090,9 @@ read_ef_pukdf (app_t app, unsigned short fid, pukdf_object_t *result)
* starting with 0x00 or 0xff as these values are commonly used to
* pad data blocks and are no valid ASN.1 encoding. Note the
* special handling for record mode at the end of the loop. */
if (record_mode && buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
while (n && *p && *p != 0xff)
{
const unsigned char *pp;
@ -2354,6 +2370,8 @@ read_ef_pukdf (app_t app, unsigned short fid, pukdf_object_t *result)
err = 0;
goto leave;
}
if (buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
p = buffer;
n = buflen;
}
@ -2404,6 +2422,9 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
starting with 0x00 or 0xff as these values are commonly used to
pad data blocks and are no valid ASN.1 encoding. Note the
special handling for record mode at the end of the loop. */
if (record_mode && buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
while (n && *p && *p != 0xff)
{
const unsigned char *pp;
@ -2625,8 +2646,8 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
err = 0;
next_record:
xfree (authid);
xfree (label);
xfree (authid); authid = NULL;
xfree (label); label = NULL;
/* If the card uses a record oriented file structure, read the
* next record. Otherwise we keep on parsing the current buffer. */
recno++;
@ -2635,11 +2656,14 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
xfree (buffer); buffer = NULL;
err = select_and_read_record (app, 0, recno, "CDF",
&buffer, &buflen, NULL);
if (err) {
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
err = 0;
goto leave;
}
if (err)
{
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
err = 0;
goto leave;
}
if (buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
p = buffer;
n = buflen;
}
@ -2728,6 +2752,9 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
starting with 0x00 or 0xff as these values are commonly used to
pad data blocks and are no valid ASN.1 encoding. Note the
special handling for record mode at the end of the loop. */
if (record_mode && buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
while (n && *p && *p != 0xff)
{
const unsigned char *pp;
@ -3299,6 +3326,8 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
err = 0;
goto leave;
}
if (buflen == 2 && !buffer[0] && !buffer[1])
goto next_record; /* Deleted record - continue with next */
p = buffer;
n = buflen;
}