xref: /aosp_15_r20/external/tink/cc/keyderivation/keyset_deriver_wrapper.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2019 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 #include "tink/keyderivation/keyset_deriver_wrapper.h"
18 
19 #include <memory>
20 #include <utility>
21 
22 #include "absl/status/status.h"
23 #include "tink/cleartext_keyset_handle.h"
24 #include "proto/tink.pb.h"
25 
26 namespace crypto {
27 namespace tink {
28 
29 namespace {
30 
31 using ::google::crypto::tink::KeyData;
32 using ::google::crypto::tink::Keyset;
33 
Validate(PrimitiveSet<KeysetDeriver> * deriver_set)34 util::Status Validate(PrimitiveSet<KeysetDeriver>* deriver_set) {
35   if (deriver_set == nullptr) {
36     return util::Status(absl::StatusCode::kInternal,
37                         "deriver_set must be non-NULL");
38   }
39   if (deriver_set->get_primary() == nullptr) {
40     return util::Status(absl::StatusCode::kInvalidArgument,
41                         "deriver_set has no primary");
42   }
43   return util::OkStatus();
44 }
45 
46 class KeysetDeriverSetWrapper : public KeysetDeriver {
47  public:
KeysetDeriverSetWrapper(std::unique_ptr<PrimitiveSet<KeysetDeriver>> deriver_set)48   explicit KeysetDeriverSetWrapper(
49       std::unique_ptr<PrimitiveSet<KeysetDeriver>> deriver_set)
50       : deriver_set_(std::move(deriver_set)) {}
51 
52   crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>> DeriveKeyset(
53       absl::string_view salt) const override;
54 
55   ~KeysetDeriverSetWrapper() override = default;
56 
57  private:
58   std::unique_ptr<PrimitiveSet<KeysetDeriver>> deriver_set_;
59 };
60 
DeriveAndGetKeyData(absl::string_view salt,const KeysetDeriver & deriver)61 crypto::tink::util::StatusOr<KeyData> DeriveAndGetKeyData(
62     absl::string_view salt, const KeysetDeriver& deriver) {
63   auto keyset_handle_or = deriver.DeriveKeyset(salt);
64   if (!keyset_handle_or.ok()) return keyset_handle_or.status();
65   const Keyset& keyset =
66       CleartextKeysetHandle::GetKeyset(*keyset_handle_or.value());
67   if (keyset.key_size() != 1) {
68     return util::Status(
69         absl::StatusCode::kInternal,
70         "Wrapper Deriver must create a keyset with exactly one KeyData");
71   }
72   return keyset.key(0).key_data();
73 }
74 
75 crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
DeriveKeyset(absl::string_view salt) const76 KeysetDeriverSetWrapper::DeriveKeyset(absl::string_view salt) const {
77   Keyset keyset;
78   for (const auto* entry : deriver_set_->get_all_in_keyset_order()) {
79     Keyset::Key* key = keyset.add_key();
80 
81     crypto::tink::util::StatusOr<KeyData> key_data_or =
82         DeriveAndGetKeyData(salt, entry->get_primitive());
83     if (!key_data_or.ok()) return key_data_or.status();
84     *key->mutable_key_data() = key_data_or.value();
85     key->set_status(entry->get_status());
86     key->set_output_prefix_type(entry->get_output_prefix_type());
87     key->set_key_id(entry->get_key_id());
88   }
89   keyset.set_primary_key_id(deriver_set_->get_primary()->get_key_id());
90   return CleartextKeysetHandle::GetKeysetHandle(keyset);
91 }
92 
93 }  // namespace
94 
95 crypto::tink::util::StatusOr<std::unique_ptr<KeysetDeriver>>
Wrap(std::unique_ptr<PrimitiveSet<KeysetDeriver>> deriver_set) const96 KeysetDeriverWrapper::Wrap(
97     std::unique_ptr<PrimitiveSet<KeysetDeriver>> deriver_set) const {
98   util::Status status = Validate(deriver_set.get());
99   if (!status.ok()) return status;
100   return {absl::make_unique<KeysetDeriverSetWrapper>(std::move(deriver_set))};
101 }
102 
103 }  // namespace tink
104 }  // namespace crypto
105