[Cryptography] Heartbleed and fundamental crypto programming practices

Jerry Leichter leichter at lrw.com
Sat Apr 12 20:05:53 EDT 2014


On Apr 12, 2014, at 5:58 PM, Viktor Dukhovni <cryptography at dukhovni.org> wrote:
>> And with a bit more work, one could even extend this technique
>> to find and alter Strings that are declared 'private' within a
>> given class. You would just have to pass in an Object and the
>> name of the field you wanted to alter. (Left as an exercise for the
>> reader.)
>> 
>>    public static void changeString(String original, String replacement)
>>    {
>>        try {
>>            Field value = String.class.getDeclaredField("value");
>>            value.setAccessible(true);
>>            value.set(original, replacement.toCharArray());
>>            Field count = String.class.getDeclaredField("count");
>>            count.setAccessible(true);
>>            count.set(original, replacement.length());
>>        } catch (Exception ex) {
>>            ; // ignore
>>        }
>>    }
> 
> This is a profound failure to understand the kind mutability required
> to securely erase sensitive data from memory.  Just because one
> can mutate values seen by users of an object's interface, does NOT
> mean that the underlying memory has been overwritten.
No, this really does over-write the underlying memory in the String object.  Doing this violates all kinds of assumptions the Java compiler and runtime environment are allowed to make.  For example, if you take a substring of a Java string, you share memory with the original.  Overwrite one, overwrite both.

*However*, I agree absolutely that this particular hack is insufficient:  Java is a GC'ed language, and its design allows (and all implementations I've ever seen use) compacting collectors.  So, you can wipe out the memory currently holding the sensitive data - but you have no way to know what other copies might be out there and where they might be, and no way at all to get at them.  JNI code can "pin" stuff in memory, but by the time you come up with a reliable way to pin all the appropriate memory, for the appropriate times, without giving the GC constipation, you might as well just write a kernel of code that deals with sensitive data in C or C++ and keep it out of Java entirely.

As far as I can see, the only way to write code that safely manages secure data in a language with a compacting GC is to extend the semantics of the language to include a "must be erased" flag that the GC will respect.  (You should also add a "zap the contents of this object now" call so that you don't have to wait for the GC to notice that some "must be erased" data is no longer being used.)

The general concept of "must be erased" data applies much more broadly.  The old VMS operating system had - still has, for those troglodytes still using it :-) - a "Data Security Erase" function - the equivalent, as a file system service, of such things as the Unix srm program.  (The system shipped with a default implementation of the function, but you could replace it if you wanted - something certain government agencies apparently did.)  But ... not only could you explicitly invoke this function on a file - you could also mark a file so that it was always erased when deleted.  Since this was built into the file system, the erasure happened no matter what program deleted the file.

A minor feature ... but illustrative of a basic concept:  Security features have to work *even if you aren't thinking about them*.  On every other system I've ever used (I suspect there are others I haven't used that someone will point out), it's up to you to remember, at exactly the time you delete a file, that it contains sensitive data and you must use srm, not rm (to use Unix terminology).  Slip up just once, and the only alternative is to wipe the disk.  Well, maybe you'll be satisfied with wiping all the unallocated space.  Delete a file implicitly - e.g., by accidentally redirecting over it - and you have the same problem.

A *robust* security implementation must make it possible for you to determine the security sensitivity of a file *at any time during its existence*, and then enforce the appropriate policy without further involvement on your part.  (Note that this overlaps the distinction between discretionary and non-discretionary access control, but is quite distinct.  *I* set the "must erase" at my discretion.)

                                                        -- Jerry



More information about the cryptography mailing list