From 4dae7cd3f0f074e01b2fe73ffff0dfbf032fa566 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date: Fri, 28 Jul 2017 21:24:02 +0200
Subject: [PATCH] Implement the CRYPTO_secure_clear_free function

Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4044)
---
 crypto/mem_sec.c         | 27 +++++++++++++++++++++++++++
 include/openssl/crypto.h |  4 ++++
 util/libcrypto.num       |  1 +
 util/private.num         |  1 +
 4 files changed, 33 insertions(+)

diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c
index 11e95c42b8..04aa94eae1 100644
--- a/crypto/mem_sec.c
+++ b/crypto/mem_sec.c
@@ -157,6 +157,33 @@ void CRYPTO_secure_free(void *ptr, const char *file, int line)
 #endif /* IMPLEMENTED */
 }
 
+void CRYPTO_secure_clear_free(void *ptr, size_t num,
+                              const char *file, int line)
+{
+#ifdef IMPLEMENTED
+    size_t actual_size;
+
+    if (ptr == NULL)
+        return;
+    if (!CRYPTO_secure_allocated(ptr)) {
+        OPENSSL_cleanse(ptr, num);
+        CRYPTO_free(ptr, file, line);
+        return;
+    }
+    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    actual_size = sh_actual_size(ptr);
+    CLEAR(ptr, actual_size);
+    secure_mem_used -= actual_size;
+    sh_free(ptr);
+    CRYPTO_THREAD_unlock(sec_malloc_lock);
+#else
+    if (ptr == NULL)
+        return;
+    OPENSSL_cleanse(ptr, num);
+    CRYPTO_free(ptr, file, line);
+#endif /* IMPLEMENTED */
+}
+
 int CRYPTO_secure_allocated(const void *ptr)
 {
 #ifdef IMPLEMENTED
diff --git a/include/openssl/crypto.h b/include/openssl/crypto.h
index f0bc98f320..cebde9734b 100644
--- a/include/openssl/crypto.h
+++ b/include/openssl/crypto.h
@@ -144,6 +144,8 @@ int CRYPTO_mem_ctrl(int mode);
         CRYPTO_secure_zalloc(num, OPENSSL_FILE, OPENSSL_LINE)
 # define OPENSSL_secure_free(addr) \
         CRYPTO_secure_free(addr, OPENSSL_FILE, OPENSSL_LINE)
+# define OPENSSL_secure_clear_free(addr, num) \
+        CRYPTO_secure_clear_free(addr, num, OPENSSL_FILE, OPENSSL_LINE)
 # define OPENSSL_secure_actual_size(ptr) \
         CRYPTO_secure_actual_size(ptr)
 
@@ -283,6 +285,8 @@ int CRYPTO_secure_malloc_done(void);
 void *CRYPTO_secure_malloc(size_t num, const char *file, int line);
 void *CRYPTO_secure_zalloc(size_t num, const char *file, int line);
 void CRYPTO_secure_free(void *ptr, const char *file, int line);
+void CRYPTO_secure_clear_free(void *ptr, size_t num,
+                              const char *file, int line);
 int CRYPTO_secure_allocated(const void *ptr);
 int CRYPTO_secure_malloc_initialized(void);
 size_t CRYPTO_secure_actual_size(void *ptr);
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 1c754b47a6..4b00b00dbb 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4370,3 +4370,4 @@ i2d_SCRYPT_PARAMS                       4312	1_1_1	EXIST::FUNCTION:SCRYPT
 d2i_SCRYPT_PARAMS                       4313	1_1_1	EXIST::FUNCTION:SCRYPT
 SCRYPT_PARAMS_it                        4314	1_1_1	EXIST:!EXPORT_VAR_AS_FUNCTION:VARIABLE:SCRYPT
 SCRYPT_PARAMS_it                        4314	1_1_1	EXIST:EXPORT_VAR_AS_FUNCTION:FUNCTION:SCRYPT
+CRYPTO_secure_clear_free                4315	1_1_0g	EXIST::FUNCTION:
diff --git a/util/private.num b/util/private.num
index f82a8f6db6..a586a9bb1d 100644
--- a/util/private.num
+++ b/util/private.num
@@ -202,6 +202,7 @@ OPENSSL_memdup                          define
 OPENSSL_no_config                       define deprecated 1.1.0
 OPENSSL_realloc                         define
 OPENSSL_secure_actual_size              define
+OPENSSL_secure_clear_free               define
 OPENSSL_secure_free                     define
 OPENSSL_secure_malloc                   define
 OPENSSL_secure_zalloc                   define
-- 
2.25.1