diff options
author | Werner Koch <wk@gnupg.org> | 2022-12-07 10:16:50 +0100 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2022-12-09 08:49:28 +0100 |
commit | 061efac03ff9b471138c76c61edb9f2c709a82ab (patch) | |
tree | 2c0167b776510c7bcd31915f2b1dd827cf9f8ac2 /scd/app-p15.c | |
parent | build: Remove Windows CE support. (diff) | |
download | gnupg2-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.c | 45 |
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; } |