The intermediate values calculated in hmac_sha1 as part of
pkcs5_pbkdf2 are not zeroed afterwards, so we leak a single-hashed
version of the key on the stack in tk[].
Also, the correct RFC defining this is
RFC 2104 - HMAC: Keyed-Hashing for Message Authentication
not
RFC 2202 - Test Cases for HMAC-MD5 and HMAC-SHA-1
>From RFC 2104, section 4, paragraph 2:
"We stress that the stored intermediate values need to
be treated and protected the same as secret keys."
So it's not just best-practice dictating that these should be
bzeroed.
Here is a patch for the same code in libutil and libsa.
Index: lib/libutil/pkcs5_pbkdf2.c
===================================================================
RCS file: /cvs/src/lib/libutil/pkcs5_pbkdf2.c,v
retrieving revision 1.9
diff -u -p -d -r1.9 pkcs5_pbkdf2.c
--- lib/libutil/pkcs5_pbkdf2.c 5 Feb 2015 12:59:57 -0000 1.9
+++ lib/libutil/pkcs5_pbkdf2.c 10 Jun 2015 19:59:09 -0000
@@ -28,7 +28,7 @@
#define MINIMUM(a,b) (((a) < (b)) ? (a) : (b))
/*
- * HMAC-SHA-1 (from RFC 2202).
+ * HMAC-SHA-1 (from RFC 2104).
*/
static void
hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
@@ -67,6 +67,10 @@ hmac_sha1(const u_int8_t *text, size_t t
SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
SHA1Final(digest, &ctx);
+
+ explicit_bzero(&ctx, sizeof(ctx));
+ explicit_bzero(k_pad, sizeof(k_pad));
+ explicit_bzero(tk, sizeof(tk));
}
/*
Index: sys/lib/libsa/hmac_sha1.c
===================================================================
RCS file: /cvs/src/sys/lib/libsa/hmac_sha1.c,v
retrieving revision 1.1
diff -u -p -d -r1.1 hmac_sha1.c
--- sys/lib/libsa/hmac_sha1.c 9 Oct 2012 12:36:50 -0000 1.1
+++ sys/lib/libsa/hmac_sha1.c 10 Jun 2015 19:58:39 -0000
@@ -23,7 +23,7 @@
#include "hmac_sha1.h"
/*
- * HMAC-SHA-1 (from RFC 2202).
+ * HMAC-SHA-1 (from RFC 2104).
*/
void
hmac_sha1(const u_int8_t *text, size_t text_len, const u_int8_t *key,
@@ -62,4 +62,8 @@ hmac_sha1(const u_int8_t *text, size_t t
SHA1Update(&ctx, k_pad, SHA1_BLOCK_LENGTH);
SHA1Update(&ctx, digest, SHA1_DIGEST_LENGTH);
SHA1Final(digest, &ctx);
+
+ explicit_bzero(&ctx, sizeof(ctx));
+ explicit_bzero(k_pad, sizeof(k_pad));
+ explicit_bzero(tk, sizeof(tk));
}