From 58daf40bad33535ea1e931c9fc6ed409aee3e865 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Thu, 21 Dec 2017 22:00:34 +0100 Subject: [PATCH] Add functions to securely fill memory with zeros. Various places are using "memset(ptr, 0, size)" which might get optimized away by the compiler if "ptr" is not used afterwards. The new functions can be used to securely clear memory instead. Bug: None Change-Id: I067a51d17ff84d95dc4934d46a24027fbcb4825d Reviewed-on: https://webrtc-review.googlesource.com/35500 Reviewed-by: Karl Wiberg Commit-Queue: Joachim Bauch Cr-Commit-Position: refs/heads/master@{#21706} --- rtc_base/BUILD.gn | 5 +++ rtc_base/zero_memory.cc | 36 ++++++++++++++++++++++ rtc_base/zero_memory.h | 33 ++++++++++++++++++++ rtc_base/zero_memory_unittest.cc | 52 ++++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+) create mode 100644 rtc_base/zero_memory.cc create mode 100644 rtc_base/zero_memory.h create mode 100644 rtc_base/zero_memory_unittest.cc diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 0b8e9ae0e9..c665e03914 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -549,6 +549,7 @@ rtc_static_library("rtc_base_generic") { ":checks", ":stringutils", "..:webrtc_common", + "../api:array_view", "../api:optional", ] public_deps = [ @@ -655,6 +656,8 @@ rtc_static_library("rtc_base_generic") { "stream.h", "thread.cc", "thread.h", + "zero_memory.cc", + "zero_memory.h", ] visibility = [ @@ -1090,6 +1093,7 @@ if (rtc_include_tests) { "stream_unittest.cc", "testclient_unittest.cc", "thread_unittest.cc", + "zero_memory_unittest.cc", ] if (is_win) { sources += [ @@ -1110,6 +1114,7 @@ if (rtc_include_tests) { ":rtc_base_tests_main", ":rtc_base_tests_utils", ":stringutils", + "../api:array_view", "../api:optional", "../test:test_support", ] diff --git a/rtc_base/zero_memory.cc b/rtc_base/zero_memory.cc new file mode 100644 index 0000000000..63600b8d2e --- /dev/null +++ b/rtc_base/zero_memory.cc @@ -0,0 +1,36 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#if defined(WEBRTC_WIN) +#include +#else +#include +#endif + +#include "rtc_base/checks.h" +#include "rtc_base/zero_memory.h" + +namespace rtc { + +// Code and comment taken from "OPENSSL_cleanse" of BoringSSL. +void ExplicitZeroMemory(void* ptr, size_t len) { + RTC_DCHECK(ptr || !len); +#if defined(WEBRTC_WIN) + SecureZeroMemory(ptr, len); +#else + memset(ptr, 0, len); + /* As best as we can tell, this is sufficient to break any optimisations that + might try to eliminate "superfluous" memsets. If there's an easy way to + detect memset_s, it would be better to use that. */ + __asm__ __volatile__("" : : "r"(ptr) : "memory"); // NOLINT +#endif +} + +} // namespace rtc diff --git a/rtc_base/zero_memory.h b/rtc_base/zero_memory.h new file mode 100644 index 0000000000..cb4646c1fe --- /dev/null +++ b/rtc_base/zero_memory.h @@ -0,0 +1,33 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef RTC_BASE_ZERO_MEMORY_H_ +#define RTC_BASE_ZERO_MEMORY_H_ + +#include + +#include "api/array_view.h" + +namespace rtc { + +// Fill memory with zeros in a way that the compiler doesn't optimize it away +// even if the pointer is not used afterwards. +void ExplicitZeroMemory(void* ptr, size_t len); + +template ::value && + std::is_trivial::value>::type* = nullptr> +void ExplicitZeroMemory(rtc::ArrayView a) { + ExplicitZeroMemory(a.data(), a.size()); +} + +} // namespace rtc + +#endif // RTC_BASE_ZERO_MEMORY_H_ diff --git a/rtc_base/zero_memory_unittest.cc b/rtc_base/zero_memory_unittest.cc new file mode 100644 index 0000000000..0f496705e7 --- /dev/null +++ b/rtc_base/zero_memory_unittest.cc @@ -0,0 +1,52 @@ +/* + * Copyright 2017 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "rtc_base/zero_memory.h" + +#include "api/array_view.h" +#include "rtc_base/buffer.h" +#include "rtc_base/gunit.h" + +namespace rtc { + +TEST(ZeroMemoryTest, TestZeroMemory) { + static const size_t kBufferSize = 32; + uint8_t buffer[kBufferSize]; + for (size_t i = 0; i < kBufferSize; i++) { + buffer[i] = static_cast(i + 1); + } + ExplicitZeroMemory(buffer, sizeof(buffer)); + for (size_t i = 0; i < kBufferSize; i++) { + EXPECT_EQ(buffer[i], 0); + } +} + +TEST(ZeroMemoryTest, TestZeroArrayView) { + static const size_t kBufferSize = 32; + uint8_t buffer[kBufferSize]; + for (size_t i = 0; i < kBufferSize; i++) { + buffer[i] = static_cast(i + 1); + } + ExplicitZeroMemory(rtc::ArrayView(buffer, sizeof(buffer))); + for (size_t i = 0; i < kBufferSize; i++) { + EXPECT_EQ(buffer[i], 0); + } +} + +// While this test doesn't actually test anything, it can be used to check +// the compiler output to make sure the call to "ExplicitZeroMemory" is not +// optimized away. +TEST(ZeroMemoryTest, TestZeroMemoryUnused) { + static const size_t kBufferSize = 32; + uint8_t buffer[kBufferSize]; + ExplicitZeroMemory(buffer, sizeof(buffer)); +} + +} // namespace rtc