mls_crypto_provider/
pki.rs

1use std::sync::Arc;
2
3use async_lock::{RwLock, RwLockReadGuard};
4use openmls_traits::{
5    authentication_service::{CredentialAuthenticationStatus, CredentialRef},
6    types::SignatureScheme,
7};
8use spki::{SignatureAlgorithmIdentifier, der::referenced::RefToOwned};
9
10use crate::error::{MlsProviderError, MlsProviderResult};
11
12#[derive(Debug, Clone, Default)]
13pub struct PkiEnvironmentProvider(Arc<RwLock<Option<wire_e2e_identity::prelude::x509::revocation::PkiEnvironment>>>);
14
15impl From<wire_e2e_identity::prelude::x509::revocation::PkiEnvironment> for PkiEnvironmentProvider {
16    fn from(value: wire_e2e_identity::prelude::x509::revocation::PkiEnvironment) -> Self {
17        Self(Arc::new(Some(value).into()))
18    }
19}
20
21impl PkiEnvironmentProvider {
22    pub async fn refresh_time_of_interest(&self) {
23        if let Some(pki) = self.0.write().await.as_mut() {
24            let _ = pki.refresh_time_of_interest();
25        }
26    }
27
28    pub async fn borrow(
29        &self,
30    ) -> RwLockReadGuard<'_, Option<wire_e2e_identity::prelude::x509::revocation::PkiEnvironment>> {
31        self.0.read().await
32    }
33
34    pub async fn is_env_setup(&self) -> bool {
35        self.0.read().await.is_some()
36    }
37
38    pub async fn update_env(
39        &self,
40        env: wire_e2e_identity::prelude::x509::revocation::PkiEnvironment,
41    ) -> MlsProviderResult<()> {
42        self.0.write().await.replace(env);
43        Ok(())
44    }
45
46    #[allow(dead_code)]
47    async fn dump_certs(&self) {
48        use x509_cert::der::EncodePem as _;
49        let env = self.0.read().await;
50        let pki_env = env.as_ref().expect("No pki env");
51        for (i, ta) in pki_env.get_trust_anchors().unwrap().iter().enumerate() {
52            let x509_cert::anchor::TrustAnchorChoice::Certificate(ta_cert) = &ta.decoded_ta else {
53                unreachable!("Kaboom");
54            };
55            println!(
56                "Trust Anchor #{i}: \n{}",
57                ta_cert.to_pem(x509_cert::der::pem::LineEnding::LF).unwrap()
58            )
59        }
60
61        for (i, cert) in pki_env.get_intermediates().unwrap().iter().enumerate() {
62            println!(
63                "Intermediate #{i}: \n{}",
64                cert.decoded_cert.to_pem(x509_cert::der::pem::LineEnding::LF).unwrap()
65            )
66        }
67    }
68}
69
70#[cfg_attr(target_family = "wasm", async_trait::async_trait(?Send))]
71#[cfg_attr(not(target_family = "wasm"), async_trait::async_trait)]
72impl openmls_traits::authentication_service::AuthenticationServiceDelegate for PkiEnvironmentProvider {
73    async fn validate_credential<'a>(&'a self, credential: CredentialRef<'a>) -> CredentialAuthenticationStatus {
74        match credential {
75            // We assume that Basic credentials are always valid
76            CredentialRef::Basic { identity: _ } => CredentialAuthenticationStatus::Valid,
77
78            CredentialRef::X509 { certificates } => {
79                self.refresh_time_of_interest().await;
80
81                let binding = self.0.read().await;
82                let Some(pki_env) = binding.as_ref() else {
83                    // This implies that we have a Basic client without a PKI environment setup. Hence they cannot
84                    // validate X509 credentials they see. So we consider it as always valid as we
85                    // have no way to assert the validity
86                    return CredentialAuthenticationStatus::Valid;
87                };
88
89                use x509_cert::der::Decode as _;
90                let Some(cert) = certificates
91                    .first()
92                    .and_then(|cert_raw| x509_cert::Certificate::from_der(cert_raw).ok())
93                else {
94                    return CredentialAuthenticationStatus::Invalid;
95                };
96
97                if let Err(validation_error) = pki_env.validate_cert_and_revocation(&cert) {
98                    use wire_e2e_identity::prelude::x509::{
99                        RustyX509CheckError,
100                        reexports::certval::{Error as CertvalError, PathValidationStatus},
101                    };
102
103                    if let RustyX509CheckError::CertValError(CertvalError::PathValidation(
104                        certificate_validation_error,
105                    )) = validation_error
106                    {
107                        match certificate_validation_error {
108                            PathValidationStatus::Valid
109                            | PathValidationStatus::RevocationStatusNotAvailable
110                            | PathValidationStatus::RevocationStatusNotDetermined => {}
111                            PathValidationStatus::CertificateRevoked
112                            | PathValidationStatus::CertificateRevokedEndEntity
113                            | PathValidationStatus::CertificateRevokedIntermediateCa => {
114                                // ? Revoked credentials are A-OK. They still degrade conversations though.
115                                // return CredentialAuthenticationStatus::Revoked;
116                            }
117                            PathValidationStatus::InvalidNotAfterDate => {
118                                // ? Expired credentials are A-OK. They still degrade conversations though.
119                                // return CredentialAuthenticationStatus::Expired;
120                            }
121                            _ => return CredentialAuthenticationStatus::Invalid,
122                        }
123                    } else {
124                        return CredentialAuthenticationStatus::Unknown;
125                    }
126                }
127
128                CredentialAuthenticationStatus::Valid
129            }
130        }
131    }
132}
133
134pub struct Ed25519PkiSignature(ed25519_dalek::Signature);
135impl spki::SignatureBitStringEncoding for Ed25519PkiSignature {
136    fn to_bitstring(&self) -> spki::der::Result<spki::der::asn1::BitString> {
137        spki::der::asn1::BitString::new(0, self.0.to_vec())
138    }
139}
140
141#[derive(Debug, Clone)]
142pub struct Ed25519PkiKeypair(ed25519_dalek::SigningKey);
143
144impl Ed25519PkiKeypair {
145    pub fn keypair_bytes(&self) -> Vec<u8> {
146        self.0.to_keypair_bytes().to_vec()
147    }
148}
149
150impl spki::SignatureAlgorithmIdentifier for Ed25519PkiKeypair {
151    type Params = spki::der::AnyRef<'static>;
152    const SIGNATURE_ALGORITHM_IDENTIFIER: spki::AlgorithmIdentifier<Self::Params> = ed25519_dalek::pkcs8::ALGORITHM_ID;
153}
154
155impl signature::Keypair for Ed25519PkiKeypair {
156    type VerifyingKey = <ed25519_dalek::SigningKey as signature::Keypair>::VerifyingKey;
157    fn verifying_key(&self) -> Self::VerifyingKey {
158        self.0.verifying_key()
159    }
160}
161
162impl signature::Signer<Ed25519PkiSignature> for Ed25519PkiKeypair {
163    fn try_sign(&self, message: &[u8]) -> Result<Ed25519PkiSignature, ed25519_dalek::SignatureError> {
164        self.0.try_sign(message).map(Ed25519PkiSignature)
165    }
166}
167
168#[derive(Clone)]
169pub struct P521PkiVerifyingKey(ecdsa::VerifyingKey<p521::NistP521>);
170impl From<ecdsa::VerifyingKey<p521::NistP521>> for P521PkiVerifyingKey {
171    fn from(k: ecdsa::VerifyingKey<p521::NistP521>) -> Self {
172        Self(k)
173    }
174}
175
176impl std::ops::Deref for P521PkiVerifyingKey {
177    type Target = ecdsa::VerifyingKey<p521::NistP521>;
178    fn deref(&self) -> &Self::Target {
179        &self.0
180    }
181}
182
183impl p521::pkcs8::EncodePublicKey for P521PkiVerifyingKey {
184    fn to_public_key_der(&self) -> spki::Result<spki::Document> {
185        self.0.to_public_key_der()
186    }
187}
188
189#[derive(Clone)]
190pub struct P521PkiKeypair(ecdsa::SigningKey<p521::NistP521>);
191
192impl spki::SignatureAlgorithmIdentifier for P521PkiKeypair {
193    type Params = spki::ObjectIdentifier;
194    const SIGNATURE_ALGORITHM_IDENTIFIER: spki::AlgorithmIdentifier<Self::Params> = spki::AlgorithmIdentifier {
195        oid: ecdsa::ECDSA_SHA512_OID,
196        parameters: None,
197    };
198}
199
200impl signature::Keypair for P521PkiKeypair {
201    type VerifyingKey = P521PkiVerifyingKey;
202    fn verifying_key(&self) -> Self::VerifyingKey {
203        (*self.0.verifying_key()).into()
204    }
205}
206
207impl signature::Signer<p521::ecdsa::DerSignature> for P521PkiKeypair {
208    fn try_sign(&self, message: &[u8]) -> Result<p521::ecdsa::DerSignature, p521::ecdsa::Error> {
209        let sk = p521::ecdsa::SigningKey::from(self.0.clone());
210        Ok(sk.try_sign(message)?.to_der())
211    }
212}
213
214#[derive(Clone)]
215pub enum PkiKeypair {
216    P256(p256::ecdsa::SigningKey),
217    P384(p384::ecdsa::SigningKey),
218    P521(P521PkiKeypair),
219    Ed25519(Ed25519PkiKeypair),
220}
221
222impl std::fmt::Debug for PkiKeypair {
223    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224        f.debug_struct("PkiKeypair")
225            .field(
226                "type",
227                &match self {
228                    Self::P256(_k) => "P256",
229                    Self::P384(_k) => "P384",
230                    Self::P521(_k) => "P521",
231                    Self::Ed25519(_k) => "Ed25519",
232                },
233            )
234            .field("key", &"[REDACTED]")
235            .finish()
236    }
237}
238
239impl PkiKeypair {
240    pub fn signing_key_bytes(&self) -> Vec<u8> {
241        match self {
242            Self::P256(sk) => sk.to_bytes().to_vec(),
243            Self::P384(sk) => sk.to_bytes().to_vec(),
244            Self::P521(sk) => sk.0.to_bytes().to_vec(),
245            Self::Ed25519(sk) => sk.0.to_bytes().to_vec(),
246        }
247    }
248
249    pub fn public_key_bytes(&self) -> Vec<u8> {
250        match self {
251            Self::P256(sk) => sk.verifying_key().to_sec1_bytes().to_vec(),
252            Self::P384(sk) => sk.verifying_key().to_sec1_bytes().to_vec(),
253            Self::P521(sk) => sk.0.verifying_key().to_sec1_bytes().to_vec(),
254            Self::Ed25519(sk) => sk.0.verifying_key().to_bytes().to_vec(),
255        }
256    }
257
258    pub fn public_key_identifier(&self) -> Vec<u8> {
259        use sha1::Digest as _;
260        sha1::Sha1::digest(self.public_key_bytes()).to_vec()
261    }
262}
263
264pub use x509_cert::builder::Profile as CertProfile;
265
266pub struct CertificateGenerationArgs<'a> {
267    pub signature_scheme: SignatureScheme,
268    pub profile: CertProfile,
269    pub serial: u64,
270    /// Duration since UNIX EPOCH
271    pub validity_start: Option<std::time::Duration>,
272    /// Duration relative to `validity_start` if present. Otherwise relative to now
273    pub validity_from_start: std::time::Duration,
274    pub org: &'a str,
275    pub common_name: Option<&'a str>,
276    pub alternative_names: Option<&'a [&'a str]>,
277    pub domain: Option<&'a str>,
278    pub crl_dps: Option<&'a [&'a str]>,
279    pub signer: Option<&'a PkiKeypair>,
280    pub is_ca: bool,
281    pub is_root: bool,
282}
283
284fn get_extended_keyusage(is_ca: bool) -> x509_cert::ext::pkix::ExtendedKeyUsage {
285    let mut ext_keyusages = vec![];
286    if !is_ca {
287        ext_keyusages.push(x509_cert::der::oid::db::rfc5280::ID_KP_CLIENT_AUTH);
288    }
289
290    x509_cert::ext::pkix::ExtendedKeyUsage(ext_keyusages)
291}
292
293macro_rules! impl_certgen {
294    (
295        $signer:expr, $signer_keypair:expr, $sig_type:path,
296        $profile:expr, $own_spki:expr, $serial:expr,
297        $subject:expr, $org:expr, $domain:expr, $validity:expr, $alt_names:expr,
298        $crl_dps:expr, $is_ca:expr, $is_root:expr
299    ) => {{
300        let add_akid = $is_ca && $profile == x509_cert::builder::Profile::Root;
301
302        let mut builder = x509_cert::builder::CertificateBuilder::new(
303            $profile,
304            $serial,
305            $validity,
306            $subject,
307            $own_spki,
308            $signer_keypair,
309        )
310        .map_err(|_| MlsProviderError::CertificateGenerationError)?;
311
312        if add_akid {
313            builder
314                .add_extension(&$signer.akid()?)
315                .map_err(|_| MlsProviderError::CertificateGenerationError)?;
316        }
317
318        builder
319            .add_extension(&get_extended_keyusage($is_ca))
320            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
321
322        if !$is_ca {
323            if let Some(alt_names) = $alt_names {
324                let mut alt_names_list = vec![];
325                for alt_name in alt_names {
326                    alt_names_list.push(x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
327                        alt_name
328                            .to_string()
329                            .try_into()
330                            .map_err(|_| MlsProviderError::CertificateGenerationError)?,
331                    ));
332                }
333
334                builder
335                    .add_extension(&x509_cert::ext::pkix::SubjectAltName(alt_names_list))
336                    .map_err(|_| MlsProviderError::CertificateGenerationError)?;
337            }
338        } else {
339            let mut permitted_subtrees = vec![
340                x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
341                    format!(".{}", $org)
342                        .try_into()
343                        .map_err(|_| MlsProviderError::CertificateGenerationError)?,
344                ),
345                x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
346                    format!("{}", $org)
347                        .try_into()
348                        .map_err(|_| MlsProviderError::CertificateGenerationError)?,
349                ),
350            ];
351
352            if let Some(domain) = $domain {
353                // Add Domain DNS SAN
354                builder
355                    .add_extension(&x509_cert::ext::pkix::SubjectAltName(vec![
356                        x509_cert::ext::pkix::name::GeneralName::DnsName(
357                            domain
358                                .to_string()
359                                .try_into()
360                                .map_err(|_| MlsProviderError::CertificateGenerationError)?,
361                        ),
362                    ]))
363                    .map_err(|_| MlsProviderError::CertificateGenerationError)?;
364
365                permitted_subtrees.push(x509_cert::ext::pkix::name::GeneralName::DnsName(
366                    domain
367                        .to_string()
368                        .try_into()
369                        .map_err(|_| MlsProviderError::CertificateGenerationError)?,
370                ));
371            }
372
373            if !$is_root {
374                builder
375                    .add_extension(&x509_cert::ext::pkix::NameConstraints {
376                        permitted_subtrees: Some(
377                            permitted_subtrees
378                                .into_iter()
379                                .map(|base| x509_cert::ext::pkix::constraints::name::GeneralSubtree {
380                                    base,
381                                    minimum: 0,
382                                    maximum: None,
383                                })
384                                .collect(),
385                        ),
386
387                        excluded_subtrees: None,
388                    })
389                    .map_err(|_| MlsProviderError::CertificateGenerationError)?;
390            }
391        }
392
393        if let Some(crl_dps) = $crl_dps {
394            let mut crl_distribution_points = vec![];
395            for dp in crl_dps {
396                crl_distribution_points.push(x509_cert::ext::pkix::crl::dp::DistributionPoint {
397                    distribution_point: Some(x509_cert::ext::pkix::name::DistributionPointName::FullName(vec![
398                        x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
399                            dp.to_string()
400                                .try_into()
401                                .map_err(|_| MlsProviderError::CertificateGenerationError)?,
402                        ),
403                    ])),
404                    crl_issuer: None,
405                    reasons: None,
406                });
407            }
408            builder
409                .add_extension(&x509_cert::ext::pkix::CrlDistributionPoints(crl_distribution_points))
410                .map_err(|_| MlsProviderError::CertificateGenerationError)?;
411        }
412
413        builder
414            .build::<$sig_type>()
415            .map_err(|_| MlsProviderError::CertificateGenerationError)?
416    }};
417}
418
419impl PkiKeypair {
420    pub fn new(signature_scheme: SignatureScheme, sk: Vec<u8>) -> MlsProviderResult<Self> {
421        match signature_scheme {
422            SignatureScheme::ECDSA_SECP256R1_SHA256 => Ok(PkiKeypair::P256(
423                p256::ecdsa::SigningKey::from_slice(sk.as_slice())
424                    .map_err(|_| MlsProviderError::CertificateGenerationError)?,
425            )),
426            SignatureScheme::ECDSA_SECP384R1_SHA384 => Ok(PkiKeypair::P384(
427                p384::ecdsa::SigningKey::from_slice(sk.as_slice())
428                    .map_err(|_| MlsProviderError::CertificateGenerationError)?,
429            )),
430            SignatureScheme::ECDSA_SECP521R1_SHA512 => Ok(PkiKeypair::P521(P521PkiKeypair(
431                ecdsa::SigningKey::<p521::NistP521>::from_slice(sk.as_slice())
432                    .map_err(|_| MlsProviderError::CertificateGenerationError)?,
433            ))),
434            SignatureScheme::ED25519 => Ok(PkiKeypair::Ed25519(Ed25519PkiKeypair(
435                crate::RustCrypto::normalize_ed25519_key(sk.as_slice())
436                    .map_err(|_| MlsProviderError::CertificateGenerationError)?,
437            ))),
438            _ => Err(MlsProviderError::UnsupportedSignatureScheme),
439        }
440    }
441
442    pub fn signature_algorithm(&self) -> spki::AlgorithmIdentifierRef<'_> {
443        match self {
444            Self::P256(_) => p256::ecdsa::SigningKey::SIGNATURE_ALGORITHM_IDENTIFIER,
445            Self::P384(_) => p384::ecdsa::SigningKey::SIGNATURE_ALGORITHM_IDENTIFIER,
446            Self::P521(_) => spki::AlgorithmIdentifierRef {
447                oid: ecdsa::ECDSA_SHA512_OID,
448                parameters: None,
449            },
450            Self::Ed25519(_) => ed25519_dalek::pkcs8::ALGORITHM_ID,
451        }
452    }
453
454    pub fn spki(&self) -> MlsProviderResult<spki::SubjectPublicKeyInfoOwned> {
455        match self {
456            Self::P256(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.verifying_key())
457                .map_err(|_| MlsProviderError::CertificateGenerationError)?),
458            Self::P384(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.verifying_key())
459                .map_err(|_| MlsProviderError::CertificateGenerationError)?),
460            Self::P521(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.0.verifying_key())
461                .map_err(|_| MlsProviderError::CertificateGenerationError)?),
462            Self::Ed25519(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(sk.0.verifying_key())
463                .map_err(|_| MlsProviderError::CertificateGenerationError)?),
464        }
465    }
466
467    pub fn akid(&self) -> MlsProviderResult<x509_cert::ext::pkix::AuthorityKeyIdentifier> {
468        Ok(x509_cert::ext::pkix::AuthorityKeyIdentifier {
469            key_identifier: Some(
470                spki::der::asn1::OctetString::new(self.public_key_identifier())
471                    .map_err(|_| MlsProviderError::CertificateGenerationError)?,
472            ),
473            authority_cert_issuer: None,
474            authority_cert_serial_number: None,
475        })
476    }
477
478    pub fn revoke_certs(
479        &self,
480        issuer_cert: &x509_cert::Certificate,
481        revoked_cert_serial_numbers: Vec<Vec<u8>>,
482    ) -> MlsProviderResult<x509_cert::crl::CertificateList> {
483        let signature_algorithm = self.signature_algorithm();
484        let now = web_time::SystemTime::now()
485            .duration_since(web_time::UNIX_EPOCH)
486            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
487        let now = x509_cert::der::asn1::GeneralizedTime::from_unix_duration(now)
488            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
489        let now = x509_cert::time::Time::GeneralTime(now);
490
491        let revoked_certificates = revoked_cert_serial_numbers
492            .into_iter()
493            .map(|serial_number| x509_cert::crl::RevokedCert {
494                serial_number: x509_cert::serial_number::SerialNumber::new(&serial_number)
495                    .expect("Non-positive serial number"),
496                revocation_date: now,
497                crl_entry_extensions: None,
498            })
499            .collect();
500
501        let tbs_cert_list = x509_cert::crl::TbsCertList {
502            version: x509_cert::Version::V3,
503            signature: signature_algorithm.ref_to_owned(),
504            issuer: issuer_cert.tbs_certificate.subject.clone(),
505            this_update: now,
506            next_update: None,
507            revoked_certificates: Some(revoked_certificates),
508            crl_extensions: None,
509        };
510
511        use spki::der::Encode as _;
512
513        let tbs = tbs_cert_list
514            .to_der()
515            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
516
517        use signature::Signer as _;
518
519        let signature: Vec<u8> = match self {
520            PkiKeypair::P256(sk) => signature::Signer::<p256::ecdsa::DerSignature>::try_sign(sk, &tbs)?
521                .to_der()
522                .map_err(|_| MlsProviderError::CertificateGenerationError),
523            PkiKeypair::P384(sk) => signature::Signer::<p384::ecdsa::DerSignature>::try_sign(sk, &tbs)?
524                .to_der()
525                .map_err(|_| MlsProviderError::CertificateGenerationError),
526            PkiKeypair::P521(sk) => {
527                let sk = p521::ecdsa::SigningKey::from(sk.0.clone());
528                let signature: p521::ecdsa::DerSignature = sk.try_sign(&tbs)?.to_der();
529
530                signature
531                    .to_der()
532                    .map_err(|_| MlsProviderError::CertificateGenerationError)
533            }
534            PkiKeypair::Ed25519(sk) => Ok(sk.try_sign(&tbs)?.0.to_vec()),
535        }?;
536
537        let signature =
538            spki::der::asn1::BitString::new(0, signature).map_err(|_| MlsProviderError::CertificateGenerationError)?;
539
540        Ok(x509_cert::crl::CertificateList {
541            tbs_cert_list,
542            signature_algorithm: signature_algorithm.ref_to_owned(),
543            signature,
544        })
545    }
546
547    pub fn re_sign(
548        &self,
549        signer_cert: &x509_cert::Certificate,
550        target: &x509_cert::Certificate,
551        validity: Option<std::time::Duration>,
552    ) -> MlsProviderResult<x509_cert::Certificate> {
553        let mut target = target.clone();
554        target.tbs_certificate.issuer = signer_cert.tbs_certificate.subject.clone();
555        let akid = self.akid()?;
556        use x509_cert::ext::AsExtension as _;
557        // Insert AKID
558        let akid_ext = akid
559            .to_extension(&target.tbs_certificate.subject, &[])
560            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
561        if let Some(exts) = &mut target.tbs_certificate.extensions {
562            use x509_cert::der::oid::AssociatedOid as _;
563
564            if let Some(akid_ext_index) = exts
565                .iter_mut()
566                .enumerate()
567                .find_map(|(i, ext)| (ext.extn_id == x509_cert::ext::pkix::AuthorityKeyIdentifier::OID).then_some(i))
568            {
569                exts.remove(akid_ext_index);
570                exts.insert(akid_ext_index, akid_ext);
571            } else {
572                exts.push(akid_ext);
573            }
574        } else {
575            target.tbs_certificate.extensions = Some(vec![akid_ext]);
576        }
577
578        // Refresh validity if provided
579        if let Some(validity) = validity {
580            target.tbs_certificate.validity = x509_cert::time::Validity::from_now(validity)
581                .map_err(|_| MlsProviderError::CertificateGenerationError)?;
582        }
583
584        // Update Serial
585        target.tbs_certificate.serial_number =
586            x509_cert::serial_number::SerialNumber::<x509_cert::certificate::Rfc5280>::from(rand::random::<u16>());
587
588        // Re-sign
589        use spki::der::Encode as _;
590        let tbs = target
591            .tbs_certificate
592            .to_der()
593            .map_err(|_| MlsProviderError::CertificateGenerationError)?;
594
595        use signature::Signer as _;
596
597        let signature: Vec<u8> = match self {
598            PkiKeypair::P256(sk) => signature::Signer::<p256::ecdsa::DerSignature>::try_sign(sk, &tbs)?
599                .to_der()
600                .map_err(|_| MlsProviderError::CertificateGenerationError),
601            PkiKeypair::P384(sk) => signature::Signer::<p384::ecdsa::DerSignature>::try_sign(sk, &tbs)?
602                .to_der()
603                .map_err(|_| MlsProviderError::CertificateGenerationError),
604            PkiKeypair::P521(sk) => {
605                let sk = p521::ecdsa::SigningKey::from(sk.0.clone());
606                let signature: p521::ecdsa::DerSignature = sk.try_sign(&tbs)?.to_der();
607
608                signature
609                    .to_der()
610                    .map_err(|_| MlsProviderError::CertificateGenerationError)
611            }
612            PkiKeypair::Ed25519(sk) => Ok(sk.try_sign(&tbs)?.0.to_vec()),
613        }?;
614
615        target.signature_algorithm = self.signature_algorithm().ref_to_owned();
616        target.signature =
617            spki::der::asn1::BitString::new(0, signature).map_err(|_| MlsProviderError::CertificateGenerationError)?;
618
619        Ok(target)
620    }
621
622    pub fn generate_cert(&self, args: CertificateGenerationArgs) -> MlsProviderResult<x509_cert::Certificate> {
623        use std::str::FromStr as _;
624
625        use x509_cert::builder::Builder as _;
626        let mut subject_fmt = format!("O={}", args.org);
627        if let Some(cn) = args.common_name {
628            subject_fmt.push_str(&format!(",CN={cn}"));
629        }
630
631        let subject =
632            x509_cert::name::Name::from_str(&subject_fmt).map_err(|_| MlsProviderError::CertificateGenerationError)?;
633
634        let validity_start = if let Some(validity_start) = args.validity_start {
635            validity_start
636        } else {
637            web_time::SystemTime::now()
638                .duration_since(web_time::UNIX_EPOCH)
639                .map_err(|_| MlsProviderError::CertificateGenerationError)?
640        } - std::time::Duration::from_secs(1); // to prevent time clipping
641
642        let validity = {
643            let not_before = x509_cert::der::asn1::GeneralizedTime::from_unix_duration(validity_start)
644                .map_err(|_| MlsProviderError::CertificateGenerationError)?
645                .into();
646            let not_after =
647                x509_cert::der::asn1::GeneralizedTime::from_unix_duration(validity_start + args.validity_from_start)
648                    .map_err(|_| MlsProviderError::CertificateGenerationError)?
649                    .into();
650            x509_cert::time::Validity { not_before, not_after }
651        };
652
653        let serial_number = x509_cert::serial_number::SerialNumber::from(args.serial);
654        let spki = self.spki()?;
655
656        let signer = args.signer.unwrap_or(self);
657
658        let cert = match signer {
659            PkiKeypair::P256(kp) => {
660                impl_certgen!(
661                    signer,
662                    kp,
663                    p256::ecdsa::DerSignature,
664                    args.profile,
665                    spki,
666                    serial_number,
667                    subject,
668                    args.org,
669                    args.domain,
670                    validity,
671                    args.alternative_names,
672                    args.crl_dps,
673                    args.is_ca,
674                    args.is_root
675                )
676            }
677            PkiKeypair::P384(kp) => {
678                impl_certgen!(
679                    signer,
680                    kp,
681                    p384::ecdsa::DerSignature,
682                    args.profile,
683                    spki,
684                    serial_number,
685                    subject,
686                    args.org,
687                    args.domain,
688                    validity,
689                    args.alternative_names,
690                    args.crl_dps,
691                    args.is_ca,
692                    args.is_root
693                )
694            }
695            PkiKeypair::P521(kp) => {
696                impl_certgen!(
697                    signer,
698                    kp,
699                    p521::ecdsa::DerSignature,
700                    args.profile,
701                    spki,
702                    serial_number,
703                    subject,
704                    args.org,
705                    args.domain,
706                    validity,
707                    args.alternative_names,
708                    args.crl_dps,
709                    args.is_ca,
710                    args.is_root
711                )
712            }
713            PkiKeypair::Ed25519(kp) => {
714                impl_certgen!(
715                    signer,
716                    kp,
717                    Ed25519PkiSignature,
718                    args.profile,
719                    spki,
720                    serial_number,
721                    subject,
722                    args.org,
723                    args.domain,
724                    validity,
725                    args.alternative_names,
726                    args.crl_dps,
727                    args.is_ca,
728                    args.is_root
729                )
730            }
731        };
732
733        Ok(cert)
734    }
735
736    pub fn rand_unchecked(alg: SignatureScheme) -> Self {
737        let provider = crate::RustCrypto::default();
738        use openmls_traits::crypto::OpenMlsCrypto;
739        Self::new(alg, provider.signature_key_gen(alg).unwrap().0).unwrap()
740    }
741
742    pub fn rand(alg: SignatureScheme, crypto: &crate::RustCrypto) -> crate::MlsProviderResult<Self> {
743        use openmls_traits::crypto::OpenMlsCrypto as _;
744        Self::new(
745            alg,
746            crypto
747                .signature_key_gen(alg)
748                .map_err(|_| crate::MlsProviderError::UnsufficientEntropy)?
749                .0,
750        )
751    }
752}