Skip to main content

wasi_crypto/symmetric/
key.rs

1use std::sync::{Arc, Mutex, MutexGuard};
2
3use super::*;
4use crate::array_output::*;
5use crate::version::*;
6use crate::CryptoCtx;
7
8#[derive(Clone)]
9pub struct SymmetricKey {
10    inner: Arc<Mutex<Box<dyn SymmetricKeyLike>>>,
11}
12
13pub trait SymmetricKeyBuilder {
14    fn generate(&self, options: Option<SymmetricOptions>) -> Result<SymmetricKey, CryptoError>;
15
16    fn import(&self, raw: &[u8]) -> Result<SymmetricKey, CryptoError>;
17
18    fn key_len(&self) -> Result<usize, CryptoError>;
19}
20
21impl SymmetricKey {
22    pub fn new(symmetric_key_like: Box<dyn SymmetricKeyLike>) -> Self {
23        SymmetricKey {
24            inner: Arc::new(Mutex::new(symmetric_key_like)),
25        }
26    }
27
28    pub fn inner(&self) -> MutexGuard<'_, Box<dyn SymmetricKeyLike>> {
29        self.inner.lock().unwrap()
30    }
31
32    pub fn locked<T, U>(&self, mut f: T) -> U
33    where
34        T: FnMut(MutexGuard<'_, Box<dyn SymmetricKeyLike>>) -> U,
35    {
36        f(self.inner())
37    }
38
39    pub fn alg(&self) -> SymmetricAlgorithm {
40        self.inner().alg()
41    }
42
43    pub fn builder(alg_str: &str) -> Result<Box<dyn SymmetricKeyBuilder>, CryptoError> {
44        let alg = SymmetricAlgorithm::try_from(alg_str)?;
45        let builder = match alg {
46            SymmetricAlgorithm::HmacSha256 | SymmetricAlgorithm::HmacSha512 => {
47                HmacSha2SymmetricKeyBuilder::new(alg)
48            }
49            SymmetricAlgorithm::HkdfSha256Expand
50            | SymmetricAlgorithm::HkdfSha256Extract
51            | SymmetricAlgorithm::HkdfSha512Expand
52            | SymmetricAlgorithm::HkdfSha512Extract => HkdfSymmetricKeyBuilder::new(alg),
53            SymmetricAlgorithm::Aes128Gcm | SymmetricAlgorithm::Aes256Gcm => {
54                AesGcmSymmetricKeyBuilder::new(alg)
55            }
56            SymmetricAlgorithm::Xoodyak128 | SymmetricAlgorithm::Xoodyak160 => {
57                XoodyakSymmetricKeyBuilder::new(alg)
58            }
59            SymmetricAlgorithm::ChaCha20Poly1305 | SymmetricAlgorithm::XChaCha20Poly1305 => {
60                ChaChaPolySymmetricKeyBuilder::new(alg)
61            }
62            _ => bail!(CryptoError::InvalidOperation),
63        };
64        Ok(builder)
65    }
66
67    fn generate(
68        alg_str: &str,
69        options: Option<SymmetricOptions>,
70    ) -> Result<SymmetricKey, CryptoError> {
71        let builder = Self::builder(alg_str)?;
72        builder.generate(options)
73    }
74
75    fn import(alg_str: &str, raw: &[u8]) -> Result<SymmetricKey, CryptoError> {
76        let builder = Self::builder(alg_str)?;
77        builder.import(raw)
78    }
79}
80
81pub trait SymmetricKeyLike: Sync + Send {
82    fn as_any(&self) -> &dyn Any;
83    fn alg(&self) -> SymmetricAlgorithm;
84    fn as_raw(&self) -> Result<&[u8], CryptoError>;
85}
86
87impl CryptoCtx {
88    pub fn symmetric_key_generate(
89        &self,
90        alg_str: &str,
91        options_handle: Option<Handle>,
92    ) -> Result<Handle, CryptoError> {
93        let options = match options_handle {
94            None => None,
95            Some(options_handle) => {
96                Some(self.handles.options.get(options_handle)?.into_symmetric()?)
97            }
98        };
99        let symmetric_key = SymmetricKey::generate(alg_str, options)?;
100        let handle = self.handles.symmetric_key.register(symmetric_key)?;
101        Ok(handle)
102    }
103
104    pub fn symmetric_key_import(&self, alg_str: &str, raw: &[u8]) -> Result<Handle, CryptoError> {
105        let symmetric_key = SymmetricKey::import(alg_str, raw)?;
106        let handle = self.handles.symmetric_key.register(symmetric_key)?;
107        Ok(handle)
108    }
109
110    pub fn symmetric_key_export(
111        &self,
112        symmetric_key_handle: Handle,
113    ) -> Result<Handle, CryptoError> {
114        let symmetric_key = self.handles.symmetric_key.get(symmetric_key_handle)?;
115        let array_output_handle =
116            ArrayOutput::register(&self.handles, symmetric_key.inner().as_raw()?.to_vec())?;
117        Ok(array_output_handle)
118    }
119
120    pub fn symmetric_key_id(
121        &self,
122        symmetric_key_handle: Handle,
123    ) -> Result<(Vec<u8>, Version), CryptoError> {
124        let _symmetric_key = self.handles.symmetric_key.get(symmetric_key_handle)?;
125        bail!(CryptoError::UnsupportedFeature)
126    }
127
128    pub fn symmetric_key_close(&self, symmetric_key_handle: Handle) -> Result<(), CryptoError> {
129        self.handles.symmetric_key.close(symmetric_key_handle)
130    }
131}