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