xref: /aosp_15_r20/external/tink/cc/util/secret_proto.h (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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_PROTO_H_
18 #define TINK_UTIL_SECRET_PROTO_H_
19 
20 #include <memory>
21 #include <utility>
22 
23 #include "google/protobuf/arena.h"
24 #include "absl/memory/memory.h"
25 #include "tink/util/secret_data.h"
26 #include "tink/util/status.h"
27 #include "tink/util/statusor.h"
28 
29 namespace crypto {
30 namespace tink {
31 namespace util {
32 
33 namespace internal {
34 
SecretArenaOptions()35 inline google::protobuf::ArenaOptions SecretArenaOptions() {
36   google::protobuf::ArenaOptions options;
37   options.block_alloc = [](size_t sz) {
38     return SanitizingAllocator<void>().allocate(sz);
39   };
40   options.block_dealloc = [](void* ptr, size_t sz) {
41     return SanitizingAllocator<void>().deallocate(ptr, sz);
42   };
43   return options;
44 }
45 
46 }  // namespace internal
47 
48 // Stores secret (sensitive) protobuf and makes sure it's marked as such and
49 // destroyed in a safe way.
50 //
51 // Note: Currently does not protect fields of type "string" and "bytes"
52 // (depends on https://github.com/protocolbuffers/protobuf/issues/1896)
53 template <typename T>
54 class SecretProto {
55  public:
ParseFromSecretData(const SecretData & data)56   static StatusOr<SecretProto<T>> ParseFromSecretData(const SecretData& data) {
57     SecretProto<T> proto;
58     if (!proto->ParseFromArray(data.data(), data.size())) {
59       return Status(absl::StatusCode::kInternal, "Could not parse proto");
60     }
61     return proto;
62   }
63 
64   SecretProto() = default;
65 
SecretProto(const SecretProto & other)66   SecretProto(const SecretProto& other) { *value_ = *other.value_; }
67 
SecretProto(SecretProto && other)68   SecretProto(SecretProto&& other) { *this = std::move(other); }
69 
SecretProto(const T & value)70   explicit SecretProto(const T& value) { *value_ = value; }
71 
72   SecretProto& operator=(const SecretProto& other) {
73     *value_ = *other.value_;
74     return *this;
75   }
76 
77   SecretProto& operator=(SecretProto&& other) {
78     using std::swap;
79     swap(arena_, other.arena_);
80     swap(value_, other.value_);
81     return *this;
82   }
83 
get()84   inline T* get() { return value_; }
85 
86   // Accessors to the underlying message.
87   inline T* operator->() { return value_; }
88   inline const T* operator->() const { return value_; }
89 
90   inline T& operator*() { return *value_; }
91   inline const T& operator*() const { return *value_; }
92 
SerializeAsSecretData()93   StatusOr<SecretData> SerializeAsSecretData() const {
94     SecretData data(value_->ByteSizeLong());
95     if (!value_->SerializeToArray(data.data(), data.size())) {
96       return Status(absl::StatusCode::kInternal, "Could not serialize proto");
97     }
98     return data;
99   }
100 
101  private:
102   std::unique_ptr<google::protobuf::Arena> arena_ =
103       absl::make_unique<google::protobuf::Arena>(internal::SecretArenaOptions());
104   T* value_ = google::protobuf::Arena::CreateMessage<T>(arena_.get());
105 };
106 
107 }  // namespace util
108 }  // namespace tink
109 }  // namespace crypto
110 
111 #endif  // TINK_UTIL_SECRET_PROTO_H_
112