1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-12-22 10:19:57 +01:00

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 <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2024-04-15 10:23:25 +09:00
parent 0eefa08295
commit 6b2ebc36a9
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054

View File

@ -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;