Zero memory in |OPENSSL_free|.

Allocations by |OPENSSL_malloc| are prefixed with their length.
|OPENSSL_free| zeros the allocation before calling free(), eliminating
the need for a separate call to |OPENSSL_cleanse| for sensitive data.

This change will be followed up by the cleanup in
https://boringssl-review.googlesource.com/c/boringssl/+/19824.

Change-Id: Ie272f07e9248d7d78af9aea81dacec0fdb7484c4
Reviewed-on: https://boringssl-review.googlesource.com/19544
Reviewed-by: Martin Kreichgauer <martinkr@google.com>
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/crypto/mem.c b/crypto/mem.c
index 576ab7f..1c19122 100644
--- a/crypto/mem.c
+++ b/crypto/mem.c
@@ -76,32 +76,66 @@
 #include "internal.h"
 
 
-void *OPENSSL_realloc_clean(void *ptr, size_t old_size, size_t new_size) {
+#define OPENSSL_MALLOC_PREFIX 8
+
+
+void *OPENSSL_malloc(size_t size) {
+  void *ptr = malloc(size + OPENSSL_MALLOC_PREFIX);
   if (ptr == NULL) {
+    return NULL;
+  }
+
+  *(size_t *)ptr = size;
+
+  return ((uint8_t *)ptr) + OPENSSL_MALLOC_PREFIX;
+}
+
+void OPENSSL_free(void *orig_ptr) {
+  if (orig_ptr == NULL) {
+    return;
+  }
+
+  void *ptr = ((uint8_t *)orig_ptr) - OPENSSL_MALLOC_PREFIX;
+
+  size_t size = *(size_t *)ptr;
+  OPENSSL_cleanse(ptr, size + OPENSSL_MALLOC_PREFIX);
+  free(ptr);
+}
+
+void *OPENSSL_realloc(void *orig_ptr, size_t new_size) {
+  if (orig_ptr == NULL) {
     return OPENSSL_malloc(new_size);
   }
 
-  if (new_size == 0) {
-    return NULL;
-  }
-
-  // We don't support shrinking the buffer. Note the memcpy that copies
-  // |old_size| bytes to the new buffer, below.
-  if (new_size < old_size) {
-    return NULL;
-  }
+  void *ptr = ((uint8_t *)orig_ptr) - OPENSSL_MALLOC_PREFIX;
+  size_t old_size = *(size_t *)ptr;
 
   void *ret = OPENSSL_malloc(new_size);
   if (ret == NULL) {
     return NULL;
   }
 
-  OPENSSL_memcpy(ret, ptr, old_size);
-  OPENSSL_cleanse(ptr, old_size);
-  OPENSSL_free(ptr);
+  size_t to_copy = new_size;
+  if (old_size < to_copy) {
+    to_copy = old_size;
+  }
+
+  memcpy(ret, orig_ptr, to_copy);
+  OPENSSL_free(orig_ptr);
+
   return ret;
 }
 
+void *OPENSSL_realloc_clean(void *orig_ptr, size_t old_size, size_t new_size) {
+  void *ptr = ((uint8_t *)orig_ptr) - OPENSSL_MALLOC_PREFIX;
+  size_t actual_size = *(size_t *)ptr;
+  if (actual_size != old_size) {
+    return NULL;
+  }
+
+  return OPENSSL_realloc(orig_ptr, new_size);
+}
+
 void OPENSSL_cleanse(void *ptr, size_t len) {
 #if defined(OPENSSL_WINDOWS)
   SecureZeroMemory(ptr, len);
@@ -155,15 +189,15 @@
   return len;
 }
 
-#if defined(OPENSSL_WINDOWS)
-
-char *OPENSSL_strdup(const char *s) { return _strdup(s); }
-
-#else
-
-char *OPENSSL_strdup(const char *s) { return strdup(s); }
-
-#endif
+char *OPENSSL_strdup(const char *s) {
+  const size_t len = strlen(s) + 1;
+  char *ret = OPENSSL_malloc(len);
+  if (ret == NULL) {
+    return NULL;
+  }
+  OPENSSL_memcpy(ret, s, len);
+  return ret;
+}
 
 int OPENSSL_tolower(int c) {
   if (c >= 'A' && c <= 'Z') {