1use anyhow::{Ok, Result};
14use cryptoki::mechanism::Mechanism;
15use cryptoki::object::ObjectHandle;
16use cryptoki::session::Session;
17use std::str::FromStr;
18
19use crate::error::HsmError;
20use crate::util::attribute::{AttrData, AttributeMap, AttributeType, KeyType, ObjectClass};
21use crate::util::wrap::Wrap;
22
23pub enum Secret {
24 Aes,
25 GenericSecret,
26}
27
28impl Secret {
29 const TEMPLATE_AES: &str = r#"{
30 "CKA_CLASS": "CKO_SECRET_KEY",
31 "CKA_DERIVE": true,
32 "CKA_ENCRYPT": true,
33 "CKA_DECRYPT": true,
34 "CKA_KEY_TYPE": "CKK_AES",
35 "CKA_SENSITIVE": true,
36 "CKA_TOKEN": true,
37 }"#;
38
39 const TEMPLATE_GENERIC_SECRET: &str = r#"{
40 "CKA_CLASS": "CKO_SECRET_KEY",
41 "CKA_DERIVE": true,
42 "CKA_KEY_TYPE": "CKK_GENERIC_SECRET",
43 "CKA_SENSITIVE": true,
44 "CKA_TOKEN": true,
45 }"#;
46
47 fn key_template(&self) -> Result<AttributeMap> {
48 let template = match self {
49 Secret::Aes => Self::TEMPLATE_AES,
50 Secret::GenericSecret => Self::TEMPLATE_GENERIC_SECRET,
51 };
52 Ok(AttributeMap::from_str(template).expect("error in TEMPLATE"))
53 }
54
55 fn key_type(&self) -> Result<KeyType> {
56 match self {
57 Secret::Aes => Ok(KeyType::Aes),
58 Secret::GenericSecret => Ok(KeyType::GenericSecret),
59 }
60 }
61
62 fn keygen_mechanism(&self) -> Result<Mechanism<'_>> {
63 match self {
64 Secret::Aes => Ok(Mechanism::AesKeyGen),
65 Secret::GenericSecret => Ok(Mechanism::GenericSecretKeyGen),
66 }
67 }
68
69 fn check(&self, map: &AttributeMap) -> Result<()> {
70 let class: ObjectClass = map
71 .get(&AttributeType::Class)
72 .ok_or_else(|| HsmError::KeyError("Key does not have a class attribute".into()))?
73 .try_into()
74 .map_err(HsmError::AttributeError)?;
75 let key_type: KeyType = map
76 .get(&AttributeType::KeyType)
77 .ok_or_else(|| HsmError::KeyError("Key does not have a key type attribute".into()))?
78 .try_into()
79 .map_err(HsmError::AttributeError)?;
80 if class != ObjectClass::SecretKey || key_type != self.key_type()? {
81 Err(HsmError::KeyError("Key is not a secret key".into()))?;
82 }
83
84 let extractable: bool = map
85 .get(&AttributeType::Extractable)
86 .ok_or_else(|| HsmError::KeyError("Key does not have an extractable attribute".into()))?
87 .try_into()
88 .map_err(HsmError::AttributeError)?;
89 if !extractable {
90 Err(HsmError::KeyError("Key is not extractable".into()))?;
91 }
92 Ok(())
93 }
94
95 pub fn generate(
96 &self,
97 session: &Session,
98 id: AttrData,
99 label: AttrData,
100 attrs: Option<AttributeMap>,
101 ) -> Result<ObjectHandle> {
102 let mut template = self.key_template()?;
103 template.insert(AttributeType::Id, id);
104 template.insert(AttributeType::Label, label);
105 template.insert(AttributeType::ValueLen, 32u64.into());
106
107 if let Some(tpl) = &attrs {
108 template.merge(tpl.clone());
109 }
110
111 log::info!("template = {}", serde_json::to_string_pretty(&template)?);
112
113 let template = template.to_vec()?;
114 Ok(session.generate_key(&self.keygen_mechanism()?, &template)?)
115 }
116
117 pub fn import(
118 &self,
119 session: &Session,
120 id: AttrData,
121 label: AttrData,
122 key: Vec<u8>,
123 attrs: Option<AttributeMap>,
124 ) -> Result<ObjectHandle> {
125 let mut template = self.key_template()?;
126 template.insert(AttributeType::Id, id);
127 template.insert(AttributeType::Label, label);
128
129 if let Some(tpl) = &attrs {
130 template.merge(tpl.clone());
131 }
132
133 log::info!("template = {}", serde_json::to_string_pretty(&template)?);
134
135 template.insert(AttributeType::Value, AttrData::from(key.as_slice()));
136 let template = template.to_vec()?;
137 Ok(session.create_object(&template)?)
138 }
139
140 pub fn export(&self, session: &Session, object: ObjectHandle) -> Result<Vec<u8>> {
141 let map = AttributeMap::from_object(session, object)?;
142 self.check(&map)?;
143 let sensitive: bool = map
144 .get(&AttributeType::Sensitive)
145 .ok_or_else(|| HsmError::KeyError("Key does not have a sensitive attribute".into()))?
146 .try_into()
147 .map_err(HsmError::AttributeError)?;
148 if sensitive {
149 Err(HsmError::KeyError("Key is marked as sensitive".into()))?;
150 }
151
152 let key: Vec<u8> = map
153 .get(&AttributeType::Value)
154 .ok_or_else(|| HsmError::KeyError("Key does not have a value attribute".into()))?
155 .try_into()
156 .map_err(HsmError::AttributeError)?;
157 Ok(key)
158 }
159
160 pub fn wrap_key(
161 &self,
162 session: &Session,
163 object: ObjectHandle,
164 wrap_key_label: Option<&str>,
165 wrap_mechanism: &Wrap,
166 ) -> Result<Vec<u8>> {
167 let map = AttributeMap::from_object(session, object)?;
168 self.check(&map)?;
169 Ok(wrap_mechanism.wrap(session, object, wrap_key_label)?)
170 }
171
172 #[allow(clippy::too_many_arguments)]
173 pub fn unwrap_key(
174 &self,
175 session: &Session,
176 id: AttrData,
177 label: AttrData,
178 key: Vec<u8>,
179 attrs: Option<AttributeMap>,
180 wrap_key_label: Option<&str>,
181 wrap_mechanism: &Wrap,
182 ) -> Result<ObjectHandle> {
183 let mut template = self.key_template()?;
184 template.insert(AttributeType::Id, id);
185 template.insert(AttributeType::Label, label);
186
187 if let Some(tpl) = &attrs {
188 template.merge(tpl.clone());
189 }
190
191 log::info!("template = {}", serde_json::to_string_pretty(&template)?);
192 Ok(wrap_mechanism.unwrap(session, key.as_slice(), wrap_key_label, &template)?)
193 }
194}