quantcrypt/cms/asn1/
auth_enveloped_data_content.rs1use crate::cea::common::cea_type::CeaType;
2use cms::{
3 content_info::{CmsVersion, ContentInfo},
4 enveloped_data::{OriginatorInfo, RecipientInfos},
5};
6use der::{Decode, Encode};
7use x509_cert::attr::Attributes;
8
9use crate::{certificates::Certificate, keys::PrivateKey, QuantCryptError};
10
11type Result<T> = std::result::Result<T, QuantCryptError>;
12
13use crate::cms::cms_util::CmsUtil;
14use const_oid::db::rfc5911::ID_CT_AUTH_ENVELOPED_DATA;
15
16use crate::cms::asn1::auth_enveloped_data_builder::ContentEncryptionAlgorithmAead;
17use crate::cms::enveloped_data_builder::EnvelopedDataBuilder;
18
19use super::auth_env_data::AuthEnvelopedData;
20
21pub struct AuthEnvelopedDataContent {
104 version: CmsVersion,
106 originator_info: Option<OriginatorInfo>,
108 recip_infos: RecipientInfos,
110 content: Vec<u8>,
112 unprotected_attrs: Option<Attributes>,
114 auth_attrs: Option<Attributes>,
116}
117
118impl AuthEnvelopedDataContent {
119 pub fn from_file_for_kem_recipient(
132 file: &str,
133 recipient_cert: &Certificate,
134 recipient_private_key: &PrivateKey,
135 ) -> Result<AuthEnvelopedDataContent> {
136 let data = std::fs::read(file).map_err(|_| QuantCryptError::FileReadError)?;
137 AuthEnvelopedDataContent::from_bytes_for_kem_recipient(
138 &data,
139 recipient_cert,
140 recipient_private_key,
141 )
142 }
143
144 pub fn from_bytes_for_kem_recipient(
157 data: &[u8],
158 recipient_cert: &Certificate,
159 recipient_private_key: &PrivateKey,
160 ) -> Result<AuthEnvelopedDataContent> {
161 let ci = if let Ok(content_info) = ContentInfo::from_der(data) {
163 content_info
164 } else {
165 let pem = pem::parse(data).map_err(|_| QuantCryptError::InvalidContent)?;
167 ContentInfo::from_der(pem.contents()).map_err(|_| QuantCryptError::InvalidContent)?
168 };
169
170 if ci.content_type != ID_CT_AUTH_ENVELOPED_DATA {
172 return Err(QuantCryptError::InvalidContent);
173 }
174
175 let enveloped_data = ci
176 .content
177 .to_der()
178 .map_err(|_| QuantCryptError::InvalidEnvelopedData)?;
179
180 let ed = AuthEnvelopedData::from_der(&enveloped_data)
181 .map_err(|_| QuantCryptError::InvalidContent)?;
182
183 let pt = CmsUtil::decrypt_kemri(data, recipient_private_key, recipient_cert)?;
185
186 Ok(AuthEnvelopedDataContent {
187 version: ed.version,
188 originator_info: ed.originator_info,
189 recip_infos: ed.recip_infos,
190 content: pt,
191 unprotected_attrs: ed.unauth_attrs,
192 auth_attrs: ed.auth_attrs,
193 })
194 }
195
196 pub fn get_version(&self) -> CmsVersion {
198 self.version
199 }
200
201 pub fn get_originator_info(&self) -> Option<OriginatorInfo> {
203 self.originator_info.clone()
204 }
205
206 pub fn get_content(&self) -> Vec<u8> {
208 self.content.clone()
209 }
210
211 pub fn get_unprotected_attrs(&self) -> Option<Attributes> {
213 self.unprotected_attrs.clone()
214 }
215
216 pub fn get_auth_attrs(&self) -> Option<Attributes> {
218 self.auth_attrs.clone()
219 }
220
221 pub fn get_recipient_infos(&self) -> RecipientInfos {
223 self.recip_infos.clone()
224 }
225
226 pub fn get_builder(
236 content_encryption_alg: ContentEncryptionAlgorithmAead,
237 ) -> Result<EnvelopedDataBuilder<'static>> {
238 let cea = match content_encryption_alg {
239 ContentEncryptionAlgorithmAead::Aes128Gcm => CeaType::Aes128Gcm,
240 ContentEncryptionAlgorithmAead::Aes192Gcm => CeaType::Aes192Gcm,
241 ContentEncryptionAlgorithmAead::Aes256Gcm => CeaType::Aes256Gcm,
242 };
243 EnvelopedDataBuilder::new(cea, true)
244 }
245}
246
247#[cfg(test)]
248mod tests {
249 use der::{asn1::SetOfVec, Tag, Tagged};
250 use spki::ObjectIdentifier;
251 use x509_cert::attr::{Attribute, AttributeValue};
252
253 use super::*;
254 use crate::{content::UserKeyingMaterial, content::WrapType, kdf::common::kdf_type::KdfType};
255
256 #[test]
257 fn test_auth_enveloped_data_content() {
258 #[cfg(feature = "ipd")]
259 let recipient_cert = Certificate::from_file(
260 "test/data_ipd/cms_cw/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_ee.der",
261 )
262 .unwrap();
263
264 #[cfg(not(feature = "ipd"))]
265 let recipient_cert =
266 Certificate::from_file("test/data/cms/2.16.840.1.101.3.4.4.1_MlKem512_ee.der").unwrap();
267
268 #[cfg(feature = "ipd")]
269 let private_key = PrivateKey::from_file(
270 "test/data_ipd/cms_cw/1.3.6.1.4.1.22554.5.6.1_ML-KEM-512-ipd_priv.der",
271 )
272 .unwrap();
273
274 #[cfg(not(feature = "ipd"))]
275 let private_key =
276 PrivateKey::from_file("test/data/cms/2.16.840.1.101.3.4.4.1_MlKem512_priv.der")
277 .unwrap();
278
279 let ukm = UserKeyingMaterial::new("test".as_bytes()).unwrap();
280 let data = b"abc";
281
282 let attribute_oid = ObjectIdentifier::new("1.3.6.1.4.1.22554.5.6").unwrap();
283 let mut attribute_vals: SetOfVec<AttributeValue> = SetOfVec::<AttributeValue>::new();
284
285 let attr_val = AttributeValue::new(Tag::OctetString, data.to_vec()).unwrap();
286 attribute_vals.insert(attr_val).unwrap();
287
288 let attribute = Attribute {
289 oid: attribute_oid,
290 values: attribute_vals,
291 };
292
293 let mut builder =
294 AuthEnvelopedDataContent::get_builder(ContentEncryptionAlgorithmAead::Aes256Gcm)
295 .unwrap();
296
297 builder
298 .kem_recipient(
299 &recipient_cert,
300 &KdfType::HkdfWithSha256,
301 &WrapType::Aes256,
302 Some(ukm),
303 )
304 .unwrap()
305 .content(data)
306 .unwrap()
307 .unprotected_attribute(&attribute)
308 .unwrap()
309 .auth_attribute(&attribute)
310 .unwrap();
311
312 let content = builder.build().unwrap();
313
314 let edc = AuthEnvelopedDataContent::from_bytes_for_kem_recipient(
316 &content,
317 &recipient_cert,
318 &private_key,
319 )
320 .unwrap();
321
322 assert_eq!(edc.get_content(), data);
323 assert_eq!(edc.get_recipient_infos().0.len(), 1);
324 assert_eq!(edc.get_unprotected_attrs().unwrap().len(), 1);
325
326 let attrs = edc.get_unprotected_attrs().unwrap();
328 let attr = attrs.get(0).unwrap();
329 assert_eq!(attr.oid.to_string(), "1.3.6.1.4.1.22554.5.6");
330 assert_eq!(attr.values.len(), 1);
331 let val: AttributeValue = attr.values.get(0).unwrap().clone();
332 assert_eq!(val.tag(), Tag::OctetString);
333 assert_eq!(val.value(), data);
334
335 let attrs = edc.get_auth_attrs().unwrap();
337 let attr = attrs.get(0).unwrap();
338 assert_eq!(attr.oid.to_string(), "1.3.6.1.4.1.22554.5.6");
339 assert_eq!(attr.values.len(), 1);
340 let val: AttributeValue = attr.values.get(0).unwrap().clone();
341 assert_eq!(val.tag(), Tag::OctetString);
342 assert_eq!(val.value(), data);
343
344 assert_eq!(edc.get_version(), CmsVersion::V0);
346
347 assert_eq!(edc.get_originator_info(), None);
349
350 assert_eq!(edc.get_recipient_infos().0.len(), 1);
352 }
353}