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) 28static 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) 39static 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 47static void * (*mbedtls_calloc_func)(size_t, size_t) = MBEDTLS_PLATFORM_STD_CALLOC; 48static void (*mbedtls_free_func)(void *) = MBEDTLS_PLATFORM_STD_FREE; 49 50void *mbedtls_calloc(size_t nmemb, size_t size) 51{ 52 return (*mbedtls_calloc_func)(nmemb, size); 53} 54 55void mbedtls_free(void *ptr) 56{ 57 (*mbedtls_free_func)(ptr); 58} 59 60int 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> 73int 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 */ 91static 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 103int (*mbedtls_snprintf)(char *s, size_t n, 104 const char *format, 105 ...) = MBEDTLS_PLATFORM_STD_SNPRINTF; 106 107int 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> 118int 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 */ 146static 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 159int (*mbedtls_vsnprintf)(char *s, size_t n, 160 const char *format, 161 va_list arg) = MBEDTLS_PLATFORM_STD_VSNPRINTF; 162 163int 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 */ 177static 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 186int (*mbedtls_printf)(const char *, ...) = MBEDTLS_PLATFORM_STD_PRINTF; 187 188int 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 */ 200static 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 210int (*mbedtls_fprintf)(FILE *, const char *, ...) = 211 MBEDTLS_PLATFORM_STD_FPRINTF; 212 213int 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 */ 225static 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 */ 233void (*mbedtls_setbuf)(FILE *stream, char *buf) = MBEDTLS_PLATFORM_STD_SETBUF; 234 235int 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 */ 247static 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 255void (*mbedtls_exit)(int status) = MBEDTLS_PLATFORM_STD_EXIT; 256 257int 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 */ 271static 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 280mbedtls_time_t (*mbedtls_time)(mbedtls_time_t *timer) = MBEDTLS_PLATFORM_STD_TIME; 281 282int 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 */ 296int 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 318int 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 */ 345static 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 */ 359static 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 369int (*mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) = 370 MBEDTLS_PLATFORM_STD_NV_SEED_READ; 371int (*mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) = 372 MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; 373 374int 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 */ 389int 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 */ 399void 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