Skip to main content

klukai_types/
tls.rs

1use std::net::IpAddr;
2
3use rcgen::{
4    BasicConstraints, Certificate, CertificateParams, DistinguishedName, DnType, DnValue, IsCa,
5    Issuer, KeyIdMethod, KeyPair, KeyUsagePurpose, SanType,
6};
7use time::OffsetDateTime;
8
9#[derive(Debug, thiserror::Error)]
10pub enum Error {
11    #[error(transparent)]
12    Rcgen(#[from] rcgen::Error),
13    #[error(transparent)]
14    Io(#[from] std::io::Error),
15}
16
17pub fn generate_ca() -> Result<(Certificate, KeyPair), Error> {
18    let key_pair = KeyPair::generate()?;
19    let mut params = CertificateParams::default();
20
21    params.key_identifier_method = KeyIdMethod::Sha384;
22
23    let mut dn = DistinguishedName::new();
24    dn.push(
25        DnType::CommonName,
26        DnValue::PrintableString("Corrosion Root CA".try_into()?),
27    );
28    params.distinguished_name = dn;
29    params.is_ca = IsCa::Ca(BasicConstraints::Unconstrained);
30
31    params.not_before = OffsetDateTime::now_utc();
32    params.not_after = OffsetDateTime::now_utc() + time::Duration::days(365 * 5);
33
34    params.key_usages = vec![KeyUsagePurpose::KeyCertSign, KeyUsagePurpose::CrlSign];
35    let cert = params.self_signed(&key_pair)?;
36
37    Ok((cert, key_pair))
38}
39
40pub fn generate_server_cert(
41    ca_cert_pem: &str,
42    ca_key_pem: &str,
43    ip: IpAddr,
44) -> Result<(Certificate, String, KeyPair), Error> {
45    let ca_cert = ca_cert(ca_cert_pem, ca_key_pem)?;
46    let key_pair = KeyPair::generate()?;
47
48    let mut params = CertificateParams::default();
49
50    params.key_identifier_method = KeyIdMethod::Sha384;
51
52    let mut dn = DistinguishedName::new();
53    dn.push(
54        DnType::CommonName,
55        DnValue::PrintableString("r.u.local".try_into()?),
56    );
57    params.distinguished_name = dn;
58
59    params.subject_alt_names = vec![SanType::IpAddress(ip)];
60
61    params.not_before = OffsetDateTime::now_utc();
62    params.not_after = OffsetDateTime::now_utc() + time::Duration::days(365);
63
64    let cert = params.signed_by(&key_pair, &ca_cert)?;
65    let cert_signed = cert.pem();
66
67    Ok((cert, cert_signed, key_pair))
68}
69
70fn ca_cert<'a>(
71    ca_cert_pem: &'a str,
72    ca_key_pem: &'a str,
73) -> Result<Issuer<'a, KeyPair>, rcgen::Error> {
74    let key_pair = KeyPair::from_pem(ca_key_pem)?;
75    Issuer::from_ca_cert_pem(ca_cert_pem, key_pair)
76}
77
78pub fn generate_client_cert(
79    ca_cert_pem: &str,
80    ca_key_pem: &str,
81) -> Result<(Certificate, String, KeyPair), Error> {
82    let ca_cert = ca_cert(ca_cert_pem, ca_key_pem)?;
83    let key_pair = KeyPair::generate()?;
84
85    let mut params = CertificateParams::default();
86
87    params.key_identifier_method = KeyIdMethod::Sha384;
88
89    let dn = DistinguishedName::new();
90    params.distinguished_name = dn;
91
92    params.not_before = OffsetDateTime::now_utc();
93    params.not_after = OffsetDateTime::now_utc() + time::Duration::days(365);
94
95    let cert = params.signed_by(&key_pair, &ca_cert)?;
96    let cert_signed = cert.pem();
97
98    Ok((cert, cert_signed, key_pair))
99}