1 // Copyright 2022 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_KEYSET_HANDLE_BUILDER_H_ 18 #define TINK_KEYSET_HANDLE_BUILDER_H_ 19 20 #include <memory> 21 #include <set> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 #include "tink/internal/keyset_handle_builder_entry.h" 27 #include "tink/key.h" 28 #include "tink/key_status.h" 29 #include "tink/keyset_handle.h" 30 #include "tink/parameters.h" 31 32 namespace crypto { 33 namespace tink { 34 35 // Creates new `KeysetHandle` objects. 36 class KeysetHandleBuilder { 37 public: 38 // Movable, but not copyable. 39 KeysetHandleBuilder(KeysetHandleBuilder&& other) = default; 40 KeysetHandleBuilder& operator=(KeysetHandleBuilder&& other) = default; 41 KeysetHandleBuilder(const KeysetHandleBuilder& other) = delete; 42 KeysetHandleBuilder& operator=(const KeysetHandleBuilder& other) = delete; 43 44 // Creates initially empty keyset handle builder. 45 KeysetHandleBuilder() = default; 46 // Creates keyset handle builder by initially moving keys from `handle`. 47 explicit KeysetHandleBuilder(const KeysetHandle& handle); 48 49 // Represents a single entry in a `KeysetHandleBuilder`. 50 class Entry { 51 public: 52 // Movable, but not copyable. 53 Entry(Entry&& other) = default; 54 Entry& operator=(Entry&& other) = default; 55 Entry(const Entry& other) = delete; 56 Entry& operator=(const Entry& other) = delete; 57 58 // Creates new KeysetHandleBuilder::Entry from a given `key`. Also, sets 59 // key `status` and whether or not the key `is_primary`. 60 static Entry CreateFromKey(std::shared_ptr<const Key> key, KeyStatus status, 61 bool is_primary); 62 63 template <typename CopyableKey> CreateFromCopyableKey(CopyableKey key,KeyStatus status,bool is_primary)64 inline static Entry CreateFromCopyableKey(CopyableKey key, KeyStatus status, 65 bool is_primary) { 66 auto copyable_key = absl::make_unique<CopyableKey>(std::move(key)); 67 return CreateFromKey(std::move(copyable_key), status, is_primary); 68 } 69 70 // Creates new KeysetHandleBuilder::Entry from given `parameters`. Also, 71 // sets key `status` and whether or not the key `is_primary`. If `id` 72 // does not have a value, then the key will be assigned a random id. 73 static Entry CreateFromParams(std::shared_ptr<const Parameters> parameters, 74 KeyStatus status, bool is_primary, 75 absl::optional<int> id = absl::nullopt); 76 77 template <typename CopyableParameters> 78 inline static Entry CreateFromCopyableParams( 79 CopyableParameters parameters, KeyStatus status, bool is_primary, 80 absl::optional<int> id = absl::nullopt) { 81 auto copyable_params = 82 absl::make_unique<CopyableParameters>(std::move(parameters)); 83 return CreateFromParams(std::move(copyable_params), status, is_primary, 84 id); 85 } 86 87 // Sets the key status of this entry. SetStatus(KeyStatus status)88 void SetStatus(KeyStatus status) { entry_->SetStatus(status); } 89 // Returns key status of this entry. GetStatus()90 KeyStatus GetStatus() const { return entry_->GetStatus(); } 91 92 // Assigns a fixed id when this keyset is built. SetFixedId(int id)93 void SetFixedId(int id) { entry_->SetFixedId(id); } 94 // Assigns an unused random id when this keyset is built. SetRandomId()95 void SetRandomId() { entry_->SetRandomId(); } 96 97 // Sets this entry as the primary key. SetPrimary()98 void SetPrimary() { entry_->SetPrimary(); } 99 // Unsets this entry as the primary key. UnsetPrimary()100 void UnsetPrimary() { entry_->UnsetPrimary(); } 101 // Returns whether or not this entry has been marked as a primary. IsPrimary()102 bool IsPrimary() const { return entry_->IsPrimary(); } 103 104 private: 105 friend class KeysetHandleBuilder; 106 Entry(std::unique_ptr<internal::KeysetHandleBuilderEntry> entry)107 explicit Entry(std::unique_ptr<internal::KeysetHandleBuilderEntry> entry) 108 : entry_(std::move(entry)) {} 109 110 // Returns whether or not this entry has a randomly assigned id. HasRandomId()111 bool HasRandomId() { 112 return entry_->GetKeyIdStrategyEnum() == 113 internal::KeyIdStrategyEnum::kRandomId; 114 } 115 GetKeyIdStrategy()116 internal::KeyIdStrategy GetKeyIdStrategy() { 117 return entry_->GetKeyIdStrategy(); 118 } 119 120 crypto::tink::util::StatusOr<google::crypto::tink::Keyset::Key> CreateKeysetKey(int id)121 CreateKeysetKey(int id) { 122 return entry_->CreateKeysetKey(id); 123 } 124 125 std::unique_ptr<internal::KeysetHandleBuilderEntry> entry_; 126 bool added_to_builder_ = false; 127 }; 128 129 // Adds an `entry` to the keyset builder. Crashes if `entry` has already been 130 // added to a keyset handle builder. 131 KeysetHandleBuilder& AddEntry(KeysetHandleBuilder::Entry entry); 132 // Removes an entry at `index` from keyset builder. 133 KeysetHandleBuilder& RemoveEntry(int index); 134 135 // Returns the number of Entry objects in this keyset builder. size()136 int size() const { return entries_.size(); } 137 138 // Returns entry from keyset builder at `index`. 139 KeysetHandleBuilder::Entry& operator[](int index) { return entries_[index]; } 140 141 // Creates a new `KeysetHandle` object. 142 // 143 // Note: Since KeysetHandleBuilder::Entry objects might have randomly 144 // generated IDs, Build() can only be called once on a single 145 // KeysetHandleBuilder object. Otherwise, the KeysetHandleBuilder::Entry 146 // IDs would randomly change for each call to Build(), which would result 147 // in incompatible keysets. 148 crypto::tink::util::StatusOr<KeysetHandle> Build(); 149 150 private: 151 // Select the next key id based on the given strategy. 152 crypto::tink::util::StatusOr<int> NextIdFromKeyIdStrategy( 153 internal::KeyIdStrategy strategy, const std::set<int>& ids_so_far); 154 155 // Unset primary flag on all entries. 156 void ClearPrimary(); 157 158 // Verify that entries with fixed IDs do not follow entries with random IDs. 159 crypto::tink::util::Status CheckIdAssignments(); 160 161 std::vector<KeysetHandleBuilder::Entry> entries_; 162 163 bool build_called_ = false; 164 }; 165 166 } // namespace tink 167 } // namespace crypto 168 169 #endif // TINK_KEYSET_HANDLE_BUILDER_H_ 170