kanidm_lib_crypto/
mtls.rs
1use crate::CryptoError;
2
3use openssl::asn1;
4use openssl::bn;
5use openssl::ec;
6use openssl::error::ErrorStack as OpenSSLError;
7use openssl::hash;
8use openssl::nid::Nid;
9use openssl::pkey::{PKey, Private};
10use openssl::x509::extension::BasicConstraints;
11use openssl::x509::extension::ExtendedKeyUsage;
12use openssl::x509::extension::KeyUsage;
13use openssl::x509::extension::SubjectAlternativeName;
14use openssl::x509::extension::SubjectKeyIdentifier;
15use openssl::x509::X509NameBuilder;
16use openssl::x509::X509;
17
18use uuid::Uuid;
19
20pub fn get_group() -> Result<ec::EcGroup, OpenSSLError> {
22 ec::EcGroup::from_curve_name(Nid::X9_62_PRIME256V1)
23}
24
25pub fn build_self_signed_server_and_client_identity(
26 cn: Uuid,
27 domain_name: &str,
28 expiration_days: u32,
29) -> Result<(PKey<Private>, X509), CryptoError> {
30 let ecgroup = get_group()?;
31 let eckey = ec::EcKey::generate(&ecgroup)?;
32 let ca_key = PKey::from_ec_key(eckey)?;
33 let mut x509_name = X509NameBuilder::new()?;
34
35 x509_name.append_entry_by_text("O", "Kanidm Replication")?;
38 x509_name.append_entry_by_text("CN", &cn.as_hyphenated().to_string())?;
39 let x509_name = x509_name.build();
40
41 let mut cert_builder = X509::builder()?;
42 cert_builder.set_version(2)?;
44
45 let serial_number = bn::BigNum::from_u32(1).and_then(|serial| serial.to_asn1_integer())?;
46
47 cert_builder.set_serial_number(&serial_number)?;
48 cert_builder.set_subject_name(&x509_name)?;
49 cert_builder.set_issuer_name(&x509_name)?;
50
51 let not_before = asn1::Asn1Time::days_from_now(0)?;
52 cert_builder.set_not_before(¬_before)?;
53 let not_after = asn1::Asn1Time::days_from_now(expiration_days)?;
54 cert_builder.set_not_after(¬_after)?;
55
56 cert_builder.append_extension(BasicConstraints::new().critical().build()?)?;
58 cert_builder.append_extension(
59 KeyUsage::new()
60 .critical()
61 .digital_signature()
62 .key_encipherment()
63 .build()?,
64 )?;
65
66 cert_builder.append_extension(
67 ExtendedKeyUsage::new()
68 .server_auth()
69 .client_auth()
70 .build()?,
71 )?;
72
73 let subject_key_identifier =
74 SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?;
75 cert_builder.append_extension(subject_key_identifier)?;
76
77 let subject_alt_name = SubjectAlternativeName::new()
78 .dns(domain_name)
79 .build(&cert_builder.x509v3_context(None, None))?;
80
81 cert_builder.append_extension(subject_alt_name)?;
82
83 cert_builder.set_pubkey(&ca_key)?;
84
85 cert_builder.sign(&ca_key, hash::MessageDigest::sha256())?;
86 let ca_cert = cert_builder.build();
87
88 Ok((ca_key, ca_cert))
89}