1 /*############################################################################
2 # Copyright 2016-2017 Intel Corporation
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 ############################################################################*/
16
17 /*!
18 * \file
19 * \brief Memory access implementation.
20 */
21
22 #include "epid/common/src/memory.h"
23
24 #include <stdint.h>
25 #include <string.h>
26
27 /// Maximum size of the destination buffer
28 #ifndef RSIZE_MAX
29 #define RSIZE_MAX ((SIZE_MAX) >> 1)
30 #endif
31
32 #ifndef MIN
33 /// Evaluate to minimum of two values
34 #define MIN(a, b) ((a) < (b) ? (a) : (b))
35 #endif // MIN
36
37 /// Copies count of character from dest to src
38 /*! \note Implementation follows C11 memcpy_s but with checks always enabled
39 */
memcpy_S(void * dest,size_t destsz,void const * src,size_t count)40 int memcpy_S(void* dest, size_t destsz, void const* src, size_t count) {
41 size_t i;
42 if (!dest || destsz > RSIZE_MAX) return -1;
43 if (!src || count > RSIZE_MAX || count > destsz ||
44 count > (dest > src ? ((uintptr_t)dest - (uintptr_t)src)
45 : ((uintptr_t)src - (uintptr_t)dest))) {
46 // zero out dest if error detected
47 memset(dest, 0, destsz);
48 return -1;
49 }
50
51 for (i = 0; i < count; i++) ((uint8_t*)dest)[i] = ((uint8_t*)src)[i];
52 return 0;
53 }
54
EpidZeroMemory(void * ptr,size_t size)55 void EpidZeroMemory(void* ptr, size_t size) { memset(ptr, 0, size); }
56
57 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
58
59 #if !defined(EPID_ALLOC_ALIGN)
60 /// Alignment constant for EpidAlloc, must be a power of two
61 #define EPID_ALLOC_ALIGN sizeof(size_t)
62 #endif // !defined(EPID_ALLOC_ALIGN)
63
64 #pragma pack(1)
65 /// Allocated memory block information
66 typedef struct EpidAllocHeader {
67 size_t length; ///< number of bytes memory block is allocated for
68 void* ptr; ///< pointer to whole memory block including EpidAllocHeader
69 } EpidAllocHeader;
70 #pragma pack()
71
72 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
73
EpidAlloc(size_t size)74 void* EpidAlloc(size_t size) {
75 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
76 void* ptr = NULL;
77 if (size <= 0) return NULL;
78 // Allocate memory enough to store size bytes and EpidAllocHeader
79 ptr = calloc(1, size + EPID_ALLOC_ALIGN - 1 + sizeof(EpidAllocHeader));
80 if (ptr) {
81 void* aligned_pointer = (void*)(((uintptr_t)ptr + EPID_ALLOC_ALIGN +
82 sizeof(EpidAllocHeader) - 1) &
83 (~(EPID_ALLOC_ALIGN - 1)));
84 ((EpidAllocHeader*)aligned_pointer)[-1].length = size;
85 ((EpidAllocHeader*)aligned_pointer)[-1].ptr = ptr;
86 return aligned_pointer;
87 }
88 return NULL;
89 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
90 return calloc(1, size);
91 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
92 }
93
EpidRealloc(void * ptr,size_t new_size)94 void* EpidRealloc(void* ptr, size_t new_size) {
95 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
96 void* new_ptr = EpidAlloc(new_size);
97 if (!new_ptr) return NULL;
98 if (ptr) {
99 // Memory copy is used to copy a buffer of variable length
100 if (0 != memcpy_S(new_ptr, ((EpidAllocHeader*)new_ptr)[-1].length, ptr,
101 MIN(((EpidAllocHeader*)ptr)[-1].length,
102 ((EpidAllocHeader*)new_ptr)[-1].length))) {
103 EpidFree(new_ptr);
104 return NULL;
105 }
106 EpidFree(ptr);
107 }
108 return new_ptr;
109 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
110 return realloc(ptr, new_size);
111 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
112 }
113
EpidFree(void * ptr)114 void EpidFree(void* ptr) {
115 #if defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
116 if (ptr) {
117 EpidZeroMemory(ptr, ((EpidAllocHeader*)ptr)[-1].length);
118 free(((EpidAllocHeader*)ptr)[-1].ptr);
119 }
120 #else // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
121 free(ptr);
122 #endif // defined(EPID_ENABLE_EPID_ZERO_MEMORY_ON_FREE)
123 }
124