Movatterモバイル変換


[0]ホーム

URL:


Google Git
Sign in
chromium /chromium /src /refs/heads/main /. /crypto /process_bound_string.h
blob: 729f75126d8edfa19cb449577465f6108fa89635 [file] [log] [blame]
Will Harrisf6cca0582024-10-11 23:53:50[diff] [blame]1// Copyright 2024 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CRYPTO_PROCESS_BOUND_STRING_H_
6#define CRYPTO_PROCESS_BOUND_STRING_H_
7
8#include<string>
9#include<vector>
10
11#include"base/check.h"
12#include"base/containers/span.h"
13#include"base/feature_list.h"
14#include"base/gtest_prod_util.h"
15#include"crypto/crypto_export.h"
16#include"crypto/features.h"
17
18namespace crypto{
19
20namespaceinternal{
21
22// Maybe round the size of the data to a size needed for the encrypt or decrypt
23// operation. Returns the new size, or `size` if no rounding up is needed.
24CRYPTO_EXPORTsize_tMaybeRoundUp(size_t size);
25
26// Maybe encrypt a buffer, in place. Returns true if the buffer was successfully
27// encrypted or false if unsupported by the platform or failed to encrypt.
28CRYPTO_EXPORTboolMaybeEncryptBuffer(base::span<uint8_t> buffer);
29
30// Maybe decrypt a buffer, in place. Returns true if the buffer was successfully
31// decrypted or false if unsupported by the platform or failed to decrypt.
32CRYPTO_EXPORTboolMaybeDecryptBuffer(base::span<uint8_t> buffer);
33
34// Securely zero a buffer using a platform specific method.
35CRYPTO_EXPORTvoidSecureZeroBuffer(base::span<uint8_t> buffer);
36
37}// namespace internal
38
39// SecureAllocator is used by the SecureString variants below to clear the
40// memory when the string moves out of scope.
41template<typename T>
42struct CRYPTO_EXPORTSecureAllocator{
43using value_type= T;
44
45SecureAllocator() noexcept=default;
46
47 T* allocate(std::size_t n){return std::allocator<T>().allocate(n);}
48
49void deallocate(T* p, std::size_t n) noexcept{
50if(p){
51// SAFETY: deallocate() has a fixed prototype from the std library, and
52// passes an unsafe buffer, so convert it to a base::span here.
53internal::SecureZeroBuffer(UNSAFE_BUFFERS(
54base::span<uint8_t>(reinterpret_cast<uint8_t*>(p), n*sizeof(T))));
55 std::allocator<T>().deallocate(p, n);
56}
57}
58};
59
60// On supported platforms, a process bound string cannot have its content read
61// by other processes on the system. On unsupported platforms it provides no
62// difference over a native string except it does more copies.
63template<typenameStringType>
64class CRYPTO_EXPORTProcessBound{
65public:
66usingCharType=typenameStringType::value_type;
67
68ProcessBound(constProcessBound& other)=default;
69ProcessBound(ProcessBound&& other)=default;
70ProcessBound&operator=(constProcessBound& other)=default;
71ProcessBound&operator=(ProcessBound&& other)=default;
72
73// Create a process bound string. Takes a copy of the string passed in.
74explicitProcessBound(constStringType& value)
75: original_size_(value.size()){
76 std::vector<CharType> data(value.begin(), value.end());
77if(base::FeatureList::IsEnabled(
78 crypto::features::kProcessBoundStringEncryption)){
79 data.resize(internal::MaybeRoundUp(data.size()));
80 encrypted_=
81internal::MaybeEncryptBuffer(base::as_writable_byte_span(data));
82}
83 maybe_encrypted_data_= std::move(data);
84}
85
86~ProcessBound()=default;
87
88// Return the decrypted string.
89StringType value()const{returnStringType(secure_value());}
90
91// Return the decrypted string as a string that attempts to wipe itself after
92// use. Prefer over calling `value()` if caller can support it.
93 std::basic_string<CharType,
94 std::char_traits<CharType>,
95SecureAllocator<CharType>>
96 secure_value()const{
97if(!encrypted_){
98return std::basic_string<CharType, std::char_traits<CharType>,
99SecureAllocator<CharType>>(
100 maybe_encrypted_data_.data(), original_size_);
101}
102
103// Copy to decrypt in-place.
104 std::basic_string<CharType, std::char_traits<CharType>,
105SecureAllocator<CharType>>
106 decrypted(maybe_encrypted_data_.begin(), maybe_encrypted_data_.end());
107// Attempt to avoid Small String Optimization (SSO) by reserving a larger
108// allocation than the SSO default, forcing a dynamic allocation to occur,
109// before any decrypted data is written to the string. This value was
110// determined empirically.
111constexprsize_t kSSOMaxSize=64u;
112if(decrypted.size()< kSSOMaxSize){
113 decrypted.reserve(kSSOMaxSize);
114}
115 CHECK(internal::MaybeDecryptBuffer(base::as_writable_byte_span(decrypted)));
116 decrypted.resize(original_size_);
117return decrypted;
118}
119
120size_t size()const{return original_size_;}
121bool empty()const{return size()==0;}
122
123private:
124 FRIEND_TEST_ALL_PREFIXES(ProcessBoundFeatureTest,Encryption);
125 std::vector<CharType> maybe_encrypted_data_;
126size_t original_size_;
127bool encrypted_=false;
128};
129
130usingProcessBoundString=ProcessBound<std::string>;
131usingProcessBoundWString=ProcessBound<std::wstring>;
132usingProcessBoundU16String=ProcessBound<std::u16string>;
133
134// SecureString variants here attempt to clean memory for the string data when
135// the string goes out of scope. However, while in memory it can be read, and if
136// copied somewhere else, the memory can also be read. This is a defense in
137// depth hardening and not meant to provide strong security guarantees.
138usingSecureString=
139 std::basic_string<std::string::value_type,
140 std::char_traits<std::string::value_type>,
141SecureAllocator<std::string::value_type>>;
142usingSecureWString=
143 std::basic_string<std::wstring::value_type,
144 std::char_traits<std::wstring::value_type>,
145SecureAllocator<std::wstring::value_type>>;
146usingSecureU16String=
147 std::basic_string<std::u16string::value_type,
148 std::char_traits<std::u16string::value_type>,
149SecureAllocator<std::u16string::value_type>>;
150
151}// namespace crypto
152
153#endif// CRYPTO_PROCESS_BOUND_STRING_H_

[8]ページ先頭

©2009-2025 Movatter.jp