g3mkcert: support tlcp certs

This commit is contained in:
Zhang Jingqiang 2023-06-14 15:27:15 +08:00
parent 34b8bb7e6a
commit 5373fa0213
7 changed files with 323 additions and 65 deletions

View file

@ -21,7 +21,7 @@ use anyhow::anyhow;
use openssl::pkey::{PKey, Private};
use openssl::x509::X509;
use g3_tls_cert::builder::ServerCertBuilder;
use g3_tls_cert::builder::{ServerCertBuilder, TlsServerCertBuilder};
use g3_types::net::Host;
use crate::frontend::ResponseData;
@ -49,7 +49,7 @@ pub(crate) struct OpensslBackend {
impl OpensslBackend {
pub(crate) fn new(config: &Arc<OpensslBackendConfig>) -> anyhow::Result<Self> {
let builder = ServerCertBuilder::new_ec256()?;
let builder = TlsServerCertBuilder::new_ec256()?;
Ok(OpensslBackend {
config: Arc::clone(config),
builder,

View file

@ -27,7 +27,9 @@ use openssl::x509::{X509Name, X509};
use g3_tls_cert::builder::{
ClientCertBuilder, IntermediateCertBuilder, RootCertBuilder, ServerCertBuilder,
SubjectNameBuilder,
SubjectNameBuilder, TlcpClientEncCertBuilder, TlcpClientSignCertBuilder,
TlcpServerEncCertBuilder, TlcpServerSignCertBuilder, TlsClientCertBuilder,
TlsServerCertBuilder,
};
use g3_types::net::Host;
@ -40,6 +42,10 @@ const ARG_ROOT: &str = "root";
const ARG_INTERMEDIATE: &str = "intermediate";
const ARG_TLS_SERVER: &str = "tls-server";
const ARG_TLS_CLIENT: &str = "tls-client";
const ARG_TLCP_SERVER_SIGN: &str = "tlcp-server-sign";
const ARG_TLCP_SERVER_ENC: &str = "tlcp-server-enc";
const ARG_TLCP_CLIENT_SIGN: &str = "tlcp-client-sign";
const ARG_TLCP_CLIENT_ENC: &str = "tlcp-client-enc";
const ARG_RSA: &str = "rsa";
const ARG_EC224: &str = "ec224";
@ -93,6 +99,14 @@ fn main() -> anyhow::Result<()> {
generate_tls_server(args)
} else if args.get_flag(ARG_TLS_CLIENT) {
generate_tls_client(args)
} else if args.get_flag(ARG_TLCP_SERVER_SIGN) {
generate_tlcp_server_sign(args)
} else if args.get_flag(ARG_TLCP_SERVER_ENC) {
generate_tlcp_server_enc(args)
} else if args.get_flag(ARG_TLCP_CLIENT_SIGN) {
generate_tlcp_client_sign(args)
} else if args.get_flag(ARG_TLCP_CLIENT_ENC) {
generate_tlcp_client_enc(args)
} else {
unreachable!()
}
@ -153,6 +167,46 @@ fn build_cli_args() -> Command {
.requires(ARG_CA_KEY)
.requires(ARG_HOST),
)
.arg(
Arg::new(ARG_TLCP_SERVER_SIGN)
.help("Generate end entity sign certificate for TLCP server")
.num_args(0)
.long(ARG_TLCP_SERVER_SIGN)
.action(ArgAction::SetTrue)
.requires(ARG_CA_CERT)
.requires(ARG_CA_KEY)
.requires(ARG_HOST),
)
.arg(
Arg::new(ARG_TLCP_SERVER_ENC)
.help("Generate end entity enc certificate for TLCP server")
.num_args(0)
.long(ARG_TLCP_SERVER_ENC)
.action(ArgAction::SetTrue)
.requires(ARG_CA_CERT)
.requires(ARG_CA_KEY)
.requires(ARG_HOST),
)
.arg(
Arg::new(ARG_TLCP_CLIENT_SIGN)
.help("Generate end entity sign certificate for TLCP client")
.num_args(0)
.long(ARG_TLCP_CLIENT_SIGN)
.action(ArgAction::SetTrue)
.requires(ARG_CA_CERT)
.requires(ARG_CA_KEY)
.requires(ARG_HOST),
)
.arg(
Arg::new(ARG_TLCP_CLIENT_ENC)
.help("Generate end entity enc certificate for TLCP client")
.num_args(0)
.long(ARG_TLCP_CLIENT_ENC)
.action(ArgAction::SetTrue)
.requires(ARG_CA_CERT)
.requires(ARG_CA_KEY)
.requires(ARG_HOST),
)
.group(
ArgGroup::new(ARG_GROUP_TYPE)
.args([
@ -160,6 +214,10 @@ fn build_cli_args() -> Command {
ARG_INTERMEDIATE,
ARG_TLS_SERVER,
ARG_TLS_CLIENT,
ARG_TLCP_SERVER_SIGN,
ARG_TLCP_SERVER_ENC,
ARG_TLCP_CLIENT_SIGN,
ARG_TLCP_CLIENT_ENC,
ARG_VERSION,
ARG_COMPLETION,
])
@ -498,30 +556,62 @@ fn generate_intermediate(args: ArgMatches) -> anyhow::Result<()> {
}
fn generate_tls_server(args: ArgMatches) -> anyhow::Result<()> {
let mut builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
ServerCertBuilder::new_rsa(*bits)?
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlsServerCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_X448) {
ServerCertBuilder::new_x448()?
TlsServerCertBuilder::new_x448()?
} else if args.get_flag(ARG_X25519) {
ServerCertBuilder::new_x25519()?
TlsServerCertBuilder::new_x25519()?
} else if args.get_flag(ARG_ED448) {
ServerCertBuilder::new_ed448()?
TlsServerCertBuilder::new_ed448()?
} else if args.get_flag(ARG_ED25519) {
ServerCertBuilder::new_ed25519()?
TlsServerCertBuilder::new_ed25519()?
} else if args.get_flag(ARG_SM2) {
ServerCertBuilder::new_sm2()?
TlsServerCertBuilder::new_sm2()?
} else if args.get_flag(ARG_EC521) {
ServerCertBuilder::new_ec521()?
TlsServerCertBuilder::new_ec521()?
} else if args.get_flag(ARG_EC384) {
ServerCertBuilder::new_ec384()?
TlsServerCertBuilder::new_ec384()?
} else if args.get_flag(ARG_EC256) {
ServerCertBuilder::new_ec256()?
TlsServerCertBuilder::new_ec256()?
} else if args.get_flag(ARG_EC224) {
ServerCertBuilder::new_ec224()?
TlsServerCertBuilder::new_ec224()?
} else {
ServerCertBuilder::new_ec256()?
TlsServerCertBuilder::new_ec256()?
};
generate_server(builder, args)
}
fn generate_tlcp_server_sign(args: ArgMatches) -> anyhow::Result<()> {
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlcpServerSignCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_SM2) {
TlcpServerSignCertBuilder::new_sm2()?
} else if args.contains_id(ARG_GROUP_ALGORITHM) {
return Err(anyhow!("unsupported signature algorithm"));
} else {
TlcpServerSignCertBuilder::new_sm2()?
};
generate_server(builder, args)
}
fn generate_tlcp_server_enc(args: ArgMatches) -> anyhow::Result<()> {
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlcpServerEncCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_SM2) {
TlcpServerEncCertBuilder::new_sm2()?
} else if args.contains_id(ARG_GROUP_ALGORITHM) {
return Err(anyhow!("unsupported signature algorithm"));
} else {
TlcpServerEncCertBuilder::new_sm2()?
};
generate_server(builder, args)
}
fn generate_server(mut builder: ServerCertBuilder, args: ArgMatches) -> anyhow::Result<()> {
let (ca_cert, ca_key) = get_ca_cert_and_key(&args)?;
let (subject_name, subject_alt_name) =
get_subject_with_host(&args, builder.subject_builder_mut())?;
@ -542,30 +632,62 @@ fn generate_tls_server(args: ArgMatches) -> anyhow::Result<()> {
}
fn generate_tls_client(args: ArgMatches) -> anyhow::Result<()> {
let mut builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
ClientCertBuilder::new_rsa(*bits)?
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlsClientCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_X448) {
ClientCertBuilder::new_x448()?
TlsClientCertBuilder::new_x448()?
} else if args.get_flag(ARG_X25519) {
ClientCertBuilder::new_x25519()?
TlsClientCertBuilder::new_x25519()?
} else if args.get_flag(ARG_ED448) {
ClientCertBuilder::new_ed448()?
TlsClientCertBuilder::new_ed448()?
} else if args.get_flag(ARG_ED25519) {
ClientCertBuilder::new_ed25519()?
TlsClientCertBuilder::new_ed25519()?
} else if args.get_flag(ARG_SM2) {
ClientCertBuilder::new_sm2()?
TlsClientCertBuilder::new_sm2()?
} else if args.get_flag(ARG_EC521) {
ClientCertBuilder::new_ec521()?
TlsClientCertBuilder::new_ec521()?
} else if args.get_flag(ARG_EC384) {
ClientCertBuilder::new_ec384()?
TlsClientCertBuilder::new_ec384()?
} else if args.get_flag(ARG_EC256) {
ClientCertBuilder::new_ec256()?
TlsClientCertBuilder::new_ec256()?
} else if args.get_flag(ARG_EC224) {
ClientCertBuilder::new_ec224()?
TlsClientCertBuilder::new_ec224()?
} else {
ClientCertBuilder::new_ec256()?
TlsClientCertBuilder::new_ec256()?
};
generate_client(builder, args)
}
fn generate_tlcp_client_sign(args: ArgMatches) -> anyhow::Result<()> {
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlcpClientSignCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_SM2) {
TlcpClientSignCertBuilder::new_sm2()?
} else if args.contains_id(ARG_GROUP_ALGORITHM) {
return Err(anyhow!("unsupported signature algorithm"));
} else {
TlcpClientSignCertBuilder::new_sm2()?
};
generate_client(builder, args)
}
fn generate_tlcp_client_enc(args: ArgMatches) -> anyhow::Result<()> {
let builder = if let Some(bits) = args.get_one::<u32>(ARG_RSA) {
TlcpClientEncCertBuilder::new_rsa(*bits)?
} else if args.get_flag(ARG_SM2) {
TlcpClientEncCertBuilder::new_sm2()?
} else if args.contains_id(ARG_GROUP_ALGORITHM) {
return Err(anyhow!("unsupported signature algorithm"));
} else {
TlcpClientEncCertBuilder::new_sm2()?
};
generate_client(builder, args)
}
fn generate_client(mut builder: ClientCertBuilder, args: ArgMatches) -> anyhow::Result<()> {
let (ca_cert, ca_key) = get_ca_cert_and_key(&args)?;
let (subject_name, subject_alt_name) =
get_subject_with_host(&args, builder.subject_builder_mut())?;

View file

@ -40,40 +40,105 @@ pub struct ClientCertBuilder {
subject_builder: SubjectNameBuilder,
}
macro_rules! impl_new {
pub struct TlsClientCertBuilder {}
macro_rules! tls_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<Self> {
pub fn $f() -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::$f()?;
ClientCertBuilder::with_pkey(pkey)
TlsClientCertBuilder::with_pkey(pkey)
}
};
}
impl ClientCertBuilder {
impl_new!(new_ec224);
impl_new!(new_ec256);
impl_new!(new_ec384);
impl_new!(new_ec521);
impl_new!(new_sm2);
impl_new!(new_ed25519);
impl_new!(new_ed448);
impl_new!(new_x25519);
impl_new!(new_x448);
impl TlsClientCertBuilder {
tls_impl_new!(new_ec224);
tls_impl_new!(new_ec256);
tls_impl_new!(new_ec384);
tls_impl_new!(new_ec521);
tls_impl_new!(new_sm2);
tls_impl_new!(new_ed25519);
tls_impl_new!(new_ed448);
tls_impl_new!(new_x25519);
tls_impl_new!(new_x448);
pub fn new_rsa(bits: u32) -> anyhow::Result<Self> {
pub fn new_rsa(bits: u32) -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
ClientCertBuilder::with_pkey(pkey)
TlsClientCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<Self> {
let serial = super::serial::random_16()?;
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ClientCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.digital_signature()
.key_encipherment()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ClientCertBuilder::new(pkey, key_usage)
}
}
pub struct TlcpClientSignCertBuilder {}
macro_rules! tlcp_sign_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::$f()?;
TlcpClientSignCertBuilder::with_pkey(pkey)
}
};
}
impl TlcpClientSignCertBuilder {
tlcp_sign_impl_new!(new_sm2);
pub fn new_rsa(bits: u32) -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
TlcpClientSignCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ClientCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.digital_signature()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ClientCertBuilder::new(pkey, key_usage)
}
}
pub struct TlcpClientEncCertBuilder {}
macro_rules! tlcp_enc_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::$f()?;
TlcpClientEncCertBuilder::with_pkey(pkey)
}
};
}
impl TlcpClientEncCertBuilder {
tlcp_enc_impl_new!(new_sm2);
pub fn new_rsa(bits: u32) -> anyhow::Result<ClientCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
TlcpClientEncCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ClientCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.key_encipherment()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ClientCertBuilder::new(pkey, key_usage)
}
}
impl ClientCertBuilder {
pub fn new(pkey: PKey<Private>, key_usage: X509Extension) -> anyhow::Result<Self> {
let serial = super::serial::random_16()?;
let ext_key_usage = ExtendedKeyUsage::new()
.client_auth()

View file

@ -67,6 +67,7 @@ impl IntermediateCertBuilder {
let key_usage = KeyUsage::new()
.critical()
.key_cert_sign()
.crl_sign()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;

View file

@ -24,10 +24,14 @@ mod time;
use time::asn1_time_from_chrono;
mod server;
pub use server::ServerCertBuilder;
pub use server::{
ServerCertBuilder, TlcpServerEncCertBuilder, TlcpServerSignCertBuilder, TlsServerCertBuilder,
};
mod client;
pub use client::ClientCertBuilder;
pub use client::{
ClientCertBuilder, TlcpClientEncCertBuilder, TlcpClientSignCertBuilder, TlsClientCertBuilder,
};
mod root;
pub use root::RootCertBuilder;

View file

@ -66,6 +66,7 @@ impl RootCertBuilder {
let key_usage = KeyUsage::new()
.critical()
.key_cert_sign()
.crl_sign()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;

View file

@ -40,40 +40,105 @@ pub struct ServerCertBuilder {
subject_builder: SubjectNameBuilder,
}
macro_rules! impl_new {
pub struct TlsServerCertBuilder {}
macro_rules! tls_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<Self> {
pub fn $f() -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::$f()?;
ServerCertBuilder::with_pkey(pkey)
TlsServerCertBuilder::with_pkey(pkey)
}
};
}
impl ServerCertBuilder {
impl_new!(new_ec224);
impl_new!(new_ec256);
impl_new!(new_ec384);
impl_new!(new_ec521);
impl_new!(new_sm2);
impl_new!(new_ed25519);
impl_new!(new_ed448);
impl_new!(new_x25519);
impl_new!(new_x448);
impl TlsServerCertBuilder {
tls_impl_new!(new_ec224);
tls_impl_new!(new_ec256);
tls_impl_new!(new_ec384);
tls_impl_new!(new_ec521);
tls_impl_new!(new_sm2);
tls_impl_new!(new_ed25519);
tls_impl_new!(new_ed448);
tls_impl_new!(new_x25519);
tls_impl_new!(new_x448);
pub fn new_rsa(bits: u32) -> anyhow::Result<Self> {
pub fn new_rsa(bits: u32) -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
ServerCertBuilder::with_pkey(pkey)
TlsServerCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<Self> {
let serial = super::serial::random_16()?;
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ServerCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.digital_signature()
.key_encipherment()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ServerCertBuilder::new(pkey, key_usage)
}
}
pub struct TlcpServerSignCertBuilder {}
macro_rules! tlcp_sign_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::$f()?;
TlcpServerSignCertBuilder::with_pkey(pkey)
}
};
}
impl TlcpServerSignCertBuilder {
tlcp_sign_impl_new!(new_sm2);
pub fn new_rsa(bits: u32) -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
TlcpServerSignCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ServerCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.digital_signature()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ServerCertBuilder::new(pkey, key_usage)
}
}
pub struct TlcpServerEncCertBuilder {}
macro_rules! tlcp_enc_impl_new {
($f:ident) => {
pub fn $f() -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::$f()?;
TlcpServerEncCertBuilder::with_pkey(pkey)
}
};
}
impl TlcpServerEncCertBuilder {
tlcp_enc_impl_new!(new_sm2);
pub fn new_rsa(bits: u32) -> anyhow::Result<ServerCertBuilder> {
let pkey = super::pkey::new_rsa(bits)?;
TlcpServerEncCertBuilder::with_pkey(pkey)
}
fn with_pkey(pkey: PKey<Private>) -> anyhow::Result<ServerCertBuilder> {
let key_usage = KeyUsage::new()
.critical()
.key_encipherment()
.build()
.map_err(|e| anyhow!("failed to build KeyUsage extension: {e}"))?;
ServerCertBuilder::new(pkey, key_usage)
}
}
impl ServerCertBuilder {
pub fn new(pkey: PKey<Private>, key_usage: X509Extension) -> anyhow::Result<Self> {
let serial = super::serial::random_16()?;
let ext_key_usage = ExtendedKeyUsage::new()
.server_auth()