mirror of
git://git.gnupg.org/gnupg.git
synced 2024-12-22 10:19:57 +01:00
kbx: Add bounds check to detect corrupt keyboxes.
* kbx/keybox-dump.c (_keybox_dump_blob): Fix the fixmes. -- kbxutil is a debug tool but nevertheless it should behave well and not read beyond allocated buffers and in turn crash. Vincent Ulitzsch and Dominik Maier were kind enough to report these crashes along with a couple of test keyboxes and crash analysis. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
26da47ae53
commit
e0a312bfd6
@ -84,6 +84,7 @@ print_checksum (const byte *buffer, size_t length, size_t unhashed, FILE *fp)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
hashlen = 20;
|
hashlen = 20;
|
||||||
|
|
||||||
if (length < 5+unhashed)
|
if (length < 5+unhashed)
|
||||||
{
|
{
|
||||||
fputs ("[blob too short for a checksum]\n", fp);
|
fputs ("[blob too short for a checksum]\n", fp);
|
||||||
@ -170,6 +171,7 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
ulong nserial;
|
ulong nserial;
|
||||||
ulong unhashed;
|
ulong unhashed;
|
||||||
const byte *p;
|
const byte *p;
|
||||||
|
const byte *pend;
|
||||||
int is_fpr32; /* blob version 2 */
|
int is_fpr32; /* blob version 2 */
|
||||||
|
|
||||||
buffer = _keybox_get_blob_image (blob, &length);
|
buffer = _keybox_get_blob_image (blob, &length);
|
||||||
@ -250,7 +252,18 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
|| rawdata_off+rawdata_len > length
|
|| rawdata_off+rawdata_len > length
|
||||||
|| rawdata_len + 4 > length
|
|| rawdata_len + 4 > length
|
||||||
|| rawdata_off+rawdata_len + 4 > length)
|
|| rawdata_off+rawdata_len + 4 > length)
|
||||||
fprintf (fp, "[Error: raw data larger than blob]\n");
|
{
|
||||||
|
fprintf (fp, "[Error: raw data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawdata_off > length
|
||||||
|
|| rawdata_len > length
|
||||||
|
|| rawdata_off + rawdata_len > length)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: unhashed data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
unhashed = length - rawdata_off - rawdata_len;
|
unhashed = length - rawdata_off - rawdata_len;
|
||||||
fprintf (fp, "Unhashed: %lu\n", unhashed);
|
fprintf (fp, "Unhashed: %lu\n", unhashed);
|
||||||
|
|
||||||
@ -263,35 +276,66 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
|
|
||||||
keyinfolen = get16 (buffer + 18 );
|
keyinfolen = get16 (buffer + 18 );
|
||||||
fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
|
fprintf (fp, "Key-Info-Length: %lu\n", keyinfolen);
|
||||||
/* fixme: check bounds */
|
|
||||||
p = buffer + 20;
|
p = buffer + 20;
|
||||||
|
pend = buffer + length;
|
||||||
for (n=0; n < nkeys; n++, p += keyinfolen)
|
for (n=0; n < nkeys; n++, p += keyinfolen)
|
||||||
{
|
{
|
||||||
ulong kidoff, kflags;
|
ulong kidoff, kflags;
|
||||||
|
|
||||||
|
if (p + keyinfolen >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: key data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
fprintf (fp, "Key-Fpr[%lu]: ", n );
|
fprintf (fp, "Key-Fpr[%lu]: ", n );
|
||||||
if (is_fpr32)
|
if (is_fpr32)
|
||||||
{
|
{
|
||||||
|
if (p + 32 + 2 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: fingerprint data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
kflags = get16 (p + 32 );
|
kflags = get16 (p + 32 );
|
||||||
for (i=0; i < ((kflags & 0x80)?32:20); i++ )
|
for (i=0; i < ((kflags & 0x80)?32:20); i++ )
|
||||||
fprintf (fp, "%02X", p[i]);
|
fprintf (fp, "%02X", p[i]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (p + 20 + 4 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: fingerprint data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
for (i=0; i < 20; i++ )
|
for (i=0; i < 20; i++ )
|
||||||
fprintf (fp, "%02X", p[i]);
|
fprintf (fp, "%02X", p[i]);
|
||||||
kidoff = get32 (p + 20);
|
kidoff = get32 (p + 20);
|
||||||
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
|
fprintf (fp, "\nKey-Kid-Off[%lu]: %lu\n", n, kidoff );
|
||||||
fprintf (fp, "Key-Kid[%lu]: ", n );
|
fprintf (fp, "Key-Kid[%lu]: ", n );
|
||||||
/* fixme: check bounds */
|
|
||||||
|
if (p + kidoff + 8 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: fingerprint data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
for (i=0; i < 8; i++ )
|
for (i=0; i < 8; i++ )
|
||||||
fprintf (fp, "%02X", buffer[kidoff+i] );
|
fprintf (fp, "%02X", buffer[kidoff+i] );
|
||||||
kflags = get16 (p + 24 );
|
if (p + 24 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: fingerprint data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
kflags = get16 (p + 24);
|
||||||
}
|
}
|
||||||
fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
|
fprintf( fp, "\nKey-Flags[%lu]: %04lX\n", n, kflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* serial number */
|
/* serial number */
|
||||||
|
if (p + 2 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
fputs ("Serial-No: ", fp);
|
fputs ("Serial-No: ", fp);
|
||||||
nserial = get16 (p);
|
nserial = get16 (p);
|
||||||
p += 2;
|
p += 2;
|
||||||
@ -299,22 +343,37 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
fputs ("none", fp);
|
fputs ("none", fp);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (p + nserial >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
for (; nserial; nserial--, p++)
|
for (; nserial; nserial--, p++)
|
||||||
fprintf (fp, "%02X", *p);
|
fprintf (fp, "%02X", *p);
|
||||||
}
|
}
|
||||||
putc ('\n', fp);
|
putc ('\n', fp);
|
||||||
|
|
||||||
/* user IDs */
|
/* user IDs */
|
||||||
|
if (p + 4 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
nuids = get16 (p);
|
nuids = get16 (p);
|
||||||
fprintf (fp, "Uid-Count: %lu\n", nuids );
|
fprintf (fp, "Uid-Count: %lu\n", nuids );
|
||||||
uidinfolen = get16 (p + 2);
|
uidinfolen = get16 (p + 2);
|
||||||
fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
|
fprintf (fp, "Uid-Info-Length: %lu\n", uidinfolen);
|
||||||
/* fixme: check bounds */
|
|
||||||
p += 4;
|
p += 4;
|
||||||
for (n=0; n < nuids; n++, p += uidinfolen)
|
for (n=0; n < nuids; n++, p += uidinfolen)
|
||||||
{
|
{
|
||||||
ulong uidoff, uidlen, uflags;
|
ulong uidoff, uidlen, uflags;
|
||||||
|
|
||||||
|
if (p + uidinfolen >= pend || uidinfolen < 8)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
uidoff = get32( p );
|
uidoff = get32( p );
|
||||||
uidlen = get32( p+4 );
|
uidlen = get32( p+4 );
|
||||||
if (type == KEYBOX_BLOBTYPE_X509 && !n)
|
if (type == KEYBOX_BLOBTYPE_X509 && !n)
|
||||||
@ -335,8 +394,21 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
|
fprintf (fp, "Uid-Len[%lu]: %lu\n", n, uidlen );
|
||||||
fprintf (fp, "Uid[%lu]: \"", n );
|
fprintf (fp, "Uid[%lu]: \"", n );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (uidoff + uidlen > length
|
||||||
|
|| uidoff + uidlen < uidoff
|
||||||
|
|| uidoff + uidlen < uidlen)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
print_string (fp, buffer+uidoff, uidlen, '\"');
|
print_string (fp, buffer+uidoff, uidlen, '\"');
|
||||||
fputs ("\"\n", fp);
|
fputs ("\"\n", fp);
|
||||||
|
if (p + 8 + 2 + 1 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
uflags = get16 (p + 8);
|
uflags = get16 (p + 8);
|
||||||
if (type == KEYBOX_BLOBTYPE_X509 && !n)
|
if (type == KEYBOX_BLOBTYPE_X509 && !n)
|
||||||
{
|
{
|
||||||
@ -355,11 +427,15 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p + 2 + 2 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
nsigs = get16 (p);
|
nsigs = get16 (p);
|
||||||
fprintf (fp, "Sig-Count: %lu\n", nsigs );
|
fprintf (fp, "Sig-Count: %lu\n", nsigs );
|
||||||
siginfolen = get16 (p + 2);
|
siginfolen = get16 (p + 2);
|
||||||
fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
|
fprintf (fp, "Sig-Info-Length: %lu\n", siginfolen );
|
||||||
/* fixme: check bounds */
|
|
||||||
p += 4;
|
p += 4;
|
||||||
{
|
{
|
||||||
int in_range = 0;
|
int in_range = 0;
|
||||||
@ -369,6 +445,11 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
{
|
{
|
||||||
ulong sflags;
|
ulong sflags;
|
||||||
|
|
||||||
|
if (p + siginfolen >= pend || siginfolen < 4)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
sflags = get32 (p);
|
sflags = get32 (p);
|
||||||
if (!in_range && !sflags)
|
if (!in_range && !sflags)
|
||||||
{
|
{
|
||||||
@ -402,6 +483,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
if (in_range)
|
if (in_range)
|
||||||
fprintf (fp, "Sig-Expire[%lu-%lu]: [not checked]\n", first, n-1);
|
fprintf (fp, "Sig-Expire[%lu-%lu]: [not checked]\n", first, n-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p + 16 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
fprintf (fp, "Ownertrust: %d\n", p[0] );
|
fprintf (fp, "Ownertrust: %d\n", p[0] );
|
||||||
fprintf (fp, "All-Validity: %d\n", p[1] );
|
fprintf (fp, "All-Validity: %d\n", p[1] );
|
||||||
p += 4;
|
p += 4;
|
||||||
@ -414,6 +501,12 @@ _keybox_dump_blob (KEYBOXBLOB blob, FILE *fp)
|
|||||||
n = get32 (p );
|
n = get32 (p );
|
||||||
p += 4;
|
p += 4;
|
||||||
fprintf (fp, "Created-At: %lu\n", n );
|
fprintf (fp, "Created-At: %lu\n", n );
|
||||||
|
|
||||||
|
if (p + 4 >= pend)
|
||||||
|
{
|
||||||
|
fprintf (fp, "[Error: data larger than blob]\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
n = get32 (p );
|
n = get32 (p );
|
||||||
fprintf (fp, "Reserved-Space: %lu\n", n );
|
fprintf (fp, "Reserved-Space: %lu\n", n );
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user