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::der::referenced::RefToOwned;
9use spki::SignatureAlgorithmIdentifier;
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 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;
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 reexports::certval::{Error as CertvalError, PathValidationStatus},
99 RustyX509CheckError,
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 }
116 PathValidationStatus::InvalidNotAfterDate => {
117 }
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 pub validity_start: Option<std::time::Duration>,
271 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 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 = fluvio_wasm_timer::SystemTime::now()
484 .duration_since(fluvio_wasm_timer::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 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 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 target.tbs_certificate.serial_number =
585 x509_cert::serial_number::SerialNumber::<x509_cert::certificate::Rfc5280>::from(rand::random::<u16>());
586
587 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 fluvio_wasm_timer::SystemTime::now()
636 .duration_since(fluvio_wasm_timer::UNIX_EPOCH)
637 .map_err(|_| MlsProviderError::CertificateGenerationError)?
638 } - std::time::Duration::from_secs(1); 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}