xref: /aosp_15_r20/external/tink/cc/internal/keyset_handle_builder_entry.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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 #include "tink/internal/keyset_handle_builder_entry.h"
18 
19 #include <memory>
20 #include <string>
21 
22 #include "absl/status/status.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/types/optional.h"
25 #include "tink/insecure_secret_key_access.h"
26 #include "tink/internal/key_status_util.h"
27 #include "tink/internal/legacy_proto_key.h"
28 #include "tink/internal/legacy_proto_parameters.h"
29 #include "tink/internal/mutable_serialization_registry.h"
30 #include "tink/internal/proto_key_serialization.h"
31 #include "tink/internal/proto_parameters_serialization.h"
32 #include "tink/internal/serialization.h"
33 #include "tink/key.h"
34 #include "tink/parameters.h"
35 #include "tink/registry.h"
36 #include "tink/restricted_data.h"
37 #include "tink/secret_key_access_token.h"
38 #include "tink/util/status.h"
39 #include "tink/util/statusor.h"
40 #include "proto/tink.pb.h"
41 
42 namespace crypto {
43 namespace tink {
44 namespace internal {
45 namespace {
46 
47 using ::google::crypto::tink::KeyData;
48 using ::google::crypto::tink::Keyset;
49 using ::google::crypto::tink::KeyStatusType;
50 
ToKeysetKey(int id,KeyStatusType status,const ProtoKeySerialization & serialization)51 Keyset::Key ToKeysetKey(int id, KeyStatusType status,
52                         const ProtoKeySerialization& serialization) {
53   KeyData key_data;
54   key_data.set_type_url(std::string(serialization.TypeUrl()));
55   // OSS proto library complains if serialized key is not converted to string.
56   key_data.set_value(std::string(serialization.SerializedKeyProto().GetSecret(
57       InsecureSecretKeyAccess::Get())));
58   key_data.set_key_material_type(serialization.KeyMaterialType());
59   Keyset::Key key;
60   key.set_status(status);
61   key.set_key_id(id);
62   key.set_output_prefix_type(serialization.GetOutputPrefixType());
63   *key.mutable_key_data() = key_data;
64   return key;
65 }
66 
SerializeParameters(const Parameters & params)67 util::StatusOr<ProtoParametersSerialization> SerializeParameters(
68     const Parameters& params) {
69   util::StatusOr<std::unique_ptr<Serialization>> serialization =
70       MutableSerializationRegistry::GlobalInstance()
71           .SerializeParameters<ProtoParametersSerialization>(params);
72   if (!serialization.ok()) return serialization.status();
73 
74   const ProtoParametersSerialization* proto_serialization =
75       dynamic_cast<const ProtoParametersSerialization*>(serialization->get());
76   if (proto_serialization == nullptr) {
77     return util::Status(absl::StatusCode::kInternal,
78                         "Failed to serialize proto parameters.");
79   }
80 
81   return *proto_serialization;
82 }
83 
SerializeLegacyParameters(const Parameters * params)84 util::StatusOr<ProtoParametersSerialization> SerializeLegacyParameters(
85     const Parameters* params) {
86   const LegacyProtoParameters* proto_params =
87       dynamic_cast<const LegacyProtoParameters*>(params);
88   if (proto_params == nullptr) {
89     return util::Status(absl::StatusCode::kInvalidArgument,
90                         "Failed to serialize legacy proto parameters.");
91   }
92   return proto_params->Serialization();
93 }
94 
SerializeKey(const Key & key)95 util::StatusOr<ProtoKeySerialization> SerializeKey(const Key& key) {
96   util::StatusOr<std::unique_ptr<Serialization>> serialization =
97       MutableSerializationRegistry::GlobalInstance()
98           .SerializeKey<ProtoKeySerialization>(key,
99                                                InsecureSecretKeyAccess::Get());
100   if (!serialization.ok()) return serialization.status();
101 
102   const ProtoKeySerialization* serialized_proto_key =
103       dynamic_cast<const ProtoKeySerialization*>(serialization->get());
104   if (serialized_proto_key == nullptr) {
105     return util::Status(absl::StatusCode::kInternal,
106                         "Failed to serialize proto key.");
107   }
108 
109   return *serialized_proto_key;
110 }
111 
SerializeLegacyKey(const Key * key)112 util::StatusOr<ProtoKeySerialization> SerializeLegacyKey(const Key* key) {
113   const LegacyProtoKey* proto_key = dynamic_cast<const LegacyProtoKey*>(key);
114   if (proto_key == nullptr) {
115     return util::Status(absl::StatusCode::kInvalidArgument,
116                         "Failed to serialize legacy proto key.");
117   }
118   util::StatusOr<const ProtoKeySerialization*> serialized_key =
119       proto_key->Serialization(InsecureSecretKeyAccess::Get());
120   if (!serialized_key.ok()) return serialized_key.status();
121 
122   return **serialized_key;
123 }
124 
CreateKeysetKeyFromProtoParametersSerialization(const ProtoParametersSerialization & serialization,int id,KeyStatusType status)125 util::StatusOr<Keyset::Key> CreateKeysetKeyFromProtoParametersSerialization(
126     const ProtoParametersSerialization& serialization, int id,
127     KeyStatusType status) {
128   util::StatusOr<std::unique_ptr<KeyData>> key_data =
129       Registry::NewKeyData(serialization.GetKeyTemplate());
130   if (!key_data.ok()) return key_data.status();
131 
132   Keyset::Key key;
133   key.set_status(status);
134   key.set_key_id(id);
135   key.set_output_prefix_type(
136       serialization.GetKeyTemplate().output_prefix_type());
137   *key.mutable_key_data() = **key_data;
138   return key;
139 }
140 
CreateKeysetKeyFromProtoKeySerialization(const ProtoKeySerialization & key,int id,KeyStatusType status)141 util::StatusOr<Keyset::Key> CreateKeysetKeyFromProtoKeySerialization(
142     const ProtoKeySerialization& key, int id, KeyStatusType status) {
143   absl::optional<int> id_requirement = key.IdRequirement();
144   if (id_requirement.has_value() && *id_requirement != id) {
145     return util::Status(absl::StatusCode::kInvalidArgument,
146                         "Wrong ID set for key with ID requirement.");
147   }
148   return ToKeysetKey(id, status, key);
149 }
150 
151 }  // namespace
152 
SetFixedId(int id)153 void KeysetHandleBuilderEntry::SetFixedId(int id) {
154   strategy_.strategy = KeyIdStrategyEnum::kFixedId;
155   strategy_.id_requirement = id;
156 }
157 
SetRandomId()158 void KeysetHandleBuilderEntry::SetRandomId() {
159   strategy_.strategy = KeyIdStrategyEnum::kRandomId;
160   strategy_.id_requirement = absl::nullopt;
161 }
162 
CreateKeysetKey(int id)163 util::StatusOr<Keyset::Key> KeyEntry::CreateKeysetKey(int id) {
164   util::StatusOr<KeyStatusType> key_status = ToKeyStatusType(key_status_);
165   if (!key_status.ok()) return key_status.status();
166 
167   if (GetKeyIdRequirement().has_value() && GetKeyIdRequirement() != id) {
168     return util::Status(absl::StatusCode::kInvalidArgument,
169                         "Requested id does not match id requirement.");
170   }
171 
172   util::StatusOr<ProtoKeySerialization> serialization = SerializeKey(*key_);
173   if (!serialization.ok() &&
174       serialization.status().code() != absl::StatusCode::kNotFound) {
175     return serialization.status();
176   }
177 
178   if (serialization.status().code() == absl::StatusCode::kNotFound) {
179     // Fallback to legacy proto key.
180     serialization = SerializeLegacyKey(key_.get());
181     if (!serialization.ok()) return serialization.status();
182   }
183 
184   return CreateKeysetKeyFromProtoKeySerialization(*serialization, id,
185                                                   *key_status);
186 }
187 
CreateKeysetKey(int id)188 util::StatusOr<Keyset::Key> ParametersEntry::CreateKeysetKey(int id) {
189   util::StatusOr<KeyStatusType> key_status = ToKeyStatusType(key_status_);
190   if (!key_status.ok()) return key_status.status();
191 
192   if (GetKeyIdRequirement().has_value() && GetKeyIdRequirement() != id) {
193     return util::Status(absl::StatusCode::kInvalidArgument,
194                         "Requested id does not match id requirement.");
195   }
196 
197   util::StatusOr<ProtoParametersSerialization> serialization =
198       SerializeParameters(*parameters_);
199   if (!serialization.ok() &&
200       serialization.status().code() != absl::StatusCode::kNotFound) {
201     return serialization.status();
202   }
203 
204   if (serialization.status().code() == absl::StatusCode::kNotFound) {
205     // Fallback to legacy proto parameters.
206     serialization = SerializeLegacyParameters(parameters_.get());
207     if (!serialization.ok()) return serialization.status();
208   }
209 
210   return CreateKeysetKeyFromProtoParametersSerialization(*serialization, id,
211                                                          *key_status);
212 }
213 
214 }  // namespace internal
215 }  // namespace tink
216 }  // namespace crypto
217