[Cryptography] Heartbleed and fundamental crypto programming practices

Jerry Leichter leichter at lrw.com
Thu Apr 10 07:15:14 EDT 2014


We've all by now heard of the Heartbleed security disaster.  I haven't seen the actual coding error, but the descriptions indicate that an attacker could cause the server to allocate and return a large buffer, almost all of which was left uninitialized - and often ended up containing various pieces of left-over sensitive information from previously-deleted and now-reused memory blocks.

Years ago, when I developed some software in C++, I had a pair of classes called RedString and BlackString, imitating classic crypto usage of the colors.  A RedString contained "sensitive" data - data to be encrypted or that had been encrypted, keys in the clear, etc.  You could convert a RedString to a BlackString by encryption, or the other way around by decryption.  You could not misused a RedString in many obvious ways - e.g., the services that sent data over a link wouldn't access a RedString.

More to the point, the destructor of a RedString cleared its memory before releasing it to the free pool.  A Heartbleed attack that revealed 64K of former RedString's would have revealed ... 64K blocks of zeros.

It is - or should be - just a fundamental principle of secure coding that you minimize the amount and time you keep "sensitive" data around in memory - *and that you never release control of it*.  It's your responsibility - you don't hand it to the memory allocator.

People will tell you they can't afford the extra CPU cost of zeroing the memory.  Nonsense.  The vast bulk of this stuff is material you're encrypting or decrypting.  Think of the zeroization as part of the encryption or decryption process.  How many cycles does it cost to zero one byte of memory?  Not in isolation, but as part of a stream of at least tens of bytes?  It's a fraction of a cycle, added to the multiple cycles you're already paying.

I happened to develop a system in C++, which is the only widely-used language that offers *compiler enforced*, user-programmable, cradle-to-grave control over memory allocation.  By putting the code to zero the memory into the destructor, I could guarantee that no RedString could make it back to the free list without being cleared.  There's no way to do that in any other language I know of.  That means you have to enforce the discipline yourself.  Make sure your analogue of a RedString is never simply free'd, or left to the garbage collector - have an explicit routine for marking it no longer used.  There are some tricks you can apply to make it more obvious if this discipline isn't followed.  In a language like C, you can have a library routine to create a RedString that allocates extra memory and returns an address offset into the block malloc() gave you.  If someone tries to free() it directly, there's a good chance the memory allocator will crash, and someone will find the problem.  In Java, you could have every constructor register the newly-allocated RedString in a hash map somewhere.  Calling the "finish()" function to clear the memory would also remove it from the hash map.  If you just abandon the RedString, it will leak - and your server will eventually run out of memory, again inducing someone to fix the damn bug.  Programmers are trained to hate crashes.  Crashes that reveal hidden bugs in security- critical are a *good* thing!  (Actually, in Java you can use a weak reference to have the GC inform you that the object is ready to be collected, and you can clear it at that point.  Whether you want to rely on a mechanism that leaves sensitive data floating around in memory - but not available to the memory allocator - for an indeterminate time is a legitimate design question.  Also, since String's are immutable in Java, you have the problem that even if you know you've got sensitive data you no longer need stored in a String ... there's nothing you can do to get rid of it.)

I've seen comments over the years that crypto- (and all security-)related programming should not be left to "general" programmers with no domain expertise.  I'm not aware of any attempt to collect a list of "issues and programming techniques a crypto programmer must know".  Might be useful to have....
                                                        -- Jerry




More information about the cryptography mailing list