From 0f9e3d940fa2abee3f7dcedceec192e45e471bc6 Mon Sep 17 00:00:00 2001
From: Bob Copeland <me@bobcopeland.com>
Date: Mon, 5 Dec 2016 10:55:49 -0500
Subject: [PATCH 3/3] pbkdf2: support openssl 1.1+

In OpenSSL 1.1, HMAC_CTX is now opaque and _init/_cleanup functions
are history.  Change the pbkdf2 implementation to conditionally
use HMAX_CTX_new()/_free() and use context pointers throughout.

Signed-off-by: Bob Copeland <copeland@lastpass.com>
---
 pbkdf2.c | 36 +++++++++++++++++++++++++-----------
 1 file changed, 25 insertions(+), 11 deletions(-)

diff --git a/pbkdf2.c b/pbkdf2.c
index f3c763420bbc..de15bae0d430 100644
--- a/pbkdf2.c
+++ b/pbkdf2.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2014-2016 Thomas Hurst.
+ * Copyright (c) 2016 LastPass.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  * of this software and associated documentation files (the "Software"), to deal
@@ -40,7 +41,7 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len,
 	const unsigned char *salt, size_t salt_len, unsigned int iterations,
 	const EVP_MD *digest, size_t key_len, unsigned char *output)
 {
-	HMAC_CTX ctx;
+	HMAC_CTX *ctx;
 	unsigned char *out = output;
 	unsigned int iter = 1, count = 1;
 	unsigned int cp_len, i, ret = 0;
@@ -52,8 +53,17 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len,
 
 	unsigned char tmp_md[md_len];
 
-	HMAC_CTX_init(&ctx);
-	ERR_IFZERO(HMAC_Init_ex(&ctx, pass, pass_len, digest, NULL));
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	HMAC_CTX real_ctx;
+	ctx = &real_ctx;
+	HMAC_CTX_init(ctx);
+#else
+	ctx = HMAC_CTX_new();
+	if (!ctx)
+		return 0;
+#endif
+
+	ERR_IFZERO(HMAC_Init_ex(ctx, pass, pass_len, digest, NULL));
 
 	while (key_left) {
 		cp_len = min(key_left, md_len);
@@ -64,16 +74,16 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len,
 		c[2] = (count >> 8) & 0xff;
 		c[3] = (count) & 0xff;
 
-		ERR_IFZERO(HMAC_Init_ex(&ctx, NULL, 0, digest, NULL));
-		ERR_IFZERO(HMAC_Update(&ctx, salt, salt_len));
-		ERR_IFZERO(HMAC_Update(&ctx, c, 4));
-		ERR_IFZERO(HMAC_Final(&ctx, tmp_md, NULL));
+		ERR_IFZERO(HMAC_Init_ex(ctx, NULL, 0, digest, NULL));
+		ERR_IFZERO(HMAC_Update(ctx, salt, salt_len));
+		ERR_IFZERO(HMAC_Update(ctx, c, 4));
+		ERR_IFZERO(HMAC_Final(ctx, tmp_md, NULL));
 		memcpy(out, tmp_md, cp_len);
 
 		for (iter=1; iter < iterations; iter++) {
-			ERR_IFZERO(HMAC_Init_ex(&ctx, NULL, 0, digest, NULL));
-			ERR_IFZERO(HMAC_Update(&ctx, tmp_md, md_len));
-			ERR_IFZERO(HMAC_Final(&ctx, tmp_md, NULL));
+			ERR_IFZERO(HMAC_Init_ex(ctx, NULL, 0, digest, NULL));
+			ERR_IFZERO(HMAC_Update(ctx, tmp_md, md_len));
+			ERR_IFZERO(HMAC_Final(ctx, tmp_md, NULL));
 
 			for (i = 0; i < cp_len; i++) {
 				out[i] ^= tmp_md[i];
@@ -87,6 +97,10 @@ int fallback_pkcs5_pbkdf2_hmac(const char *pass, size_t pass_len,
 	ret = 1;
 
 ERR_LABEL
-	HMAC_CTX_cleanup(&ctx);
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+	HMAC_CTX_cleanup(ctx);
+#else
+	HMAC_CTX_free(ctx);
+#endif
 	return ret;
 }
-- 
2.11.0

