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 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 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 }
117 PathValidationStatus::InvalidNotAfterDate => {
118 }
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 pub validity_start: Option<std::time::Duration>,
272 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 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 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 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 target.tbs_certificate.serial_number =
586 x509_cert::serial_number::SerialNumber::<x509_cert::certificate::Rfc5280>::from(rand::random::<u16>());
587
588 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); 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}