LCOV - code coverage report
Current view: top level - externals/mbedtls/library - platform_util.c (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 10 10
Test Date: 2026-01-29 09:48:10 Functions: 100.0 % 2 2
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50.0 % 4 2

             Branch data     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                 :      330262 : void mbedtls_platform_zeroize(void *buf, size_t len)
      95                 :             : {
      96         [ +  - ]:      330262 :     if (len > 0) {
      97                 :             : #if defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO)
      98                 :      330262 :         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                 :      330262 :         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                 :      330262 : }
     137                 :             : #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
     138                 :             : 
     139                 :      288223 : void mbedtls_zeroize_and_free(void *buf, size_t len)
     140                 :             : {
     141         [ +  - ]:      288223 :     if (buf != NULL) {
     142                 :      288223 :         mbedtls_platform_zeroize(buf, len);
     143                 :             :     }
     144                 :             : 
     145                 :      288223 :     mbedtls_free(buf);
     146                 :      288223 : }
     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                 :             : 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                 :             :     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                 :             : 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                 :             :     ret = clock_gettime(CLOCK_BOOTTIME, &tv);
     236                 :             : #else
     237                 :             :     ret = clock_gettime(CLOCK_MONOTONIC, &tv);
     238                 :             : #endif
     239                 :             :     if (ret) {
     240                 :             :         return time(NULL) * 1000;
     241                 :             :     }
     242                 :             : 
     243                 :             :     current_ms = tv.tv_sec;
     244                 :             : 
     245                 :             :     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