summaryrefslogtreecommitdiffstats
path: root/scd/app-p15.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2022-12-07 10:16:50 +0100
committerWerner Koch <wk@gnupg.org>2022-12-09 08:49:28 +0100
commit061efac03ff9b471138c76c61edb9f2c709a82ab (patch)
tree2c0167b776510c7bcd31915f2b1dd827cf9f8ac2 /scd/app-p15.c
parentbuild: Remove Windows CE support. (diff)
downloadgnupg2-061efac03ff9b471138c76c61edb9f2c709a82ab.tar.xz
gnupg2-061efac03ff9b471138c76c61edb9f2c709a82ab.zip
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.
Diffstat (limited to '')
-rw-r--r--scd/app-p15.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/scd/app-p15.c b/scd/app-p15.c
index 0e92edf56..bfd693466 100644
--- a/scd/app-p15.c
+++ b/scd/app-p15.c
@@ -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;
}