| // Copyright 2024 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "crypto/process_bound_string.h" |
| |
| #include "base/containers/span.h" |
| #include "build/build_config.h" |
| |
| #if BUILDFLAG(IS_WIN) |
| #include <windows.h> |
| |
| #include <dpapi.h> |
| |
| #include "base/process/memory.h" |
| #include "base/trace_event/trace_event.h" |
| #else |
| #include "third_party/boringssl/src/include/openssl/mem.h" |
| #endif // BUILDFLAG(IS_WIN) |
| |
| namespace crypto::internal { |
| |
| #if BUILDFLAG(IS_WIN) |
| constexpr char const* kTraceCategory = |
| TRACE_DISABLED_BY_DEFAULT("crypto.dpapi"); |
| |
| static_assert(CRYPTPROTECTMEMORY_BLOCK_SIZE > 0 && |
| (CRYPTPROTECTMEMORY_BLOCK_SIZE & |
| (CRYPTPROTECTMEMORY_BLOCK_SIZE - 1)) == 0, |
| "CRYPTPROTECTMEMORY_BLOCK_SIZE must be a power of two"); |
| #endif // BUILDFLAG(IS_WIN) |
| |
| size_t MaybeRoundUp(size_t size) { |
| #if BUILDFLAG(IS_WIN) |
| return (size + CRYPTPROTECTMEMORY_BLOCK_SIZE - 1u) & |
| ~(CRYPTPROTECTMEMORY_BLOCK_SIZE - 1u); |
| #else |
| return size; |
| #endif // BUILDFLAG(IS_WIN) |
| } |
| |
| bool MaybeEncryptBuffer(base::span<uint8_t> buffer) { |
| #if BUILDFLAG(IS_WIN) |
| TRACE_EVENT0(kTraceCategory, "ProcessBoundString::EncryptBuffer"); |
| if (::CryptProtectMemory(buffer.data(), buffer.size(), |
| CRYPTPROTECTMEMORY_SAME_PROCESS)) { |
| return true; |
| } |
| #endif // BUILDFLAG(IS_WIN) |
| return false; |
| } |
| |
| bool MaybeDecryptBuffer(base::span<uint8_t> buffer) { |
| #if BUILDFLAG(IS_WIN) |
| TRACE_EVENT0(kTraceCategory, "ProcessBoundString::DecryptBuffer"); |
| if (::CryptUnprotectMemory(buffer.data(), buffer.size(), |
| CRYPTPROTECTMEMORY_SAME_PROCESS)) { |
| return true; |
| } |
| static constexpr DWORD kOomErrors[] = { |
| ERROR_WORKING_SET_QUOTA, |
| ERROR_NO_SYSTEM_RESOURCES, |
| }; |
| for (const auto error = ::GetLastError(); const auto oom_error : kOomErrors) { |
| if (error == oom_error) { |
| base::TerminateBecauseOutOfMemory(/*size=*/0); |
| } |
| } |
| #endif // BUILDFLAG(IS_WIN) |
| return false; |
| } |
| |
| void SecureZeroBuffer(base::span<uint8_t> buffer) { |
| #if BUILDFLAG(IS_WIN) |
| ::SecureZeroMemory(buffer.data(), buffer.size()); |
| #else |
| OPENSSL_cleanse(buffer.data(), buffer.size()); |
| #endif // BUILDFLAG(IS_WIN) |
| } |
| |
| } // namespace crypto::internal |