[Cryptography] Secure erasure

John Denker jsd at av8n.com
Sat Sep 10 20:49:43 EDT 2016


On 09/10/2016 02:10 PM, Patrick Pelletier wrote:

> the most likely threat comes from a Heartbleed-style vulnerability,
> where your own process gets tricked into revealing the contents of
> its own memory.  In that sort of a threat model, the hardware doesn't
> matter, swap doesn't matter, caches don't matter.  All that matters
> is what's visible in the process's address space.

OK, good point, that's a useful addition to the list of threats
to worry about.

> This is the sort
> of threat that the original question in this thread can defend
> against, by zeroing memory.

However, the style of solution proposed by the OP still doesn't work.
If we focus on heartbleed in particular, it depends on out-of-bounds
array access.  That produces explicitly /undefined behavior/ according
to the C standard.  As the saying goes, in such a case, the compiler
can order pizza.

Specifically:  If the only way the zeroized memory can affect the
operation of the program is via out-of-bounds array access, the
compiler is allowed to elide everything including the zeroization
... and indeed allowed to do much worse than that.

So we come by a different path to the same conclusion:  There is
nothing you can do using only native C-language constructs that
will reliably solve this problem.

  There may be ways of inveigling a particular version of a
  particular brand of compiler to do what you want, but this
  is not reproducible across other versions or other brands.
  Even if it works today it might fail tomorrow.

  Eventus incertus delendus est.

  That is to say:  any language that has "undefined behavior"
  in its specification is not well suited for writing critical
  applications.

Furthermore, previous remarks still apply:  Even if you don't get
screwed by the compiler, you might get screwed by the hardware.
Even if you manage to zeroize the copy in L2 cache, it's hard to
guarantee that the cache gets spilled to main memory, so you might
remain vulnerable to cold boot attacks and whatnot.

However, on a more constructive note:

1a) Consider munmap().  It is documented to remove the specified
 memory from your address space.  This solves the heartbleed
 problem and more than a few similar problems.  If you think
 that is the "most likely threat" you're in luck.

1b) Along the same lines, consider the "electric fence" version
 of malloc().

Both (1a) and (1b) depend on hardware features that are present on
the vast majority of platforms that we think of as "computers".
(In contrast, in the IoT controller world, life is more difficult.)

2a) Something to dream about:  Imagine reading from /dev/hardware/zero.
 That is a real piece of hardware that does DMA to main memory, and
 (in the usual way) invalidates all caches of the affected memory.

 I mention this because I/O is one of the hardest things for the
 compiler to be smart-alecky about.  I/O devices can have all
 sorts of internal state that the compiler doesn't know how to
 model.

 Back in the Olden Days some timesharing machines had such a
 device, so pages could be zeroized without gobbling up CPU
 cycles.

2b) Even in today's world, if your main worry is some smart-aleck
 compiler, reading from /dev/zero might be a reasonable option.

 This does not solve the fundamental problems, but it might
 provide some traction on the narrow question the OP asked.

2c) Another approach is to zeroize the buffer in software and
 then /write/ the buffer to some chosen FD.  Once again, the
 logic is that the compiler can't optimize out the zeroization,
 because it doesn't know at runtime whether you plan to connect
 the FD to /dev/null or to something else.  Writing to /dev/null
 is remarkably efficient.

3) If necessary, one could imagine negotiating a way to ask the
 compiler explicitly to not be so smart-alecky, e.g.
    -Wno-optimize-erasure-please-please-please  or
    -Wsecure-erasure-please-please-please

 That leads to obvious portability problems.  Still, I reckon
 obvious problems are preferable to insidious problems.

4) The combination of zeroizing and then munmapping is better than
 either one separately.



More information about the cryptography mailing list