192f3ab15Sopenharmony_ci#![allow(clippy::uninlined_format_args)] 292f3ab15Sopenharmony_ci 392f3ab15Sopenharmony_ci//! A program that generates ca certs, certs verified by the ca, and public 492f3ab15Sopenharmony_ci//! and private keys. 592f3ab15Sopenharmony_ci 692f3ab15Sopenharmony_ciuse openssl::asn1::Asn1Time; 792f3ab15Sopenharmony_ciuse openssl::bn::{BigNum, MsbOption}; 892f3ab15Sopenharmony_ciuse openssl::error::ErrorStack; 992f3ab15Sopenharmony_ciuse openssl::hash::MessageDigest; 1092f3ab15Sopenharmony_ciuse openssl::pkey::{PKey, PKeyRef, Private}; 1192f3ab15Sopenharmony_ciuse openssl::rsa::Rsa; 1292f3ab15Sopenharmony_ciuse openssl::x509::extension::{ 1392f3ab15Sopenharmony_ci AuthorityKeyIdentifier, BasicConstraints, KeyUsage, SubjectAlternativeName, 1492f3ab15Sopenharmony_ci SubjectKeyIdentifier, 1592f3ab15Sopenharmony_ci}; 1692f3ab15Sopenharmony_ciuse openssl::x509::{X509NameBuilder, X509Ref, X509Req, X509ReqBuilder, X509VerifyResult, X509}; 1792f3ab15Sopenharmony_ci 1892f3ab15Sopenharmony_ci/// Make a CA certificate and private key 1992f3ab15Sopenharmony_cifn mk_ca_cert() -> Result<(X509, PKey<Private>), ErrorStack> { 2092f3ab15Sopenharmony_ci let rsa = Rsa::generate(2048)?; 2192f3ab15Sopenharmony_ci let key_pair = PKey::from_rsa(rsa)?; 2292f3ab15Sopenharmony_ci 2392f3ab15Sopenharmony_ci let mut x509_name = X509NameBuilder::new()?; 2492f3ab15Sopenharmony_ci x509_name.append_entry_by_text("C", "US")?; 2592f3ab15Sopenharmony_ci x509_name.append_entry_by_text("ST", "TX")?; 2692f3ab15Sopenharmony_ci x509_name.append_entry_by_text("O", "Some CA organization")?; 2792f3ab15Sopenharmony_ci x509_name.append_entry_by_text("CN", "ca test")?; 2892f3ab15Sopenharmony_ci let x509_name = x509_name.build(); 2992f3ab15Sopenharmony_ci 3092f3ab15Sopenharmony_ci let mut cert_builder = X509::builder()?; 3192f3ab15Sopenharmony_ci cert_builder.set_version(2)?; 3292f3ab15Sopenharmony_ci let serial_number = { 3392f3ab15Sopenharmony_ci let mut serial = BigNum::new()?; 3492f3ab15Sopenharmony_ci serial.rand(159, MsbOption::MAYBE_ZERO, false)?; 3592f3ab15Sopenharmony_ci serial.to_asn1_integer()? 3692f3ab15Sopenharmony_ci }; 3792f3ab15Sopenharmony_ci cert_builder.set_serial_number(&serial_number)?; 3892f3ab15Sopenharmony_ci cert_builder.set_subject_name(&x509_name)?; 3992f3ab15Sopenharmony_ci cert_builder.set_issuer_name(&x509_name)?; 4092f3ab15Sopenharmony_ci cert_builder.set_pubkey(&key_pair)?; 4192f3ab15Sopenharmony_ci let not_before = Asn1Time::days_from_now(0)?; 4292f3ab15Sopenharmony_ci cert_builder.set_not_before(¬_before)?; 4392f3ab15Sopenharmony_ci let not_after = Asn1Time::days_from_now(365)?; 4492f3ab15Sopenharmony_ci cert_builder.set_not_after(¬_after)?; 4592f3ab15Sopenharmony_ci 4692f3ab15Sopenharmony_ci cert_builder.append_extension(BasicConstraints::new().critical().ca().build()?)?; 4792f3ab15Sopenharmony_ci cert_builder.append_extension( 4892f3ab15Sopenharmony_ci KeyUsage::new() 4992f3ab15Sopenharmony_ci .critical() 5092f3ab15Sopenharmony_ci .key_cert_sign() 5192f3ab15Sopenharmony_ci .crl_sign() 5292f3ab15Sopenharmony_ci .build()?, 5392f3ab15Sopenharmony_ci )?; 5492f3ab15Sopenharmony_ci 5592f3ab15Sopenharmony_ci let subject_key_identifier = 5692f3ab15Sopenharmony_ci SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(None, None))?; 5792f3ab15Sopenharmony_ci cert_builder.append_extension(subject_key_identifier)?; 5892f3ab15Sopenharmony_ci 5992f3ab15Sopenharmony_ci cert_builder.sign(&key_pair, MessageDigest::sha256())?; 6092f3ab15Sopenharmony_ci let cert = cert_builder.build(); 6192f3ab15Sopenharmony_ci 6292f3ab15Sopenharmony_ci Ok((cert, key_pair)) 6392f3ab15Sopenharmony_ci} 6492f3ab15Sopenharmony_ci 6592f3ab15Sopenharmony_ci/// Make a X509 request with the given private key 6692f3ab15Sopenharmony_cifn mk_request(key_pair: &PKey<Private>) -> Result<X509Req, ErrorStack> { 6792f3ab15Sopenharmony_ci let mut req_builder = X509ReqBuilder::new()?; 6892f3ab15Sopenharmony_ci req_builder.set_pubkey(key_pair)?; 6992f3ab15Sopenharmony_ci 7092f3ab15Sopenharmony_ci let mut x509_name = X509NameBuilder::new()?; 7192f3ab15Sopenharmony_ci x509_name.append_entry_by_text("C", "US")?; 7292f3ab15Sopenharmony_ci x509_name.append_entry_by_text("ST", "TX")?; 7392f3ab15Sopenharmony_ci x509_name.append_entry_by_text("O", "Some organization")?; 7492f3ab15Sopenharmony_ci x509_name.append_entry_by_text("CN", "www.example.com")?; 7592f3ab15Sopenharmony_ci let x509_name = x509_name.build(); 7692f3ab15Sopenharmony_ci req_builder.set_subject_name(&x509_name)?; 7792f3ab15Sopenharmony_ci 7892f3ab15Sopenharmony_ci req_builder.sign(key_pair, MessageDigest::sha256())?; 7992f3ab15Sopenharmony_ci let req = req_builder.build(); 8092f3ab15Sopenharmony_ci Ok(req) 8192f3ab15Sopenharmony_ci} 8292f3ab15Sopenharmony_ci 8392f3ab15Sopenharmony_ci/// Make a certificate and private key signed by the given CA cert and private key 8492f3ab15Sopenharmony_cifn mk_ca_signed_cert( 8592f3ab15Sopenharmony_ci ca_cert: &X509Ref, 8692f3ab15Sopenharmony_ci ca_key_pair: &PKeyRef<Private>, 8792f3ab15Sopenharmony_ci) -> Result<(X509, PKey<Private>), ErrorStack> { 8892f3ab15Sopenharmony_ci let rsa = Rsa::generate(2048)?; 8992f3ab15Sopenharmony_ci let key_pair = PKey::from_rsa(rsa)?; 9092f3ab15Sopenharmony_ci 9192f3ab15Sopenharmony_ci let req = mk_request(&key_pair)?; 9292f3ab15Sopenharmony_ci 9392f3ab15Sopenharmony_ci let mut cert_builder = X509::builder()?; 9492f3ab15Sopenharmony_ci cert_builder.set_version(2)?; 9592f3ab15Sopenharmony_ci let serial_number = { 9692f3ab15Sopenharmony_ci let mut serial = BigNum::new()?; 9792f3ab15Sopenharmony_ci serial.rand(159, MsbOption::MAYBE_ZERO, false)?; 9892f3ab15Sopenharmony_ci serial.to_asn1_integer()? 9992f3ab15Sopenharmony_ci }; 10092f3ab15Sopenharmony_ci cert_builder.set_serial_number(&serial_number)?; 10192f3ab15Sopenharmony_ci cert_builder.set_subject_name(req.subject_name())?; 10292f3ab15Sopenharmony_ci cert_builder.set_issuer_name(ca_cert.subject_name())?; 10392f3ab15Sopenharmony_ci cert_builder.set_pubkey(&key_pair)?; 10492f3ab15Sopenharmony_ci let not_before = Asn1Time::days_from_now(0)?; 10592f3ab15Sopenharmony_ci cert_builder.set_not_before(¬_before)?; 10692f3ab15Sopenharmony_ci let not_after = Asn1Time::days_from_now(365)?; 10792f3ab15Sopenharmony_ci cert_builder.set_not_after(¬_after)?; 10892f3ab15Sopenharmony_ci 10992f3ab15Sopenharmony_ci cert_builder.append_extension(BasicConstraints::new().build()?)?; 11092f3ab15Sopenharmony_ci 11192f3ab15Sopenharmony_ci cert_builder.append_extension( 11292f3ab15Sopenharmony_ci KeyUsage::new() 11392f3ab15Sopenharmony_ci .critical() 11492f3ab15Sopenharmony_ci .non_repudiation() 11592f3ab15Sopenharmony_ci .digital_signature() 11692f3ab15Sopenharmony_ci .key_encipherment() 11792f3ab15Sopenharmony_ci .build()?, 11892f3ab15Sopenharmony_ci )?; 11992f3ab15Sopenharmony_ci 12092f3ab15Sopenharmony_ci let subject_key_identifier = 12192f3ab15Sopenharmony_ci SubjectKeyIdentifier::new().build(&cert_builder.x509v3_context(Some(ca_cert), None))?; 12292f3ab15Sopenharmony_ci cert_builder.append_extension(subject_key_identifier)?; 12392f3ab15Sopenharmony_ci 12492f3ab15Sopenharmony_ci let auth_key_identifier = AuthorityKeyIdentifier::new() 12592f3ab15Sopenharmony_ci .keyid(false) 12692f3ab15Sopenharmony_ci .issuer(false) 12792f3ab15Sopenharmony_ci .build(&cert_builder.x509v3_context(Some(ca_cert), None))?; 12892f3ab15Sopenharmony_ci cert_builder.append_extension(auth_key_identifier)?; 12992f3ab15Sopenharmony_ci 13092f3ab15Sopenharmony_ci let subject_alt_name = SubjectAlternativeName::new() 13192f3ab15Sopenharmony_ci .dns("*.example.com") 13292f3ab15Sopenharmony_ci .dns("hello.com") 13392f3ab15Sopenharmony_ci .build(&cert_builder.x509v3_context(Some(ca_cert), None))?; 13492f3ab15Sopenharmony_ci cert_builder.append_extension(subject_alt_name)?; 13592f3ab15Sopenharmony_ci 13692f3ab15Sopenharmony_ci cert_builder.sign(ca_key_pair, MessageDigest::sha256())?; 13792f3ab15Sopenharmony_ci let cert = cert_builder.build(); 13892f3ab15Sopenharmony_ci 13992f3ab15Sopenharmony_ci Ok((cert, key_pair)) 14092f3ab15Sopenharmony_ci} 14192f3ab15Sopenharmony_ci 14292f3ab15Sopenharmony_cifn real_main() -> Result<(), ErrorStack> { 14392f3ab15Sopenharmony_ci let (ca_cert, ca_key_pair) = mk_ca_cert()?; 14492f3ab15Sopenharmony_ci let (cert, _key_pair) = mk_ca_signed_cert(&ca_cert, &ca_key_pair)?; 14592f3ab15Sopenharmony_ci 14692f3ab15Sopenharmony_ci // Verify that this cert was issued by this ca 14792f3ab15Sopenharmony_ci match ca_cert.issued(&cert) { 14892f3ab15Sopenharmony_ci X509VerifyResult::OK => println!("Certificate verified!"), 14992f3ab15Sopenharmony_ci ver_err => println!("Failed to verify certificate: {}", ver_err), 15092f3ab15Sopenharmony_ci }; 15192f3ab15Sopenharmony_ci 15292f3ab15Sopenharmony_ci Ok(()) 15392f3ab15Sopenharmony_ci} 15492f3ab15Sopenharmony_ci 15592f3ab15Sopenharmony_cifn main() { 15692f3ab15Sopenharmony_ci match real_main() { 15792f3ab15Sopenharmony_ci Ok(()) => println!("Finished."), 15892f3ab15Sopenharmony_ci Err(e) => println!("Error: {}", e), 15992f3ab15Sopenharmony_ci }; 16092f3ab15Sopenharmony_ci} 161