aboutsummaryrefslogtreecommitdiffstats
path: root/scd/app-openpgp.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2024-04-15 01:23:25 +0000
committerNIIBE Yutaka <[email protected]>2024-05-16 00:42:47 +0000
commit6b2ebc36a932a53e137c429bc1e385054f3bb5cc (patch)
treee00361441df50d9432566c39dd35cb5b2959d17b /scd/app-openpgp.c
parentgpg: Allow no CRC24 checksum in armor. (diff)
downloadgnupg-6b2ebc36a932a53e137c429bc1e385054f3bb5cc.tar.gz
gnupg-6b2ebc36a932a53e137c429bc1e385054f3bb5cc.zip
scd:openpgp: Robust Data Object handling for constructed case.
* scd/app-openpgp.c (get_cached_data): When it comes with its tag and length for the constructed Data Object, remove them. -- Cherry-pick master commit of: 35ef87d8d9db42c3077996317781986a692552cc GnuPG-bug-id: 7058 Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to '')
-rw-r--r--scd/app-openpgp.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index 1f5d64e6a..fe0855e77 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -409,6 +409,10 @@ get_cached_data (app_t app, int tag,
size_t len;
struct cache_s *c;
int exmode;
+ int do_constructed = 0;
+
+ if ((tag < 0x0100 && (tag & 0x20)) || (tag >= 0x0100 && (tag & 0x2000)))
+ do_constructed = 1;
*result = NULL;
*resultlen = 0;
@@ -451,6 +455,52 @@ get_cached_data (app_t app, int tag,
err = iso7816_get_data (app_get_slot (app), exmode, tag, &p, &len);
if (err)
return err;
+
+ /* When Data Object is constructed, when it comes with its tag and
+ length, remove them before storing it into the cache, because
+ it's redundant and takes space. This handling also works well
+ with the card implementation which doesn't include its tag and
+ length for the DO value returned by GET DATA. */
+ if (do_constructed)
+ {
+ if (len && tag < 0x0100 && p[0] == tag)
+ {
+ if (len >= 2 && p[1] < 0x80 && p[1] == len - 2)
+ {
+ len -= 2;
+ memmove (p, p+2, len);
+ }
+ else if (len >= 3 && p[1] == 0x81 && p[2] == len - 3)
+ {
+ len -= 3;
+ memmove (p, p+3, len);
+ }
+ else if (len >= 4 && p[1] == 0x82 && ((p[2] << 8) | p[3]) == len - 4)
+ {
+ len -= 4;
+ memmove (p, p+4, len);
+ }
+ }
+ else if (len >= 2 && tag >= 0x0100 && ((p[0] << 8) | p[1]) == tag)
+ {
+ if (len >= 3 && p[2] < 0x80 && p[2] == len - 2)
+ {
+ len -= 3;
+ memmove (p, p+3, len);
+ }
+ else if (len >= 4 && p[2] == 0x81 && p[3] == len - 3)
+ {
+ len -= 4;
+ memmove (p, p+4, len);
+ }
+ else if (len >= 5 && p[2] == 0x82 && ((p[3] << 8) | p[4]) == len - 4)
+ {
+ len -= 5;
+ memmove (p, p+5, len);
+ }
+ }
+ }
+
if (len)
*result = p;
*resultlen = len;