192f3ab15Sopenharmony_ci//! Add extensions to an `X509` certificate or certificate request.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! The extensions defined for X.509 v3 certificates provide methods for
492f3ab15Sopenharmony_ci//! associating additional attributes with users or public keys and for
592f3ab15Sopenharmony_ci//! managing relationships between CAs. The extensions created using this
692f3ab15Sopenharmony_ci//! module can be used with `X509v3Context` objects.
792f3ab15Sopenharmony_ci//!
892f3ab15Sopenharmony_ci//! # Example
992f3ab15Sopenharmony_ci//!
1092f3ab15Sopenharmony_ci//! ```rust
1192f3ab15Sopenharmony_ci//! use openssl::x509::extension::BasicConstraints;
1292f3ab15Sopenharmony_ci//! use openssl::x509::X509Extension;
1392f3ab15Sopenharmony_ci//!
1492f3ab15Sopenharmony_ci//! let mut bc = BasicConstraints::new();
1592f3ab15Sopenharmony_ci//! let bc = bc.critical().ca().pathlen(1);
1692f3ab15Sopenharmony_ci//!
1792f3ab15Sopenharmony_ci//! let extension: X509Extension = bc.build().unwrap();
1892f3ab15Sopenharmony_ci//! ```
1992f3ab15Sopenharmony_ciuse std::fmt::Write;
2092f3ab15Sopenharmony_ci
2192f3ab15Sopenharmony_ciuse crate::asn1::Asn1Object;
2292f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
2392f3ab15Sopenharmony_ciuse crate::nid::Nid;
2492f3ab15Sopenharmony_ciuse crate::x509::{GeneralName, Stack, X509Extension, X509v3Context};
2592f3ab15Sopenharmony_ciuse foreign_types::ForeignType;
2692f3ab15Sopenharmony_ci
2792f3ab15Sopenharmony_ci/// An extension which indicates whether a certificate is a CA certificate.
2892f3ab15Sopenharmony_cipub struct BasicConstraints {
2992f3ab15Sopenharmony_ci    critical: bool,
3092f3ab15Sopenharmony_ci    ca: bool,
3192f3ab15Sopenharmony_ci    pathlen: Option<u32>,
3292f3ab15Sopenharmony_ci}
3392f3ab15Sopenharmony_ci
3492f3ab15Sopenharmony_ciimpl Default for BasicConstraints {
3592f3ab15Sopenharmony_ci    fn default() -> BasicConstraints {
3692f3ab15Sopenharmony_ci        BasicConstraints::new()
3792f3ab15Sopenharmony_ci    }
3892f3ab15Sopenharmony_ci}
3992f3ab15Sopenharmony_ci
4092f3ab15Sopenharmony_ciimpl BasicConstraints {
4192f3ab15Sopenharmony_ci    /// Construct a new `BasicConstraints` extension.
4292f3ab15Sopenharmony_ci    pub fn new() -> BasicConstraints {
4392f3ab15Sopenharmony_ci        BasicConstraints {
4492f3ab15Sopenharmony_ci            critical: false,
4592f3ab15Sopenharmony_ci            ca: false,
4692f3ab15Sopenharmony_ci            pathlen: None,
4792f3ab15Sopenharmony_ci        }
4892f3ab15Sopenharmony_ci    }
4992f3ab15Sopenharmony_ci
5092f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
5192f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut BasicConstraints {
5292f3ab15Sopenharmony_ci        self.critical = true;
5392f3ab15Sopenharmony_ci        self
5492f3ab15Sopenharmony_ci    }
5592f3ab15Sopenharmony_ci
5692f3ab15Sopenharmony_ci    /// Sets the `ca` flag to `true`.
5792f3ab15Sopenharmony_ci    pub fn ca(&mut self) -> &mut BasicConstraints {
5892f3ab15Sopenharmony_ci        self.ca = true;
5992f3ab15Sopenharmony_ci        self
6092f3ab15Sopenharmony_ci    }
6192f3ab15Sopenharmony_ci
6292f3ab15Sopenharmony_ci    /// Sets the `pathlen` to an optional non-negative value. The `pathlen` is the
6392f3ab15Sopenharmony_ci    /// maximum number of CAs that can appear below this one in a chain.
6492f3ab15Sopenharmony_ci    pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints {
6592f3ab15Sopenharmony_ci        self.pathlen = Some(pathlen);
6692f3ab15Sopenharmony_ci        self
6792f3ab15Sopenharmony_ci    }
6892f3ab15Sopenharmony_ci
6992f3ab15Sopenharmony_ci    /// Return the `BasicConstraints` extension as an `X509Extension`.
7092f3ab15Sopenharmony_ci    // Temporarily silence the deprecation warning - this should be ported to
7192f3ab15Sopenharmony_ci    // `X509Extension::new_internal`.
7292f3ab15Sopenharmony_ci    #[allow(deprecated)]
7392f3ab15Sopenharmony_ci    pub fn build(&self) -> Result<X509Extension, ErrorStack> {
7492f3ab15Sopenharmony_ci        let mut value = String::new();
7592f3ab15Sopenharmony_ci        if self.critical {
7692f3ab15Sopenharmony_ci            value.push_str("critical,");
7792f3ab15Sopenharmony_ci        }
7892f3ab15Sopenharmony_ci        value.push_str("CA:");
7992f3ab15Sopenharmony_ci        if self.ca {
8092f3ab15Sopenharmony_ci            value.push_str("TRUE");
8192f3ab15Sopenharmony_ci        } else {
8292f3ab15Sopenharmony_ci            value.push_str("FALSE");
8392f3ab15Sopenharmony_ci        }
8492f3ab15Sopenharmony_ci        if let Some(pathlen) = self.pathlen {
8592f3ab15Sopenharmony_ci            write!(value, ",pathlen:{}", pathlen).unwrap();
8692f3ab15Sopenharmony_ci        }
8792f3ab15Sopenharmony_ci        X509Extension::new_nid(None, None, Nid::BASIC_CONSTRAINTS, &value)
8892f3ab15Sopenharmony_ci    }
8992f3ab15Sopenharmony_ci}
9092f3ab15Sopenharmony_ci
9192f3ab15Sopenharmony_ci/// An extension consisting of a list of names of the permitted key usages.
9292f3ab15Sopenharmony_cipub struct KeyUsage {
9392f3ab15Sopenharmony_ci    critical: bool,
9492f3ab15Sopenharmony_ci    digital_signature: bool,
9592f3ab15Sopenharmony_ci    non_repudiation: bool,
9692f3ab15Sopenharmony_ci    key_encipherment: bool,
9792f3ab15Sopenharmony_ci    data_encipherment: bool,
9892f3ab15Sopenharmony_ci    key_agreement: bool,
9992f3ab15Sopenharmony_ci    key_cert_sign: bool,
10092f3ab15Sopenharmony_ci    crl_sign: bool,
10192f3ab15Sopenharmony_ci    encipher_only: bool,
10292f3ab15Sopenharmony_ci    decipher_only: bool,
10392f3ab15Sopenharmony_ci}
10492f3ab15Sopenharmony_ci
10592f3ab15Sopenharmony_ciimpl Default for KeyUsage {
10692f3ab15Sopenharmony_ci    fn default() -> KeyUsage {
10792f3ab15Sopenharmony_ci        KeyUsage::new()
10892f3ab15Sopenharmony_ci    }
10992f3ab15Sopenharmony_ci}
11092f3ab15Sopenharmony_ci
11192f3ab15Sopenharmony_ciimpl KeyUsage {
11292f3ab15Sopenharmony_ci    /// Construct a new `KeyUsage` extension.
11392f3ab15Sopenharmony_ci    pub fn new() -> KeyUsage {
11492f3ab15Sopenharmony_ci        KeyUsage {
11592f3ab15Sopenharmony_ci            critical: false,
11692f3ab15Sopenharmony_ci            digital_signature: false,
11792f3ab15Sopenharmony_ci            non_repudiation: false,
11892f3ab15Sopenharmony_ci            key_encipherment: false,
11992f3ab15Sopenharmony_ci            data_encipherment: false,
12092f3ab15Sopenharmony_ci            key_agreement: false,
12192f3ab15Sopenharmony_ci            key_cert_sign: false,
12292f3ab15Sopenharmony_ci            crl_sign: false,
12392f3ab15Sopenharmony_ci            encipher_only: false,
12492f3ab15Sopenharmony_ci            decipher_only: false,
12592f3ab15Sopenharmony_ci        }
12692f3ab15Sopenharmony_ci    }
12792f3ab15Sopenharmony_ci
12892f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
12992f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut KeyUsage {
13092f3ab15Sopenharmony_ci        self.critical = true;
13192f3ab15Sopenharmony_ci        self
13292f3ab15Sopenharmony_ci    }
13392f3ab15Sopenharmony_ci
13492f3ab15Sopenharmony_ci    /// Sets the `digitalSignature` flag to `true`.
13592f3ab15Sopenharmony_ci    pub fn digital_signature(&mut self) -> &mut KeyUsage {
13692f3ab15Sopenharmony_ci        self.digital_signature = true;
13792f3ab15Sopenharmony_ci        self
13892f3ab15Sopenharmony_ci    }
13992f3ab15Sopenharmony_ci
14092f3ab15Sopenharmony_ci    /// Sets the `nonRepudiation` flag to `true`.
14192f3ab15Sopenharmony_ci    pub fn non_repudiation(&mut self) -> &mut KeyUsage {
14292f3ab15Sopenharmony_ci        self.non_repudiation = true;
14392f3ab15Sopenharmony_ci        self
14492f3ab15Sopenharmony_ci    }
14592f3ab15Sopenharmony_ci
14692f3ab15Sopenharmony_ci    /// Sets the `keyEncipherment` flag to `true`.
14792f3ab15Sopenharmony_ci    pub fn key_encipherment(&mut self) -> &mut KeyUsage {
14892f3ab15Sopenharmony_ci        self.key_encipherment = true;
14992f3ab15Sopenharmony_ci        self
15092f3ab15Sopenharmony_ci    }
15192f3ab15Sopenharmony_ci
15292f3ab15Sopenharmony_ci    /// Sets the `dataEncipherment` flag to `true`.
15392f3ab15Sopenharmony_ci    pub fn data_encipherment(&mut self) -> &mut KeyUsage {
15492f3ab15Sopenharmony_ci        self.data_encipherment = true;
15592f3ab15Sopenharmony_ci        self
15692f3ab15Sopenharmony_ci    }
15792f3ab15Sopenharmony_ci
15892f3ab15Sopenharmony_ci    /// Sets the `keyAgreement` flag to `true`.
15992f3ab15Sopenharmony_ci    pub fn key_agreement(&mut self) -> &mut KeyUsage {
16092f3ab15Sopenharmony_ci        self.key_agreement = true;
16192f3ab15Sopenharmony_ci        self
16292f3ab15Sopenharmony_ci    }
16392f3ab15Sopenharmony_ci
16492f3ab15Sopenharmony_ci    /// Sets the `keyCertSign` flag to `true`.
16592f3ab15Sopenharmony_ci    pub fn key_cert_sign(&mut self) -> &mut KeyUsage {
16692f3ab15Sopenharmony_ci        self.key_cert_sign = true;
16792f3ab15Sopenharmony_ci        self
16892f3ab15Sopenharmony_ci    }
16992f3ab15Sopenharmony_ci
17092f3ab15Sopenharmony_ci    /// Sets the `cRLSign` flag to `true`.
17192f3ab15Sopenharmony_ci    pub fn crl_sign(&mut self) -> &mut KeyUsage {
17292f3ab15Sopenharmony_ci        self.crl_sign = true;
17392f3ab15Sopenharmony_ci        self
17492f3ab15Sopenharmony_ci    }
17592f3ab15Sopenharmony_ci
17692f3ab15Sopenharmony_ci    /// Sets the `encipherOnly` flag to `true`.
17792f3ab15Sopenharmony_ci    pub fn encipher_only(&mut self) -> &mut KeyUsage {
17892f3ab15Sopenharmony_ci        self.encipher_only = true;
17992f3ab15Sopenharmony_ci        self
18092f3ab15Sopenharmony_ci    }
18192f3ab15Sopenharmony_ci
18292f3ab15Sopenharmony_ci    /// Sets the `decipherOnly` flag to `true`.
18392f3ab15Sopenharmony_ci    pub fn decipher_only(&mut self) -> &mut KeyUsage {
18492f3ab15Sopenharmony_ci        self.decipher_only = true;
18592f3ab15Sopenharmony_ci        self
18692f3ab15Sopenharmony_ci    }
18792f3ab15Sopenharmony_ci
18892f3ab15Sopenharmony_ci    /// Return the `KeyUsage` extension as an `X509Extension`.
18992f3ab15Sopenharmony_ci    // Temporarily silence the deprecation warning - this should be ported to
19092f3ab15Sopenharmony_ci    // `X509Extension::new_internal`.
19192f3ab15Sopenharmony_ci    #[allow(deprecated)]
19292f3ab15Sopenharmony_ci    pub fn build(&self) -> Result<X509Extension, ErrorStack> {
19392f3ab15Sopenharmony_ci        let mut value = String::new();
19492f3ab15Sopenharmony_ci        let mut first = true;
19592f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.critical, "critical");
19692f3ab15Sopenharmony_ci        append(
19792f3ab15Sopenharmony_ci            &mut value,
19892f3ab15Sopenharmony_ci            &mut first,
19992f3ab15Sopenharmony_ci            self.digital_signature,
20092f3ab15Sopenharmony_ci            "digitalSignature",
20192f3ab15Sopenharmony_ci        );
20292f3ab15Sopenharmony_ci        append(
20392f3ab15Sopenharmony_ci            &mut value,
20492f3ab15Sopenharmony_ci            &mut first,
20592f3ab15Sopenharmony_ci            self.non_repudiation,
20692f3ab15Sopenharmony_ci            "nonRepudiation",
20792f3ab15Sopenharmony_ci        );
20892f3ab15Sopenharmony_ci        append(
20992f3ab15Sopenharmony_ci            &mut value,
21092f3ab15Sopenharmony_ci            &mut first,
21192f3ab15Sopenharmony_ci            self.key_encipherment,
21292f3ab15Sopenharmony_ci            "keyEncipherment",
21392f3ab15Sopenharmony_ci        );
21492f3ab15Sopenharmony_ci        append(
21592f3ab15Sopenharmony_ci            &mut value,
21692f3ab15Sopenharmony_ci            &mut first,
21792f3ab15Sopenharmony_ci            self.data_encipherment,
21892f3ab15Sopenharmony_ci            "dataEncipherment",
21992f3ab15Sopenharmony_ci        );
22092f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.key_agreement, "keyAgreement");
22192f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.key_cert_sign, "keyCertSign");
22292f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.crl_sign, "cRLSign");
22392f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.encipher_only, "encipherOnly");
22492f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.decipher_only, "decipherOnly");
22592f3ab15Sopenharmony_ci        X509Extension::new_nid(None, None, Nid::KEY_USAGE, &value)
22692f3ab15Sopenharmony_ci    }
22792f3ab15Sopenharmony_ci}
22892f3ab15Sopenharmony_ci
22992f3ab15Sopenharmony_ci/// An extension consisting of a list of usages indicating purposes
23092f3ab15Sopenharmony_ci/// for which the certificate public key can be used for.
23192f3ab15Sopenharmony_cipub struct ExtendedKeyUsage {
23292f3ab15Sopenharmony_ci    critical: bool,
23392f3ab15Sopenharmony_ci    items: Vec<String>,
23492f3ab15Sopenharmony_ci}
23592f3ab15Sopenharmony_ci
23692f3ab15Sopenharmony_ciimpl Default for ExtendedKeyUsage {
23792f3ab15Sopenharmony_ci    fn default() -> ExtendedKeyUsage {
23892f3ab15Sopenharmony_ci        ExtendedKeyUsage::new()
23992f3ab15Sopenharmony_ci    }
24092f3ab15Sopenharmony_ci}
24192f3ab15Sopenharmony_ci
24292f3ab15Sopenharmony_ciimpl ExtendedKeyUsage {
24392f3ab15Sopenharmony_ci    /// Construct a new `ExtendedKeyUsage` extension.
24492f3ab15Sopenharmony_ci    pub fn new() -> ExtendedKeyUsage {
24592f3ab15Sopenharmony_ci        ExtendedKeyUsage {
24692f3ab15Sopenharmony_ci            critical: false,
24792f3ab15Sopenharmony_ci            items: vec![],
24892f3ab15Sopenharmony_ci        }
24992f3ab15Sopenharmony_ci    }
25092f3ab15Sopenharmony_ci
25192f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
25292f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut ExtendedKeyUsage {
25392f3ab15Sopenharmony_ci        self.critical = true;
25492f3ab15Sopenharmony_ci        self
25592f3ab15Sopenharmony_ci    }
25692f3ab15Sopenharmony_ci
25792f3ab15Sopenharmony_ci    /// Sets the `serverAuth` flag to `true`.
25892f3ab15Sopenharmony_ci    pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage {
25992f3ab15Sopenharmony_ci        self.other("serverAuth")
26092f3ab15Sopenharmony_ci    }
26192f3ab15Sopenharmony_ci
26292f3ab15Sopenharmony_ci    /// Sets the `clientAuth` flag to `true`.
26392f3ab15Sopenharmony_ci    pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage {
26492f3ab15Sopenharmony_ci        self.other("clientAuth")
26592f3ab15Sopenharmony_ci    }
26692f3ab15Sopenharmony_ci
26792f3ab15Sopenharmony_ci    /// Sets the `codeSigning` flag to `true`.
26892f3ab15Sopenharmony_ci    pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage {
26992f3ab15Sopenharmony_ci        self.other("codeSigning")
27092f3ab15Sopenharmony_ci    }
27192f3ab15Sopenharmony_ci
27292f3ab15Sopenharmony_ci    /// Sets the `emailProtection` flag to `true`.
27392f3ab15Sopenharmony_ci    pub fn email_protection(&mut self) -> &mut ExtendedKeyUsage {
27492f3ab15Sopenharmony_ci        self.other("emailProtection")
27592f3ab15Sopenharmony_ci    }
27692f3ab15Sopenharmony_ci
27792f3ab15Sopenharmony_ci    /// Sets the `timeStamping` flag to `true`.
27892f3ab15Sopenharmony_ci    pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage {
27992f3ab15Sopenharmony_ci        self.other("timeStamping")
28092f3ab15Sopenharmony_ci    }
28192f3ab15Sopenharmony_ci
28292f3ab15Sopenharmony_ci    /// Sets the `msCodeInd` flag to `true`.
28392f3ab15Sopenharmony_ci    pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage {
28492f3ab15Sopenharmony_ci        self.other("msCodeInd")
28592f3ab15Sopenharmony_ci    }
28692f3ab15Sopenharmony_ci
28792f3ab15Sopenharmony_ci    /// Sets the `msCodeCom` flag to `true`.
28892f3ab15Sopenharmony_ci    pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage {
28992f3ab15Sopenharmony_ci        self.other("msCodeCom")
29092f3ab15Sopenharmony_ci    }
29192f3ab15Sopenharmony_ci
29292f3ab15Sopenharmony_ci    /// Sets the `msCTLSign` flag to `true`.
29392f3ab15Sopenharmony_ci    pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage {
29492f3ab15Sopenharmony_ci        self.other("msCTLSign")
29592f3ab15Sopenharmony_ci    }
29692f3ab15Sopenharmony_ci
29792f3ab15Sopenharmony_ci    /// Sets the `msSGC` flag to `true`.
29892f3ab15Sopenharmony_ci    pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage {
29992f3ab15Sopenharmony_ci        self.other("msSGC")
30092f3ab15Sopenharmony_ci    }
30192f3ab15Sopenharmony_ci
30292f3ab15Sopenharmony_ci    /// Sets the `msEFS` flag to `true`.
30392f3ab15Sopenharmony_ci    pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage {
30492f3ab15Sopenharmony_ci        self.other("msEFS")
30592f3ab15Sopenharmony_ci    }
30692f3ab15Sopenharmony_ci
30792f3ab15Sopenharmony_ci    /// Sets the `nsSGC` flag to `true`.
30892f3ab15Sopenharmony_ci    pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage {
30992f3ab15Sopenharmony_ci        self.other("nsSGC")
31092f3ab15Sopenharmony_ci    }
31192f3ab15Sopenharmony_ci
31292f3ab15Sopenharmony_ci    /// Sets a flag not already defined.
31392f3ab15Sopenharmony_ci    pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage {
31492f3ab15Sopenharmony_ci        self.items.push(other.to_string());
31592f3ab15Sopenharmony_ci        self
31692f3ab15Sopenharmony_ci    }
31792f3ab15Sopenharmony_ci
31892f3ab15Sopenharmony_ci    /// Return the `ExtendedKeyUsage` extension as an `X509Extension`.
31992f3ab15Sopenharmony_ci    pub fn build(&self) -> Result<X509Extension, ErrorStack> {
32092f3ab15Sopenharmony_ci        let mut stack = Stack::new()?;
32192f3ab15Sopenharmony_ci        for item in &self.items {
32292f3ab15Sopenharmony_ci            stack.push(Asn1Object::from_str(item)?)?;
32392f3ab15Sopenharmony_ci        }
32492f3ab15Sopenharmony_ci        unsafe {
32592f3ab15Sopenharmony_ci            X509Extension::new_internal(Nid::EXT_KEY_USAGE, self.critical, stack.as_ptr().cast())
32692f3ab15Sopenharmony_ci        }
32792f3ab15Sopenharmony_ci    }
32892f3ab15Sopenharmony_ci}
32992f3ab15Sopenharmony_ci
33092f3ab15Sopenharmony_ci/// An extension that provides a means of identifying certificates that contain a
33192f3ab15Sopenharmony_ci/// particular public key.
33292f3ab15Sopenharmony_cipub struct SubjectKeyIdentifier {
33392f3ab15Sopenharmony_ci    critical: bool,
33492f3ab15Sopenharmony_ci}
33592f3ab15Sopenharmony_ci
33692f3ab15Sopenharmony_ciimpl Default for SubjectKeyIdentifier {
33792f3ab15Sopenharmony_ci    fn default() -> SubjectKeyIdentifier {
33892f3ab15Sopenharmony_ci        SubjectKeyIdentifier::new()
33992f3ab15Sopenharmony_ci    }
34092f3ab15Sopenharmony_ci}
34192f3ab15Sopenharmony_ci
34292f3ab15Sopenharmony_ciimpl SubjectKeyIdentifier {
34392f3ab15Sopenharmony_ci    /// Construct a new `SubjectKeyIdentifier` extension.
34492f3ab15Sopenharmony_ci    pub fn new() -> SubjectKeyIdentifier {
34592f3ab15Sopenharmony_ci        SubjectKeyIdentifier { critical: false }
34692f3ab15Sopenharmony_ci    }
34792f3ab15Sopenharmony_ci
34892f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
34992f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut SubjectKeyIdentifier {
35092f3ab15Sopenharmony_ci        self.critical = true;
35192f3ab15Sopenharmony_ci        self
35292f3ab15Sopenharmony_ci    }
35392f3ab15Sopenharmony_ci
35492f3ab15Sopenharmony_ci    /// Return a `SubjectKeyIdentifier` extension as an `X509Extension`.
35592f3ab15Sopenharmony_ci    // Temporarily silence the deprecation warning - this should be ported to
35692f3ab15Sopenharmony_ci    // `X509Extension::new_internal`.
35792f3ab15Sopenharmony_ci    #[allow(deprecated)]
35892f3ab15Sopenharmony_ci    pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
35992f3ab15Sopenharmony_ci        let mut value = String::new();
36092f3ab15Sopenharmony_ci        let mut first = true;
36192f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.critical, "critical");
36292f3ab15Sopenharmony_ci        append(&mut value, &mut first, true, "hash");
36392f3ab15Sopenharmony_ci        X509Extension::new_nid(None, Some(ctx), Nid::SUBJECT_KEY_IDENTIFIER, &value)
36492f3ab15Sopenharmony_ci    }
36592f3ab15Sopenharmony_ci}
36692f3ab15Sopenharmony_ci
36792f3ab15Sopenharmony_ci/// An extension that provides a means of identifying the public key corresponding
36892f3ab15Sopenharmony_ci/// to the private key used to sign a CRL.
36992f3ab15Sopenharmony_cipub struct AuthorityKeyIdentifier {
37092f3ab15Sopenharmony_ci    critical: bool,
37192f3ab15Sopenharmony_ci    keyid: Option<bool>,
37292f3ab15Sopenharmony_ci    issuer: Option<bool>,
37392f3ab15Sopenharmony_ci}
37492f3ab15Sopenharmony_ci
37592f3ab15Sopenharmony_ciimpl Default for AuthorityKeyIdentifier {
37692f3ab15Sopenharmony_ci    fn default() -> AuthorityKeyIdentifier {
37792f3ab15Sopenharmony_ci        AuthorityKeyIdentifier::new()
37892f3ab15Sopenharmony_ci    }
37992f3ab15Sopenharmony_ci}
38092f3ab15Sopenharmony_ci
38192f3ab15Sopenharmony_ciimpl AuthorityKeyIdentifier {
38292f3ab15Sopenharmony_ci    /// Construct a new `AuthorityKeyIdentifier` extension.
38392f3ab15Sopenharmony_ci    pub fn new() -> AuthorityKeyIdentifier {
38492f3ab15Sopenharmony_ci        AuthorityKeyIdentifier {
38592f3ab15Sopenharmony_ci            critical: false,
38692f3ab15Sopenharmony_ci            keyid: None,
38792f3ab15Sopenharmony_ci            issuer: None,
38892f3ab15Sopenharmony_ci        }
38992f3ab15Sopenharmony_ci    }
39092f3ab15Sopenharmony_ci
39192f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
39292f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier {
39392f3ab15Sopenharmony_ci        self.critical = true;
39492f3ab15Sopenharmony_ci        self
39592f3ab15Sopenharmony_ci    }
39692f3ab15Sopenharmony_ci
39792f3ab15Sopenharmony_ci    /// Sets the `keyid` flag.
39892f3ab15Sopenharmony_ci    pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
39992f3ab15Sopenharmony_ci        self.keyid = Some(always);
40092f3ab15Sopenharmony_ci        self
40192f3ab15Sopenharmony_ci    }
40292f3ab15Sopenharmony_ci
40392f3ab15Sopenharmony_ci    /// Sets the `issuer` flag.
40492f3ab15Sopenharmony_ci    pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier {
40592f3ab15Sopenharmony_ci        self.issuer = Some(always);
40692f3ab15Sopenharmony_ci        self
40792f3ab15Sopenharmony_ci    }
40892f3ab15Sopenharmony_ci
40992f3ab15Sopenharmony_ci    /// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`.
41092f3ab15Sopenharmony_ci    // Temporarily silence the deprecation warning - this should be ported to
41192f3ab15Sopenharmony_ci    // `X509Extension::new_internal`.
41292f3ab15Sopenharmony_ci    #[allow(deprecated)]
41392f3ab15Sopenharmony_ci    pub fn build(&self, ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
41492f3ab15Sopenharmony_ci        let mut value = String::new();
41592f3ab15Sopenharmony_ci        let mut first = true;
41692f3ab15Sopenharmony_ci        append(&mut value, &mut first, self.critical, "critical");
41792f3ab15Sopenharmony_ci        match self.keyid {
41892f3ab15Sopenharmony_ci            Some(true) => append(&mut value, &mut first, true, "keyid:always"),
41992f3ab15Sopenharmony_ci            Some(false) => append(&mut value, &mut first, true, "keyid"),
42092f3ab15Sopenharmony_ci            None => {}
42192f3ab15Sopenharmony_ci        }
42292f3ab15Sopenharmony_ci        match self.issuer {
42392f3ab15Sopenharmony_ci            Some(true) => append(&mut value, &mut first, true, "issuer:always"),
42492f3ab15Sopenharmony_ci            Some(false) => append(&mut value, &mut first, true, "issuer"),
42592f3ab15Sopenharmony_ci            None => {}
42692f3ab15Sopenharmony_ci        }
42792f3ab15Sopenharmony_ci        X509Extension::new_nid(None, Some(ctx), Nid::AUTHORITY_KEY_IDENTIFIER, &value)
42892f3ab15Sopenharmony_ci    }
42992f3ab15Sopenharmony_ci}
43092f3ab15Sopenharmony_ci
43192f3ab15Sopenharmony_cienum RustGeneralName {
43292f3ab15Sopenharmony_ci    Dns(String),
43392f3ab15Sopenharmony_ci    Email(String),
43492f3ab15Sopenharmony_ci    Uri(String),
43592f3ab15Sopenharmony_ci    Ip(String),
43692f3ab15Sopenharmony_ci    Rid(String),
43792f3ab15Sopenharmony_ci    OtherName(Asn1Object, Vec<u8>),
43892f3ab15Sopenharmony_ci}
43992f3ab15Sopenharmony_ci
44092f3ab15Sopenharmony_ci/// An extension that allows additional identities to be bound to the subject
44192f3ab15Sopenharmony_ci/// of the certificate.
44292f3ab15Sopenharmony_cipub struct SubjectAlternativeName {
44392f3ab15Sopenharmony_ci    critical: bool,
44492f3ab15Sopenharmony_ci    items: Vec<RustGeneralName>,
44592f3ab15Sopenharmony_ci}
44692f3ab15Sopenharmony_ci
44792f3ab15Sopenharmony_ciimpl Default for SubjectAlternativeName {
44892f3ab15Sopenharmony_ci    fn default() -> SubjectAlternativeName {
44992f3ab15Sopenharmony_ci        SubjectAlternativeName::new()
45092f3ab15Sopenharmony_ci    }
45192f3ab15Sopenharmony_ci}
45292f3ab15Sopenharmony_ci
45392f3ab15Sopenharmony_ciimpl SubjectAlternativeName {
45492f3ab15Sopenharmony_ci    /// Construct a new `SubjectAlternativeName` extension.
45592f3ab15Sopenharmony_ci    pub fn new() -> SubjectAlternativeName {
45692f3ab15Sopenharmony_ci        SubjectAlternativeName {
45792f3ab15Sopenharmony_ci            critical: false,
45892f3ab15Sopenharmony_ci            items: vec![],
45992f3ab15Sopenharmony_ci        }
46092f3ab15Sopenharmony_ci    }
46192f3ab15Sopenharmony_ci
46292f3ab15Sopenharmony_ci    /// Sets the `critical` flag to `true`. The extension will be critical.
46392f3ab15Sopenharmony_ci    pub fn critical(&mut self) -> &mut SubjectAlternativeName {
46492f3ab15Sopenharmony_ci        self.critical = true;
46592f3ab15Sopenharmony_ci        self
46692f3ab15Sopenharmony_ci    }
46792f3ab15Sopenharmony_ci
46892f3ab15Sopenharmony_ci    /// Sets the `email` flag.
46992f3ab15Sopenharmony_ci    pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName {
47092f3ab15Sopenharmony_ci        self.items.push(RustGeneralName::Email(email.to_string()));
47192f3ab15Sopenharmony_ci        self
47292f3ab15Sopenharmony_ci    }
47392f3ab15Sopenharmony_ci
47492f3ab15Sopenharmony_ci    /// Sets the `uri` flag.
47592f3ab15Sopenharmony_ci    pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName {
47692f3ab15Sopenharmony_ci        self.items.push(RustGeneralName::Uri(uri.to_string()));
47792f3ab15Sopenharmony_ci        self
47892f3ab15Sopenharmony_ci    }
47992f3ab15Sopenharmony_ci
48092f3ab15Sopenharmony_ci    /// Sets the `dns` flag.
48192f3ab15Sopenharmony_ci    pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName {
48292f3ab15Sopenharmony_ci        self.items.push(RustGeneralName::Dns(dns.to_string()));
48392f3ab15Sopenharmony_ci        self
48492f3ab15Sopenharmony_ci    }
48592f3ab15Sopenharmony_ci
48692f3ab15Sopenharmony_ci    /// Sets the `rid` flag.
48792f3ab15Sopenharmony_ci    pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName {
48892f3ab15Sopenharmony_ci        self.items.push(RustGeneralName::Rid(rid.to_string()));
48992f3ab15Sopenharmony_ci        self
49092f3ab15Sopenharmony_ci    }
49192f3ab15Sopenharmony_ci
49292f3ab15Sopenharmony_ci    /// Sets the `ip` flag.
49392f3ab15Sopenharmony_ci    pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName {
49492f3ab15Sopenharmony_ci        self.items.push(RustGeneralName::Ip(ip.to_string()));
49592f3ab15Sopenharmony_ci        self
49692f3ab15Sopenharmony_ci    }
49792f3ab15Sopenharmony_ci
49892f3ab15Sopenharmony_ci    /// Sets the `dirName` flag.
49992f3ab15Sopenharmony_ci    ///
50092f3ab15Sopenharmony_ci    /// Not currently actually supported, always panics.
50192f3ab15Sopenharmony_ci    #[deprecated = "dir_name is deprecated and always panics. Please file a bug if you have a use case for this."]
50292f3ab15Sopenharmony_ci    pub fn dir_name(&mut self, _dir_name: &str) -> &mut SubjectAlternativeName {
50392f3ab15Sopenharmony_ci        unimplemented!(
50492f3ab15Sopenharmony_ci            "This has not yet been adapted for the new internals. File a bug if you need this."
50592f3ab15Sopenharmony_ci        );
50692f3ab15Sopenharmony_ci    }
50792f3ab15Sopenharmony_ci
50892f3ab15Sopenharmony_ci    /// Sets the `otherName` flag.
50992f3ab15Sopenharmony_ci    ///
51092f3ab15Sopenharmony_ci    /// Not currently actually supported, always panics. Please use other_name2
51192f3ab15Sopenharmony_ci    #[deprecated = "other_name is deprecated and always panics. Please use other_name2."]
51292f3ab15Sopenharmony_ci    pub fn other_name(&mut self, _other_name: &str) -> &mut SubjectAlternativeName {
51392f3ab15Sopenharmony_ci        unimplemented!("This has not yet been adapted for the new internals. Use other_name2.");
51492f3ab15Sopenharmony_ci    }
51592f3ab15Sopenharmony_ci
51692f3ab15Sopenharmony_ci    /// Sets the `otherName` flag.
51792f3ab15Sopenharmony_ci    ///
51892f3ab15Sopenharmony_ci    /// `content` must be a valid der encoded ASN1_TYPE
51992f3ab15Sopenharmony_ci    ///
52092f3ab15Sopenharmony_ci    /// If you want to add just a ia5string use `other_name_ia5string`
52192f3ab15Sopenharmony_ci    pub fn other_name2(&mut self, oid: Asn1Object, content: &[u8]) -> &mut SubjectAlternativeName {
52292f3ab15Sopenharmony_ci        self.items
52392f3ab15Sopenharmony_ci            .push(RustGeneralName::OtherName(oid, content.into()));
52492f3ab15Sopenharmony_ci        self
52592f3ab15Sopenharmony_ci    }
52692f3ab15Sopenharmony_ci
52792f3ab15Sopenharmony_ci    /// Return a `SubjectAlternativeName` extension as an `X509Extension`.
52892f3ab15Sopenharmony_ci    pub fn build(&self, _ctx: &X509v3Context<'_>) -> Result<X509Extension, ErrorStack> {
52992f3ab15Sopenharmony_ci        let mut stack = Stack::new()?;
53092f3ab15Sopenharmony_ci        for item in &self.items {
53192f3ab15Sopenharmony_ci            let gn = match item {
53292f3ab15Sopenharmony_ci                RustGeneralName::Dns(s) => GeneralName::new_dns(s.as_bytes())?,
53392f3ab15Sopenharmony_ci                RustGeneralName::Email(s) => GeneralName::new_email(s.as_bytes())?,
53492f3ab15Sopenharmony_ci                RustGeneralName::Uri(s) => GeneralName::new_uri(s.as_bytes())?,
53592f3ab15Sopenharmony_ci                RustGeneralName::Ip(s) => {
53692f3ab15Sopenharmony_ci                    GeneralName::new_ip(s.parse().map_err(|_| ErrorStack::get())?)?
53792f3ab15Sopenharmony_ci                }
53892f3ab15Sopenharmony_ci                RustGeneralName::Rid(s) => GeneralName::new_rid(Asn1Object::from_str(s)?)?,
53992f3ab15Sopenharmony_ci                RustGeneralName::OtherName(oid, content) => {
54092f3ab15Sopenharmony_ci                    GeneralName::new_other_name(oid.clone(), content)?
54192f3ab15Sopenharmony_ci                }
54292f3ab15Sopenharmony_ci            };
54392f3ab15Sopenharmony_ci            stack.push(gn)?;
54492f3ab15Sopenharmony_ci        }
54592f3ab15Sopenharmony_ci
54692f3ab15Sopenharmony_ci        unsafe {
54792f3ab15Sopenharmony_ci            X509Extension::new_internal(Nid::SUBJECT_ALT_NAME, self.critical, stack.as_ptr().cast())
54892f3ab15Sopenharmony_ci        }
54992f3ab15Sopenharmony_ci    }
55092f3ab15Sopenharmony_ci}
55192f3ab15Sopenharmony_ci
55292f3ab15Sopenharmony_cifn append(value: &mut String, first: &mut bool, should: bool, element: &str) {
55392f3ab15Sopenharmony_ci    if !should {
55492f3ab15Sopenharmony_ci        return;
55592f3ab15Sopenharmony_ci    }
55692f3ab15Sopenharmony_ci
55792f3ab15Sopenharmony_ci    if !*first {
55892f3ab15Sopenharmony_ci        value.push(',');
55992f3ab15Sopenharmony_ci    }
56092f3ab15Sopenharmony_ci    *first = false;
56192f3ab15Sopenharmony_ci    value.push_str(element);
56292f3ab15Sopenharmony_ci}
563