xref: /aosp_15_r20/external/tink/cc/util/secret_data.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ///////////////////////////////////////////////////////////////////////////////
16 
17 #ifndef TINK_UTIL_SECRET_DATA_H_
18 #define TINK_UTIL_SECRET_DATA_H_
19 
20 #include <memory>
21 #include <string>
22 #include <type_traits>
23 #include <vector>
24 
25 #include "absl/strings/string_view.h"
26 #include "tink/util/secret_data_internal.h"
27 
28 namespace crypto {
29 namespace tink {
30 namespace util {
31 namespace internal {
32 
33 template <typename T>
34 struct SanitizingDeleter {
operatorSanitizingDeleter35   void operator()(T* ptr) {
36     ptr->~T();  // Invoke destructor. Must do this before sanitize.
37     SanitizingAllocator<T>().deallocate(ptr, 1);
38   }
39 };
40 
41 }  // namespace internal
42 
43 // Stores secret (sensitive) data and makes sure it's marked as such and
44 // destroyed in a safe way.
45 // This should be the first choice when handling key/key derived values.
46 //
47 // Example:
48 // class MyCryptoPrimitive {
49 //  public:
50 //   MyCryptoPrimitive(absl::string_view key_value) :
51 //     key_(SecretDataFromStringView(key_value)) {}
52 //   [...]
53 //  private:
54 //   const util::SecretData key_;
55 // }
56 using SecretData = std::vector<uint8_t, internal::SanitizingAllocator<uint8_t>>;
57 
58 // Stores secret (sensitive) object and makes sure it's marked as such and
59 // destroyed in a safe way.
60 // SecretUniquePtr MUST be constructed using MakeSecretUniquePtr function.
61 // Generally SecretUniquePtr should be used iff SecretData is unsuitable.
62 //
63 // Example:
64 // class MyCryptoPrimitive {
65 //  public:
66 //   MyEncryptionPrimitive(absl::string_view key_value) {
67 //     AES_set_encrypt_key(key_value.data(), key_value.size() * 8, key_.get());
68 //   }
69 //   [...]
70 //  private:
71 //   util::SecretUniquePtr<AES_KEY> key_ = util::MakeSecretUniquePtr<AES_KEY>();
72 // }
73 //
74 // NOTE: SecretUniquePtr<T> will only protect the data which is stored in the
75 // memory which a T object takes on the stack. In particular, std::string and
76 // std::vector SHOULD NOT be used as arguments of T: they allocate memory
77 // on the heap, and hence the data stored in them will NOT be protected.
78 template <typename T>
79 class SecretUniquePtr {
80  private:
81   using Value = std::unique_ptr<T, internal::SanitizingDeleter<T>>;
82 
83  public:
84   using pointer = typename Value::pointer;
85   using element_type = typename Value::element_type;
86   using deleter_type = typename Value::deleter_type;
87 
88   SecretUniquePtr() = default;
89 
get()90   pointer get() const { return value_.get(); }
get_deleter()91   deleter_type& get_deleter() { return value_.get_deleter(); }
get_deleter()92   const deleter_type& get_deleter() const { return value_.get_deleter(); }
swap(SecretUniquePtr & other)93   void swap(SecretUniquePtr& other) { value_.swap(other.value_); }
reset()94   void reset() { value_.reset(); }
95 
96   typename std::add_lvalue_reference<T>::type operator*() const {
97     return value_.operator*();
98   }
99   pointer operator->() const { return value_.operator->(); }
100   explicit operator bool() const { return value_.operator bool(); }
101 
102  private:
103   template <typename S, typename... Args>
104   friend SecretUniquePtr<S> MakeSecretUniquePtr(Args&&... args);
SecretUniquePtr(Value && value)105   explicit SecretUniquePtr(Value&& value) : value_(std::move(value)) {}
106   Value value_;
107 };
108 
109 template <typename T, typename... Args>
MakeSecretUniquePtr(Args &&...args)110 SecretUniquePtr<T> MakeSecretUniquePtr(Args&&... args) {
111   T* ptr = internal::SanitizingAllocator<T>().allocate(1);
112   new (ptr)
113       T(std::forward<Args>(args)...);  // Invoke constructor "placement new"
114   return SecretUniquePtr<T>({ptr, internal::SanitizingDeleter<T>()});
115 }
116 
117 // Convenience conversion functions
SecretDataAsStringView(const SecretData & secret)118 inline absl::string_view SecretDataAsStringView(const SecretData& secret) {
119   return {reinterpret_cast<const char*>(secret.data()), secret.size()};
120 }
121 
SecretDataFromStringView(absl::string_view secret)122 inline SecretData SecretDataFromStringView(absl::string_view secret) {
123   return {secret.begin(), secret.end()};
124 }
125 
126 // The same as SecretUniquePtr, but with value semantics.
127 //
128 // NOTE: SecretValue<T> will only protect the data which is stored in the
129 // memory which a T object takes on the stack. In particular, std::string and
130 // std::vector SHOULD NOT be used as arguments of T: they allocate memory
131 // on the heap, and hence the data stored in them will NOT be protected.
132 template <typename T>
133 class SecretValue {
134  public:
135   explicit SecretValue(T t = T())
ptr_(MakeSecretUniquePtr<T> (std::move (t)))136       : ptr_(MakeSecretUniquePtr<T>(std::move(t))) {}
137 
SecretValue(const SecretValue & other)138   SecretValue(const SecretValue& other) {
139     ptr_ = MakeSecretUniquePtr<T>(*other.ptr_);
140   }
141 
142   SecretValue& operator=(const SecretValue& other) {
143     *ptr_ = *other.ptr_;
144     return *this;
145   }
146 
value()147   T& value() { return *ptr_; }
value()148   const T& value() const { return *ptr_; }
149 
150  private:
151   SecretUniquePtr<T> ptr_;
152 };
153 
SafeZeroMemory(void * ptr,std::size_t size)154 inline void SafeZeroMemory(void* ptr, std::size_t size) {
155   internal::SafeZeroMemory(ptr, size);
156 }
157 
SafeZeroString(std::string * str)158 inline void SafeZeroString(std::string* str) {
159   SafeZeroMemory(&(*str)[0], str->size());
160 }
161 
162 }  // namespace util
163 }  // namespace tink
164 }  // namespace crypto
165 
166 #endif  // TINK_UTIL_SECRET_DATA_H_
167