1use std::{
2 cell::Cell,
3 sync::{RwLockReadGuard, RwLockWriteGuard},
4};
5
6use serde::Serialize;
7use zeroize::Zeroizing;
8
9use super::KeyStoreInner;
10use crate::{
11 derive_shareable_key, error::UnsupportedOperation, signing, store::backend::StoreBackend,
12 AsymmetricCryptoKey, CryptoError, EncString, KeyId, KeyIds, Result, Signature,
13 SignatureAlgorithm, SignedObject, SignedPublicKey, SignedPublicKeyMessage, SigningKey,
14 SymmetricCryptoKey, UnsignedSharedKey,
15};
16
17#[must_use]
70pub struct KeyStoreContext<'a, Ids: KeyIds> {
71 pub(super) global_keys: GlobalKeys<'a, Ids>,
72
73 pub(super) local_symmetric_keys: Box<dyn StoreBackend<Ids::Symmetric>>,
74 pub(super) local_asymmetric_keys: Box<dyn StoreBackend<Ids::Asymmetric>>,
75 pub(super) local_signing_keys: Box<dyn StoreBackend<Ids::Signing>>,
76
77 pub(super) _phantom: std::marker::PhantomData<(Cell<()>, RwLockReadGuard<'static, ()>)>,
79}
80
81pub(crate) enum GlobalKeys<'a, Ids: KeyIds> {
87 ReadOnly(RwLockReadGuard<'a, KeyStoreInner<Ids>>),
88 ReadWrite(RwLockWriteGuard<'a, KeyStoreInner<Ids>>),
89}
90
91impl<Ids: KeyIds> GlobalKeys<'_, Ids> {
92 pub fn get(&self) -> &KeyStoreInner<Ids> {
93 match self {
94 GlobalKeys::ReadOnly(keys) => keys,
95 GlobalKeys::ReadWrite(keys) => keys,
96 }
97 }
98
99 pub fn get_mut(&mut self) -> Result<&mut KeyStoreInner<Ids>> {
100 match self {
101 GlobalKeys::ReadOnly(_) => Err(CryptoError::ReadOnlyKeyStore),
102 GlobalKeys::ReadWrite(keys) => Ok(keys),
103 }
104 }
105}
106
107impl<Ids: KeyIds> KeyStoreContext<'_, Ids> {
108 pub fn clear_local(&mut self) {
112 self.local_symmetric_keys.clear();
113 self.local_asymmetric_keys.clear();
114 self.local_signing_keys.clear();
115 }
116
117 pub fn retain_symmetric_keys(&mut self, f: fn(Ids::Symmetric) -> bool) {
120 if let Ok(keys) = self.global_keys.get_mut() {
121 keys.symmetric_keys.retain(f);
122 }
123 self.local_symmetric_keys.retain(f);
124 }
125
126 pub fn retain_asymmetric_keys(&mut self, f: fn(Ids::Asymmetric) -> bool) {
129 if let Ok(keys) = self.global_keys.get_mut() {
130 keys.asymmetric_keys.retain(f);
131 }
132 self.local_asymmetric_keys.retain(f);
133 }
134
135 pub fn unwrap_symmetric_key(
148 &mut self,
149 encryption_key: Ids::Symmetric,
150 new_key_id: Ids::Symmetric,
151 encrypted_key: &EncString,
152 ) -> Result<Ids::Symmetric> {
153 let mut new_key_material =
154 self.decrypt_data_with_symmetric_key(encryption_key, encrypted_key)?;
155
156 #[allow(deprecated)]
157 self.set_symmetric_key(
158 new_key_id,
159 SymmetricCryptoKey::try_from(new_key_material.as_mut_slice())?,
160 )?;
161
162 Ok(new_key_id)
164 }
165
166 pub fn wrap_symmetric_key(
175 &self,
176 wrapping_key: Ids::Symmetric,
177 key_to_wrap: Ids::Symmetric,
178 ) -> Result<EncString> {
179 use SymmetricCryptoKey::*;
180
181 let wrapping_key_instance = self.get_symmetric_key(wrapping_key)?;
182 let key_to_wrap_instance = self.get_symmetric_key(key_to_wrap)?;
183 match (wrapping_key_instance, key_to_wrap_instance) {
189 (Aes256CbcHmacKey(_), Aes256CbcHmacKey(_) | Aes256CbcKey(_)) => self
190 .encrypt_data_with_symmetric_key(
191 wrapping_key,
192 key_to_wrap_instance.to_encoded().as_slice(),
193 ),
194 _ => Err(CryptoError::OperationNotSupported(
195 UnsupportedOperation::EncryptionNotImplementedForKey,
196 )),
197 }
198 }
199
200 pub fn decapsulate_key_unsigned(
210 &mut self,
211 decapsulation_key: Ids::Asymmetric,
212 new_key_id: Ids::Symmetric,
213 encapsulated_shared_key: &UnsignedSharedKey,
214 ) -> Result<Ids::Symmetric> {
215 let decapsulation_key = self.get_asymmetric_key(decapsulation_key)?;
216 let decapsulated_key =
217 encapsulated_shared_key.decapsulate_key_unsigned(decapsulation_key)?;
218
219 #[allow(deprecated)]
220 self.set_symmetric_key(new_key_id, decapsulated_key)?;
221
222 Ok(new_key_id)
224 }
225
226 pub fn encapsulate_key_unsigned(
235 &self,
236 encapsulation_key: Ids::Asymmetric,
237 shared_key: Ids::Symmetric,
238 ) -> Result<UnsignedSharedKey> {
239 UnsignedSharedKey::encapsulate_key_unsigned(
240 self.get_symmetric_key(shared_key)?,
241 &self.get_asymmetric_key(encapsulation_key)?.to_public_key(),
242 )
243 }
244
245 pub fn has_symmetric_key(&self, key_id: Ids::Symmetric) -> bool {
247 self.get_symmetric_key(key_id).is_ok()
248 }
249
250 pub fn has_asymmetric_key(&self, key_id: Ids::Asymmetric) -> bool {
252 self.get_asymmetric_key(key_id).is_ok()
253 }
254
255 pub fn has_signing_key(&self, key_id: Ids::Signing) -> bool {
257 self.get_signing_key(key_id).is_ok()
258 }
259
260 pub fn generate_symmetric_key(&mut self, key_id: Ids::Symmetric) -> Result<Ids::Symmetric> {
262 let key = SymmetricCryptoKey::make_aes256_cbc_hmac_key();
263 #[allow(deprecated)]
264 self.set_symmetric_key(key_id, key)?;
265 Ok(key_id)
266 }
267
268 pub fn make_signing_key(&mut self, key_id: Ids::Signing) -> Result<Ids::Signing> {
271 let key = SigningKey::make(SignatureAlgorithm::default_algorithm());
272 #[allow(deprecated)]
273 self.set_signing_key(key_id, key)?;
274 Ok(key_id)
275 }
276
277 pub fn derive_shareable_key(
282 &mut self,
283 key_id: Ids::Symmetric,
284 secret: Zeroizing<[u8; 16]>,
285 name: &str,
286 info: Option<&str>,
287 ) -> Result<Ids::Symmetric> {
288 #[allow(deprecated)]
289 self.set_symmetric_key(
290 key_id,
291 SymmetricCryptoKey::Aes256CbcHmacKey(derive_shareable_key(secret, name, info)),
292 )?;
293 Ok(key_id)
294 }
295
296 #[deprecated(note = "This function should ideally never be used outside this crate")]
297 #[allow(missing_docs)]
298 pub fn dangerous_get_symmetric_key(
299 &self,
300 key_id: Ids::Symmetric,
301 ) -> Result<&SymmetricCryptoKey> {
302 self.get_symmetric_key(key_id)
303 }
304
305 #[deprecated(note = "This function should ideally never be used outside this crate")]
306 #[allow(missing_docs)]
307 pub fn dangerous_get_asymmetric_key(
308 &self,
309 key_id: Ids::Asymmetric,
310 ) -> Result<&AsymmetricCryptoKey> {
311 self.get_asymmetric_key(key_id)
312 }
313
314 pub fn make_signed_public_key(
318 &self,
319 private_key_id: Ids::Asymmetric,
320 signing_key_id: Ids::Signing,
321 ) -> Result<SignedPublicKey> {
322 let public_key = self.get_asymmetric_key(private_key_id)?.to_public_key();
323 let signing_key = self.get_signing_key(signing_key_id)?;
324 let signed_public_key =
325 SignedPublicKeyMessage::from_public_key(&public_key)?.sign(signing_key)?;
326 Ok(signed_public_key)
327 }
328
329 fn get_symmetric_key(&self, key_id: Ids::Symmetric) -> Result<&SymmetricCryptoKey> {
330 if key_id.is_local() {
331 self.local_symmetric_keys.get(key_id)
332 } else {
333 self.global_keys.get().symmetric_keys.get(key_id)
334 }
335 .ok_or_else(|| crate::CryptoError::MissingKeyId(format!("{key_id:?}")))
336 }
337
338 fn get_asymmetric_key(&self, key_id: Ids::Asymmetric) -> Result<&AsymmetricCryptoKey> {
339 if key_id.is_local() {
340 self.local_asymmetric_keys.get(key_id)
341 } else {
342 self.global_keys.get().asymmetric_keys.get(key_id)
343 }
344 .ok_or_else(|| crate::CryptoError::MissingKeyId(format!("{key_id:?}")))
345 }
346
347 fn get_signing_key(&self, key_id: Ids::Signing) -> Result<&SigningKey> {
348 if key_id.is_local() {
349 self.local_signing_keys.get(key_id)
350 } else {
351 self.global_keys.get().signing_keys.get(key_id)
352 }
353 .ok_or_else(|| crate::CryptoError::MissingKeyId(format!("{key_id:?}")))
354 }
355
356 #[deprecated(note = "This function should ideally never be used outside this crate")]
357 #[allow(missing_docs)]
358 pub fn set_symmetric_key(
359 &mut self,
360 key_id: Ids::Symmetric,
361 key: SymmetricCryptoKey,
362 ) -> Result<()> {
363 if key_id.is_local() {
364 self.local_symmetric_keys.upsert(key_id, key);
365 } else {
366 self.global_keys
367 .get_mut()?
368 .symmetric_keys
369 .upsert(key_id, key);
370 }
371 Ok(())
372 }
373
374 #[deprecated(note = "This function should ideally never be used outside this crate")]
375 #[allow(missing_docs)]
376 pub fn set_asymmetric_key(
377 &mut self,
378 key_id: Ids::Asymmetric,
379 key: AsymmetricCryptoKey,
380 ) -> Result<()> {
381 if key_id.is_local() {
382 self.local_asymmetric_keys.upsert(key_id, key);
383 } else {
384 self.global_keys
385 .get_mut()?
386 .asymmetric_keys
387 .upsert(key_id, key);
388 }
389 Ok(())
390 }
391
392 #[deprecated(note = "This function should ideally never be used outside this crate")]
394 pub fn set_signing_key(&mut self, key_id: Ids::Signing, key: SigningKey) -> Result<()> {
395 if key_id.is_local() {
396 self.local_signing_keys.upsert(key_id, key);
397 } else {
398 self.global_keys.get_mut()?.signing_keys.upsert(key_id, key);
399 }
400 Ok(())
401 }
402
403 pub(crate) fn decrypt_data_with_symmetric_key(
404 &self,
405 key: Ids::Symmetric,
406 data: &EncString,
407 ) -> Result<Vec<u8>> {
408 let key = self.get_symmetric_key(key)?;
409
410 match (data, key) {
411 (EncString::Aes256Cbc_B64 { iv, data }, SymmetricCryptoKey::Aes256CbcKey(key)) => {
412 crate::aes::decrypt_aes256(iv, data.clone(), &key.enc_key)
413 }
414 (
415 EncString::Aes256Cbc_HmacSha256_B64 { iv, mac, data },
416 SymmetricCryptoKey::Aes256CbcHmacKey(key),
417 ) => crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), &key.mac_key, &key.enc_key),
418 _ => Err(CryptoError::InvalidKey),
419 }
420 }
421
422 pub(crate) fn encrypt_data_with_symmetric_key(
423 &self,
424 key: Ids::Symmetric,
425 data: &[u8],
426 ) -> Result<EncString> {
427 let key = self.get_symmetric_key(key)?;
428 match key {
429 SymmetricCryptoKey::Aes256CbcKey(_) => Err(CryptoError::OperationNotSupported(
430 UnsupportedOperation::EncryptionNotImplementedForKey,
431 )),
432 SymmetricCryptoKey::Aes256CbcHmacKey(key) => EncString::encrypt_aes256_hmac(data, key),
433 SymmetricCryptoKey::XChaCha20Poly1305Key(key) => {
434 EncString::encrypt_xchacha20_poly1305(data, key)
435 }
436 }
437 }
438
439 #[allow(unused)]
443 pub(crate) fn sign<Message: Serialize>(
444 &self,
445 key: Ids::Signing,
446 message: &Message,
447 namespace: &crate::SigningNamespace,
448 ) -> Result<SignedObject> {
449 self.get_signing_key(key)?.sign(message, namespace)
450 }
451
452 #[allow(unused)]
456 pub(crate) fn sign_detached<Message: Serialize>(
457 &self,
458 key: Ids::Signing,
459 message: &Message,
460 namespace: &crate::SigningNamespace,
461 ) -> Result<(Signature, signing::SerializedMessage)> {
462 self.get_signing_key(key)?.sign_detached(message, namespace)
463 }
464}
465
466#[cfg(test)]
467#[allow(deprecated)]
468mod tests {
469 use serde::{Deserialize, Serialize};
470
471 use crate::{
472 store::{tests::DataView, KeyStore},
473 traits::tests::{TestIds, TestSigningKey, TestSymmKey},
474 CryptoError, Decryptable, Encryptable, SignatureAlgorithm, SigningKey, SigningNamespace,
475 SymmetricCryptoKey,
476 };
477
478 #[test]
479 fn test_set_signing_key() {
480 let store: KeyStore<TestIds> = KeyStore::default();
481
482 let key_a0_id = TestSigningKey::A(0);
484 let key_a0 = SigningKey::make(SignatureAlgorithm::Ed25519);
485 store
486 .context_mut()
487 .set_signing_key(key_a0_id, key_a0)
488 .unwrap();
489 }
490
491 #[test]
492 fn test_set_keys_for_encryption() {
493 let store: KeyStore<TestIds> = KeyStore::default();
494
495 let key_a0_id = TestSymmKey::A(0);
497 let key_a0 = SymmetricCryptoKey::make_aes256_cbc_hmac_key();
498
499 store
500 .context_mut()
501 .set_symmetric_key(TestSymmKey::A(0), key_a0.clone())
502 .unwrap();
503
504 assert!(store.context().has_symmetric_key(key_a0_id));
505
506 let data = DataView("Hello, World!".to_string(), key_a0_id);
508 let _encrypted = data.encrypt(&mut store.context(), key_a0_id).unwrap();
509 }
510
511 #[test]
512 fn test_key_encryption() {
513 let store: KeyStore<TestIds> = KeyStore::default();
514
515 let mut ctx = store.context();
516
517 let key_1_id = TestSymmKey::C(1);
519 let key_1 = SymmetricCryptoKey::make_aes256_cbc_hmac_key();
520
521 ctx.set_symmetric_key(key_1_id, key_1.clone()).unwrap();
522
523 assert!(ctx.has_symmetric_key(key_1_id));
524
525 let key_2_id = TestSymmKey::C(2);
527 let key_2 = SymmetricCryptoKey::make_aes256_cbc_hmac_key();
528
529 ctx.set_symmetric_key(key_2_id, key_2.clone()).unwrap();
530
531 assert!(ctx.has_symmetric_key(key_2_id));
532
533 let key_2_enc = ctx.wrap_symmetric_key(key_1_id, key_2_id).unwrap();
535
536 let new_key_id = TestSymmKey::C(3);
538
539 ctx.unwrap_symmetric_key(key_1_id, new_key_id, &key_2_enc)
540 .unwrap();
541
542 let data = DataView("Hello, World!".to_string(), key_2_id);
546 let encrypted = data.encrypt(&mut ctx, key_2_id).unwrap();
547
548 let decrypted1 = encrypted.decrypt(&mut ctx, key_2_id).unwrap();
549 let decrypted2 = encrypted.decrypt(&mut ctx, new_key_id).unwrap();
550
551 assert_eq!(decrypted1.0, decrypted2.0);
553 }
554
555 #[test]
556 fn test_signing() {
557 let store: KeyStore<TestIds> = KeyStore::default();
558
559 let key_a0_id = TestSigningKey::A(0);
561 let key_a0 = SigningKey::make(SignatureAlgorithm::Ed25519);
562 let verifying_key = key_a0.to_verifying_key();
563 store
564 .context_mut()
565 .set_signing_key(key_a0_id, key_a0)
566 .unwrap();
567
568 assert!(store.context().has_signing_key(key_a0_id));
569
570 #[derive(Serialize, Deserialize)]
572 struct TestData {
573 data: String,
574 }
575 let signed_object = store
576 .context()
577 .sign(
578 key_a0_id,
579 &TestData {
580 data: "Hello".to_string(),
581 },
582 &SigningNamespace::ExampleNamespace,
583 )
584 .unwrap();
585 let payload: Result<TestData, CryptoError> =
586 signed_object.verify_and_unwrap(&verifying_key, &SigningNamespace::ExampleNamespace);
587 assert!(payload.is_ok());
588
589 let (signature, serialized_message) = store
590 .context()
591 .sign_detached(
592 key_a0_id,
593 &TestData {
594 data: "Hello".to_string(),
595 },
596 &SigningNamespace::ExampleNamespace,
597 )
598 .unwrap();
599 assert!(signature.verify(
600 serialized_message.as_bytes(),
601 &verifying_key,
602 &SigningNamespace::ExampleNamespace
603 ))
604 }
605}