aboutsummaryrefslogtreecommitdiff
path: root/sys/geom
diff options
context:
space:
mode:
authorAllan Jude <allanjude@FreeBSD.org>2017-02-19 19:30:31 +0000
committerAllan Jude <allanjude@FreeBSD.org>2017-02-19 19:30:31 +0000
commit85c15ab853199df53a3cb52dd5e09edaf013e9d0 (patch)
tree35ba2d9a31ef6814e5266457ff48d5834f0e07b1 /sys/geom
parentd7aee58a789a4aa10d9cba210f24e406625c79f7 (diff)
downloadsrc-85c15ab853199df53a3cb52dd5e09edaf013e9d0.tar.gz
src-85c15ab853199df53a3cb52dd5e09edaf013e9d0.zip
improve PBKDF2 performance
The PBKDF2 in sys/geom/eli/pkcs5v2.c is around half the speed it could be GELI's PBKDF2 uses a simple benchmark to determine a number of iterations that will takes approximately 2 seconds. The security provided is actually half what is expected, because an attacker could use the optimized algorithm to brute force the key in half the expected time. With this change, all newly generated GELI keys will be approximately 2x as strong. Previously generated keys will talk half as long to calculate, resulting in faster mounting of encrypted volumes. Users may choose to rekey, to generate a new key with the larger default number of iterations using the geli(8) setkey command. Security of existing data is not compromised, as ~1 second per brute force attempt is still a very high threshold. PR: 202365 Original Research: https://jbp.io/2015/08/11/pbkdf2-performance-matters/ Submitted by: Joe Pixton <jpixton@gmail.com> (Original Version), jmg (Later Version) Reviewed by: ed, pjd, delphij Approved by: secteam, pjd (maintainer) MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D8236
Notes
Notes: svn path=/head/; revision=313962
Diffstat (limited to 'sys/geom')
-rw-r--r--sys/geom/eli/g_eli.h4
-rw-r--r--sys/geom/eli/g_eli_hmac.c39
-rw-r--r--sys/geom/eli/pkcs5v2.c20
3 files changed, 35 insertions, 28 deletions
diff --git a/sys/geom/eli/g_eli.h b/sys/geom/eli/g_eli.h
index b6a28d05a9a6..846bf7eae81b 100644
--- a/sys/geom/eli/g_eli.h
+++ b/sys/geom/eli/g_eli.h
@@ -692,8 +692,8 @@ int g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
const u_char *key, size_t keysize);
struct hmac_ctx {
- SHA512_CTX shactx;
- u_char k_opad[128];
+ SHA512_CTX innerctx;
+ SHA512_CTX outerctx;
};
void g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
diff --git a/sys/geom/eli/g_eli_hmac.c b/sys/geom/eli/g_eli_hmac.c
index 36b76deb9fda..cc350bd9b6e7 100644
--- a/sys/geom/eli/g_eli_hmac.c
+++ b/sys/geom/eli/g_eli_hmac.c
@@ -47,7 +47,7 @@ void
g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
size_t hkeylen)
{
- u_char k_ipad[128], key[128];
+ u_char k_ipad[128], k_opad[128], key[128];
SHA512_CTX lctx;
u_int i;
@@ -66,13 +66,17 @@ g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
/* XOR key with ipad and opad values. */
for (i = 0; i < sizeof(key); i++) {
k_ipad[i] = key[i] ^ 0x36;
- ctx->k_opad[i] = key[i] ^ 0x5c;
+ k_opad[i] = key[i] ^ 0x5c;
}
- bzero(key, sizeof(key));
- /* Perform inner SHA512. */
- SHA512_Init(&ctx->shactx);
- SHA512_Update(&ctx->shactx, k_ipad, sizeof(k_ipad));
- bzero(k_ipad, sizeof(k_ipad));
+ explicit_bzero(key, sizeof(key));
+ /* Start inner SHA512. */
+ SHA512_Init(&ctx->innerctx);
+ SHA512_Update(&ctx->innerctx, k_ipad, sizeof(k_ipad));
+ explicit_bzero(k_ipad, sizeof(k_ipad));
+ /* Start outer SHA512. */
+ SHA512_Init(&ctx->outerctx);
+ SHA512_Update(&ctx->outerctx, k_opad, sizeof(k_opad));
+ explicit_bzero(k_opad, sizeof(k_opad));
}
void
@@ -80,28 +84,27 @@ g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
size_t datasize)
{
- SHA512_Update(&ctx->shactx, data, datasize);
+ SHA512_Update(&ctx->innerctx, data, datasize);
}
void
g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
{
u_char digest[SHA512_MDLEN];
- SHA512_CTX lctx;
- SHA512_Final(digest, &ctx->shactx);
- /* Perform outer SHA512. */
- SHA512_Init(&lctx);
- SHA512_Update(&lctx, ctx->k_opad, sizeof(ctx->k_opad));
- bzero(ctx, sizeof(*ctx));
- SHA512_Update(&lctx, digest, sizeof(digest));
- SHA512_Final(digest, &lctx);
- bzero(&lctx, sizeof(lctx));
+ /* Complete inner hash */
+ SHA512_Final(digest, &ctx->innerctx);
+
+ /* Complete outer hash */
+ SHA512_Update(&ctx->outerctx, digest, sizeof(digest));
+ SHA512_Final(digest, &ctx->outerctx);
+
+ explicit_bzero(ctx, sizeof(*ctx));
/* mdsize == 0 means "Give me the whole hash!" */
if (mdsize == 0)
mdsize = SHA512_MDLEN;
bcopy(digest, md, mdsize);
- bzero(digest, sizeof(digest));
+ explicit_bzero(digest, sizeof(digest));
}
void
diff --git a/sys/geom/eli/pkcs5v2.c b/sys/geom/eli/pkcs5v2.c
index 6992801958ce..1bfdaf89a41e 100644
--- a/sys/geom/eli/pkcs5v2.c
+++ b/sys/geom/eli/pkcs5v2.c
@@ -56,6 +56,7 @@ pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
uint8_t *counter, *keyp;
u_int i, bsize, passlen;
uint32_t count;
+ struct hmac_ctx startpoint, ctx;
passlen = strlen(passphrase);
bzero(key, keylen);
@@ -66,20 +67,23 @@ pkcs5v2_genkey(uint8_t *key, unsigned keylen, const uint8_t *salt,
for (count = 1; keylen > 0; count++, keylen -= bsize, keyp += bsize) {
bsize = MIN(keylen, sizeof(md));
- counter[0] = (count >> 24) & 0xff;
- counter[1] = (count >> 16) & 0xff;
- counter[2] = (count >> 8) & 0xff;
- counter[3] = count & 0xff;
- g_eli_crypto_hmac(passphrase, passlen, saltcount,
- sizeof(saltcount), md, 0);
+ be32enc(counter, count);
+
+ g_eli_crypto_hmac_init(&startpoint, passphrase, passlen);
+ ctx = startpoint;
+ g_eli_crypto_hmac_update(&ctx, saltcount, sizeof(saltcount));
+ g_eli_crypto_hmac_final(&ctx, md, sizeof(md));
xor(keyp, md, bsize);
for(i = 1; i < iterations; i++) {
- g_eli_crypto_hmac(passphrase, passlen, md, sizeof(md),
- md, 0);
+ ctx = startpoint;
+ g_eli_crypto_hmac_update(&ctx, md, sizeof(md));
+ g_eli_crypto_hmac_final(&ctx, md, sizeof(md));
xor(keyp, md, bsize);
}
}
+ explicit_bzero(&startpoint, sizeof(startpoint));
+ explicit_bzero(&ctx, sizeof(ctx));
}
#ifndef _KERNEL