fn generate_cert()

in key/aziot-key-openssl-engine-shared-test/src/main.rs [194:289]


fn generate_cert(
    key_handle: String,
    out_file: &std::path::Path,
    subject: &str,
    kind: &GenerateCertKind,
) -> Result<(), Error> {
    let mut engine = load_engine()?;

    let mut builder = openssl::x509::X509::builder()?;

    builder.set_version(2)?;

    let public_key = load_public_key(&mut engine, key_handle.clone())?;
    builder.set_pubkey(&public_key)?;

    let not_after = openssl::asn1::Asn1Time::days_from_now(match &kind {
        GenerateCertKind::Ca => 365,
        GenerateCertKind::Client { .. } | GenerateCertKind::Server { .. } => 30,
    })?;
    builder.set_not_after(std::borrow::Borrow::borrow(&not_after))?;

    let not_before = openssl::asn1::Asn1Time::days_from_now(0)?;
    builder.set_not_before(std::borrow::Borrow::borrow(&not_before))?;

    let mut subject_name = openssl::x509::X509Name::builder()?;
    subject_name.append_entry_by_text("CN", subject)?;
    let subject_name = subject_name.build();
    builder.set_subject_name(&subject_name)?;

    match &kind {
        GenerateCertKind::Ca => {
            builder.set_issuer_name(&subject_name)?;

            let ca_extension = openssl::x509::extension::BasicConstraints::new()
                .ca()
                .build()?;
            builder.append_extension(ca_extension)?;
        }

        GenerateCertKind::Client { ca_cert, .. } | GenerateCertKind::Server { ca_cert, .. } => {
            let ca_cert = std::fs::read(ca_cert)?;
            let ca_cert = openssl::x509::X509::from_pem(&ca_cert)?;
            builder.set_issuer_name(ca_cert.subject_name())?;

            match kind {
                GenerateCertKind::Ca => unreachable!(),

                GenerateCertKind::Client { .. } => {
                    let client_extension = openssl::x509::extension::ExtendedKeyUsage::new()
                        .client_auth()
                        .build()?;
                    builder.append_extension(client_extension)?;
                }

                GenerateCertKind::Server { .. } => {
                    let server_extension = openssl::x509::extension::ExtendedKeyUsage::new()
                        .server_auth()
                        .build()?;
                    builder.append_extension(server_extension)?;

                    let context = builder.x509v3_context(Some(&ca_cert), None);
                    let san_extension = openssl::x509::extension::SubjectAlternativeName::new()
                        .ip("127.0.0.1")
                        .build(&context)?;
                    builder.append_extension(san_extension)?;
                }
            }
        }
    }

    let ca_key_handle = match &kind {
        GenerateCertKind::Ca => key_handle,
        GenerateCertKind::Client { ca_key_handle, .. }
        | GenerateCertKind::Server { ca_key_handle, .. } => ca_key_handle.clone(),
    };
    let ca_key = load_private_key(&mut engine, ca_key_handle)?;
    builder.sign(&ca_key, openssl::hash::MessageDigest::sha256())?;

    let cert = builder.build();

    let cert = cert.to_pem()?;

    let mut out_file = std::fs::File::create(out_file)?;
    std::io::Write::write_all(&mut out_file, &cert)?;
    match &kind {
        GenerateCertKind::Ca => (),

        GenerateCertKind::Client { ca_cert, .. } | GenerateCertKind::Server { ca_cert, .. } => {
            let ca_cert = std::fs::read(ca_cert)?;
            std::io::Write::write_all(&mut out_file, &ca_cert)?;
        }
    }
    std::io::Write::flush(&mut out_file)?;

    Ok(())
}