/src/openssl/crypto/aligned_alloc.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #include "internal/e_os.h" |
11 | | #include "internal/cryptlib.h" |
12 | | #include "internal/mem_alloc_utils.h" |
13 | | #include "crypto/cryptlib.h" |
14 | | #include <stdlib.h> |
15 | | |
16 | | void *ossl_malloc_align(size_t num, size_t alignment, void **freeptr, |
17 | | const char *file, int line) |
18 | 0 | { |
19 | 0 | size_t alloc_bytes; |
20 | 0 | void *ret; |
21 | |
|
22 | 0 | *freeptr = NULL; |
23 | | |
24 | | /* Ensure that alignment is a power of two no larger than 65536 */ |
25 | 0 | if (alignment == 0 || (alignment & (alignment - 1)) != 0 |
26 | 0 | || alignment > 65536) { |
27 | 0 | ossl_report_alloc_err_inv(file, line); |
28 | 0 | return NULL; |
29 | 0 | } |
30 | | |
31 | | /* |
32 | | * Note: Windows supports an _aligned_malloc call, but we choose |
33 | | * not to use it here, because allocations from that function |
34 | | * require that they be freed via _aligned_free. Given that |
35 | | * we can't differentiate plain malloc blocks from blocks obtained |
36 | | * via _aligned_malloc, just avoid its use entirely |
37 | | */ |
38 | | |
39 | 0 | if (ossl_unlikely(!ossl_size_add(num, alignment, &alloc_bytes, file, line))) |
40 | 0 | return NULL; |
41 | | |
42 | | /* |
43 | | * Step 1: Allocate an amount of memory that is <alignment> |
44 | | * bytes bigger than requested |
45 | | */ |
46 | 0 | *freeptr = CRYPTO_malloc(alloc_bytes, file, line); |
47 | 0 | if (*freeptr == NULL) |
48 | 0 | return NULL; |
49 | | |
50 | | /* |
51 | | * Step 2: Add <alignment - 1> bytes to the pointer |
52 | | * This will cross the alignment boundary that is |
53 | | * requested |
54 | | */ |
55 | 0 | ret = (void *)((char *)*freeptr + (alignment - 1)); |
56 | | |
57 | | /* |
58 | | * Step 3: Use the alignment as a mask to translate the |
59 | | * least significant bits of the allocation at the alignment |
60 | | * boundary to 0. ret now holds a pointer to the memory |
61 | | * buffer at the requested alignment |
62 | | * NOTE: It is a documented requirement that alignment be a |
63 | | * power of 2, which is what allows this to work |
64 | | */ |
65 | 0 | ret = (void *)((uintptr_t)ret & (uintptr_t)(~(alignment - 1))); |
66 | |
|
67 | 0 | return ret; |
68 | 0 | } |