| // Copyright 2022 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| #ifndef TINK_KEYSET_HANDLE_BUILDER_H_ |
| #define TINK_KEYSET_HANDLE_BUILDER_H_ |
| |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "tink/internal/keyset_handle_builder_entry.h" |
| #include "tink/key.h" |
| #include "tink/key_status.h" |
| #include "tink/keyset_handle.h" |
| #include "tink/parameters.h" |
| |
| namespace crypto { |
| namespace tink { |
| |
| // Creates new `KeysetHandle` objects. |
| class KeysetHandleBuilder { |
| public: |
| // Movable, but not copyable. |
| KeysetHandleBuilder(KeysetHandleBuilder&& other) = default; |
| KeysetHandleBuilder& operator=(KeysetHandleBuilder&& other) = default; |
| KeysetHandleBuilder(const KeysetHandleBuilder& other) = delete; |
| KeysetHandleBuilder& operator=(const KeysetHandleBuilder& other) = delete; |
| |
| // Creates initially empty keyset handle builder. |
| KeysetHandleBuilder() = default; |
| // Creates keyset handle builder by initially moving keys from `handle`. |
| explicit KeysetHandleBuilder(const KeysetHandle& handle); |
| |
| // Represents a single entry in a `KeysetHandleBuilder`. |
| class Entry { |
| public: |
| // Movable, but not copyable. |
| Entry(Entry&& other) = default; |
| Entry& operator=(Entry&& other) = default; |
| Entry(const Entry& other) = delete; |
| Entry& operator=(const Entry& other) = delete; |
| |
| // Creates new KeysetHandleBuilder::Entry from a given `key`. Also, sets |
| // key `status` and whether or not the key `is_primary`. |
| static Entry CreateFromKey(std::shared_ptr<const Key> key, KeyStatus status, |
| bool is_primary); |
| |
| template <typename CopyableKey> |
| inline static Entry CreateFromCopyableKey(CopyableKey key, KeyStatus status, |
| bool is_primary) { |
| auto copyable_key = absl::make_unique<CopyableKey>(std::move(key)); |
| return CreateFromKey(std::move(copyable_key), status, is_primary); |
| } |
| |
| // Creates new KeysetHandleBuilder::Entry from given `parameters`. Also, |
| // sets key `status` and whether or not the key `is_primary`. If `id` |
| // does not have a value, then the key will be assigned a random id. |
| static Entry CreateFromParams(std::shared_ptr<const Parameters> parameters, |
| KeyStatus status, bool is_primary, |
| absl::optional<int> id = absl::nullopt); |
| |
| template <typename CopyableParameters> |
| inline static Entry CreateFromCopyableParams( |
| CopyableParameters parameters, KeyStatus status, bool is_primary, |
| absl::optional<int> id = absl::nullopt) { |
| auto copyable_params = |
| absl::make_unique<CopyableParameters>(std::move(parameters)); |
| return CreateFromParams(std::move(copyable_params), status, is_primary, |
| id); |
| } |
| |
| // Sets the key status of this entry. |
| void SetStatus(KeyStatus status) { entry_->SetStatus(status); } |
| // Returns key status of this entry. |
| KeyStatus GetStatus() const { return entry_->GetStatus(); } |
| |
| // Assigns a fixed id when this keyset is built. |
| void SetFixedId(int id) { entry_->SetFixedId(id); } |
| // Assigns an unused random id when this keyset is built. |
| void SetRandomId() { entry_->SetRandomId(); } |
| |
| // Sets this entry as the primary key. |
| void SetPrimary() { entry_->SetPrimary(); } |
| // Unsets this entry as the primary key. |
| void UnsetPrimary() { entry_->UnsetPrimary(); } |
| // Returns whether or not this entry has been marked as a primary. |
| bool IsPrimary() const { return entry_->IsPrimary(); } |
| |
| private: |
| friend class KeysetHandleBuilder; |
| |
| explicit Entry(std::unique_ptr<internal::KeysetHandleBuilderEntry> entry) |
| : entry_(std::move(entry)) {} |
| |
| // Returns whether or not this entry has a randomly assigned id. |
| bool HasRandomId() { |
| return entry_->GetKeyIdStrategyEnum() == |
| internal::KeyIdStrategyEnum::kRandomId; |
| } |
| |
| internal::KeyIdStrategy GetKeyIdStrategy() { |
| return entry_->GetKeyIdStrategy(); |
| } |
| |
| crypto::tink::util::StatusOr<google::crypto::tink::Keyset::Key> |
| CreateKeysetKey(int id) { |
| return entry_->CreateKeysetKey(id); |
| } |
| |
| std::unique_ptr<internal::KeysetHandleBuilderEntry> entry_; |
| bool added_to_builder_ = false; |
| }; |
| |
| // Adds an `entry` to the keyset builder. Crashes if `entry` has already been |
| // added to a keyset handle builder. |
| KeysetHandleBuilder& AddEntry(KeysetHandleBuilder::Entry entry); |
| // Removes an entry at `index` from keyset builder. |
| KeysetHandleBuilder& RemoveEntry(int index); |
| |
| // Returns the number of Entry objects in this keyset builder. |
| int size() const { return entries_.size(); } |
| |
| // Returns entry from keyset builder at `index`. |
| KeysetHandleBuilder::Entry& operator[](int index) { return entries_[index]; } |
| |
| // Creates a new `KeysetHandle` object. |
| // |
| // Note: Since KeysetHandleBuilder::Entry objects might have randomly |
| // generated IDs, Build() can only be called once on a single |
| // KeysetHandleBuilder object. Otherwise, the KeysetHandleBuilder::Entry |
| // IDs would randomly change for each call to Build(), which would result |
| // in incompatible keysets. |
| crypto::tink::util::StatusOr<KeysetHandle> Build(); |
| |
| private: |
| // Select the next key id based on the given strategy. |
| crypto::tink::util::StatusOr<int> NextIdFromKeyIdStrategy( |
| internal::KeyIdStrategy strategy, const std::set<int>& ids_so_far); |
| |
| // Unset primary flag on all entries. |
| void ClearPrimary(); |
| |
| // Verify that entries with fixed IDs do not follow entries with random IDs. |
| crypto::tink::util::Status CheckIdAssignments(); |
| |
| std::vector<KeysetHandleBuilder::Entry> entries_; |
| |
| bool build_called_ = false; |
| }; |
| |
| } // namespace tink |
| } // namespace crypto |
| |
| #endif // TINK_KEYSET_HANDLE_BUILDER_H_ |