Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions cmake/functions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -976,9 +976,11 @@ function(generate_lib_src_list LIB_SOURCES)
wolfcrypt/src/wolfmath.c)
endif()

if(BUILD_MEMORY)
list(APPEND LIB_SOURCES wolfcrypt/src/memory.c)
endif()
# memory.c also holds the aligned/scrubbing allocators (wc_MallocAlign(),
# wc_ReallocScrubbed(), ...) that types.h binds unconditionally, so it is
# built even without memory callbacks; the callback code inside it is
# gated on USE_WOLFSSL_MEMORY.
list(APPEND LIB_SOURCES wolfcrypt/src/memory.c)

if(NOT BUILD_FIPS_RAND)
if(NOT BUILD_FIPS_V2 AND BUILD_DH)
Expand Down
188 changes: 188 additions & 0 deletions doc/dox_comments/header_files/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -636,3 +636,191 @@ void wc_UnloadStaticMemory(WOLFSSL_HEAP_HINT* heap);
int wolfSSL_StaticBufferSz_ex(unsigned int listSz,
const word32 *sizeList, const word32 *distList,
byte* buffer, word32 sz, int flag);

/*!
\ingroup Memory

\brief Aligned allocation over XMALLOC(), honoring heap and tag (static
memory pools, wolfSSL_SetAllocators() callbacks, user allocators, ports).
Over-allocates and stores a small header just below the returned pointer.
Called through macro XMALLOCALIGN.

\return pointer to aligned allocation
\return NULL if alignment is not 0 or a power of 2, the padded size
overflows, or the allocation fails.

\param alignment 0 or a power of 2; values below 2*sizeof(size_t) are
raised to it
\param size size, in bytes, of the memory to allocate
\param heap heap hint to use for memory. Can be NULL
\param tag dynamic type (see DYNAMIC_TYPE_ list in types.h)

_Example_
\code
byte* buf = (byte*)wc_MallocAlign(64, 1024, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
...
wc_FreeAlign(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
\endcode

\sa wc_FreeAlign
\sa wc_ReallocAlign
\sa XMALLOCALIGN
*/
void *wc_MallocAlign(size_t alignment, size_t size, void *heap, int tag);

/*!
\ingroup Memory

\brief Frees memory returned by wc_MallocAlign(), wc_ReallocAlign() or
wc_ReallocAlignScrubbed(), by calling XFREE(). Aligned and plain
(XMALLOC()) allocations must not be mixed. Not called directly by
wolfSSL, but through macro XFREEALIGN.

\return void

\param ptr aligned pointer to free. NULL is a no-op.
\param heap heap hint used for the allocation. Can be NULL
\param tag dynamic type used for the allocation

_Example_
\code
byte* buf = (byte*)wc_MallocAlign(64, 1024, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
...
wc_FreeAlign(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
\endcode

\sa wc_MallocAlign
\sa XFREEALIGN
*/
void wc_FreeAlign(void *ptr, void *heap, int tag);

/*!
\ingroup Memory

\brief Reallocates memory from wc_MallocAlign(), using XMALLOC() and
XFREE(). A new block is allocated, the leading min(old size, size) bytes
are preserved at the new alignment, and ptr is freed. If XMALLOC() returns
the block already in use, as fixed IO pools (WOLFMEM_IO_POOL_FIXED) do for
IO tags, the data is moved within that block, and the returned pointer may
be equal to ptr. Not called directly by wolfSSL, but through macro
XREALLOCALIGN.

\return pointer to the new aligned block on success.
\return NULL when size is 0 (ptr is freed), or on failure (ptr is left
intact, including when alignment is rejected).

\param ptr NULL, or memory from wc_MallocAlign()/wc_ReallocAlign*().
A NULL ptr behaves as wc_MallocAlign().
\param alignment as for wc_MallocAlign()
\param size new size in bytes
\param heap heap hint. Can be NULL
\param tag dynamic type

_Example_
\code
byte* buf2 = NULL;
byte* buf = (byte*)wc_MallocAlign(64, 1024, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL)
- fail -

buf2 = (byte*)wc_ReallocAlign(buf, 64, 4000, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (buf2 == NULL)
- fail -
...

wc_FreeAlign(buf2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
\endcode

\sa wc_ReallocAlignScrubbed
\sa wc_MallocAlign
\sa XREALLOCALIGN
*/
void *wc_ReallocAlign(void *ptr, size_t alignment, size_t size, void *heap,
int tag);

