[Cryptography] Heartbleed and fundamental crypto programming practices

Bear bear at sonic.net
Tue Apr 15 18:14:05 EDT 2014


On Tue, 2014-04-15 at 22:52 +0200, tpb-crypto at laposte.net wrote:
> > De : "danimoth" 
> > On 10/04/14 at 03:49pm, Bear wrote:

> > > In most languages, there is absolutely no standard way to be sure 
> > > of getting an optimizing compiler to leave final writes alone.
> > [cut]
> > 
> > If I understood correctly, all crypto software should be compiled with 
> > -O0 flag... 
> 
> Well, depends on what kind of attack you want to avoid,

Indeed, the real issue is that security software cares about 
"outputs" that are important in no other kind of programming.  All 
your dev tools and language implementations are written under the 
assumption that the program's outputs are that which the program 
is directed to write to a place where other programs (or people) 
are *expected* to read it - that is, to output ports, to files, 
to the console, to the screen, etc.  All other effects of executing 
the program, it is presumed - those you do not command, and which 
are not left in places where they are *expected* to be read - are 
not "outputs" and do not matter.

But security is all about ensuring that nobody can take advantage 
of any effect of executing the program to disclose information 
that the program was supposed to keep private.  All the other 
effects of executing the program that someone can find *any* way 
to read, ARE therefore outputs that matter to the correctness of
your program.

That includes but is not limited to, the traces on the swap 
partition, the stale values in memory, the bits left over in 
deallocated inodes in the file system, the amount of time the 
program is taking between two known system calls, etc. 

This violates the fundamental assumptions under which development 
tools are written.  With security software, you're suddenly caring
about outputs that the tools do not acknowledge and are programmed 
to assume you don't care about.  In trying to restrict the information
available on those channels, IOW, you're making what the author of 
your dev tools would have regarded as a spectacularly nonsensical
requirement, and one which has nothing to do with any kind of 
objective or goal that his programming language left you any way 
to explicitly state.

I myself have implemented a nice lisp.  It's memory safe, mostly 
functional, has a beautiful lock-free threading model with zero
contention because it uses copy-on-write semantics with shared 
memory between threads.  A lot like Clojure, but it has memory 
versioning so that if something doesn't work out you can just 
rewind and try it again, which is neat. It gives you beautiful
expressive power, but absolutely no control over any channels 
other than the explicit channels you might be *intentionally* 
writing.  And that's the norm as regards explicit vs. implicit 
channels.

Memory safe languages that give you nice abstractions and 
guaranteed initialization, etc, are making no promises to you
other than the promise that your code will produce *explicit* 
outputs indistinguishable from those it would produce if those 
initializations/finalizations/etc were actually performed.

As far as I know, C (and C++) with its 'volatile' directive are 
the only language standards that give you a promise about being 
able to force something to never get swapped out and never have 
a read or write specified by the code omitted - which means a 
way to control many of the *implicit* channels you have to care 
about in security code.  

Bear




More information about the cryptography mailing list