/* * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include "internal/e_os.h" #include "internal/cryptlib.h" #include "internal/mem_alloc_utils.h" #include "crypto/cryptlib.h" #include void *ossl_malloc_align(size_t num, size_t alignment, void **freeptr, const char *file, int line) { size_t alloc_bytes; void *ret; *freeptr = NULL; /* Ensure that alignment is a power of two no larger than 65536 */ if (alignment == 0 || (alignment & (alignment - 1)) != 0 || alignment > 65536) { ossl_report_alloc_err_inv(file, line); return NULL; } /* * Note: Windows supports an _aligned_malloc call, but we choose * not to use it here, because allocations from that function * require that they be freed via _aligned_free. Given that * we can't differentiate plain malloc blocks from blocks obtained * via _aligned_malloc, just avoid its use entirely */ if (ossl_unlikely(!ossl_size_add(num, alignment, &alloc_bytes, file, line))) return NULL; /* * Step 1: Allocate an amount of memory that is * bytes bigger than requested */ *freeptr = CRYPTO_malloc(alloc_bytes, file, line); if (*freeptr == NULL) return NULL; /* * Step 2: Add bytes to the pointer * This will cross the alignment boundary that is * requested */ ret = (void *)((char *)*freeptr + (alignment - 1)); /* * Step 3: Use the alignment as a mask to translate the * least significant bits of the allocation at the alignment * boundary to 0. ret now holds a pointer to the memory * buffer at the requested alignment * NOTE: It is a documented requirement that alignment be a * power of 2, which is what allows this to work */ ret = (void *)((uintptr_t)ret & (uintptr_t)(~(alignment - 1))); return ret; }