1 | /* |
2 | * Platform abstraction layer |
3 | * |
4 | * Copyright The Mbed TLS Contributors |
5 | * SPDX-License-Identifier: Apache-2.0 |
6 | * |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
8 | * not use this file except in compliance with the License. |
9 | * You may obtain a copy of the License at |
10 | * |
11 | * http://www.apache.org/licenses/LICENSE-2.0 |
12 | * |
13 | * Unless required by applicable law or agreed to in writing, software |
14 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
15 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
16 | * See the License for the specific language governing permissions and |
17 | * limitations under the License. |
18 | */ |
19 | |
20 | #include "common.h" |
21 | |
22 | #if defined(MBEDTLS_PLATFORM_C) |
23 | |
24 | #include "mbedtls/platform.h" |
25 | #include "mbedtls/platform_util.h" |
26 | #include "mbedtls/error.h" |
27 | |
28 | /* The compile time configuration of memory allocation via the macros |
29 | * MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO takes precedence over the runtime |
30 | * configuration via mbedtls_platform_set_calloc_free(). So, omit everything |
31 | * related to the latter if MBEDTLS_PLATFORM_{FREE/CALLOC}_MACRO are defined. */ |
32 | #if defined(MBEDTLS_PLATFORM_MEMORY) && \ |
33 | !(defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && \ |
34 | defined(MBEDTLS_PLATFORM_FREE_MACRO)) |
35 | |
36 | #if !defined(MBEDTLS_PLATFORM_STD_CALLOC) |
37 | static void *platform_calloc_uninit(size_t n, size_t size) |
38 | { |
39 | ((void) n); |
40 | ((void) size); |
41 | return NULL; |
42 | } |
43 | |
44 | #define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit |
45 | #endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ |
46 | |
47 | #if !defined(MBEDTLS_PLATFORM_STD_FREE) |
48 | static void platform_free_uninit(void *ptr) |
49 | { |
50 | ((void) ptr); |
51 | } |
52 | |
53 | #define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit |
54 | #endif /* !MBEDTLS_PLATFORM_STD_FREE */ |
55 | |
56 | static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC; |
57 | static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE; |
58 | |
59 | void *mbedtls_calloc(size_t nmemb, size_t size) |
60 | { |
61 | return (*mbedtls_calloc_func)(nmemb, size); |
62 | } |
63 | |
64 | void mbedtls_free(void *ptr) |
65 | { |
66 | (*mbedtls_free_func)(ptr); |
67 | } |
68 | |
69 | int mbedtls_platform_set_calloc_free(void *(*calloc_func)(size_t, size_t), |
70 | void (*free_func)(void *)) |
71 | { |
72 | mbedtls_calloc_func = calloc_func; |
73 | mbedtls_free_func = free_func; |
74 | return 0; |
75 | } |
76 | #endif /* MBEDTLS_PLATFORM_MEMORY && |
77 | !( defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && |
78 | defined(MBEDTLS_PLATFORM_FREE_MACRO) ) */ |
79 | |
80 | #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_SNPRINTF) |
81 | #include <stdarg.h> |
82 | int mbedtls_platform_win32_snprintf(char *s, size_t n, const char *fmt, ...) |
83 | { |
84 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
85 | va_list argp; |
86 | |
87 | va_start(argp, fmt); |
88 | ret = mbedtls_vsnprintf(s, n, fmt, argp); |
89 | va_end(argp); |
90 | |
91 | return ret; |
92 | } |
93 | #endif |
94 | |
95 | #if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) |
96 | #if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) |
97 | /* |
98 | * Make dummy function to prevent NULL pointer dereferences |
99 | */ |
100 | static int platform_snprintf_uninit(char *s, size_t n, |
101 | const char *format, ...) |
102 | { |
103 | ((void) s); |
104 | ((void) n); |
105 | ((void) format); |
106 | return 0; |
107 | } |
108 | |
109 | #define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit |
110 | #endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ |
111 | |
112 | int (*mbedtls_snprintf)(char *s, size_t n, |
113 | const char *format, |
114 | ...) = MBEDTLS_PLATFORM_STD_SNPRINTF; |
115 | |
116 | int mbedtls_platform_set_snprintf(int (*snprintf_func)(char *s, size_t n, |
117 | const char *format, |
118 | ...)) |
119 | { |
120 | mbedtls_snprintf = snprintf_func; |
121 | return 0; |
122 | } |
123 | #endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ |
124 | |
125 | #if defined(MBEDTLS_PLATFORM_HAS_NON_CONFORMING_VSNPRINTF) |
126 | #include <stdarg.h> |
127 | int mbedtls_platform_win32_vsnprintf(char *s, size_t n, const char *fmt, va_list arg) |
128 | { |
129 | int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; |
130 | |
131 | /* Avoid calling the invalid parameter handler by checking ourselves */ |
132 | if (s == NULL || n == 0 || fmt == NULL) { |
133 | return -1; |
134 | } |
135 | |
136 | #if defined(_TRUNCATE) |
137 | ret = vsnprintf_s(s, n, _TRUNCATE, fmt, arg); |
138 | #else |
139 | ret = vsnprintf(s, n, fmt, arg); |
140 | if (ret < 0 || (size_t) ret == n) { |
141 | s[n-1] = '\0'; |
142 | ret = -1; |
143 | } |
144 | #endif |
145 | |
146 | return ret; |
147 | } |
148 | #endif |
149 | |
150 | #if defined(MBEDTLS_PLATFORM_VSNPRINTF_ALT) |
151 | #if !defined(MBEDTLS_PLATFORM_STD_VSNPRINTF) |
152 | /* |
153 | * Make dummy function to prevent NULL pointer dereferences |
154 | */ |
155 | static int platform_vsnprintf_uninit(char *s, size_t n, |
156 | const char *format, va_list arg) |
157 | { |
158 | ((void) s); |
159 | ((void) n); |
160 | ((void) format); |
161 | ((void) arg); |
162 | return -1; |
163 | } |
164 | |
165 | #define MBEDTLS_PLATFORM_STD_VSNPRINTF platform_vsnprintf_uninit |
166 | #endif /* !MBEDTLS_PLATFORM_STD_VSNPRINTF */ |
167 | |
168 | int (*mbedtls_vsnprintf)(char *s, size_t n, |
169 | const char *format, |
170 | va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF; |
171 | |
172 | int mbedtls_platform_set_vsnprintf(int (*vsnprintf_func)(char *s, size_t n, |
173 | const char *format, |
174 | va_list arg)) |
175 | { |
176 | mbedtls_vsnprintf = vsnprintf_func; |
177 | return 0; |
178 | } |
179 | #endif /* MBEDTLS_PLATFORM_VSNPRINTF_ALT */ |
180 | |
181 | #if defined(MBEDTLS_PLATFORM_PRINTF_ALT) |
182 | #if !defined(MBEDTLS_PLATFORM_STD_PRINTF) |
183 | /* |
184 | * Make dummy function to prevent NULL pointer dereferences |
185 | */ |
186 | static int platform_printf_uninit(const char *format, ...) |
187 | { |
188 | ((void) format); |
189 | return 0; |
190 | } |
191 | |
192 | #define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit |
193 | #endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ |
194 | |
195 | int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF; |
196 | |
197 | int mbedtls_platform_set_printf(int (*printf_func)(const char *, ...)) |
198 | { |
199 | mbedtls_printf = printf_func; |
200 | return 0; |
201 | } |
202 | #endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ |
203 | |
204 | #if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) |
205 | #if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) |
206 | /* |
207 | * Make dummy function to prevent NULL pointer dereferences |
208 | */ |
209 | static int platform_fprintf_uninit(FILE *stream, const char *format, ...) |
210 | { |
211 | ((void) stream); |
212 | ((void) format); |
213 | return 0; |
214 | } |
215 | |
216 | #define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit |
217 | #endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ |
218 | |
219 | int (*mbedtls_fprintf)(FILE *, const char *, ...) = |
220 | MBEDTLS_PLATFORM_STD_FPRINTF; |
221 | |
222 | int mbedtls_platform_set_fprintf(int (*fprintf_func)(FILE *, const char *, ...)) |
223 | { |
224 | mbedtls_fprintf = fprintf_func; |
225 | return 0; |
226 | } |
227 | #endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ |
228 | |
229 | #if defined(MBEDTLS_PLATFORM_EXIT_ALT) |
230 | #if !defined(MBEDTLS_PLATFORM_STD_EXIT) |
231 | /* |
232 | * Make dummy function to prevent NULL pointer dereferences |
233 | */ |
234 | static void platform_exit_uninit(int status) |
235 | { |
236 | ((void) status); |
237 | } |
238 | |
239 | #define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit |
240 | #endif /* !MBEDTLS_PLATFORM_STD_EXIT */ |
241 | |
242 | void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT; |
243 | |
244 | int mbedtls_platform_set_exit(void (*exit_func)(int status)) |
245 | { |
246 | mbedtls_exit = exit_func; |
247 | return 0; |
248 | } |
249 | #endif /* MBEDTLS_PLATFORM_EXIT_ALT */ |
250 | |
251 | #if defined(MBEDTLS_HAVE_TIME) |
252 | |
253 | #if defined(MBEDTLS_PLATFORM_TIME_ALT) |
254 | #if !defined(MBEDTLS_PLATFORM_STD_TIME) |
255 | /* |
256 | * Make dummy function to prevent NULL pointer dereferences |
257 | */ |
258 | static mbedtls_time_t platform_time_uninit(mbedtls_time_t *timer) |
259 | { |
260 | ((void) timer); |
261 | return 0; |
262 | } |
263 | |
264 | #define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit |
265 | #endif /* !MBEDTLS_PLATFORM_STD_TIME */ |
266 | |
267 | mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME; |
268 | |
269 | int mbedtls_platform_set_time(mbedtls_time_t (*time_func)(mbedtls_time_t *timer)) |
270 | { |
271 | mbedtls_time = time_func; |
272 | return 0; |
273 | } |
274 | #endif /* MBEDTLS_PLATFORM_TIME_ALT */ |
275 | |
276 | #endif /* MBEDTLS_HAVE_TIME */ |
277 | |
278 | #if defined(MBEDTLS_ENTROPY_NV_SEED) |
279 | #if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) |
280 | /* Default implementations for the platform independent seed functions use |
281 | * standard libc file functions to read from and write to a pre-defined filename |
282 | */ |
283 | int mbedtls_platform_std_nv_seed_read(unsigned char *buf, size_t buf_len) |
284 | { |
285 | FILE *file; |
286 | size_t n; |
287 | |
288 | if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" )) == NULL) { |
289 | return -1; |
290 | } |
291 | |
292 | if ((n = fread(buf, 1, buf_len, file)) != buf_len) { |
293 | fclose(file); |
294 | mbedtls_platform_zeroize(buf, buf_len); |
295 | return -1; |
296 | } |
297 | |
298 | fclose(file); |
299 | return (int) n; |
300 | } |
301 | |
302 | int mbedtls_platform_std_nv_seed_write(unsigned char *buf, size_t buf_len) |
303 | { |
304 | FILE *file; |
305 | size_t n; |
306 | |
307 | if ((file = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" )) == NULL) { |
308 | return -1; |
309 | } |
310 | |
311 | if ((n = fwrite(buf, 1, buf_len, file)) != buf_len) { |
312 | fclose(file); |
313 | return -1; |
314 | } |
315 | |
316 | fclose(file); |
317 | return (int) n; |
318 | } |
319 | #endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ |
320 | |
321 | #if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) |
322 | #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) |
323 | /* |
324 | * Make dummy function to prevent NULL pointer dereferences |
325 | */ |
326 | static int platform_nv_seed_read_uninit(unsigned char *buf, size_t buf_len) |
327 | { |
328 | ((void) buf); |
329 | ((void) buf_len); |
330 | return -1; |
331 | } |
332 | |
333 | #define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit |
334 | #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ |
335 | |
336 | #if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) |
337 | /* |
338 | * Make dummy function to prevent NULL pointer dereferences |
339 | */ |
340 | static int platform_nv_seed_write_uninit(unsigned char *buf, size_t buf_len) |
341 | { |
342 | ((void) buf); |
343 | ((void) buf_len); |
344 | return -1; |
345 | } |
346 | |
347 | #define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit |
348 | #endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ |
349 | |
350 | int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) = |
351 | MBEDTLS_PLATFORM_STD_NV_SEED_READ; |
352 | int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) = |
353 | MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; |
354 | |
355 | int mbedtls_platform_set_nv_seed( |
356 | int (*nv_seed_read_func)(unsigned char *buf, size_t buf_len), |
357 | int (*nv_seed_write_func)(unsigned char *buf, size_t buf_len)) |
358 | { |
359 | mbedtls_nv_seed_read = nv_seed_read_func; |
360 | mbedtls_nv_seed_write = nv_seed_write_func; |
361 | return 0; |
362 | } |
363 | #endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ |
364 | #endif /* MBEDTLS_ENTROPY_NV_SEED */ |
365 | |
366 | #if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) |
367 | /* |
368 | * Placeholder platform setup that does nothing by default |
369 | */ |
370 | int mbedtls_platform_setup(mbedtls_platform_context *ctx) |
371 | { |
372 | (void) ctx; |
373 | |
374 | return 0; |
375 | } |
376 | |
377 | /* |
378 | * Placeholder platform teardown that does nothing by default |
379 | */ |
380 | void mbedtls_platform_teardown(mbedtls_platform_context *ctx) |
381 | { |
382 | (void) ctx; |
383 | } |
384 | #endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ |
385 | |
386 | #endif /* MBEDTLS_PLATFORM_C */ |
387 | |