Bugtraq mailing list archives

RE: When scrubbing secrets in memory doesn't work


From: Michael Wojcik <Michael.Wojcik () microfocus com>
Date: Tue, 12 Nov 2002 08:07:20 -0800

Reposted.

-----Original Message-----
From: Michael Wojcik 
Sent: Wednesday, November 06, 2002 12:25 AM
To: 'Michael Howard'
Cc: bugtraq () securityfocus com
Subject: RE: When scrubbing secrets in memory doesn't work


From: Michael Howard [mailto:mikehow () microsoft com]
Sent: Tuesday, November 05, 2002 5:13 PM

[memset doesn't always]

I don't know if you followed the discussion on Vuln-dev after 
Peter Gutmann mentioned your article, 30-31 October, but Dom 
De Vitto[1] and I both described ways of avoiding this 
problem that work on any conforming C90/94/99 
implementation[2].  Pavel Kankovsky[3] and I both noted that 
De Vitto's simple suggestion of using the "volatile" 
sc-specifier should sufficient for any conforming C 
implementation, at least as we read the standards (and with 
the caveat that passing a volatile-qualified pointer to 
memset may not be valid, so assignment might have to be done 
manually), though I prefer the "external memset" approach for 
various reasons[4].  Dan Kaminsky makes the general point 
that introducing dependencies that can only be evaluated at 
run time also does the trick[5], though that's generally more 
work than the simple "volatile" and "external memset" solutions.

In sum, this is not a particularly interesting problem.  It's 
useful to have it pointed out (and we might have hoped that 
the authors of security-sensitive software would be more 
familiar with optimization techniques, the language 
standards, and what might happen to this kind of application 
of memset), and the maintainers of code that handles 
passwords should check for and correct it, but contra Peter 
Gutmann it does not appear to be a hard problem to solve, nor 
need solutions be necessarily implementation-specific.

Of the solutions given in your article, all should work on 
your implementation, but the first:

      memset(ptr, 0, len);
      (volatile char *)ptr[0] = (volatile char *)ptr[1];

is clearly preferable as it is portable.  (I think - that 
lvalue cast may not be legal, actually.  Or, for that matter, 
casting on volatility.  I'd have to check.)

It's worth noting that I believe the standard *still* allows 
a conforming implementation to skip the memset in the case of 
your first solution, too.  Because the pointer being passed 
to memset is not itself volatile-qualified, the 
implementation can apply the "as if" rule - the generated 
code need only behave *as if* following the rules of the 
abstract machine, provided all side effects visible to the 
program are maintained.  (That's a gloss, not language taken 
directly from the standard, but it's the basic idea.)  A 
clever optimiser could note that it is only necessary that it 
perform the volatile read and write in the second line.

So that's not a portable solution either, actually.  My 
advice: use an external memset wrapper.  Simple, safe, portable.

1. http://makeashorterlink.com/?A5C922B52
2. http://makeashorterlink.com/?E50A12B52
3. http://makeashorterlink.com/?J11A62B52
4. http://makeashorterlink.com/?H32A23B52
5. http://makeashorterlink.com/?T1A924B52

Michael Wojcik
Principal Software Systems Developer, Micro Focus



Current thread: