Jämes
Jämes

Reputation: 7265

GuardedString and memory persistence with the JVM

Context

I recently had a cryptography lecture and we discussed about persistence of critical elements in memory. Typically, C/C++ library Libsodium suggests to clear any buffer that contained sensitive information, such as a secret (ref). I know that GuardedString is backed by an array of bytes and the docs recommends to call the method dispose once the stored secret is no longer used, that fills the array of bytes using Arrays.fill.

Question

Does the JVM guarantee that the values of the byte array are gone when overwritten or may the original values remain in memory under certain conditions ? For example, unused/unreferenced Strings are conserved in the Java String Pool until a garbage collection is triggered. Are there similar caching or mechanisms for other types such as the byte array that can compromise the secret that should be disposed from the GuardedString ? Any reference in the specs of the JVM ?

Many thanks !

Upvotes: 1

Views: 2505

Answers (1)

Karol Dowbecki
Karol Dowbecki

Reputation: 44980

In Java one usually would use char[] array instead of String because this allows to manually zero the data in the array.

However even then the data might not be fully unset as per this answer:

As noted in the comments, it's possible that arrays being moved by the garbage collector will leave stray copies of the data in memory. I believe this is implementation-specific - the garbage collector may clear all memory as it goes, to avoid this sort of thing. Even if it does, there's still the time during which the char[] contains the actual characters as an attack window.

Similar problem exists in C/C++ if the compiler decides to optimize out memset. As per 11.4. Specially Protect Secrets (Passwords and Keys) in User Memory:

A Bugtraq post by Andy Polyakov (November 7, 2002) reported that the C/C++ compilers gcc version 3 or higher, SGI MIPSpro, and the Microsoft compilers eliminated simple inlined calls to memset intended to overwrite secrets. This is allowed by the C and C++ standards. Other C/C++ compilers (such as gcc less than version 3) preserved the inlined call to memset at all optimization levels, showing that the issue is compiler-specific. Simply declaring that the destination data is volatile doesn’t help on all compilers; both the MIPSpro and Microsoft compilers ignored simple "volatilization". Simply "touching" the first byte of the secret data doesn’t help either; he found that the MIPSpro and GCC>=3 cleverly nullify only the first byte and leave the rest intact (which is actually quite clever - the problem is that the compiler’s cleverness is interfering with our goals).

Upvotes: 1

Related Questions