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/internal/prf_based_deriver.h"
18
19 #include <memory>
20 #include <utility>
21
22 #include "tink/cleartext_keyset_handle.h"
23 #include "tink/keyset_handle.h"
24 #include "tink/registry.h"
25 #include "tink/subtle/prf/streaming_prf.h"
26 #include "proto/tink.pb.h"
27
28 namespace crypto {
29 namespace tink {
30 namespace internal {
31
32 using ::google::crypto::tink::KeyData;
33 using ::google::crypto::tink::Keyset;
34 using ::google::crypto::tink::KeyStatusType;
35 using ::google::crypto::tink::KeyTemplate;
36 using ::google::crypto::tink::OutputPrefixType;
37
New(const KeyData & prf_key,const KeyTemplate & key_template)38 util::StatusOr<std::unique_ptr<KeysetDeriver>> PrfBasedDeriver::New(
39 const KeyData& prf_key, const KeyTemplate& key_template) {
40 // Validate `prf_key`.
41 util::StatusOr<std::unique_ptr<StreamingPrf>> streaming_prf =
42 Registry::GetPrimitive<StreamingPrf>(prf_key);
43 if (!streaming_prf.ok()) {
44 return streaming_prf.status();
45 }
46
47 // Validate `key_template`.
48 std::unique_ptr<InputStream> randomness = (*streaming_prf)->ComputePrf("s");
49 util::StatusOr<KeyData> key_data =
50 internal::RegistryImpl::GlobalInstance().DeriveKey(key_template,
51 randomness.get());
52 if (!key_data.ok()) {
53 return key_data.status();
54 }
55
56 return {absl::WrapUnique<PrfBasedDeriver>(
57 new PrfBasedDeriver(*std::move(streaming_prf), key_template))};
58 }
59
DeriveKeyset(absl::string_view salt) const60 util::StatusOr<std::unique_ptr<KeysetHandle>> PrfBasedDeriver::DeriveKeyset(
61 absl::string_view salt) const {
62 std::unique_ptr<InputStream> randomness = streaming_prf_->ComputePrf(salt);
63
64 util::StatusOr<KeyData> key_data =
65 crypto::tink::internal::RegistryImpl::GlobalInstance().DeriveKey(
66 key_template_, randomness.get());
67 if (!key_data.ok()) {
68 return key_data.status();
69 }
70
71 // Fill in placeholder values for key ID, status, and output prefix type.
72 // These will be populated with the correct values in the keyset deriver
73 // factory. This is acceptable because the keyset as-is will never leave Tink,
74 // and the user only interacts via the keyset deriver factory.
75 Keyset::Key key;
76 *key.mutable_key_data() = *key_data;
77 key.set_status(KeyStatusType::UNKNOWN_STATUS);
78 key.set_key_id(0);
79 key.set_output_prefix_type(OutputPrefixType::UNKNOWN_PREFIX);
80
81 Keyset keyset;
82 *keyset.add_key() = key;
83 keyset.set_primary_key_id(0);
84
85 return CleartextKeysetHandle::GetKeysetHandle(keyset);
86 }
87
88 } // namespace internal
89 } // namespace tink
90 } // namespace crypto
91