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