From: Eugene Syromiatnikov Date: Mon, 18 Aug 2025 12:24:23 +0000 (+0200) Subject: Move the open-coded aligned alloc in a separate file and use it in FIPS module X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8e28f5c0b96c5d71b74cc8fdb2cfb5b3300f2708;p=thirdparty%2Fopenssl.git Move the open-coded aligned alloc in a separate file and use it in FIPS module Factor the open-coded aligned allocation implementation in a separate file and use it instead of just returning NULL in CRYPTO_aligned_alloc implementation in the FIPS provider. Signed-off-by: Eugene Syromiatnikov Reviewed-by: Neil Horman Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/28295) --- diff --git a/crypto/aligned_alloc.c b/crypto/aligned_alloc.c new file mode 100644 index 00000000000..dcc2b406a20 --- /dev/null +++ b/crypto/aligned_alloc.c @@ -0,0 +1,67 @@ +/* + * 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 */ + if (alignment == 0 || (alignment & (alignment - 1)) != 0) { + 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; +} diff --git a/crypto/build.info b/crypto/build.info index 872684cd7a3..1f522a729f8 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -100,7 +100,7 @@ $UTIL_COMMON=\ threads_pthread.c threads_win.c threads_none.c threads_common.c \ initthread.c context.c sparse_array.c asn1_dsa.c packet.c \ param_build.c param_build_set.c der_writer.c threads_lib.c \ - params_dup.c time.c array_alloc.c deterministic_nonce.c + params_dup.c time.c array_alloc.c aligned_alloc.c deterministic_nonce.c SOURCE[../libcrypto]=$UTIL_COMMON \ mem.c mem_sec.c \ diff --git a/crypto/mem.c b/crypto/mem.c index f1448606a70..985359a6813 100644 --- a/crypto/mem.c +++ b/crypto/mem.c @@ -231,9 +231,6 @@ void *CRYPTO_zalloc(size_t num, const char *file, int line) void *CRYPTO_aligned_alloc(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 */ @@ -246,6 +243,7 @@ void *CRYPTO_aligned_alloc(size_t num, size_t alignment, void **freeptr, if (malloc_impl == CRYPTO_malloc) { #if defined(_BSD_SOURCE) || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) int memalign_ret; + void *ret; /* posix_memalign() requires alignment to be at least sizeof(void *) */ if (alignment < sizeof(void *)) @@ -267,44 +265,7 @@ void *CRYPTO_aligned_alloc(size_t num, size_t alignment, void **freeptr, #endif } - /* we have to do this the hard way */ - - /* - * 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; + return ossl_malloc_align(num, alignment, freeptr, file, line); } void *CRYPTO_realloc(void *str, size_t num, const char *file, int line) diff --git a/include/internal/mem_alloc_utils.h b/include/internal/mem_alloc_utils.h index 4d87179f6bd..a392a65724c 100644 --- a/include/internal/mem_alloc_utils.h +++ b/include/internal/mem_alloc_utils.h @@ -26,6 +26,15 @@ OSSL_SAFE_MATH_UNSIGNED(size_t, size_t) +/* + * A helper open-coded aligned alloc implementation around CRYPTO_malloc(), + * for use in cases where non-standard malloc implementation is (or may be, + * as it is the case of the FIPS module) used, or posix_memalign + * is not available. + */ +void *ossl_malloc_align(size_t num, size_t alignment, void **freeptr, + const char *file, int line); + /* * A helper routine to report memory allocation errors. * Similar to the ERR_raise() macro, but accepts explicit file/line arguments, diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index dea863c79f2..cb04b2a62ca 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -29,6 +29,7 @@ #include "crypto/context.h" #include "fipscommon.h" #include "internal/core.h" +#include "internal/mem_alloc_utils.h" static const char FIPS_DEFAULT_PROPERTIES[] = "provider=fips,fips=yes"; static const char FIPS_UNAPPROVED_PROPERTIES[] = "provider=fips,fips=no"; @@ -1183,7 +1184,7 @@ int CRYPTO_secure_allocated(const void *ptr) void *CRYPTO_aligned_alloc(size_t num, size_t align, void **freeptr, const char *file, int line) { - return NULL; + return ossl_malloc_align(num, align, freeptr, file, line); } int BIO_snprintf(char *buf, size_t n, const char *format, ...)