[Cryptography] Other obvious issues being ignored?

Viktor Dukhovni cryptography at dukhovni.org
Mon Oct 26 21:42:52 EDT 2015


On Mon, Oct 26, 2015 at 03:06:25PM -0400, Arnold Reinhold wrote:

> Developing compiler features that support safe cryptography could be as
> intellectually challenging and interesting as squeezing the last fraction
> of a percent of code efficiency.

The main security issue in software systems is not the difficulty
of writing reliable cryptographic code (which is necessary, but
far from sufficient).  Rather, by far the more important issue is
just writing safe code to handle the usual marshaling, unmarshaling
and processing of untrusted data.

Yes, cryptography introduces a minor twist in the form of a need
for secure erasure of keys, but this twist is rather easy to
accomplish.  The much more difficult issues around optimizing away
unspecified overflow behaviour for signed types is a problem for
all C code, not just cryptography code.

So if there is to be a community drive to implore the compiler
developers to relent on some optimizations, that drive should
represent a community broader than just cryptographers.

Implementing crypto already requires extraordinary skills beyond
those of most mortal developers, and if it were just the few super-men
who work on crypto that would have to work a bit harder, the compiler
developers might well be argued to be making a sensible trade-off.

The real issue is that that the optimizations expose all developers
to risks, not just cryptographers (who largely know where the mines
are, even if not always successful in stepping over them).

A C specification that lays traps for intuitive implementations of
basic sanity checks is I think problematic.

I know I depend on undefined unsigned overflow in Postfix (in the
case I am about to describe this is a matter of protocol correctness
not security).  Postfix converts decimal strings representing
message sizes to an "offset_t" since this is the signed data type
for the size of stored files.  There is no defined unsigned version
of "offset_t".  We also restrict ourselves to pre-C99 dialects of
C, since Postfix still supports rather dated systems that lack
<stdint.h>.

I am the author of the code that handles this conversion:

    off_t   off_cvt_string(const char *str)
    {
	int     ch;
	off_t   result;
	off_t   res2;
	off_t   res4;
	off_t   res8;
	off_t   res10;

	/*
	 * Multiplication by numbers > 2 can overflow without producing a smaller
	 * result mod 2^N (where N is the number of bits in the result type).
	 * (Victor Duchovni, Morgan Stanley).
	 */
	for (result = 0; (ch = *(unsigned char *) str) != 0; str++) {
	    if (!ISDIGIT(ch))
		return (-1);
	    if ((res2 = result + result) < result)
		return (-1);
	    if ((res4 = res2 + res2) < res2)
		return (-1);
	    if ((res8 = res4 + res4) < res4)
		return (-1);
	    if ((res10 = res8 + res2) < res8)
		return (-1);
	    if ((result = res10 + ch - '0') < res10)
		return (-1);
	}
	return (result);
    }

This code assumes that addition of positive signed integers, either
produces a larger signed integer, or else overflows to a smaller
signed integer, and that this can be tested.

A sufficiently "clever" compiler could optimize this away, since
every test depends on signed overflow.  So far we've seen no compiler
that clever, but this could change.  

If some day some SMTP server advertised a message size limit in
excess of 2^31 or 2^63 (!) bytes, the Postfix SMTP client might
then misparse the server's message size limit and bounce mail that
fits well within that limit.  This possibility seems remote, and
we have better things to spend our precious time on fine-tuning
than this function, so UB it remains.

Yes, now I've outed myself in public as a UB-perpetrator, I could
perhaps repent and write a portable solution in C (that predates
C99).  But, this is unlikely to happen in the near future.  More
important things to do...

-- 
	Viktor.


More information about the cryptography mailing list