trz_gateway_common/x509/signed_extension/
make.rs

1use nameth::NamedEnumValues as _;
2use nameth::nameth;
3use openssl::asn1::Asn1OctetString;
4use openssl::cms::CmsContentInfo;
5use openssl::error::ErrorStack;
6use openssl::stack::StackRef;
7use openssl::x509::X509;
8use openssl::x509::X509Extension;
9
10use super::MakeCertificatePropertiesHashError;
11use super::cms_options;
12use super::make_certificate_properties_hash;
13use super::signed_extension_oid;
14use crate::certificate_info::X509CertificateInfoRef;
15use crate::x509::validity::Validity;
16
17/// Creates a custom [X509Extension] signed by our issuer.
18pub fn make_signed_extension(
19    common_name: &str,
20    validity: Validity,
21    public_key_der: &[u8],
22    intermediate_certificates: Option<&StackRef<X509>>,
23    signer: X509CertificateInfoRef,
24) -> Result<X509Extension, MakeSignedExtensionError> {
25    let certificate_properties_hash =
26        make_certificate_properties_hash(common_name, validity, public_key_der)?;
27    let signed_cms = CmsContentInfo::sign(
28        Some(signer.certificate),
29        Some(signer.private_key),
30        intermediate_certificates,
31        Some(&certificate_properties_hash),
32        cms_options(),
33    )
34    .map_err(MakeSignedExtensionError::CmsSign)?;
35    let signed_cms_der = signed_cms
36        .to_der()
37        .map_err(MakeSignedExtensionError::CmsToDer)?;
38    let der_encoded_extension = Asn1OctetString::new_from_bytes(&signed_cms_der)
39        .map_err(MakeSignedExtensionError::Asn1OctetString)?;
40    let x509_extension =
41        X509Extension::new_from_der(signed_extension_oid(), false, &der_encoded_extension)
42            .map_err(MakeSignedExtensionError::X509Extension)?;
43    Ok(x509_extension)
44}
45
46#[nameth]
47#[derive(thiserror::Error, Debug)]
48pub enum MakeSignedExtensionError {
49    #[error("[{n}] {0}", n = self.name())]
50    CertificatePropertiesHash(#[from] MakeCertificatePropertiesHashError),
51
52    #[error("[{n}] Failed sign the certificate properties hash: {0}", n = self.name())]
53    CmsSign(ErrorStack),
54
55    #[error("[{n}] Failed convert signed CMS to DER: {0}", n = self.name())]
56    CmsToDer(ErrorStack),
57
58    #[error("[{n}] Failed to convert the signed CMS DER into a Asn1OctetString: {0}", n = self.name())]
59    Asn1OctetString(ErrorStack),
60
61    #[error("[{n}] Failed to make the X509Extension: {0}", n = self.name())]
62    X509Extension(ErrorStack),
63}