[Cryptography] Secure erasure

John Denker jsd at av8n.com
Wed Sep 7 20:24:34 EDT 2016


On 09/07/2016 01:04 PM, Ray Dillinger wrote:
[snip]
> Can anybody think of any way that a standard-compliant
> compiler is allowed to mess this up?

AFAICT it is simply not possible to write a truly secure erase
routine in C.  The language is defined with respect to an abstract
machine that does not support the concept of erasure, secure or
otherwise.

  You can implement "some" measures that take away "some" of
  the attack surface, but that's far removed from a complete,
  provably-correct solution.

The language is guaranteed to produce "the" right answer and leave
it in "the" appropriate place.  It offers no guarantees as to how
many extraneous copies are left lying around.

For starters, on a typical system, you have no idea how many times
your program was interrupted.  Each context switch saves the
registers "somewhere".  You have no idea where.  This happens
at a layer several jumps removed from the language specification.

Similar words apply to swapping.  Sometimes you can lock your
variables in main memory ... but that is far outside the C
specification.

It gets worse.  If you are running on a virtual machine, which
is not particularly rare these days, the host can pillage your
memory and there's nothing the language can do about it.

"Volatile" means that the memory location could change behind
your back, as is typical of PDP-11 memory-mapped I/O registers,
and typical of memory shared between multiple processes.  It
offers not the slightest guarantee of security against copying
the value.  Volatile applies to the memory /location/; it does
not protect the /value/ that you tried to store there.

The guys who defined the language were not thinking like cryptographers.
This was in the early 70s, when telnet expected you to send your
password in the clear over the network.

Data security includes two things:
  a) secure against loss of information, and
  b) secure against unauthorized copying.

Objective (a) suggests making lots of backups;
Objective (b) suggests just the opposite.

========

To say almost the same thing another way:
The typical operating system clears stuff (memory, swap space, registers,
et cetera) as late as possible, right before giving it away to some new
process.  Type-(b) security would suggest clearing it as early as possible,
but that would incur a performance penalty, so they don't do it.

By not doing it, they leave a large attack surface, including cold boot,
reading /dev/kmem, reading /dev/swap, et cetera.

As long as the operating system is running correctly, you don't need to
worry.  Clearing stuff late is the same as clearing stuff early.  Erasure
is only important if you think the OS is going to lose control.  That
includes things like cold-boot attacks, attackers with root privilege,
et cetera.  All such attacks are waaaaay outside the specification of
the abstract machine used to define C.

AFAICT if you want to shrink the attack surface, it requires rethinking
and redesigning everything including hardware, operating system, and
language.  There needs to be a concept of protecting the /value/ from
undesired copying.  This is very, very different from protecting a
memory /location/ from undesired loss of information.

One approach is to define a smallish security perimeter, perhaps the
CPU chip itself, and require that everything that crosses the perimeter
must be encrypted.  Then "crypto erase" consists of throwing away the
session key, then zeroizing any copies inside the perimeter, including
L2 cache, general registers, MMX registers, et cetera.

Zeroizing flash memory requires changes to the flash controller, at a
level only one step above the raw memory transistors.  This is verrrry
far removed from the C language specification.  It would make a epic
Master of Engineering thesis project for some hotshot.



More information about the cryptography mailing list