Prev: Parallel quicksort
Next: Using Java 7
From: rossum on 15 May 2010 16:34 In a secure program I want to be able to wipe the byte array containing the key, mKey[], before releasing the memory back to the system. To do that I wrote a simple dispose() method to do a reasonably secure overwrite of the array: public void dispose() { if (mKey != null) { for (int i = 0; i < mKey.length; ++i) { for (int j = 0; j < 5; ++j) { mKey[i] = (byte)0x55; mKey[i] = (byte)0xFF; mKey[i] = (byte)0xAA; mKey[i] = (byte)0x00; } // end for } // end for mKey = null; } // end if } // end dispose() Obviously any reasonably good JIT compiler can look at that and optimise it to the equivalent of: public void dispose() { if (mKey != null) { mKey = null; } // end if } // end dispose() That is not what I want, since the repeated overwrites make it more difficult for an attacker to recover the former contents of memory. Is there some way to tell the JIT compiler that I do not want this method to be optimised but to be run as written? Effectively an @Pessimise annotation for just this method. rossum
From: Mike Schilling on 15 May 2010 16:47 rossum wrote: > In a secure program I want to be able to wipe the byte array > containing the key, mKey[], before releasing the memory back to the > system. To do that I wrote a simple dispose() method to do a > reasonably secure overwrite of the array: > > public void dispose() { > if (mKey != null) { > for (int i = 0; i < mKey.length; ++i) { > for (int j = 0; j < 5; ++j) { > mKey[i] = (byte)0x55; > mKey[i] = (byte)0xFF; > mKey[i] = (byte)0xAA; > mKey[i] = (byte)0x00; > } // end for > } // end for > mKey = null; > } // end if > } // end dispose() > > Obviously any reasonably good JIT compiler can look at that and > optimise it to the equivalent of: > > public void dispose() { > if (mKey != null) { > mKey = null; > } // end if > } // end dispose() > > That is not what I want, since the repeated overwrites make it more > difficult for an attacker to recover the former contents of memory. > Is there some way to tell the JIT compiler that I do not want this > method to be optimised but to be run as written? Effectively an > @Pessimise annotation for just this method. I presume you can complicate the logic to where a JIT couldn't optimize all of it away: public void disposeArray { // overwrite array // add array to global list of disposed objects // if the list now has more than 16 members, clear it. } But I'm curious about mKey[i] = (byte)0x55; mKey[i] = (byte)0xFF; mKey[i] = (byte)0xAA; mKey[i] = (byte)0x00; Any JIT wirth its salt is going to optimze this to mKey[i] = (byte)0x00; and why not? I know that overwirting a disk repeatedly with different patterns makes ir more difficult to recover the original data, but does this really apply to memory?
From: rossum on 15 May 2010 16:54 On Sat, 15 May 2010 13:47:52 -0700, "Mike Schilling" <mscottschilling(a)hotmail.com> wrote: >I know that overwirting a disk repeatedly with different >patterns makes ir more difficult to recover the original data, but does this >really apply to memory? Yes. Memory in standby can retain a lot of information, including some indications of previous memory contents at that address. It is more difficult than with a disk but it is possible. Security being security you have to assume that the attacker has the latest equipment available. IIRC even if you switch the computer off if the attacker cen get its memory chips into a freezer quickly enough the memory may be recoverable for up to 20 minutes. rossum
From: John B. Matthews on 15 May 2010 17:06 In article <u31uu51a8uohb8c38mrajfjt6ssh7sn231(a)4ax.com>, rossum <rossum48(a)coldmail.com> wrote: > In a secure program I want to be able to wipe the byte array > containing the key, mKey[], before releasing the memory back to the > system. To do that I wrote a simple dispose() method to do a > reasonably secure overwrite of the array: > > public void dispose() { > if (mKey != null) { > for (int i = 0; i < mKey.length; ++i) { > for (int j = 0; j < 5; ++j) { > mKey[i] = (byte)0x55; > mKey[i] = (byte)0xFF; > mKey[i] = (byte)0xAA; > mKey[i] = (byte)0x00; > } // end for > } // end for > mKey = null; > } // end if > } // end dispose() > > Obviously any reasonably good JIT compiler can look at that and > optimise it to the equivalent of: > > public void dispose() { > if (mKey != null) { > mKey = null; > } // end if > } // end dispose() > > That is not what I want, since the repeated overwrites make it more > difficult for an attacker to recover the former contents of memory. > Is there some way to tell the JIT compiler that I do not want this > method to be optimised but to be run as written? Effectively an > @Pessimise annotation for just this method. Is there some scope that could obviate the "mKey = null" step? The dispose() method would become erase(), effectively re-using the same storage for the life of the program. -- John B. Matthews trashgod at gmail dot com <http://sites.google.com/site/drjohnbmatthews>
From: Arne Vajhøj on 15 May 2010 17:21
On 15-05-2010 16:34, rossum wrote: > In a secure program I want to be able to wipe the byte array > containing the key, mKey[], before releasing the memory back to the > system. To do that I wrote a simple dispose() method to do a > reasonably secure overwrite of the array: > > public void dispose() { > if (mKey != null) { > for (int i = 0; i< mKey.length; ++i) { > for (int j = 0; j< 5; ++j) { > mKey[i] = (byte)0x55; > mKey[i] = (byte)0xFF; > mKey[i] = (byte)0xAA; > mKey[i] = (byte)0x00; > } // end for > } // end for > mKey = null; > } // end if > } // end dispose() > > Obviously any reasonably good JIT compiler can look at that and > optimise it to the equivalent of: > > public void dispose() { > if (mKey != null) { > mKey = null; > } // end if > } // end dispose() > > That is not what I want, since the repeated overwrites make it more > difficult for an attacker to recover the former contents of memory. > Is there some way to tell the JIT compiler that I do not want this > method to be optimised but to be run as written? Effectively an > @Pessimise annotation for just this method. I have two ideas: 1) store the key in native memory and access it via JNI - you can much better control the C optimizer 2) See if you can find confirmation or rejection for that: Compiler.disable(); // your code Compiler.enable(); actuall does what the names seems to indicate. Arne |