1#![allow(unused)]
4use std::sync::Arc;
5
6use async_lock::{RwLock, RwLockReadGuard};
7use openmls_traits::{
8 authentication_service::{CredentialAuthenticationStatus, CredentialRef},
9 crypto::OpenMlsCrypto,
10 types::SignatureScheme,
11};
12use spki::{SignatureAlgorithmIdentifier, der::referenced::RefToOwned};
13
14use crate::error::{E2eIdentityError, E2eIdentityResult};
15
16pub struct Ed25519PkiSignature(ed25519_dalek::Signature);
17impl spki::SignatureBitStringEncoding for Ed25519PkiSignature {
18 fn to_bitstring(&self) -> spki::der::Result<spki::der::asn1::BitString> {
19 spki::der::asn1::BitString::new(0, self.0.to_vec())
20 }
21}
22
23#[derive(Debug, Clone)]
24pub struct Ed25519PkiKeypair(ed25519_dalek::SigningKey);
25
26impl Ed25519PkiKeypair {
27 pub fn keypair_bytes(&self) -> Vec<u8> {
28 self.0.to_keypair_bytes().to_vec()
29 }
30}
31
32impl spki::SignatureAlgorithmIdentifier for Ed25519PkiKeypair {
33 type Params = spki::der::AnyRef<'static>;
34 const SIGNATURE_ALGORITHM_IDENTIFIER: spki::AlgorithmIdentifier<Self::Params> = ed25519_dalek::pkcs8::ALGORITHM_ID;
35}
36
37impl signature::Keypair for Ed25519PkiKeypair {
38 type VerifyingKey = <ed25519_dalek::SigningKey as signature::Keypair>::VerifyingKey;
39 fn verifying_key(&self) -> Self::VerifyingKey {
40 self.0.verifying_key()
41 }
42}
43
44impl signature::Signer<Ed25519PkiSignature> for Ed25519PkiKeypair {
45 fn try_sign(&self, message: &[u8]) -> Result<Ed25519PkiSignature, ed25519_dalek::SignatureError> {
46 self.0.try_sign(message).map(Ed25519PkiSignature)
47 }
48}
49
50#[derive(Clone)]
51pub struct P521PkiVerifyingKey(ecdsa::VerifyingKey<p521::NistP521>);
52impl From<ecdsa::VerifyingKey<p521::NistP521>> for P521PkiVerifyingKey {
53 fn from(k: ecdsa::VerifyingKey<p521::NistP521>) -> Self {
54 Self(k)
55 }
56}
57
58impl std::ops::Deref for P521PkiVerifyingKey {
59 type Target = ecdsa::VerifyingKey<p521::NistP521>;
60 fn deref(&self) -> &Self::Target {
61 &self.0
62 }
63}
64
65impl p521::pkcs8::EncodePublicKey for P521PkiVerifyingKey {
66 fn to_public_key_der(&self) -> spki::Result<spki::Document> {
67 self.0.to_public_key_der()
68 }
69}
70
71#[derive(Clone)]
72pub struct P521PkiKeypair(ecdsa::SigningKey<p521::NistP521>);
73
74impl spki::SignatureAlgorithmIdentifier for P521PkiKeypair {
75 type Params = spki::ObjectIdentifier;
76 const SIGNATURE_ALGORITHM_IDENTIFIER: spki::AlgorithmIdentifier<Self::Params> = spki::AlgorithmIdentifier {
77 oid: ecdsa::ECDSA_SHA512_OID,
78 parameters: None,
79 };
80}
81
82impl signature::Keypair for P521PkiKeypair {
83 type VerifyingKey = P521PkiVerifyingKey;
84 fn verifying_key(&self) -> Self::VerifyingKey {
85 (*self.0.verifying_key()).into()
86 }
87}
88
89impl signature::Signer<p521::ecdsa::DerSignature> for P521PkiKeypair {
90 fn try_sign(&self, message: &[u8]) -> Result<p521::ecdsa::DerSignature, p521::ecdsa::Error> {
91 let sk = p521::ecdsa::SigningKey::from(self.0.clone());
92 Ok(sk.try_sign(message)?.to_der())
93 }
94}
95
96#[derive(Clone)]
97pub enum PkiKeypair {
98 P256(p256::ecdsa::SigningKey),
99 P384(p384::ecdsa::SigningKey),
100 P521(P521PkiKeypair),
101 Ed25519(Ed25519PkiKeypair),
102}
103
104impl std::fmt::Debug for PkiKeypair {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 f.debug_struct("PkiKeypair")
107 .field(
108 "type",
109 &match self {
110 Self::P256(_k) => "P256",
111 Self::P384(_k) => "P384",
112 Self::P521(_k) => "P521",
113 Self::Ed25519(_k) => "Ed25519",
114 },
115 )
116 .field("key", &"[REDACTED]")
117 .finish()
118 }
119}
120
121impl PkiKeypair {
122 pub fn signing_key_bytes(&self) -> Vec<u8> {
123 match self {
124 Self::P256(sk) => sk.to_bytes().to_vec(),
125 Self::P384(sk) => sk.to_bytes().to_vec(),
126 Self::P521(sk) => sk.0.to_bytes().to_vec(),
127 Self::Ed25519(sk) => sk.0.to_bytes().to_vec(),
128 }
129 }
130
131 pub fn public_key_bytes(&self) -> Vec<u8> {
132 match self {
133 Self::P256(sk) => sk.verifying_key().to_sec1_bytes().to_vec(),
134 Self::P384(sk) => sk.verifying_key().to_sec1_bytes().to_vec(),
135 Self::P521(sk) => sk.0.verifying_key().to_sec1_bytes().to_vec(),
136 Self::Ed25519(sk) => sk.0.verifying_key().to_bytes().to_vec(),
137 }
138 }
139
140 pub fn public_key_identifier(&self) -> Vec<u8> {
141 use sha1::Digest as _;
142 sha1::Sha1::digest(self.public_key_bytes()).to_vec()
143 }
144}
145
146pub use x509_cert::builder::Profile as CertProfile;
147
148pub struct CertificateGenerationArgs<'a> {
149 pub signature_scheme: SignatureScheme,
150 pub profile: CertProfile,
151 pub serial: u64,
152 pub validity_start: Option<std::time::Duration>,
154 pub validity_from_start: std::time::Duration,
156 pub org: &'a str,
157 pub common_name: Option<&'a str>,
158 pub alternative_names: Option<&'a [&'a str]>,
159 pub domain: Option<&'a str>,
160 pub crl_dps: Option<&'a [&'a str]>,
161 pub signer: Option<&'a PkiKeypair>,
162 pub is_ca: bool,
163 pub is_root: bool,
164}
165
166fn get_extended_keyusage(is_ca: bool) -> x509_cert::ext::pkix::ExtendedKeyUsage {
167 let mut ext_keyusages = vec![];
168 if !is_ca {
169 ext_keyusages.push(x509_cert::der::oid::db::rfc5280::ID_KP_CLIENT_AUTH);
170 }
171
172 x509_cert::ext::pkix::ExtendedKeyUsage(ext_keyusages)
173}
174
175macro_rules! impl_certgen {
176 (
177 $signer:expr, $signer_keypair:expr, $sig_type:path,
178 $profile:expr, $own_spki:expr, $serial:expr,
179 $subject:expr, $org:expr, $domain:expr, $validity:expr, $alt_names:expr,
180 $crl_dps:expr, $is_ca:expr, $is_root:expr
181 ) => {{
182 let add_akid = $is_ca && $profile == x509_cert::builder::Profile::Root;
183
184 let mut builder = x509_cert::builder::CertificateBuilder::new(
185 $profile,
186 $serial,
187 $validity,
188 $subject,
189 $own_spki,
190 $signer_keypair,
191 )
192 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
193
194 if add_akid {
195 builder
196 .add_extension(&$signer.akid()?)
197 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
198 }
199
200 builder
201 .add_extension(&get_extended_keyusage($is_ca))
202 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
203
204 if !$is_ca {
205 if let Some(alt_names) = $alt_names {
206 let mut alt_names_list = vec![];
207 for alt_name in alt_names {
208 alt_names_list.push(x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
209 alt_name
210 .to_string()
211 .try_into()
212 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
213 ));
214 }
215
216 builder
217 .add_extension(&x509_cert::ext::pkix::SubjectAltName(alt_names_list))
218 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
219 }
220 } else {
221 let mut permitted_subtrees = vec![
222 x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
223 format!(".{}", $org)
224 .try_into()
225 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
226 ),
227 x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
228 format!("{}", $org)
229 .try_into()
230 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
231 ),
232 ];
233
234 if let Some(domain) = $domain {
235 builder
237 .add_extension(&x509_cert::ext::pkix::SubjectAltName(vec![
238 x509_cert::ext::pkix::name::GeneralName::DnsName(
239 domain
240 .to_string()
241 .try_into()
242 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
243 ),
244 ]))
245 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
246
247 permitted_subtrees.push(x509_cert::ext::pkix::name::GeneralName::DnsName(
248 domain
249 .to_string()
250 .try_into()
251 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
252 ));
253 }
254
255 if !$is_root {
256 builder
257 .add_extension(&x509_cert::ext::pkix::NameConstraints {
258 permitted_subtrees: Some(
259 permitted_subtrees
260 .into_iter()
261 .map(|base| x509_cert::ext::pkix::constraints::name::GeneralSubtree {
262 base,
263 minimum: 0,
264 maximum: None,
265 })
266 .collect(),
267 ),
268
269 excluded_subtrees: None,
270 })
271 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
272 }
273 }
274
275 if let Some(crl_dps) = $crl_dps {
276 let mut crl_distribution_points = vec![];
277 for dp in crl_dps {
278 crl_distribution_points.push(x509_cert::ext::pkix::crl::dp::DistributionPoint {
279 distribution_point: Some(x509_cert::ext::pkix::name::DistributionPointName::FullName(vec![
280 x509_cert::ext::pkix::name::GeneralName::UniformResourceIdentifier(
281 dp.to_string()
282 .try_into()
283 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
284 ),
285 ])),
286 crl_issuer: None,
287 reasons: None,
288 });
289 }
290 builder
291 .add_extension(&x509_cert::ext::pkix::CrlDistributionPoints(crl_distribution_points))
292 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
293 }
294
295 builder
296 .build::<$sig_type>()
297 .map_err(|_| E2eIdentityError::CertificateGenerationError)?
298 }};
299}
300
301impl PkiKeypair {
302 pub fn new(signature_scheme: SignatureScheme, sk: Vec<u8>) -> E2eIdentityResult<Self> {
303 match signature_scheme {
304 SignatureScheme::ECDSA_SECP256R1_SHA256 => Ok(PkiKeypair::P256(
305 p256::ecdsa::SigningKey::from_slice(sk.as_slice())
306 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
307 )),
308 SignatureScheme::ECDSA_SECP384R1_SHA384 => Ok(PkiKeypair::P384(
309 p384::ecdsa::SigningKey::from_slice(sk.as_slice())
310 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
311 )),
312 SignatureScheme::ECDSA_SECP521R1_SHA512 => Ok(PkiKeypair::P521(P521PkiKeypair(
313 ecdsa::SigningKey::<p521::NistP521>::from_slice(sk.as_slice())
314 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
315 ))),
316 SignatureScheme::ED25519 => Ok(PkiKeypair::Ed25519(Ed25519PkiKeypair(
317 ed25519_dalek::SigningKey::from_bytes(
318 sk.as_slice()
319 .try_into()
320 .expect("private key must be exactly {ed25519_dalek::SECRET_KEY_LENGTH} bytes"),
321 ),
322 ))),
323 _ => Err(E2eIdentityError::UnsupportedSignatureScheme),
324 }
325 }
326
327 pub fn signature_algorithm(&self) -> spki::AlgorithmIdentifierRef<'_> {
328 match self {
329 Self::P256(_) => p256::ecdsa::SigningKey::SIGNATURE_ALGORITHM_IDENTIFIER,
330 Self::P384(_) => p384::ecdsa::SigningKey::SIGNATURE_ALGORITHM_IDENTIFIER,
331 Self::P521(_) => spki::AlgorithmIdentifierRef {
332 oid: ecdsa::ECDSA_SHA512_OID,
333 parameters: None,
334 },
335 Self::Ed25519(_) => ed25519_dalek::pkcs8::ALGORITHM_ID,
336 }
337 }
338
339 pub fn spki(&self) -> E2eIdentityResult<spki::SubjectPublicKeyInfoOwned> {
340 match self {
341 Self::P256(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.verifying_key())
342 .map_err(|_| E2eIdentityError::CertificateGenerationError)?),
343 Self::P384(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.verifying_key())
344 .map_err(|_| E2eIdentityError::CertificateGenerationError)?),
345 Self::P521(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(*sk.0.verifying_key())
346 .map_err(|_| E2eIdentityError::CertificateGenerationError)?),
347 Self::Ed25519(sk) => Ok(spki::SubjectPublicKeyInfoOwned::from_key(sk.0.verifying_key())
348 .map_err(|_| E2eIdentityError::CertificateGenerationError)?),
349 }
350 }
351
352 pub fn akid(&self) -> E2eIdentityResult<x509_cert::ext::pkix::AuthorityKeyIdentifier> {
353 Ok(x509_cert::ext::pkix::AuthorityKeyIdentifier {
354 key_identifier: Some(
355 spki::der::asn1::OctetString::new(self.public_key_identifier())
356 .map_err(|_| E2eIdentityError::CertificateGenerationError)?,
357 ),
358 authority_cert_issuer: None,
359 authority_cert_serial_number: None,
360 })
361 }
362
363 pub fn revoke_certs(
364 &self,
365 issuer_cert: &x509_cert::Certificate,
366 revoked_cert_serial_numbers: Vec<Vec<u8>>,
367 ) -> E2eIdentityResult<x509_cert::crl::CertificateList> {
368 let signature_algorithm = self.signature_algorithm();
369 let now = web_time::SystemTime::now()
370 .duration_since(web_time::UNIX_EPOCH)
371 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
372 let now = x509_cert::der::asn1::GeneralizedTime::from_unix_duration(now)
373 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
374 let now = x509_cert::time::Time::GeneralTime(now);
375
376 let revoked_certificates = revoked_cert_serial_numbers
377 .into_iter()
378 .map(|serial_number| x509_cert::crl::RevokedCert {
379 serial_number: x509_cert::serial_number::SerialNumber::new(&serial_number)
380 .expect("Non-positive serial number"),
381 revocation_date: now,
382 crl_entry_extensions: None,
383 })
384 .collect();
385
386 let tbs_cert_list = x509_cert::crl::TbsCertList {
387 version: x509_cert::Version::V3,
388 signature: signature_algorithm.ref_to_owned(),
389 issuer: issuer_cert.tbs_certificate.subject.clone(),
390 this_update: now,
391 next_update: None,
392 revoked_certificates: Some(revoked_certificates),
393 crl_extensions: None,
394 };
395
396 use spki::der::Encode as _;
397
398 let tbs = tbs_cert_list
399 .to_der()
400 .map_err(|_| E2eIdentityError::CertificateGenerationError)?;
401
402 use signature::Signer as _;
403
404 let signature: Vec<u8> = match self {
405 PkiKeypair::P256(sk) => signature::Signer::<p256::ecdsa::DerSignature>::try_sign(sk, &tbs)?
406 .to_der()
407 .map_err(|_| E2eIdentityError::CertificateGenerationError),
408 PkiKeypair::P384(sk) => signature::Signer::<p384::ecdsa::DerSignature>::try_sign(sk, &tbs)?
409 .to_der()
410 .map_err(|_| E2eIdentityError::CertificateGenerationError),
411 PkiKeypair::P521(sk) => {
412 let sk = p521::ecdsa::SigningKey::from(sk.0.clone());
413 let signature: p521::ecdsa::DerSignature = sk.try_sign(&tbs)?.to_der();
414
415 signature
416 .to_der()
417 .map_err(|_| E2eIdentityError::CertificateGenerationError)
418 }
419 PkiKeypair::Ed25519(sk) => Ok(sk.try_sign(&tbs)?.0.to_vec()),
420 }?;
421
422 let signature =
423 spki::der::asn1::BitString::new(0, signature).map_err(|_| E2eIdentityError::CertificateGenerationError)?;
424
425 Ok(x509_cert::crl::CertificateList {
426 tbs_cert_list,
427 signature_algorithm: signature_algorithm.ref_to_owned(),
428 signature,
429 })
430 }
431
432 pub fn generate_cert(&self, args: CertificateGenerationArgs) -> E2eIdentityResult<x509_cert::Certificate> {
433 use std::str::FromStr as _;
434
435 use x509_cert::builder::Builder as _;
436 let mut subject_fmt = format!("O={}", args.org);
437 if let Some(cn) = args.common_name {
438 subject_fmt.push_str(&format!(",CN={cn}"));
439 }
440
441 let subject =
442 x509_cert::name::Name::from_str(&subject_fmt).map_err(|_| E2eIdentityError::CertificateGenerationError)?;
443
444 let validity_start = if let Some(validity_start) = args.validity_start {
445 validity_start
446 } else {
447 web_time::SystemTime::now()
448 .duration_since(web_time::UNIX_EPOCH)
449 .map_err(|_| E2eIdentityError::CertificateGenerationError)?
450 } - std::time::Duration::from_secs(1); let validity = {
453 let not_before = x509_cert::der::asn1::GeneralizedTime::from_unix_duration(validity_start)
454 .map_err(|_| E2eIdentityError::CertificateGenerationError)?
455 .into();
456 let not_after =
457 x509_cert::der::asn1::GeneralizedTime::from_unix_duration(validity_start + args.validity_from_start)
458 .map_err(|_| E2eIdentityError::CertificateGenerationError)?
459 .into();
460 x509_cert::time::Validity { not_before, not_after }
461 };
462
463 let serial_number = x509_cert::serial_number::SerialNumber::from(args.serial);
464 let spki = self.spki()?;
465
466 let signer = args.signer.unwrap_or(self);
467
468 let cert = match signer {
469 PkiKeypair::P256(kp) => {
470 impl_certgen!(
471 signer,
472 kp,
473 p256::ecdsa::DerSignature,
474 args.profile,
475 spki,
476 serial_number,
477 subject,
478 args.org,
479 args.domain,
480 validity,
481 args.alternative_names,
482 args.crl_dps,
483 args.is_ca,
484 args.is_root
485 )
486 }
487 PkiKeypair::P384(kp) => {
488 impl_certgen!(
489 signer,
490 kp,
491 p384::ecdsa::DerSignature,
492 args.profile,
493 spki,
494 serial_number,
495 subject,
496 args.org,
497 args.domain,
498 validity,
499 args.alternative_names,
500 args.crl_dps,
501 args.is_ca,
502 args.is_root
503 )
504 }
505 PkiKeypair::P521(kp) => {
506 impl_certgen!(
507 signer,
508 kp,
509 p521::ecdsa::DerSignature,
510 args.profile,
511 spki,
512 serial_number,
513 subject,
514 args.org,
515 args.domain,
516 validity,
517 args.alternative_names,
518 args.crl_dps,
519 args.is_ca,
520 args.is_root
521 )
522 }
523 PkiKeypair::Ed25519(kp) => {
524 impl_certgen!(
525 signer,
526 kp,
527 Ed25519PkiSignature,
528 args.profile,
529 spki,
530 serial_number,
531 subject,
532 args.org,
533 args.domain,
534 validity,
535 args.alternative_names,
536 args.crl_dps,
537 args.is_ca,
538 args.is_root
539 )
540 }
541 };
542
543 Ok(cert)
544 }
545
546 pub fn rand(alg: SignatureScheme, crypto: &impl OpenMlsCrypto) -> super::E2eIdentityResult<Self> {
547 Self::new(
548 alg,
549 crypto
550 .signature_key_gen(alg)
551 .map_err(|_| super::E2eIdentityError::SignatureKeyGenerationFailed)?
552 .0,
553 )
554 }
555}