platform_util.c 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  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
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  9. * not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  16. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. /*
  21. * Ensure gmtime_r is available even with -std=c99; must be defined before
  22. * mbedtls_config.h, which pulls in glibc's features.h. Harmless on other platforms
  23. * except OpenBSD, where it stops us accessing explicit_bzero.
  24. */
  25. #if !defined(_POSIX_C_SOURCE) && !defined(__OpenBSD__)
  26. #define _POSIX_C_SOURCE 200112L
  27. #endif
  28. #if !defined(_GNU_SOURCE)
  29. /* Clang requires this to get support for explicit_bzero */
  30. #define _GNU_SOURCE
  31. #endif
  32. #include "common.h"
  33. #include "mbedtls/platform_util.h"
  34. #include "mbedtls/platform.h"
  35. #include "mbedtls/threading.h"
  36. #include <stddef.h>
  37. #ifndef __STDC_WANT_LIB_EXT1__
  38. #define __STDC_WANT_LIB_EXT1__ 1 /* Ask for the C11 gmtime_s() and memset_s() if available */
  39. #endif
  40. #include <string.h>
  41. #if defined(_WIN32)
  42. #include <windows.h>
  43. #endif
  44. // Detect platforms known to support explicit_bzero()
  45. #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 25)
  46. #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
  47. #elif (defined(__FreeBSD__) && (__FreeBSD_version >= 1100037)) || defined(__OpenBSD__)
  48. #define MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO 1
  49. #endif
  50. #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT)
  51. #undef HAVE_MEMORY_SANITIZER
  52. #if defined(__has_feature)
  53. #if __has_feature(memory_sanitizer)
  54. #include <sanitizer/msan_interface.h>
  55. #define HAVE_MEMORY_SANITIZER
  56. #endif
  57. #endif
  58. /*
  59. * Where possible, we try to detect the presence of a platform-provided
  60. * secure memset, such as explicit_bzero(), that is safe against being optimized
  61. * out, and use that.
  62. *
  63. * For other platforms, we provide an implementation that aims not to be
  64. * optimized out by the compiler.
  65. *
  66. * This implementation for mbedtls_platform_zeroize() was inspired from Colin
  67. * Percival's blog article at:
  68. *
  69. * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html
  70. *
  71. * It uses a volatile function pointer to the standard memset(). Because the
  72. * pointer is volatile the compiler expects it to change at
  73. * any time and will not optimize out the call that could potentially perform
  74. * other operations on the input buffer instead of just setting it to 0.
  75. * Nevertheless, as pointed out by davidtgoldblatt on Hacker News
  76. * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for
  77. * details), optimizations of the following form are still possible:
  78. *
  79. * if (memset_func != memset)
  80. * memset_func(buf, 0, len);
  81. *
  82. * Note that it is extremely difficult to guarantee that
  83. * the memset() call will not be optimized out by aggressive compilers
  84. * in a portable way. For this reason, Mbed TLS also provides the configuration
  85. * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure
  86. * mbedtls_platform_zeroize() to use a suitable implementation for their
  87. * platform and needs.
  88. */
  89. #if !defined(MBEDTLS_PLATFORM_HAS_EXPLICIT_BZERO) && !defined(__STDC_LIB_EXT1__) \
  90. && !defined(_WIN32)
  91. static void *(*const volatile memset_func)(void *, int, size_t) = memset;
  92. #endif
  93. void mbedtls_platform_zeroize(void *buf, size_t len)
  94. {
  95. MBEDTLS_INTERNAL_VALIDATE(len == 0 || buf != NULL);
  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__)
  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. }
  117. #endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */
  118. #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT)
  119. #include <time.h>
  120. #if !defined(_WIN32) && (defined(unix) || \
  121. defined(__unix) || defined(__unix__) || (defined(__APPLE__) && \
  122. defined(__MACH__)))
  123. #include <unistd.h>
  124. #endif /* !_WIN32 && (unix || __unix || __unix__ ||
  125. * (__APPLE__ && __MACH__)) */
  126. #if !((defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L) || \
  127. (defined(_POSIX_THREAD_SAFE_FUNCTIONS) && \
  128. _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L))
  129. /*
  130. * This is a convenience shorthand macro to avoid checking the long
  131. * preprocessor conditions above. Ideally, we could expose this macro in
  132. * platform_util.h and simply use it in platform_util.c, threading.c and
  133. * threading.h. However, this macro is not part of the Mbed TLS public API, so
  134. * we keep it private by only defining it in this file
  135. */
  136. #if !(defined(_WIN32) && !defined(EFIX64) && !defined(EFI32)) || \
  137. (defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR))
  138. #define PLATFORM_UTIL_USE_GMTIME
  139. #endif
  140. #endif /* !( ( defined(_POSIX_VERSION) && _POSIX_VERSION >= 200809L ) || \
  141. ( defined(_POSIX_THREAD_SAFE_FUNCTIONS ) && \
  142. _POSIX_THREAD_SAFE_FUNCTIONS >= 200112L ) ) */
  143. struct tm *mbedtls_platform_gmtime_r(const mbedtls_time_t *tt,
  144. struct tm *tm_buf)
  145. {
  146. #if defined(_WIN32) && !defined(PLATFORM_UTIL_USE_GMTIME)
  147. #if defined(__STDC_LIB_EXT1__)
  148. return (gmtime_s(tt, tm_buf) == 0) ? NULL : tm_buf;
  149. #else
  150. /* MSVC and mingw64 argument order and return value are inconsistent with the C11 standard */
  151. return (gmtime_s(tm_buf, tt) == 0) ? tm_buf : NULL;
  152. #endif
  153. #elif !defined(PLATFORM_UTIL_USE_GMTIME)
  154. return gmtime_r(tt, tm_buf);
  155. #else
  156. struct tm *lt;
  157. #if defined(MBEDTLS_THREADING_C)
  158. if (mbedtls_mutex_lock(&mbedtls_threading_gmtime_mutex) != 0) {
  159. return NULL;
  160. }
  161. #endif /* MBEDTLS_THREADING_C */
  162. lt = gmtime(tt);
  163. if (lt != NULL) {
  164. memcpy(tm_buf, lt, sizeof(struct tm));
  165. }
  166. #if defined(MBEDTLS_THREADING_C)
  167. if (mbedtls_mutex_unlock(&mbedtls_threading_gmtime_mutex) != 0) {
  168. return NULL;
  169. }
  170. #endif /* MBEDTLS_THREADING_C */
  171. return (lt == NULL) ? NULL : tm_buf;
  172. #endif /* _WIN32 && !EFIX64 && !EFI32 */
  173. }
  174. #endif /* MBEDTLS_HAVE_TIME_DATE && MBEDTLS_PLATFORM_GMTIME_R_ALT */
  175. #if defined(MBEDTLS_TEST_HOOKS)
  176. void (*mbedtls_test_hook_test_fail)(const char *, int, const char *);
  177. #endif /* MBEDTLS_TEST_HOOKS */
  178. /*
  179. * Provide external definitions of some inline functions so that the compiler
  180. * has the option to not inline them
  181. */
  182. extern inline void mbedtls_xor(unsigned char *r,
  183. const unsigned char *a,
  184. const unsigned char *b,
  185. size_t n);
  186. extern inline uint16_t mbedtls_get_unaligned_uint16(const void *p);
  187. extern inline void mbedtls_put_unaligned_uint16(void *p, uint16_t x);
  188. extern inline uint32_t mbedtls_get_unaligned_uint32(const void *p);
  189. extern inline void mbedtls_put_unaligned_uint32(void *p, uint32_t x);
  190. extern inline uint64_t mbedtls_get_unaligned_uint64(const void *p);
  191. extern inline void mbedtls_put_unaligned_uint64(void *p, uint64_t x);