Re: CRC32 check for IDAT chunks

Cosmin Truta <[email protected]> Wed, 30 Jan 2019 23:44:24 -0500
Newsgroups gmane.comp.graphics.png.devel
Message-ID <CAAoVtZzbaTb5FGLL3-i06Ux5AytYc+s9J-zgJO4xxAyi_-gURg@mail.gmail.com>
On Wed, 30 Jan 2019 at 13:16, Nicolas Badoux
<[email protected]> wrote:
> I'm looking at the code of libpng and was wondering why there is not always a check to verify the CRC32 value when reading IDAT chunks.

CRC is always checked. An incorrect CRC causes a benign error for an
ancillary chunk, or a severe error for a critical chunk.

> If I'm correct, the CRC is calculated at line 4193 of pngrutil.c (lbpng-1.6.36). The call to inflate on line 4225 can happen without that the CRC value was checked against the value in the file.

CRC is independent of inflate. To the CRC calculation, the compressed
deflate stream is just raw data. The validity of inflate is
checksum'ed by Adler32.

What you're seeing is merely an update of the CRC. Specifically, an
update to png_ptr->crc. See the function png_calculate_crc().

> Is this done willingly to spare time as inflate will likely fail anyway?

That's not what's happening. You may verify that by creating a PNG
file with an incorrect CRC (or taking a correct PNG file and altering
the CRC in a hex editor, for example), and then seeing the CRC error
being raised by libpng.

But Bob is right. An attacker can purposely corrupt an image and
update the CRC accordingly, and nobody would notice. An attacker can
even keep the same CRC and create a corrupt image that matches the
original CRC, by the means of a computational trial-and-error process,
with trivial effort. A CRC is not a secure checksum (like SHA-1, for
example), nor is it intended to be.

For securing your image, you may use an external digest program
(sha1sum, sha256sum, b2sum, etc.) or, in theory, an internal PNG dSIG
chunk. I say "in theory" because dSIG is an officially registered PNG
extension, and yet I don't know what software (if any) recognizes it.

> If I got something wrong, can you point me to the line where the CRC value of IDAT chunks are checked?

You can see png_ptr->crc being updated in png_calculate_crc(), and
checked in png_crc_error().

Sincerely,
Cosmin