mls_crypto_provider/
pki.rs

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