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