LCOV - code coverage report
Current view: top level - os_stub/mbedtlslib/mbedtls/library - platform_util.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 53.8 % 13 7
Test Date: 2025-06-29 08:09:00 Functions: 66.7 % 3 2

            Line data    Source code
       1              : /*
       2              :  * Common and shared functions used by multiple modules in the Mbed TLS
       3              :  * library.
       4              :  *
       5              :  *  Copyright The Mbed TLS Contributors
       6              :  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       7              :  */
       8              : 
       9              : /*
      10              :  * Ensure gmtime_r is available even with -std=c99; must be defined before
      11              :  * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms
      12              :  * except OpenBSD, where it stops us accessing explicit_bzero.
      13              :  */
      14              : #if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
      15              : #define _POSIX_C_SOURCE 200112L
      16              : #endif
      17              : 
      18              : #if !defined(_GNU_SOURCE)
      19              : /* Clang requires this to get support for explicit_bzero */
      20              : #define _GNU_SOURCE
      21              : #endif
      22              : 
      23              : #include "common.h"
      24              : 
      25              : #include "mbedtls/platform_util.h"
      26              : #include "mbedtls/platform.h"
      27              : #include "mbedtls/threading.h"
      28              : 
      29              : #include <stddef.h>
      30              : 
      31              : #ifndef __STDC_WANT_LIB_EXT1__
      32              : #define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */
      33              : #endif
      34              : #include <string.h>
      35              : 
      36              : #if defined(_WIN32)
      37              : #include <windows.h>
      38              : #endif
      39              : 
      40              : // Detect platforms known to support explicit_bzero()
      41              : #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
      42              : #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
      43              : #elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)
      44              : #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
      45              : #endif
      46              : 
      47              : #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
      48              : 
      49              : #undef HAVE_MEMORY_SANITIZER
      50              : #if defined(__has_feature)
      51              : #if __has_feature(memory_sanitizer)
      52              : #include <sanitizer/msan_interface.h>
      53              : #define HAVE_MEMORY_SANITIZER
      54              : #endif
      55              : #endif
      56              : 
      57              : /*
      58              :  * Where possible, we try to detect the presence of a platform-provided
      59              :  * secure memset, such as explicit_bzero(), that is safe against being optimized
      60              :  * out, and use that.
      61              :  *
      62              :  * For other platforms, we provide an implementation that aims not to be
      63              :  * optimized out by the compiler.
      64              :  *
      65              :  * This implementation for mbedtls_platform_zeroize() was inspired from Colin
      66              :  * Percival's blog article at:
      67              :  *
      68              :  * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
      69              :  *
      70              :  * It uses a volatile function pointer to the standard memset(). Because the
      71              :  * pointer is volatile the compiler expects it to change at
      72              :  * any time and will not optimize out the call that could potentially perform
      73              :  * other operations on the input buffer instead of just setting it to 0.
      74              :  * Nevertheless, as pointed out by davidtgoldblatt on Hacker News
      75              :  * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
      76              :  * details), optimizations of the following form are still possible:
      77              :  *
      78              :  * if (memset_func != memset)
      79              :  *     memset_func(buf, 0, len);
      80              :  *
      81              :  * Note that it is extremely difficult to guarantee that
      82              :  * the memset() call will not be optimized out by aggressive compilers
      83              :  * in a portable way. For this reason, Mbed TLS also provides the configuration
      84              :  * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
      85              :  * mbedtls_platform_zeroize() to use a suitable implementation for their
      86              :  * platform and needs.
      87              :  */
      88              : #if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !(defined(__STDC_LIB_EXT1__) && \
      89              :     !defined(__IAR_SYSTEMS_ICC__)) \
      90              :     && !defined(_WIN32)
      91              : static void *(*const volatile memset_func)(void *, int, size_t) = memset;
      92              : #endif
      93              : 
      94              : void mbedtls_platform_zeroize(void *buf, size_t len)
      95              : {
      96              :     if (len > 0) {
      97              : #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
      98              :         explicit_bzero(buf, len);
      99              : #if defined(HAVE_MEMORY_SANITIZER)
     100              :         /* You'd think that Msan would recognize explicit_bzero() as
     101              :          * equivalent to bzero(), but it actually doesn't on several
     102              :          * platforms, including Linux (Ubuntu 20.04).
     103              :          * https://github.com/google/sanitizers/issues/1507
     104              :          * https://github.com/openssh/openssh-portable/commit/74433a19bb6f4cef607680fa4d1d7d81ca3826aa
     105              :          */
     106              :         __msan_unpoison(buf, len);
     107              : #endif
     108              : #elif defined(__STDC_LIB_EXT1__) && !defined(__IAR_SYSTEMS_ICC__)
     109              :         memset_s(buf, len, 0, len);
     110              : #elif defined(_WIN32)
     111              :         SecureZeroMemory(buf, len);
     112              : #else
     113              :         memset_func(buf, 0, len);
     114              : #endif
     115              : 
     116              : #if defined(__GNUC__)
     117              :         /* For clang and recent gcc, pretend that we have some assembly that reads the
     118              :          * zero'd memory as an additional protection against being optimised away. */
     119              : #if defined(__clang__) || (__GNUC__ >= 10)
     120              : #if defined(__clang__)
     121              : #pragma clang diagnostic push
     122              : #pragma clang diagnostic ignored "-Wvla"
     123              : #elif defined(MBEDTLS_COMPILER_IS_GCC)
     124              : #pragma GCC diagnostic push
     125              : #pragma GCC diagnostic ignored "-Wvla"
     126              : #endif
     127              :         asm volatile ("" : : "m" (*(char (*)[len]) buf) :);
     128              : #if defined(__clang__)
     129              : #pragma clang diagnostic pop
     130              : #elif defined(MBEDTLS_COMPILER_IS_GCC)
     131              : #pragma GCC diagnostic pop
     132              : #endif
     133              : #endif
     134              : #endif
     135              :     }
     136              : }
     137              : #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
     138              : 
     139      2641903 : void mbedtls_zeroize_and_free(void *buf, size_t len)
     140              : {
     141      2641903 :     if (buf != NULL) {
     142      2641903 :         mbedtls_platform_zeroize(buf, len);
     143              :     }
     144              : 
     145      2641903 :     mbedtls_free(buf);
     146      2641903 : }
     147              : 
     148              : #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
     149              : #include <time.h>
     150              : #if !defined(_WIN32) && (defined(unix) || \
     151              :     defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
     152              :     defined(__MACH__)) || defined(__midipix__))
     153              : #include <unistd.h>
     154              : #endif /* !_WIN32 && (unix || __unix || __unix__ ||
     155              :         * (__APPLE__ && __MACH__) || __midipix__) */
     156              : 
     157              : #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) ||     \
     158              :     (defined(_POSIX_THREAD_SAFE_FUNCTIONS) &&                     \
     159              :     _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))
     160              : /*
     161              :  * This is a convenience shorthand macro to avoid checking the long
     162              :  * preprocessor conditions above. Ideally, we could expose this macro in
     163              :  * platform_util.h and simply use it in platform_util.c, threading.c and
     164              :  * threading.h. However, this macro is not part of the Mbed TLS public API, so
     165              :  * we keep it private by only defining it in this file
     166              :  */
     167              : #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \
     168              :     (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
     169              : #define PLATFORM_UTIL_USE_GMTIME
     170              : #endif
     171              : 
     172              : #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
     173              :              ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
     174              :                 _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
     175              : 
     176         2375 : struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,
     177              :                                      struct tm *tm_buf)
     178              : {
     179              : #if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME)
     180              : #if defined(__STDC_LIB_EXT1__)
     181              :     return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf;
     182              : #else
     183              :     /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */
     184              :     return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL;
     185              : #endif
     186              : #elif !defined(PLATFORM_UTIL_USE_GMTIME)
     187         2375 :     return gmtime_r(tt, tm_buf);
     188              : #else
     189              :     struct tm *lt;
     190              : 
     191              : #if defined(MBEDTLS_THREADING_C)
     192              :     if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) {
     193              :         return NULL;
     194              :     }
     195              : #endif /* MBEDTLS_THREADING_C */
     196              : 
     197              :     lt = gmtime(tt);
     198              : 
     199              :     if (lt != NULL) {
     200              :         memcpy(tm_buf, lt, sizeof(struct tm));
     201              :     }
     202              : 
     203              : #if defined(MBEDTLS_THREADING_C)
     204              :     if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) {
     205              :         return NULL;
     206              :     }
     207              : #endif /* MBEDTLS_THREADING_C */
     208              : 
     209              :     return (lt == NULL) ? NULL : tm_buf;
     210              : #endif /* _WIN32 && !EFIX64 && !EFI32 */
     211              : }
     212              : #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
     213              : 
     214              : #if defined(MBEDTLS_TEST_HOOKS)
     215              : void (*mbedtls_test_hook_test_fail)(const char *, int, const char *);
     216              : #endif /* MBEDTLS_TEST_HOOKS */
     217              : 
     218              : #if defined(MBEDTLS_HAVE_TIME) && !defined(MBEDTLS_PLATFORM_MS_TIME_ALT)
     219              : 
     220              : #include <time.h>
     221              : #if !defined(_WIN32) && \
     222              :     (defined(unix) || defined(__unix) || defined(__unix__) || \
     223              :     (defined(__APPLE__) && defined(__MACH__)) || defined(__HAIKU__) || defined(__midipix__))
     224              : #include <unistd.h>
     225              : #endif \
     226              :     /* !_WIN32 && (unix || __unix || __unix__ || (__APPLE__ && __MACH__) || __HAIKU__ || __midipix__) */
     227              : #if (defined(_POSIX_VERSION) && _POSIX_VERSION >= 199309L) || defined(__HAIKU__)
     228            0 : mbedtls_ms_time_t mbedtls_ms_time(void)
     229              : {
     230              :     int ret;
     231              :     struct timespec tv;
     232              :     mbedtls_ms_time_t current_ms;
     233              : 
     234              : #if defined(__linux__) && defined(CLOCK_BOOTTIME) || defined(__midipix__)
     235            0 :     ret = clock_gettime(CLOCK_BOOTTIME, &tv);
     236              : #else
     237              :     ret = clock_gettime(CLOCK_MONOTONIC, &tv);
     238              : #endif
     239            0 :     if (ret) {
     240            0 :         return time(NULL) * 1000;
     241              :     }
     242              : 
     243            0 :     current_ms = tv.tv_sec;
     244              : 
     245            0 :     return current_ms*1000 + tv.tv_nsec / 1000000;
     246              : }
     247              : #elif defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
     248              :     defined(__MINGW32__) || defined(_WIN64)
     249              : #include <windows.h>
     250              : mbedtls_ms_time_t mbedtls_ms_time(void)
     251              : {
     252              :     FILETIME ct;
     253              :     mbedtls_ms_time_t current_ms;
     254              : 
     255              :     GetSystemTimeAsFileTime(&ct);
     256              :     current_ms = ((mbedtls_ms_time_t) ct.dwLowDateTime +
     257              :                   ((mbedtls_ms_time_t) (ct.dwHighDateTime) << 32LL))/10000;
     258              :     return current_ms;
     259              : }
     260              : #else
     261              : #error "No mbedtls_ms_time available"
     262              : #endif
     263              : #endif /* MBEDTLS_HAVE_TIME && !MBEDTLS_PLATFORM_MS_TIME_ALT */
        

Generated by: LCOV version 2.0-1