Open-Source Wikis

/

OpenSSL

/

Subsystems

/

Memory

openssl/openssl

Memory

Active contributors: Pauli, Bob Beck, Tomas Mraz, Matt Caswell

Purpose

OpenSSL has two heaps:

  • A general heap (OPENSSL_malloc, OPENSSL_realloc, OPENSSL_free, OPENSSL_zalloc, …). Use this for everything that isn't sensitive.
  • A secure heap (OPENSSL_secure_malloc, OPENSSL_secure_free, …). Use this for keys and other secrets that must be mlock'd and zeroed on free.

Both have hooks for custom allocators, instrumentation, and sanitizers. Implementations live in crypto/mem.c (10 KB) and crypto/mem_sec.c (20 KB), with platform-specific helpers in crypto/mem_clr.c.

General heap

void *OPENSSL_malloc(size_t num);
void *OPENSSL_zalloc(size_t num);   /* malloc + memset(0) */
void *OPENSSL_realloc(void *p, size_t num);
void *OPENSSL_clear_realloc(void *p, size_t old_len, size_t num);  /* zeroes old contents */
void  OPENSSL_free(void *ptr);
void  OPENSSL_clear_free(void *p, size_t len);  /* zero then free */
char *OPENSSL_strdup(const char *str);
char *OPENSSL_strndup(const char *str, size_t s);

Custom allocators can be installed via CRYPTO_set_mem_functions. The hook is set very early; it must be installed before any other OpenSSL function is called. This is how integrations with custom allocators (e.g. a process-wide pool, jemalloc, a sandboxed allocator) are wired in.

Secure heap

crypto/mem_sec.c implements a buddy-style allocator over a single mlock'd (or VirtualLock'd) region:

int  CRYPTO_secure_malloc_init(size_t size, size_t minsize);
void CRYPTO_secure_malloc_done(void);
void *OPENSSL_secure_malloc(size_t num);
void *OPENSSL_secure_zalloc(size_t num);
int   CRYPTO_secure_allocated(const void *p);
size_t OPENSSL_secure_actual_size(void *p);
void  OPENSSL_secure_free(void *p);          /* zeroes before free */
void  OPENSSL_secure_clear_free(void *p, size_t l);

Properties of the secure heap:

  • A single mmap(MAP_PRIVATE | MAP_ANONYMOUS) region of the size requested by CRYPTO_secure_malloc_init.
  • The region is mlock'd and madvise(MADV_DONTDUMP)'d so it doesn't appear in core dumps (where the OS supports those operations).
  • Allocations are tracked with a buddy allocator inside the region; freeing returns memory to the buddy structure. Block headers and footers are protected by guard pages.
  • Free zeroes the contents before reuse.
  • A small statistics surface (CRYPTO_secure_used, CRYPTO_secure_actual_size) is exposed.

If CRYPTO_secure_malloc_init is not called or fails, OPENSSL_secure_malloc falls back to OPENSSL_malloc and the security guarantees degrade.

apps/openssl provides -secmem flags on most subcommands to opt in.

Zeroing

OPENSSL_cleanse (in crypto/mem_clr.c) is OpenSSL's memset_s-equivalent. It zeroes a buffer in a way the compiler cannot optimise away:

void OPENSSL_cleanse(void *ptr, size_t len);

Implementation tricks vary by platform — explicit memory barriers, volatile-pointer dance, asm clobbers — but the contract is the same.

OPENSSL_clear_free and OPENSSL_clear_realloc use it on the way out.

Aligned allocation

crypto/aligned_alloc.c exposes OPENSSL_aligned_alloc(size, align, &freeptr) for callers that need cache-line-aligned data (e.g. AES-GCM tables). The freeptr is what you pass back to OPENSSL_free.

Instrumentation

OpenSSL's debug heap (enable-crypto-mdebug) intercepts malloc/free and tracks every outstanding allocation with file/line. mem_dbg.c (when enabled) writes a leak report at exit.

When built with enable-asan or enable-msan, the allocator routes through the sanitizer's malloc so red zones and use-after-free are caught. The allocation-failure-injection harness (OPENSSL_TEST_MFAIL_*, see how-to-contribute/testing) plugs in here too.

Stack-allocated stacks

STACK_OF(T) (include/openssl/stack.h, include/openssl/safestack.h.in) is OpenSSL's polymorphic dynamic array. It is used pervasively in the parse layers (a STACK_OF(X509_EXTENSION), STACK_OF(X509), STACK_OF(GENERAL_NAME), …). Storage is from the general heap; the API tracks ownership via a free callback set when the stack is created (sk_X509_pop_free, etc.).

Integration points

  • Every allocation in libcrypto / libssl / providers / apps goes through OPENSSL_malloc or OPENSSL_secure_malloc. There are intentionally no calls to bare malloc in the library code (they would skip instrumentation and sanitizer hooks).
  • Custom allocators set via CRYPTO_set_mem_functions see every allocation, so they can pool, account, or trap.
  • The secure heap is opt-in per-call (OPENSSL_secure_malloc); subsystems that hold private keys (crypto/rsa/, crypto/ec/, the keymgmt providers) reach for it explicitly.

Entry points for modification

  • Custom alloc strategy: CRYPTO_set_mem_functions. Must be called before any other OpenSSL function.
  • Secure-heap policy: crypto/mem_sec.c. Tweak guard pages, alignment, or fallback behaviour.
  • Zero-on-free: extend OPENSSL_cleanse or its callers if you need additional protections (e.g. a memory-tagged secret).

Documentation

  • doc/man3/OPENSSL_malloc.pod, OPENSSL_secure_malloc.pod, OPENSSL_cleanse.pod, CRYPTO_set_mem_functions.pod.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Memory – OpenSSL wiki | Factory