X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fmem_sec.c;h=1c1327037acfc00bad0130792cf33ad64a8b1f34;hp=4ccff34e5e8fa71a4929cfbc6008eaebe3bb3ddd;hb=39df51522ba2e3773ae2f1d4df5a6031ef41c1ba;hpb=4f22f40507fea3f272637eb8e00cadf1f34b10d9 diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c index 4ccff34e5e..1c1327037a 100644 --- a/crypto/mem_sec.c +++ b/crypto/mem_sec.c @@ -1,5 +1,6 @@ /* - * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2015-2018 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 @@ -19,18 +15,29 @@ * For details on that implementation, see below (look for uppercase * "SECURE HEAP IMPLEMENTATION"). */ +#include "e_os.h" #include -#include #include -#if defined(OPENSSL_SYS_LINUX) || defined(OPENSSL_SYS_UNIX) +/* e_os.h includes unistd.h, which defines _POSIX_VERSION */ +#if !defined(OPENSSL_NO_SECURE_MEMORY) && defined(OPENSSL_SYS_UNIX) \ + && ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \ + || defined(__sun) || defined(__hpux) || defined(__sgi) \ + || defined(__osf__) ) # define IMPLEMENTED # include # include # include # include # include +# if defined(OPENSSL_SYS_LINUX) +# include +# if defined(SYS_mlock2) +# include +# include +# endif +# endif # include # include # include @@ -40,6 +47,9 @@ #ifndef PAGE_SIZE # define PAGE_SIZE 4096 #endif +#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS) +# define MAP_ANON MAP_ANONYMOUS +#endif #ifdef IMPLEMENTED static size_t secure_mem_used; @@ -52,8 +62,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 +78,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 +99,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 +166,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,11 +378,12 @@ 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; - memset(&sh, 0, sizeof sh); + memset(&sh, 0, sizeof(sh)); /* make sure size and minsize are powers of 2 */ OPENSSL_assert(size > 0); @@ -352,15 +395,22 @@ static int sh_init(size_t size, int minsize) if (minsize <= 0 || (minsize & (minsize - 1)) != 0) goto err; + while (minsize < (int)sizeof(SH_LIST)) + minsize *= 2; + sh.arena_size = size; sh.minsize = minsize; sh.bittable_size = (sh.arena_size / sh.minsize) * 2; + /* Prevent allocations of size 0 later on */ + if (sh.bittable_size >> 3 == 0) + goto err; + sh.freelist_size = -1; for (i = sh.bittable_size; i; i >>= 1) sh.freelist_size++; - sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof (char *)); + sh.freelist = OPENSSL_zalloc(sh.freelist_size * sizeof(char *)); OPENSSL_assert(sh.freelist != NULL); if (sh.freelist == NULL) goto err; @@ -407,7 +457,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); @@ -426,8 +475,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; @@ -447,7 +507,7 @@ static void sh_done() OPENSSL_free(sh.bitmalloc); if (sh.map_result != NULL && sh.map_size) munmap(sh.map_result, sh.map_size); - memset(&sh, 0, sizeof sh); + memset(&sh, 0, sizeof(sh)); } static int sh_allocated(const char *ptr) @@ -469,12 +529,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--; @@ -528,10 +591,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;