1use crate::{utils::wrap_err, TinkError};
20use std::{convert::TryFrom, sync::Arc};
21use tink_proto::{key_data::KeyMaterialType, prost::Message, Keyset, KeysetInfo};
22
23pub struct Handle {
26 ks: Keyset,
27}
28
29impl Handle {
30 pub fn new(kt: &tink_proto::KeyTemplate) -> Result<Self, TinkError> {
33 let mut ksm = super::Manager::new();
34 ksm.rotate(kt)
35 .map_err(|e| wrap_err("keyset::Handle: cannot generate new keyset", e))?;
36 ksm.handle()
37 .map_err(|e| wrap_err("keyset::Handle: cannot get keyset handle", e))
38 }
39
40 pub fn new_with_no_secrets(ks: Keyset) -> Result<Self, TinkError> {
43 let h = Handle {
44 ks: validate_keyset(ks)?,
45 };
46 if h.has_secrets()? {
47 return Err("importing unencrypted secret key material is forbidden".into());
50 }
51 Ok(h)
52 }
53
54 pub fn read<T>(reader: &mut T, master_key: Box<dyn crate::Aead>) -> Result<Self, TinkError>
57 where
58 T: crate::keyset::Reader,
59 {
60 Self::read_with_associated_data(reader, master_key, &[])
61 }
62
63 pub fn read_with_associated_data<T>(
66 reader: &mut T,
67 master_key: Box<dyn crate::Aead>,
68 associated_data: &[u8],
69 ) -> Result<Self, TinkError>
70 where
71 T: crate::keyset::Reader,
72 {
73 let encrypted_keyset = reader.read_encrypted()?;
74 let ks = decrypt(&encrypted_keyset, master_key, associated_data)?;
75 Ok(Handle {
76 ks: validate_keyset(ks)?,
77 })
78 }
79
80 pub fn read_with_no_secrets<T>(reader: &mut T) -> Result<Self, TinkError>
83 where
84 T: crate::keyset::Reader,
85 {
86 let ks = reader.read()?;
87 Handle::new_with_no_secrets(ks)
88 }
89
90 pub fn public(&self) -> Result<Self, TinkError> {
92 let priv_keys = &self.ks.key;
93 let mut pub_keys = Vec::with_capacity(priv_keys.len());
94 for priv_key in priv_keys {
95 let priv_key_data = priv_key
96 .key_data
97 .as_ref()
98 .ok_or_else(|| TinkError::new("keyset::Handle: invalid keyset"))?;
99 let pub_key_data =
100 public_key_data(priv_key_data).map_err(|e| wrap_err("keyset::Handle", e))?;
101 pub_keys.push(tink_proto::keyset::Key {
102 key_data: Some(pub_key_data),
103 status: priv_key.status,
104 key_id: priv_key.key_id,
105 output_prefix_type: priv_key.output_prefix_type,
106 });
107 }
108 let ks = Keyset {
109 primary_key_id: self.ks.primary_key_id,
110 key: pub_keys,
111 };
112 Ok(Handle { ks })
113 }
114
115 pub fn write<T>(
117 &self,
118 writer: &mut T,
119 master_key: Box<dyn crate::Aead>,
120 ) -> Result<(), TinkError>
121 where
122 T: super::Writer,
123 {
124 self.write_with_associated_data(writer, master_key, &[])
125 }
126
127 pub fn write_with_associated_data<T>(
129 &self,
130 writer: &mut T,
131 master_key: Box<dyn crate::Aead>,
132 associated_data: &[u8],
133 ) -> Result<(), TinkError>
134 where
135 T: super::Writer,
136 {
137 let encrypted = encrypt(&self.ks, master_key, associated_data)?;
138 writer.write_encrypted(&encrypted)
139 }
140
141 pub fn write_with_no_secrets<T>(&self, w: &mut T) -> Result<(), TinkError>
144 where
145 T: super::Writer,
146 {
147 if self.has_secrets()? {
148 Err("exporting unencrypted secret key material is forbidden".into())
149 } else {
150 w.write(&self.ks)
151 }
152 }
153
154 pub fn primitives(&self) -> Result<crate::primitiveset::PrimitiveSet, TinkError> {
161 self.primitives_with_key_manager(None)
162 }
163
164 pub fn primitives_with_key_manager(
177 &self,
178 km: Option<Arc<dyn crate::registry::KeyManager>>,
179 ) -> Result<crate::primitiveset::PrimitiveSet, TinkError> {
180 super::validate(&self.ks)
181 .map_err(|e| wrap_err("primitives_with_key_manager: invalid keyset", e))?;
182 let mut primitive_set = crate::primitiveset::PrimitiveSet::new();
183 for key in &self.ks.key {
184 if key.status != tink_proto::KeyStatusType::Enabled as i32 {
185 continue;
186 }
187 let key_data = key
188 .key_data
189 .as_ref()
190 .ok_or_else(|| TinkError::new("primitives_with_key_manager: no key_data"))?;
191 let primitive = match &km {
192 Some(km) if km.does_support(&key_data.type_url) => km.primitive(&key_data.value),
193 Some(_) | None => crate::registry::primitive_from_key_data(key_data),
194 }
195 .map_err(|e| {
196 wrap_err(
197 "primitives_with_key_manager: cannot get primitive from key",
198 e,
199 )
200 })?;
201
202 let entry = primitive_set
203 .add(primitive, key)
204 .map_err(|e| wrap_err("primitives_with_key_manager: cannot add primitive", e))?;
205 if key.key_id == self.ks.primary_key_id {
206 primitive_set.primary = Some(entry.clone());
207 }
208 }
209 Ok(primitive_set)
210 }
211
212 fn has_secrets(&self) -> Result<bool, TinkError> {
216 let mut result = false;
217 for k in &self.ks.key {
218 match &k.key_data {
219 None => return Err("invalid keyset".into()),
220 Some(kd) => match KeyMaterialType::try_from(kd.key_material_type) {
221 Ok(KeyMaterialType::UnknownKeymaterial) => result = true,
222 Ok(KeyMaterialType::Symmetric) => result = true,
223 Ok(KeyMaterialType::AsymmetricPrivate) => result = true,
224 Ok(KeyMaterialType::AsymmetricPublic) => {}
225 Ok(KeyMaterialType::Remote) => {}
226 Err(_) => return Err("invalid key material type".into()),
227 },
228 }
229 }
230 Ok(result)
231 }
232
233 pub fn keyset_info(&self) -> KeysetInfo {
236 get_keyset_info(&self.ks)
237 }
238
239 pub(crate) fn into_inner(self) -> Keyset {
241 self.ks
242 }
243
244 #[cfg(feature = "insecure")]
247 #[cfg_attr(docsrs, doc(cfg(feature = "insecure")))]
248 pub(crate) fn clone_keyset(&self) -> Keyset {
249 self.ks.clone()
250 }
251
252 pub(crate) fn from_keyset(ks: Keyset) -> Result<Self, TinkError> {
255 Ok(Handle {
256 ks: validate_keyset(ks)?,
257 })
258 }
259}
260
261fn validate_keyset(ks: Keyset) -> Result<Keyset, TinkError> {
263 for k in &ks.key {
264 match &k.key_data {
265 None if k.status == tink_proto::KeyStatusType::Destroyed as i32 => {}
266 None => return Err("invalid keyset".into()),
267 Some(kd) => match KeyMaterialType::try_from(kd.key_material_type) {
268 Ok(_) => {}
269 Err(_) => return Err("invalid key material type".into()),
270 },
271 }
272 }
273 Ok(ks)
274}
275
276fn public_key_data(priv_key_data: &tink_proto::KeyData) -> Result<tink_proto::KeyData, TinkError> {
278 if priv_key_data.key_material_type
279 != tink_proto::key_data::KeyMaterialType::AsymmetricPrivate as i32
280 {
281 return Err("keyset::Handle: keyset contains a non-private key".into());
282 }
283 let km = crate::registry::get_key_manager(&priv_key_data.type_url)?;
284
285 if !km.supports_private_keys() {
286 return Err(format!(
287 "keyset::Handle: {} does not belong to a KeyManager that handles private keys",
288 priv_key_data.type_url
289 )
290 .into());
291 }
292 km.public_key_data(&priv_key_data.value)
293}
294
295fn decrypt(
297 encrypted_keyset: &tink_proto::EncryptedKeyset,
298 master_key: Box<dyn crate::Aead>,
299 associated_data: &[u8],
300) -> Result<Keyset, TinkError> {
301 let decrypted = master_key
302 .decrypt(&encrypted_keyset.encrypted_keyset, associated_data)
303 .map_err(|e| wrap_err("keyset::Handle: decryption failed", e))?;
304 Keyset::decode(&decrypted[..]).map_err(|_| TinkError::new("keyset::Handle:: invalid keyset"))
305}
306
307fn encrypt(
309 keyset: &Keyset,
310 master_key: Box<dyn crate::Aead>,
311 associated_data: &[u8],
312) -> Result<tink_proto::EncryptedKeyset, TinkError> {
313 let mut serialized_keyset = vec![];
314 keyset
315 .encode(&mut serialized_keyset)
316 .map_err(|e| wrap_err("keyset::Handle: invalid keyset", e))?;
317 let encrypted = master_key
318 .encrypt(&serialized_keyset, associated_data)
319 .map_err(|e| wrap_err("keyset::Handle: encrypted failed", e))?;
320 Ok(tink_proto::EncryptedKeyset {
321 encrypted_keyset: encrypted,
322 keyset_info: Some(get_keyset_info(keyset)),
323 })
324}
325
326fn get_keyset_info(keyset: &Keyset) -> KeysetInfo {
328 let n_key = keyset.key.len();
329 let mut key_infos = Vec::with_capacity(n_key);
330 for key in &keyset.key {
331 key_infos.push(get_key_info(key));
332 }
333 KeysetInfo {
334 primary_key_id: keyset.primary_key_id,
335 key_info: key_infos,
336 }
337}
338
339fn get_key_info(key: &tink_proto::keyset::Key) -> tink_proto::keyset_info::KeyInfo {
342 tink_proto::keyset_info::KeyInfo {
343 type_url: match &key.key_data {
344 Some(kd) => kd.type_url.clone(),
345 None => "".to_string(),
346 },
347 status: key.status,
348 key_id: key.key_id,
349 output_prefix_type: key.output_prefix_type,
350 }
351}
352
353impl std::fmt::Debug for Handle {
354 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
357 write!(f, "{:?}", get_keyset_info(&self.ks))
358 }
359}