/*!
\ingroup Memory

\brief As wc_ReallocAlign(), but the old data is zeroized before the old
block is freed, including when size is 0. If the old and new allocations
share a block, only the old data outside of the new allocation is zeroized.
On failure the old block is left intact and not zeroized. Not called
directly by wolfSSL, but through macro XREALLOCALIGN_SCRUBBED.

\return pointer to the new aligned block on success.
\return NULL when size is 0 (ptr is zeroized and freed), or on failure.

\param ptr NULL, or memory from wc_MallocAlign()/wc_ReallocAlign*()
\param alignment as for wc_MallocAlign()
\param size new size in bytes
\param heap heap hint. Can be NULL
\param tag dynamic type

_Example_
\code
byte* buf2 = NULL;
byte* buf = (byte*)wc_MallocAlign(64, 1024, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL)
- fail -

buf2 = (byte*)wc_ReallocAlignScrubbed(buf, 64, 4000, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (buf2 == NULL)
- fail -

- buf freed and zeroed post ReallocAlignScrubbed-
...

wc_FreeAlign(buf2, NULL, DYNAMIC_TYPE_TMP_BUFFER);
\endcode

\sa wc_ReallocAlign
\sa XREALLOCALIGN_SCRUBBED
*/
void *wc_ReallocAlignScrubbed(void *ptr, size_t alignment, size_t size,
void *heap, int tag);

/*!
\ingroup Memory

\brief Reallocates memory from XMALLOC(), zeroizing the old block before
it is freed. A new block is allocated with XMALLOC(), the leading
min(old_size, size) bytes are copied, old_size bytes of ptr are zeroized,
and ptr is freed with XFREE(). If XMALLOC() returns ptr itself, as fixed IO
pools (WOLFMEM_IO_POOL_FIXED) do for IO tags, the data stays in place and
only the bytes past size are zeroized. Not called directly by wolfSSL, but
through macro XREALLOC_SCRUBBED.

\return pointer to the new block on success.
\return NULL when size is 0 (ptr is zeroized and freed), or on failure
(ptr is left intact and not zeroized).

\param ptr NULL, or memory from XMALLOC()/XREALLOC(). A NULL ptr behaves
as XMALLOC(size).
\param old_size current size of ptr in bytes. Must not exceed the real
allocation size, or the copy and zeroization overrun it.
\param size new size in bytes
\param heap heap hint. Can be NULL
\param tag dynamic type

_Example_
\code
byte* key = (byte*)XMALLOC(32, NULL, DYNAMIC_TYPE_TMP_BUFFER);
byte* tmp;
...
tmp = (byte*)wc_ReallocScrubbed(key, 32, 64, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
if (tmp != NULL)
key = tmp;
\endcode

\sa wc_ReallocAlignScrubbed
\sa XREALLOC_SCRUBBED
*/
void *wc_ReallocScrubbed(void *ptr, size_t old_size, size_t size,
void *heap, int tag);
157 changes: 157 additions & 0 deletions doc/dox_comments/header_files/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,163 @@ void* XREALLOC(void *p, size_t n, void* heap, int type);
*/
void XFREE(void *p, void* heap, int type);

/*!
\ingroup Memory

\brief This is not actually a function, but rather a preprocessor macro,
which allocates memory aligned to a given boundary. By default it maps to
wc_MallocAlign(), which over-allocates through XMALLOC() and stores a
small header just below the returned pointer, so heap and type reach
every allocator (static memory, wolfSSL_SetAllocators() callbacks,
XMALLOC_USER, ports). A port or user may supply its own implementation,
but XMALLOCALIGN, XFREEALIGN, XREALLOCALIGN and XREALLOCALIGN_SCRUBBED
must then all be defined together, and must return NULL for an alignment
that is not 0 or a power of 2. An implementation may also return NULL for
an alignment it cannot meet: Linux kernel module builds that bind these
macros to kmalloc() reject alignments above PAGE_SIZE.
Memory from XMALLOCALIGN must be released with XFREEALIGN, never XFREE,
and XFREEALIGN must not be used on memory from XMALLOC.

\return pointer to n bytes aligned to a on success.
\return NULL if a is not 0 or a power of 2, the implementation cannot meet
a, or the allocation fails.

\param a alignment: 0 or a power of 2. The default implementation raises
values below 2*sizeof(size_t) (including 0) to it.
\param n size, in bytes, of the memory to allocate
\param h pointer to the heap to use
\param t memory allocation type for user hints. See enum in types.h

_Example_
\code
byte* buf = (byte*)XMALLOCALIGN(64, 1024, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL) {
return MEMORY_E;
}
...
XFREEALIGN(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
\endcode

\sa XFREEALIGN
\sa XREALLOCALIGN
\sa wc_MallocAlign
*/
void* XMALLOCALIGN(size_t a, size_t n, void* heap, int type);

