Use "" not <> on e_os.h include
[openssl.git] / crypto / mem_sec.c
index 4a3f2a84a2175eca14b9b44f3e7f8a2073e53ddc..703ddad5e596b15684f439f16453d8a5c81145ad 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2014, Akamai Technologies. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -7,11 +8,6 @@
  * https://www.openssl.org/source/license.html
  */
 
-/*
- * Copyright 2004-2014, Akamai Technologies. All Rights Reserved.
- * This file is distributed under the terms of the OpenSSL license.
- */
-
 /*
  * This file is in two halves. The first half implements the public API
  * to be used by external consumers, and to be used by OpenSSL to store
@@ -20,7 +16,7 @@
  * "SECURE HEAP IMPLEMENTATION").
  */
 #include <openssl/crypto.h>
-#include <e_os.h>
+#include "e_os.h"
 
 #include <string.h>
 
 # include <unistd.h>
 # include <sys/types.h>
 # include <sys/mman.h>
+# if defined(OPENSSL_SYS_LINUX)
+#  include <sys/syscall.h>
+#  include <linux/mman.h>
+#  include <errno.h>
+# endif
 # include <sys/param.h>
 # include <sys/stat.h>
 # include <fcntl.h>
@@ -52,8 +53,8 @@ static CRYPTO_RWLOCK *sec_malloc_lock = NULL;
  * These are the functions that must be implemented by a secure heap (sh).
  */
 static int sh_init(size_t size, int minsize);
-static char *sh_malloc(size_t size);
-static void sh_free(char *ptr);
+static void *sh_malloc(size_t size);
+static void sh_free(void *ptr);
 static void sh_done(void);
 static size_t sh_actual_size(char *ptr);
 static int sh_allocated(const char *ptr);
@@ -68,8 +69,12 @@ int CRYPTO_secure_malloc_init(size_t size, int minsize)
         sec_malloc_lock = CRYPTO_THREAD_lock_new();
         if (sec_malloc_lock == NULL)
             return 0;
-        ret = sh_init(size, minsize);
-        secure_mem_initialized = 1;
+        if ((ret = sh_init(size, minsize)) != 0) {
+            secure_mem_initialized = 1;
+        } else {
+            CRYPTO_THREAD_lock_free(sec_malloc_lock);
+            sec_malloc_lock = NULL;
+        }
     }
 
     return ret;
@@ -85,6 +90,7 @@ int CRYPTO_secure_malloc_done()
         sh_done();
         secure_mem_initialized = 0;
         CRYPTO_THREAD_lock_free(sec_malloc_lock);
+        sec_malloc_lock = NULL;
         return 1;
     }
 #endif /* IMPLEMENTED */
@@ -151,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
@@ -336,7 +369,8 @@ static void sh_remove_from_list(char *ptr)
 
 static int sh_init(size_t size, int minsize)
 {
-    int i, ret;
+    int ret;
+    size_t i;
     size_t pgsize;
     size_t aligned;
 
@@ -414,7 +448,6 @@ static int sh_init(size_t size, int minsize)
             close(fd);
         }
     }
-    OPENSSL_assert(sh.map_result != MAP_FAILED);
     if (sh.map_result == MAP_FAILED)
         goto err;
     sh.arena = (char *)(sh.map_result + pgsize);
@@ -433,8 +466,19 @@ static int sh_init(size_t size, int minsize)
     if (mprotect(sh.map_result + aligned, pgsize, PROT_NONE) < 0)
         ret = 2;
 
+#if defined(OPENSSL_SYS_LINUX) && defined(MLOCK_ONFAULT) && defined(SYS_mlock2)
+    if (syscall(SYS_mlock2, sh.arena, sh.arena_size, MLOCK_ONFAULT) < 0) {
+        if (errno == ENOSYS) {
+            if (mlock(sh.arena, sh.arena_size) < 0)
+                ret = 2;
+        } else {
+            ret = 2;
+        }
+    }
+#else
     if (mlock(sh.arena, sh.arena_size) < 0)
         ret = 2;
+#endif
 #ifdef MADV_DONTDUMP
     if (madvise(sh.arena, sh.arena_size, MADV_DONTDUMP) < 0)
         ret = 2;
@@ -476,12 +520,15 @@ static char *sh_find_my_buddy(char *ptr, int list)
     return chunk;
 }
 
-static char *sh_malloc(size_t size)
+static void *sh_malloc(size_t size)
 {
     ossl_ssize_t list, slist;
     size_t i;
     char *chunk;
 
+    if (size > sh.arena_size)
+        return NULL;
+
     list = sh.freelist_size - 1;
     for (i = sh.minsize; i < size; i <<= 1)
         list--;
@@ -535,10 +582,10 @@ static char *sh_malloc(size_t size)
     return chunk;
 }
 
-static void sh_free(char *ptr)
+static void sh_free(void *ptr)
 {
     size_t list;
-    char *buddy;
+    void *buddy;
 
     if (ptr == NULL)
         return;