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