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