aboutsummaryrefslogtreecommitdiffstats
path: root/src/tests
diff options
context:
space:
mode:
authorRenĂ© Korthaus <[email protected]>2016-09-05 11:01:42 +0200
committerRenĂ© Korthaus <[email protected]>2016-12-02 11:01:59 +0100
commite8b3e26f4167524216718204c6b5a14ed0e7942d (patch)
tree12e4469750d81a565185212766c0d51a7312ea4d /src/tests
parent5c49dbac212e53be821b0771d3df46f78801efbe (diff)
Allow custom extensions in X509_Cert_Options
Allow custom extensions in CA-signed cert requests Add templated getter for extensions
Diffstat (limited to 'src/tests')
-rw-r--r--src/tests/unit_x509.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/src/tests/unit_x509.cpp b/src/tests/unit_x509.cpp
index 7a22033a8..ceed26c75 100644
--- a/src/tests/unit_x509.cpp
+++ b/src/tests/unit_x509.cpp
@@ -17,6 +17,8 @@
#include <botan/x509path.h>
#include <botan/x509_ca.h>
#include <botan/pk_algs.h>
+#include <botan/ber_dec.h>
+#include <botan/der_enc.h>
#endif
@@ -710,6 +712,117 @@ Test::Result test_valid_constraints(const std::string& pk_algo)
return result;
}
+/**
+ * @brief X.509v3 extension that encodes a given string
+ */
+class String_Extension : public Botan::Certificate_Extension
+ {
+ public:
+ String_Extension(const Botan::OID& oid, const std::string& val) : m_oid(oid), m_contents(val) {}
+
+ std::string value() const { return m_contents; }
+
+ String_Extension* copy() const override { return new String_Extension(m_oid, m_contents); }
+
+ Botan::OID oid_of() const override { return m_oid; }
+ std::string oid_name() const override { return "String Extension"; }
+
+ void contents_to(Botan::Data_Store&, Botan::Data_Store&) const override {}
+
+ std::vector<byte> encode_inner() const override
+ {
+ return Botan::DER_Encoder().encode(Botan::ASN1_String(m_contents, Botan::UTF8_STRING)).get_contents_unlocked();
+ }
+
+ void decode_inner(const std::vector<byte>& in) override
+ {
+ Botan::ASN1_String str;
+ Botan::BER_Decoder(in).decode(str, Botan::UTF8_STRING).verify_end();
+ m_contents = str.value();
+ }
+
+ private:
+ Botan::OID m_oid;
+ std::string m_contents;
+ };
+
+Test::Result test_x509_extensions(const std::string& sig_algo, const std::string& hash_fn = "SHA-256")
+ {
+ using Botan::Key_Constraints;
+
+ Test::Result result("X509 Extensions");
+
+ /* Create the CA's key and self-signed cert */
+ std::unique_ptr<Botan::Private_Key> ca_key(make_a_private_key(sig_algo));
+
+ if(!ca_key)
+ {
+ // Failure because X.509 enabled but requested signature algorithm is not present
+ result.test_note("Skipping due to missing signature algorithm: " + sig_algo);
+ return result;
+ }
+
+ /* Create the self-signed cert */
+ Botan::X509_Certificate ca_cert =
+ Botan::X509::create_self_signed_cert(ca_opts(),
+ *ca_key,
+ hash_fn,
+ Test::rng());
+
+ /* Create the CA object */
+ Botan::X509_CA ca(ca_cert, *ca_key, hash_fn);
+
+ std::unique_ptr<Botan::Private_Key> user_key(make_a_private_key(sig_algo));
+
+ Botan::X509_Cert_Options opts("Test User 1/US/Botan Project/Testing");
+ opts.constraints = Key_Constraints::DIGITAL_SIGNATURE;
+
+ // include a custom extension in the request
+ Botan::Extensions req_extensions;
+ Botan::OID oid("1.2.3.4.5.6.7.8.9.1");
+ req_extensions.add(new String_Extension(oid, "1Test"), false);
+ opts.extensions = req_extensions;
+
+ /* Create a self-signed certificate */
+ Botan::X509_Certificate self_signed_cert = Botan::X509::create_self_signed_cert(opts, *user_key, hash_fn, Test::rng());
+
+ // check if custom extension is present in cert
+ // it would be nice if we could use v3_extensions().extensions() instead
+ auto ext_raw = self_signed_cert.v3_extensions().extensions_raw();
+ if(result.confirm("Custom extension present in self-signed certificate", ext_raw.count(oid) > 0))
+ {
+ std::vector<byte> in = ext_raw.at(oid).first;
+ String_Extension ext(oid, "");
+ ext.decode_inner(in);
+
+ result.confirm("Custom extension value matches in self-signed certificate", ext.value() == "1Test");
+ }
+
+
+ Botan::PKCS10_Request user_req =
+ Botan::X509::create_cert_req(opts,
+ *user_key,
+ hash_fn,
+ Test::rng());
+
+ /* Create a CA-signed certificate */
+ Botan::X509_Certificate user_cert =
+ ca.sign_request(user_req, Test::rng(),
+ from_date(2008, 01, 01),
+ from_date(2033, 01, 01));
+
+ ext_raw = user_cert.v3_extensions().extensions_raw();
+ if(result.confirm("Custom extension present in user certificate", ext_raw.count(oid) > 0))
+ {
+ std::vector<byte> in = ext_raw.at(oid).first;
+ String_Extension ext(oid, "");
+ ext.decode_inner(in);
+
+ result.confirm("Custom extension value matches in user certificate", ext.value() == "1Test");
+ }
+
+ return result;
+ }
class X509_Cert_Unit_Tests : public Test
{
@@ -722,6 +835,7 @@ class X509_Cert_Unit_Tests : public Test
Test::Result cert_result("X509 Unit");
Test::Result usage_result("X509 Usage");
Test::Result self_issued_result("X509 Self Issued");
+ Test::Result extensions_result("X509 Extensions");
for(const auto& algo : sig_algos)
{
@@ -748,11 +862,20 @@ class X509_Cert_Unit_Tests : public Test
{
self_issued_result.test_failure("test_self_issued " + algo, e.what());
}
+
+ try {
+ extensions_result.merge(test_x509_extensions(algo));
+ }
+ catch(std::exception& e)
+ {
+ extensions_result.test_failure("test_extensions " + algo, e.what());
+ }
}
results.push_back(cert_result);
results.push_back(usage_result);
results.push_back(self_issued_result);
+ results.push_back(extensions_result);
const std::vector<std::string> pk_algos { "DH", "ECDH", "RSA", "ElGamal", "GOST-34.10",
"DSA", "ECDSA", "ECGDSA", "ECKCDSA" };