From: rossum on
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
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
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
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
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

 |  Next  |  Last
Pages: 1 2 3 4 5
Prev: Parallel quicksort
Next: Using Java 7