1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include <stdlib.h>
17 #include "securec.h"
18 #include "hitls_build.h"
19 #include "bsl_log_internal.h"
20 #include "bsl_errno.h"
21 #include "bsl_sal.h"
22 #include "bsl_binlog_id.h"
23 #include "sal_memimpl.h"
24
25 static BSL_SAL_MemCallback g_memCallback = {0};
26
BSL_SAL_Malloc(uint32_t size)27 void *BSL_SAL_Malloc(uint32_t size)
28 {
29 // When size is 0, malloc of different systems may return NULL or non-NULL. Here, a definite result is required.
30 // If the callback is registered, everything is determined by the callback.
31 if (g_memCallback.pfMalloc != NULL && g_memCallback.pfMalloc != BSL_SAL_Malloc) {
32 return g_memCallback.pfMalloc(size);
33 }
34 if (size == 0) {
35 return NULL;
36 }
37 #if defined(HITLS_BSL_SAL_MEM) && defined(HITLS_BSL_SAL_LINUX)
38 return SAL_MallocImpl(size);
39 #else
40 return NULL;
41 #endif
42 }
43
BSL_SAL_Free(void * value)44 void BSL_SAL_Free(void *value)
45 {
46 if (g_memCallback.pfFree == NULL || g_memCallback.pfFree == BSL_SAL_Free) {
47 #if defined(HITLS_BSL_SAL_MEM) && defined(HITLS_BSL_SAL_LINUX)
48 SAL_FreeImpl(value);
49 #endif
50 return;
51 }
52 g_memCallback.pfFree(value);
53 }
54
BSL_SAL_Calloc(uint32_t num,uint32_t size)55 void *BSL_SAL_Calloc(uint32_t num, uint32_t size)
56 {
57 if (num == 0 || size == 0) {
58 return BSL_SAL_Malloc(0);
59 }
60 if (num > UINT32_MAX / size) { // process the rewinding according to G.INT.02 in the HW C Coding Specifications V5.1
61 return NULL;
62 }
63 uint32_t blockSize = num * size;
64 uint8_t *ptr = BSL_SAL_Malloc(blockSize);
65 if (ptr == NULL) {
66 return NULL;
67 }
68 // If the value is greater than SECUREC_MEM_MAX_LEN, segment processing is required.
69 // This is because memset_s can process only the value which the size is SECUREC_MEM_MAX_LEN.
70 uint32_t offset = 0;
71 while (blockSize > SECUREC_MEM_MAX_LEN) {
72 if (memset_s(&ptr[offset], SECUREC_MEM_MAX_LEN, 0, SECUREC_MEM_MAX_LEN) != EOK) {
73 BSL_SAL_FREE(ptr);
74 return NULL;
75 }
76 offset += SECUREC_MEM_MAX_LEN;
77 blockSize -= SECUREC_MEM_MAX_LEN;
78 }
79 if (memset_s(&ptr[offset], blockSize, 0, blockSize) != EOK) {
80 BSL_SAL_FREE(ptr);
81 return NULL;
82 }
83 return ptr;
84 }
85
BSL_SAL_Realloc(void * addr,uint32_t newSize,uint32_t oldSize)86 void *BSL_SAL_Realloc(void *addr, uint32_t newSize, uint32_t oldSize)
87 {
88 if (addr == NULL) {
89 return BSL_SAL_Malloc(newSize);
90 }
91 uint32_t minSize = (oldSize > newSize) ? newSize : oldSize;
92
93 void *ptr = BSL_SAL_Malloc(newSize);
94 if (ptr == NULL) {
95 return NULL;
96 }
97
98 if (memcpy_s(ptr, newSize, addr, minSize) != EOK) {
99 BSL_SAL_FREE(ptr);
100 } else {
101 BSL_SAL_FREE(addr);
102 }
103
104 return ptr;
105 }
106
BSL_SAL_Dump(const void * src,uint32_t size)107 void *BSL_SAL_Dump(const void *src, uint32_t size)
108 {
109 if (src == NULL) {
110 return NULL;
111 }
112 void *ptr = BSL_SAL_Malloc(size);
113 if (ptr == NULL) {
114 return NULL;
115 }
116
117 if (memcpy_s(ptr, size, src, size) != EOK) {
118 BSL_SAL_FREE(ptr);
119 return NULL;
120 }
121
122 return ptr;
123 }
124
SAL_MemCallBack_Ctrl(BSL_SAL_CB_FUNC_TYPE type,void * funcCb)125 int32_t SAL_MemCallBack_Ctrl(BSL_SAL_CB_FUNC_TYPE type, void *funcCb)
126 {
127 if (type > BSL_SAL_MEM_FREE || type < BSL_SAL_MEM_MALLOC) {
128 return BSL_SAL_ERR_BAD_PARAM;
129 }
130 uint32_t offset = (uint32_t)(type - BSL_SAL_MEM_MALLOC);
131 ((void **)&g_memCallback)[offset] = funcCb;
132 return BSL_SUCCESS;
133 }
134
135 #if !defined(__clang__)
136 #pragma GCC push_options
137 #pragma GCC optimize("O3")
138 #endif
139 #define CLEAN_THRESHOLD_SIZE 16UL
140
CleanSensitiveDataLess16Byte(void * buf,uint32_t bufLen)141 static void CleanSensitiveDataLess16Byte(void *buf, uint32_t bufLen)
142 {
143 uint8_t *tmp = (uint8_t *)buf;
144 switch (bufLen) {
145 case 16: *(tmp++) = (uint8_t)0;
146 /* FALLTHRU */
147 case 15: *(tmp++) = (uint8_t)0;
148 /* FALLTHRU */
149 case 14: *(tmp++) = (uint8_t)0;
150 /* FALLTHRU */
151 case 13: *(tmp++) = (uint8_t)0;
152 /* FALLTHRU */
153 case 12: *(tmp++) = (uint8_t)0;
154 /* FALLTHRU */
155 case 11: *(tmp++) = (uint8_t)0;
156 /* FALLTHRU */
157 case 10: *(tmp++) = (uint8_t)0;
158 /* FALLTHRU */
159 case 9: *(tmp++) = (uint8_t)0;
160 /* FALLTHRU */
161 case 8: *(tmp++) = (uint8_t)0;
162 /* FALLTHRU */
163 case 7: *(tmp++) = (uint8_t)0;
164 /* FALLTHRU */
165 case 6: *(tmp++) = (uint8_t)0;
166 /* FALLTHRU */
167 case 5: *(tmp++) = (uint8_t)0;
168 /* FALLTHRU */
169 case 4: *(tmp++) = (uint8_t)0;
170 /* FALLTHRU */
171 case 3: *(tmp++) = (uint8_t)0;
172 /* FALLTHRU */
173 case 2: *(tmp++) = (uint8_t)0;
174 /* FALLTHRU */
175 case 1: *(tmp) = (uint8_t)0;
176 /* FALLTHRU */
177 default:
178 break;
179 }
180 }
181
CleanSensitiveData(void * buf,uint32_t bufLen)182 static void CleanSensitiveData(void *buf, uint32_t bufLen)
183 {
184 uint8_t *tmp = (uint8_t *)buf;
185 uint32_t boundOpt;
186
187 if (((uintptr_t)buf & 0x3) == 0) { // buf & 0x3, used to determine whether 4-byte alignment
188 // shift rightwards by 4 bits and then leftwards by 4 bits, which is used to calculate an integer multiple of 16
189 boundOpt = (bufLen >> 4) << 4;
190 for (uint32_t i = 0; i < boundOpt; i += 16) { // Clear 16 pieces of memory each time.
191 uint32_t *ctmp = (uint32_t *)(tmp + i);
192 ctmp[0] = 0;
193 ctmp[1] = 0;
194 ctmp[2] = 0;
195 ctmp[3] = 0;
196 }
197 } else {
198 // shifted rightward by 2 bits and then left by 2 bits, used to calculate an integer multiple of 4.
199 boundOpt = (bufLen >> 2) << 2;
200 for (uint32_t i = 0; i < boundOpt; i += 4) { // Clear 4 pieces of memory each time.
201 tmp[i] = 0;
202 tmp[i + 1] = 0;
203 tmp[i + 2] = 0;
204 tmp[i + 3] = 0;
205 }
206 }
207 for (uint32_t i = boundOpt; i < bufLen; ++i) {
208 tmp[i] = 0;
209 }
210 }
211
BSL_SAL_CleanseData(void * ptr,uint32_t size)212 void BSL_SAL_CleanseData(void *ptr, uint32_t size)
213 {
214 if (ptr == NULL) {
215 return;
216 }
217 if (size > CLEAN_THRESHOLD_SIZE) {
218 CleanSensitiveData(ptr, size);
219 } else {
220 CleanSensitiveDataLess16Byte(ptr, size);
221 }
222 }
223
BSL_SAL_ClearFree(void * ptr,uint32_t size)224 void BSL_SAL_ClearFree(void *ptr, uint32_t size)
225 {
226 if (ptr == NULL) {
227 return;
228 }
229 if (size != 0) {
230 BSL_SAL_CleanseData(ptr, size);
231 }
232 BSL_SAL_FREE(ptr);
233 }
234
235 #if !defined(__clang__)
236 #pragma GCC pop_options
237 #endif
238