From b121d57e84f02135f6970b4cb89a254af3b6e4b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fischer?= Date: Fri, 27 Oct 2023 09:34:57 +0200 Subject: [PATCH 1/2] Add an example for X.509 path validation --- doc/api_ref/x509.rst | 11 ++++++++++- src/examples/x509_path.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/examples/x509_path.cpp diff --git a/doc/api_ref/x509.rst b/doc/api_ref/x509.rst index 26c5c3d12e2..0971e8fbe00 100644 --- a/doc/api_ref/x509.rst +++ b/doc/api_ref/x509.rst @@ -471,7 +471,7 @@ implementation of this interface for sqlite3, and a subclass of const std::string& passwd, RandomNumberGenerator& rng, const std::string& table_prefix = "") Create or open an existing certificate store from an sqlite database file. - The password in ``passwd`` will be used to encrypt private keys. + The password in ``passwd`` will be used to encrypt private keys. Path Validation ---------------------------------------- @@ -580,6 +580,15 @@ step. The two constructors are: and, if `minimum_key_strength` is less than or equal to 80, then SHA-1 signatures will also be accepted. +Code Example +----------------- + +For sheer demonstrative purposes, the following code verifies an +end entity certificate against a trusted Root CA certificate. + +.. literalinclude:: /../src/examples/x509_path.cpp + :language: cpp + Creating New Certificates --------------------------------- diff --git a/src/examples/x509_path.cpp b/src/examples/x509_path.cpp new file mode 100644 index 00000000000..fc55af9d1af --- /dev/null +++ b/src/examples/x509_path.cpp @@ -0,0 +1,30 @@ +#include +#include + +int main() { + // Create a certificate store and add the trusted CA certificate + Botan::Certificate_Store_In_Memory store; + store.add_certificate(Botan::X509_Certificate("ca.crt")); + + // Load the end entity certificate from file + Botan::X509_Certificate end_entity("ee.crt"); // The end-entity certificate + + // Optional: Set up restrictions, e.g. min. key strength, maximum age of OCSP responses + Botan::Path_Validation_Restrictions restrictions; + + // Optional: Specify usage type, compared against the key usage in endEntityCert + Botan::Usage_Type usage = Botan::Usage_Type::UNSPECIFIED; + + // Optional: Specify hostname, if not empty, compared against the DNS name in endEntityCert + std::string hostname = ""; + + Botan::Path_Validation_Result validationResult = + Botan::x509_path_validate(end_entity, restrictions, store, hostname, usage); + + if(!validationResult.successful_validation()) { + // call validationResult.result() to get the overall status code + return -1; + } + + return 0; // Verification succeeded +} From 8c3d97b15fd866e0d3069efaacb75b83e97604a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Fischer?= Date: Sat, 28 Oct 2023 14:33:03 +0200 Subject: [PATCH 2/2] Use intermediate CAs and system certificate store --- src/examples/x509_path.cpp | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/examples/x509_path.cpp b/src/examples/x509_path.cpp index fc55af9d1af..f9a215b7687 100644 --- a/src/examples/x509_path.cpp +++ b/src/examples/x509_path.cpp @@ -1,13 +1,21 @@ +#include #include #include int main() { - // Create a certificate store and add the trusted CA certificate - Botan::Certificate_Store_In_Memory store; - store.add_certificate(Botan::X509_Certificate("ca.crt")); + // Create a certificate store and add a locally trusted CA certificate + Botan::Certificate_Store_In_Memory customStore; + customStore.add_certificate(Botan::X509_Certificate("ca.crt")); - // Load the end entity certificate from file - Botan::X509_Certificate end_entity("ee.crt"); // The end-entity certificate + // Additionally trust all system-specific CA certificates + Botan::System_Certificate_Store systemStore; + std::vector trusted_roots{&customStore, &systemStore}; + + // Load the end entity certificate and two untrusted intermediate CAs from file + std::vector end_certs; + end_certs.emplace_back(Botan::X509_Certificate("ee.crt")); // The end-entity certificate, must come first + end_certs.emplace_back(Botan::X509_Certificate("int2.crt")); // intermediate 2 + end_certs.emplace_back(Botan::X509_Certificate("int1.crt")); // intermediate 1 // Optional: Set up restrictions, e.g. min. key strength, maximum age of OCSP responses Botan::Path_Validation_Restrictions restrictions; @@ -19,7 +27,7 @@ int main() { std::string hostname = ""; Botan::Path_Validation_Result validationResult = - Botan::x509_path_validate(end_entity, restrictions, store, hostname, usage); + Botan::x509_path_validate(end_certs, restrictions, trusted_roots, hostname, usage); if(!validationResult.successful_validation()) { // call validationResult.result() to get the overall status code