/*!
\ingroup Memory

\brief This is not actually a function, but rather a preprocessor macro,
which frees memory from XMALLOCALIGN, XREALLOCALIGN or
XREALLOCALIGN_SCRUBBED. By default it maps to wc_FreeAlign().

\return none No returns.

\param p aligned pointer to free. NULL is a no-op.
\param h pointer to the heap used for the allocation
\param t memory allocation type used for the allocation

\sa XMALLOCALIGN
\sa wc_FreeAlign
*/
void XFREEALIGN(void *p, void* heap, int type);

/*!
\ingroup Memory

\brief This is not actually a function, but rather a preprocessor macro,
which reallocates memory from XMALLOCALIGN. The leading min(old size, n)
bytes are preserved in a block aligned to a, and p must not be used after
success, even if the returned pointer is equal to it. The new block may
share storage with p: fixed IO pools (WOLFMEM_IO_POOL_FIXED) reuse the
same block for IO tags, moving the data within it if the alignment
changes, and Linux kernel module builds may resize in place. By default it
maps to wc_ReallocAlign().

\return pointer to the new aligned block on success.
\return NULL when n is 0 (p is freed), or on failure (p is left intact,
including when a is rejected).

\param p NULL, or memory from XMALLOCALIGN/XREALLOCALIGN*. A NULL p
behaves as XMALLOCALIGN.
\param a alignment, as for XMALLOCALIGN
\param n new size in bytes
\param h pointer to the heap to use
\param t memory allocation type for user hints. See enum in types.h

_Example_
\code
byte* buf = (byte*)XMALLOCALIGN(64, 128, NULL, DYNAMIC_TYPE_TMP_BUFFER);
byte* tmp;
...
tmp = (byte*)XREALLOCALIGN(buf, 64, 256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmp != NULL)
buf = tmp;
\endcode

\sa XREALLOCALIGN_SCRUBBED
\sa XMALLOCALIGN
\sa wc_ReallocAlign
*/
void* XREALLOCALIGN(void *p, size_t a, size_t n, void* heap, int type);

/*!
\ingroup Memory

\brief This is not actually a function, but rather a preprocessor macro.
As XREALLOCALIGN, but the old data is zeroized before the old block is
freed, including when n is 0. If the new block shares storage with p, only
the old data outside of the new allocation is zeroized. On failure the old
block is left intact and not zeroized. Use for buffers holding sensitive
data. By default it maps to wc_ReallocAlignScrubbed().

\return pointer to the new aligned block on success.
\return NULL when n is 0 (p is zeroized and freed), or on failure.

\param p NULL, or memory from XMALLOCALIGN/XREALLOCALIGN*
\param a alignment, as for XMALLOCALIGN
\param old_size current size of p in bytes. Unused by the default
implementation, which tracks the size itself, but available to
overrides that need it. Must not exceed the real allocation size.
\param n new size in bytes
\param h pointer to the heap to use
\param t memory allocation type for user hints. See enum in types.h

\sa XREALLOCALIGN
\sa wc_ReallocAlignScrubbed
*/
void* XREALLOCALIGN_SCRUBBED(void *p, size_t a, size_t old_size, size_t n,
void* heap, int type);

/*!
\ingroup Memory

\brief This is not actually a function, but rather a preprocessor macro,
which reallocates memory from XMALLOC and zeroizes the old block before
it is freed. A new block is allocated with XMALLOC, the leading
min(old_size, n) bytes are copied, old_size bytes of p are zeroized, and p
is freed with XFREE. If XMALLOC returns p itself, as fixed IO pools
(WOLFMEM_IO_POOL_FIXED) do for IO tags, the data stays in place and only
the bytes past n are zeroized. By default it maps to wc_ReallocScrubbed().

\return pointer to the new block on success.
\return NULL when n is 0 (p is zeroized and freed), or on failure (p is
left intact and not zeroized).

\param p NULL, or memory from XMALLOC/XREALLOC. A NULL p behaves as
XMALLOC.
\param old_size current size of p in bytes. Must not exceed the real
allocation size, or the copy and zeroization overrun it.
\param n new size in bytes
\param h pointer to the heap to use
\param t memory allocation type for user hints. See enum in types.h

\sa XREALLOCALIGN_SCRUBBED
\sa wc_ReallocScrubbed
*/
void* XREALLOC_SCRUBBED(void *p, size_t old_size, size_t n, void* heap,
int type);

/*!
\ingroup Math

Expand Down
Loading
Loading