oss-sec mailing list archives

OpenSSL and *BSD *_Final context struct zeroization (was: weird crypt-sha* in DragonFly BSD)


From: Solar Designer <solar () openwall com>
Date: Mon, 2 Jan 2012 03:55:30 +0400

On Tue, Nov 15, 2011 at 11:52:34PM +0400, Solar Designer wrote:
On Tue, Nov 15, 2011 at 06:35:02AM +0400, Solar Designer wrote:
There's also minor weirdness in the code - such as two local pointer
variables being declared static seemingly for no reason, and only
"final" but not "ctx" being zeroized in the end.  But even this lack of
proper cleanup is very minor compared to the lack of stretching.

It turns out that these other minor issues were inherited from phk's
md5crypt.c from FreeBSD.

Currently in FreeBSD, crypt-md5.c: crypt_md5() has extra static
declarations (not only the output buffer, but also three pointers), and
it forgets to zeroize ctx and ctx1 (even though it does zeroize final).

md5crypt.c: __md5crypt() in NetBSD no longer has the extra statics, but
it does forget to zeroize ctx and ctx1.

md5crypt.c: md5crypt() in OpenBSD has the weird static pointers and
forgets to zeroize ctx and ctx1.

I was wrong about the not zeroized ctx* - it turns out that *BSD's
MD5Final and the like, unlike OpenSSL's, fully zeroize the context
struct.  I've tested this with MD5Final corresponding to <md5.h> on
OpenBSD 4.6 (whatever I happened to have installed).  I did not test on
other *BSD's and other of their *Final functions, but I hope they're
similar.  Sorry for the noise.  (The weirdness with static pointers on
some systems still applies, though.  But it has no security relevance.)

However, this made me discover something else: OpenSSL's *_Final() (at
least MD5_Final() on my build of OpenSSL 1.0.0d as well as on OpenBSD 4.6)
partially zeroizes the context structure.  This makes little sense to
me: why zeroize _partially_?  Then the caller is expected to zeroize
fully (if it cares) anyway.

Specifically, the computed hash and the length of input in bits remain
in the context struct after MD5_Final() (and likely after other
*_Final()s as well).  My only guess as to the rationale may be that the
API is defined such that *_Final() may be called multiple times, so it
does what it can as it relates to zeroization under this limitation.
Is this the case?  ...No, not confirmed: calling OpenSSL's MD5_Final() a
second time in a row yields a different hash value.

So the partial zeroization in OpenSSL looks like an implementation bug
to me, then.

Alexander


Current thread: