]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Move the open-coded aligned alloc in a separate file and use it in FIPS module
authorEugene Syromiatnikov <esyr@openssl.org>
Mon, 18 Aug 2025 12:24:23 +0000 (14:24 +0200)
committerNeil Horman <nhorman@openssl.org>
Tue, 16 Sep 2025 13:59:13 +0000 (09:59 -0400)
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 <esyr@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Saša Nedvědický <sashan@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/28295)

crypto/aligned_alloc.c [new file with mode: 0644]
crypto/build.info
crypto/mem.c
include/internal/mem_alloc_utils.h
providers/fips/fipsprov.c

diff --git a/crypto/aligned_alloc.c b/crypto/aligned_alloc.c
new file mode 100644 (file)
index 0000000..dcc2b40
--- /dev/null
@@ -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 <stdlib.h>
+
+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 <alignment>
+     * bytes bigger than requested
+     */
+    *freeptr = CRYPTO_malloc(alloc_bytes, file, line);
+    if (*freeptr == NULL)
+        return NULL;
+
+    /*
+     * Step 2: Add <alignment - 1> 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;
+}
index 872684cd7a3a446c7fc3723ec769fd23c72030ff..1f522a729f8929d8a71b675f983998b48bf4ca93 100644 (file)
@@ -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 \
index f1448606a708acbe0ebe2141cc6e7ba1d9e4a75a..985359a68137fef1e0b2f4ddc1e8895c826d4cd5 100644 (file)
@@ -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 <alignment>
-     * bytes bigger than requested
-     */
-    *freeptr = CRYPTO_malloc(alloc_bytes, file, line);
-    if (*freeptr == NULL)
-        return NULL;
-
-    /*
-     * Step 2: Add <alignment - 1> 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)
index 4d87179f6bd7ea75c0d24aee20b511600999b71b..a392a65724c5de54bf6ab2313278aa6767218172 100644 (file)
 
 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,
index dea863c79f283fe1374ce73f88e5fa8edfff79a2..cb04b2a62ca1fee59cd2ae4374efbf78de570be7 100644 (file)
@@ -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, ...)