summaryrefslogtreecommitdiffstats
path: root/rust/vendor/x509-parser/examples
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 17:39:49 +0000
commita0aa2307322cd47bbf416810ac0292925e03be87 (patch)
tree37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/x509-parser/examples
parentInitial commit. (diff)
downloadsuricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz
suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/x509-parser/examples')
-rw-r--r--rust/vendor/x509-parser/examples/print-cert.rs417
-rw-r--r--rust/vendor/x509-parser/examples/print-crl.rs154
2 files changed, 571 insertions, 0 deletions
diff --git a/rust/vendor/x509-parser/examples/print-cert.rs b/rust/vendor/x509-parser/examples/print-cert.rs
new file mode 100644
index 0000000..9792085
--- /dev/null
+++ b/rust/vendor/x509-parser/examples/print-cert.rs
@@ -0,0 +1,417 @@
+use der_parser::der::Tag;
+use der_parser::oid::Oid;
+use nom::HexDisplay;
+use std::cmp::min;
+use std::convert::TryFrom;
+use std::env;
+use std::io;
+use std::net::{Ipv4Addr, Ipv6Addr};
+use x509_parser::prelude::*;
+use x509_parser::public_key::PublicKey;
+use x509_parser::signature_algorithm::SignatureAlgorithm;
+
+const PARSE_ERRORS_FATAL: bool = false;
+#[cfg(feature = "validate")]
+const VALIDATE_ERRORS_FATAL: bool = false;
+
+fn print_hex_dump(bytes: &[u8], max_len: usize) {
+ let m = min(bytes.len(), max_len);
+ print!("{}", &bytes[..m].to_hex(16));
+ if bytes.len() > max_len {
+ println!("... <continued>");
+ }
+}
+
+fn format_oid(oid: &Oid) -> String {
+ match oid2sn(oid, oid_registry()) {
+ Ok(s) => s.to_owned(),
+ _ => format!("{}", oid),
+ }
+}
+
+fn generalname_to_string(gn: &GeneralName) -> String {
+ match gn {
+ GeneralName::DNSName(name) => format!("DNSName:{}", name),
+ GeneralName::DirectoryName(n) => format!("DirName:{}", n),
+ GeneralName::EDIPartyName(obj) => format!("EDIPartyName:{:?}", obj),
+ GeneralName::IPAddress(n) => format!("IPAddress:{:?}", n),
+ GeneralName::OtherName(oid, n) => format!("OtherName:{}, {:?}", oid, n),
+ GeneralName::RFC822Name(n) => format!("RFC822Name:{}", n),
+ GeneralName::RegisteredID(oid) => format!("RegisteredID:{}", oid),
+ GeneralName::URI(n) => format!("URI:{}", n),
+ GeneralName::X400Address(obj) => format!("X400Address:{:?}", obj),
+ }
+}
+
+fn print_x509_extension(oid: &Oid, ext: &X509Extension) {
+ println!(
+ " [crit:{} l:{}] {}: ",
+ ext.critical,
+ ext.value.len(),
+ format_oid(oid)
+ );
+ match ext.parsed_extension() {
+ ParsedExtension::AuthorityKeyIdentifier(aki) => {
+ println!(" X509v3 Authority Key Identifier");
+ if let Some(key_id) = &aki.key_identifier {
+ println!(" Key Identifier: {:x}", key_id);
+ }
+ if let Some(issuer) = &aki.authority_cert_issuer {
+ for name in issuer {
+ println!(" Cert Issuer: {}", name);
+ }
+ }
+ if let Some(serial) = aki.authority_cert_serial {
+ println!(" Cert Serial: {}", format_serial(serial));
+ }
+ }
+ ParsedExtension::BasicConstraints(bc) => {
+ println!(" X509v3 CA: {}", bc.ca);
+ }
+ ParsedExtension::CRLDistributionPoints(points) => {
+ println!(" X509v3 CRL Distribution Points:");
+ for point in points.iter() {
+ if let Some(name) = &point.distribution_point {
+ println!(" Full Name: {:?}", name);
+ }
+ if let Some(reasons) = &point.reasons {
+ println!(" Reasons: {}", reasons);
+ }
+ if let Some(crl_issuer) = &point.crl_issuer {
+ print!(" CRL Issuer: ");
+ for gn in crl_issuer {
+ print!("{} ", generalname_to_string(gn));
+ }
+ println!();
+ }
+ println!();
+ }
+ }
+ ParsedExtension::KeyUsage(ku) => {
+ println!(" X509v3 Key Usage: {}", ku);
+ }
+ ParsedExtension::NSCertType(ty) => {
+ println!(" Netscape Cert Type: {}", ty);
+ }
+ ParsedExtension::SubjectAlternativeName(san) => {
+ for name in &san.general_names {
+ let s = match name {
+ GeneralName::DNSName(s) => {
+ format!("DNS:{}", s)
+ }
+ GeneralName::IPAddress(b) => {
+ let ip = match b.len() {
+ 4 => {
+ let b = <[u8; 4]>::try_from(*b).unwrap();
+ let ip = Ipv4Addr::from(b);
+ format!("{}", ip)
+ }
+ 16 => {
+ let b = <[u8; 16]>::try_from(*b).unwrap();
+ let ip = Ipv6Addr::from(b);
+ format!("{}", ip)
+ }
+ l => format!("invalid (len={})", l),
+ };
+ format!("IP Address:{}", ip)
+ }
+ _ => {
+ format!("{:?}", name)
+ }
+ };
+ println!(" X509v3 SAN: {}", s);
+ }
+ }
+ ParsedExtension::SubjectKeyIdentifier(id) => {
+ println!(" X509v3 Subject Key Identifier: {:x}", id);
+ }
+ x => println!(" {:?}", x),
+ }
+}
+
+fn print_x509_digest_algorithm(alg: &AlgorithmIdentifier, level: usize) {
+ println!(
+ "{:indent$}Oid: {}",
+ "",
+ format_oid(&alg.algorithm),
+ indent = level
+ );
+ if let Some(parameter) = &alg.parameters {
+ let s = match parameter.tag() {
+ Tag::Oid => {
+ let oid = parameter.as_oid().unwrap();
+ format_oid(&oid)
+ }
+ _ => format!("{}", parameter.tag()),
+ };
+ println!("{:indent$}Parameter: <PRESENT> {}", "", s, indent = level);
+ let bytes = parameter.as_bytes();
+ print_hex_dump(bytes, 32);
+ } else {
+ println!("{:indent$}Parameter: <ABSENT>", "", indent = level);
+ }
+}
+
+fn print_x509_info(x509: &X509Certificate) -> io::Result<()> {
+ let version = x509.version();
+ if version.0 < 3 {
+ println!(" Version: {}", version);
+ } else {
+ println!(" Version: INVALID({})", version.0);
+ }
+ println!(" Serial: {}", x509.tbs_certificate.raw_serial_as_string());
+ println!(" Subject: {}", x509.subject());
+ println!(" Issuer: {}", x509.issuer());
+ println!(" Validity:");
+ println!(" NotBefore: {}", x509.validity().not_before);
+ println!(" NotAfter: {}", x509.validity().not_after);
+ println!(" is_valid: {}", x509.validity().is_valid());
+ println!(" Subject Public Key Info:");
+ print_x509_ski(x509.public_key());
+ print_x509_signature_algorithm(&x509.signature_algorithm, 4);
+
+ println!(" Signature Value:");
+ for l in format_number_to_hex_with_colon(&x509.signature_value.data, 16) {
+ println!(" {}", l);
+ }
+ println!(" Extensions:");
+ for ext in x509.extensions() {
+ print_x509_extension(&ext.oid, ext);
+ }
+ println!();
+ print!("Structure validation status: ");
+ #[cfg(feature = "validate")]
+ {
+ let mut logger = VecLogger::default();
+ // structure validation status
+ let ok = X509StructureValidator
+ .chain(X509CertificateValidator)
+ .validate(x509, &mut logger);
+ if ok {
+ println!("Ok");
+ } else {
+ println!("FAIL");
+ }
+ for warning in logger.warnings() {
+ println!(" [W] {}", warning);
+ }
+ for error in logger.errors() {
+ println!(" [E] {}", error);
+ }
+ println!();
+ if VALIDATE_ERRORS_FATAL && !logger.errors().is_empty() {
+ return Err(io::Error::new(io::ErrorKind::Other, "validation failed"));
+ }
+ }
+ #[cfg(not(feature = "validate"))]
+ {
+ println!("Unknown (feature 'validate' not enabled)");
+ }
+ #[cfg(feature = "verify")]
+ {
+ print!("Signature verification: ");
+ if x509.subject() == x509.issuer() {
+ if x509.verify_signature(None).is_ok() {
+ println!("OK");
+ println!(" [I] certificate is self-signed");
+ } else if x509.subject() == x509.issuer() {
+ println!("FAIL");
+ println!(" [W] certificate looks self-signed, but signature verification failed");
+ }
+ } else {
+ // if subject is different from issuer, we cannot verify certificate without the public key of the issuer
+ println!("N/A");
+ }
+ }
+ Ok(())
+}
+
+fn print_x509_signature_algorithm(signature_algorithm: &AlgorithmIdentifier, indent: usize) {
+ match SignatureAlgorithm::try_from(signature_algorithm) {
+ Ok(sig_alg) => {
+ print!(" Signature Algorithm: ");
+ match sig_alg {
+ SignatureAlgorithm::DSA => println!("DSA"),
+ SignatureAlgorithm::ECDSA => println!("ECDSA"),
+ SignatureAlgorithm::ED25519 => println!("ED25519"),
+ SignatureAlgorithm::RSA => println!("RSA"),
+ SignatureAlgorithm::RSASSA_PSS(params) => {
+ println!("RSASSA-PSS");
+ let indent_s = format!("{:indent$}", "", indent = indent + 2);
+ println!(
+ "{}Hash Algorithm: {}",
+ indent_s,
+ format_oid(params.hash_algorithm_oid()),
+ );
+ print!("{}Mask Generation Function: ", indent_s);
+ if let Ok(mask_gen) = params.mask_gen_algorithm() {
+ println!(
+ "{}/{}",
+ format_oid(&mask_gen.mgf),
+ format_oid(&mask_gen.hash),
+ );
+ } else {
+ println!("INVALID");
+ }
+ println!("{}Salt Length: {}", indent_s, params.salt_length());
+ }
+ SignatureAlgorithm::RSAAES_OAEP(params) => {
+ println!("RSAAES-OAEP");
+ let indent_s = format!("{:indent$}", "", indent = indent + 2);
+ println!(
+ "{}Hash Algorithm: {}",
+ indent_s,
+ format_oid(params.hash_algorithm_oid()),
+ );
+ print!("{}Mask Generation Function: ", indent_s);
+ if let Ok(mask_gen) = params.mask_gen_algorithm() {
+ println!(
+ "{}/{}",
+ format_oid(&mask_gen.mgf),
+ format_oid(&mask_gen.hash),
+ );
+ } else {
+ println!("INVALID");
+ }
+ println!(
+ "{}pSourceFunc: {}",
+ indent_s,
+ format_oid(&params.p_source_alg().algorithm),
+ );
+ }
+ }
+ }
+ Err(e) => {
+ eprintln!("Could not parse signature algorithm: {}", e);
+ println!(" Signature Algorithm:");
+ print_x509_digest_algorithm(signature_algorithm, indent);
+ }
+ }
+}
+
+fn print_x509_ski(public_key: &SubjectPublicKeyInfo) {
+ println!(" Public Key Algorithm:");
+ print_x509_digest_algorithm(&public_key.algorithm, 6);
+ match public_key.parsed() {
+ Ok(PublicKey::RSA(rsa)) => {
+ println!(" RSA Public Key: ({} bit)", rsa.key_size());
+ // print_hex_dump(rsa.modulus, 1024);
+ for l in format_number_to_hex_with_colon(rsa.modulus, 16) {
+ println!(" {}", l);
+ }
+ if let Ok(e) = rsa.try_exponent() {
+ println!(" exponent: 0x{:x} ({})", e, e);
+ } else {
+ println!(" exponent: <INVALID>:");
+ print_hex_dump(rsa.exponent, 32);
+ }
+ }
+ Ok(PublicKey::EC(ec)) => {
+ println!(" EC Public Key: ({} bit)", ec.key_size());
+ for l in format_number_to_hex_with_colon(ec.data(), 16) {
+ println!(" {}", l);
+ }
+ // // identify curve
+ // if let Some(params) = &public_key.algorithm.parameters {
+ // let curve_oid = params.as_oid();
+ // let curve = curve_oid
+ // .map(|oid| {
+ // oid_registry()
+ // .get(oid)
+ // .map(|entry| entry.sn())
+ // .unwrap_or("<UNKNOWN>")
+ // })
+ // .unwrap_or("<ERROR: NOT AN OID>");
+ // println!(" Curve: {}", curve);
+ // }
+ }
+ Ok(PublicKey::DSA(y)) => {
+ println!(" DSA Public Key: ({} bit)", 8 * y.len());
+ for l in format_number_to_hex_with_colon(y, 16) {
+ println!(" {}", l);
+ }
+ }
+ Ok(PublicKey::GostR3410(y)) => {
+ println!(" GOST R 34.10-94 Public Key: ({} bit)", 8 * y.len());
+ for l in format_number_to_hex_with_colon(y, 16) {
+ println!(" {}", l);
+ }
+ }
+ Ok(PublicKey::GostR3410_2012(y)) => {
+ println!(" GOST R 34.10-2012 Public Key: ({} bit)", 8 * y.len());
+ for l in format_number_to_hex_with_colon(y, 16) {
+ println!(" {}", l);
+ }
+ }
+ Ok(PublicKey::Unknown(b)) => {
+ println!(" Unknown key type");
+ print_hex_dump(b, 256);
+ if let Ok((rem, res)) = der_parser::parse_der(b) {
+ eprintln!("rem: {} bytes", rem.len());
+ eprintln!("{:?}", res);
+ } else {
+ eprintln!(" <Could not parse key as DER>");
+ }
+ }
+ Err(_) => {
+ println!(" INVALID PUBLIC KEY");
+ }
+ }
+ // dbg!(&public_key);
+ // todo!();
+}
+
+fn format_number_to_hex_with_colon(b: &[u8], row_size: usize) -> Vec<String> {
+ let mut v = Vec::with_capacity(1 + b.len() / row_size);
+ for r in b.chunks(row_size) {
+ let s = r.iter().fold(String::with_capacity(3 * r.len()), |a, b| {
+ a + &format!("{:02x}:", b)
+ });
+ v.push(s)
+ }
+ v
+}
+
+fn handle_certificate(file_name: &str, data: &[u8]) -> io::Result<()> {
+ match parse_x509_certificate(data) {
+ Ok((_, x509)) => {
+ print_x509_info(&x509)?;
+ Ok(())
+ }
+ Err(e) => {
+ let s = format!("Error while parsing {}: {}", file_name, e);
+ if PARSE_ERRORS_FATAL {
+ Err(io::Error::new(io::ErrorKind::Other, s))
+ } else {
+ eprintln!("{}", s);
+ Ok(())
+ }
+ }
+ }
+}
+
+pub fn main() -> io::Result<()> {
+ for file_name in env::args().skip(1) {
+ println!("File: {}", file_name);
+ let data = std::fs::read(file_name.clone()).expect("Unable to read file");
+ if matches!((data[0], data[1]), (0x30, 0x81..=0x83)) {
+ // probably DER
+ handle_certificate(&file_name, &data)?;
+ } else {
+ // try as PEM
+ for (n, pem) in Pem::iter_from_buffer(&data).enumerate() {
+ match pem {
+ Ok(pem) => {
+ let data = &pem.contents;
+ println!("Certificate [{}]", n);
+ handle_certificate(&file_name, data)?;
+ }
+ Err(e) => {
+ eprintln!("Error while decoding PEM entry {}: {}", n, e);
+ }
+ }
+ }
+ }
+ }
+ Ok(())
+}
diff --git a/rust/vendor/x509-parser/examples/print-crl.rs b/rust/vendor/x509-parser/examples/print-crl.rs
new file mode 100644
index 0000000..73337cb
--- /dev/null
+++ b/rust/vendor/x509-parser/examples/print-crl.rs
@@ -0,0 +1,154 @@
+use der_parser::oid::Oid;
+use nom::HexDisplay;
+use std::cmp::min;
+use std::env;
+use std::io;
+use x509_parser::prelude::*;
+
+fn print_hex_dump(bytes: &[u8], max_len: usize) {
+ let m = min(bytes.len(), max_len);
+ print!("{}", &bytes[..m].to_hex(16));
+ if bytes.len() > max_len {
+ println!("... <continued>");
+ }
+}
+
+fn format_oid(oid: &Oid) -> String {
+ match oid2sn(oid, oid_registry()) {
+ Ok(s) => s.to_owned(),
+ _ => format!("{}", oid),
+ }
+}
+
+fn print_authority_key_identifier(aki: &AuthorityKeyIdentifier, level: usize) {
+ if let Some(id) = &aki.key_identifier {
+ println!("{:indent$}keyid: {:x}", "", id, indent = level);
+ }
+ if aki.authority_cert_issuer.is_some() {
+ unimplemented!();
+ }
+ if let Some(serial) = aki.authority_cert_serial {
+ let s = format_serial(serial);
+ println!("{:indent$}serial: {}", "", &s, indent = level);
+ }
+}
+
+fn print_x509_extension(oid: &Oid, ext: &X509Extension, level: usize) {
+ match ext.parsed_extension() {
+ ParsedExtension::CRLNumber(num) => {
+ println!("{:indent$}X509v3 CRL Number: {}", "", num, indent = level);
+ }
+ ParsedExtension::ReasonCode(code) => {
+ println!(
+ "{:indent$}X509v3 CRL Reason Code: {}",
+ "",
+ code,
+ indent = level
+ );
+ }
+ ParsedExtension::InvalidityDate(date) => {
+ println!("{:indent$}Invalidity Date: {}", "", date, indent = level);
+ }
+ ParsedExtension::AuthorityKeyIdentifier(aki) => {
+ println!(
+ "{:indent$}X509v3 Authority Key Identifier:",
+ "",
+ indent = level
+ );
+ print_authority_key_identifier(aki, level + 2);
+ }
+ x => {
+ print!("{:indent$}{}:", "", format_oid(oid), indent = level);
+ print!(" Critical={}", ext.critical);
+ print!(" len={}", ext.value.len());
+ println!();
+ println!(" {:indent$}{:?}", "", x, indent = level);
+ }
+ }
+}
+
+fn print_x509_digest_algorithm(alg: &AlgorithmIdentifier, level: usize) {
+ println!(
+ "{:indent$}Oid: {}",
+ "",
+ format_oid(&alg.algorithm),
+ indent = level
+ );
+ if let Some(parameter) = &alg.parameters {
+ println!(
+ "{:indent$}Parameter: <PRESENT> {:?}",
+ "",
+ parameter.tag(),
+ indent = level
+ );
+ let bytes = parameter.as_bytes();
+ print_hex_dump(bytes, 32);
+ } else {
+ println!("{:indent$}Parameter: <ABSENT>", "", indent = level);
+ }
+}
+
+fn print_revoked_certificate(revoked: &RevokedCertificate, level: usize) {
+ println!(
+ "{:indent$}Serial number: {}",
+ "",
+ revoked.raw_serial_as_string(),
+ indent = level
+ );
+ println!(
+ "{:indent$}Revocation Date: {}",
+ "",
+ revoked.revocation_date,
+ indent = level + 2
+ );
+ println!("{:indent$}CRL Extensions:", "", indent = level + 2);
+ for ext in revoked.extensions() {
+ print_x509_extension(&ext.oid, ext, level + 4);
+ }
+}
+
+fn print_crl_info(crl: &CertificateRevocationList) {
+ println!(" Version: {}", crl.version().unwrap_or(X509Version(0)));
+ // println!(" Subject: {}", crl.subject());
+ println!(" Signature Algorithm:");
+ print_x509_digest_algorithm(&crl.signature_algorithm, 4);
+ println!(" Issuer: {}", crl.issuer());
+ // println!(" Serial: {}", crl.tbs_certificate.raw_serial_as_string());
+ println!(" Last Update: {}", crl.last_update());
+ println!(
+ " Next Update: {}",
+ crl.next_update()
+ .map_or_else(|| "NONE".to_string(), |d| d.to_string())
+ );
+ println!("{:indent$}CRL Extensions:", "", indent = 2);
+ for ext in crl.extensions() {
+ print_x509_extension(&ext.oid, ext, 4);
+ }
+ println!(" Revoked certificates:");
+ for revoked in crl.iter_revoked_certificates() {
+ print_revoked_certificate(revoked, 4);
+ }
+ println!();
+}
+
+pub fn main() -> io::Result<()> {
+ for file_name in env::args().skip(1) {
+ // placeholder to store decoded PEM data, if needed
+ let tmpdata;
+
+ println!("File: {}", file_name);
+ let data = std::fs::read(file_name.clone()).expect("Unable to read file");
+ let der_data: &[u8] = if (data[0], data[1]) == (0x30, 0x82) {
+ // probably DER
+ &data
+ } else {
+ // try as PEM
+ let (_, data) = parse_x509_pem(&data).expect("Could not decode the PEM file");
+ tmpdata = data;
+ &tmpdata.contents
+ };
+ let (_, crl) = parse_x509_crl(der_data).expect("Could not decode DER data");
+ print_crl_info(&crl);
+ }
+ Ok(())
+}